Master HistropediaJS

Build immersive, interactive timelines with confidence using our complete documentation and best practices.

Getting Started

Build your first interactive timeline in minutes.

Installation

1. Install from npm

For bundlers and ESM-capable runtimes, install the package from npm:

Shell
npm install histropediajs

2. Load the library

Use ESM imports with a bundler, or load the UMD build from a CDN for script-tag embeds.

JavaScript
import Histropedia, { Timeline, Dmy } from 'histropediajs';

const container = document.getElementById('timeline');
const timeline = new Timeline(container);

console.log(Histropedia.Timeline === Timeline);

HistropediaJS is published as an ESM package for npm and bundlers. CommonJS require('histropediajs') is not supported.

For non-module browser usage, use the UMD script-tag build shown above, or self-host histropedia.umd.js / histropedia.umd.min.js.

TypeScript definitions are included with the npm package. The download bundle also includes histropedia.esm.d.ts for direct ESM usage.

CDN URLs

For direct CDN imports, you can target the package default or a specific build file:

Text
https://cdn.jsdelivr.net/npm/[email protected]
https://cdn.jsdelivr.net/npm/[email protected]/dist/histropedia.esm.js
https://cdn.jsdelivr.net/npm/[email protected]/dist/histropedia.umd.js
https://cdn.jsdelivr.net/npm/[email protected]/dist/histropedia.umd.min.js

Your First Timeline

With HistropediaJS loaded (see Installation), you're ready to render a timeline. Create a container element, instantiate the timeline, and load a few events.

HTML
<div id="timeline"></div>
JavaScript
import { Timeline } from 'histropediajs';

const container = document.getElementById('timeline');
const timeline = new Timeline(container, {
  width: 1000,
  height: 500,
  initialDate: { year: 1989, month: 3, day: 12 },
  zoom: { initial: 34 },
});

timeline.load([
  {
    id: 1,
    title: 'Moon Landing',
    subtitle: 'Apollo 11',
    from: { year: 1969, month: 7, day: 16 },
    to: { year: 1969, month: 7, day: 24 },
  },
  {
    id: 2,
    title: 'World Wide Web',
    subtitle: 'Tim Berners-Lee proposal',
    from: { year: 1989, month: 3, day: 12 },
  },
  {
    id: 3,
    title: 'iPhone Launch',
    subtitle: 'Apple unveils the iPhone',
    from: { year: 2007, month: 1, day: 9 },
  },
]);
🎉

Congratulations!

You've rendered your first interactive timeline. Head to the configuration and data model sections to customize it further.



Core Concepts

Understand the core concepts that power HistropediaJS.

Timeline

The Timeline is the engine that renders and manages the interactive canvas. Creating a Timeline instance is the first step and provides the foundation for configuration, loaded Articles, Lanes, Time Bands, event listeners, and other features.

You can create multiple timelines on the same page, each with its own configuration, data, and render state.

API reference: Timeline Options, Timeline Methods

Article

An Article is a single item on the timeline, representing an event which may be an instant or a period of time. Articles are added to the timeline using the timeline.load method and follow the Article Schema.

Each Article appears as a card attached to a period line that represents its time span. Article options control behaviour and the type of card layout ("portrait", "landscape", or a custom layout) and article styles define the appearance for whichever layout has been selected.

API reference: Load Articles Method, Article Schema, Article Options, Article Style

Lane new

A Lane is a horizontal section for grouping related Articles while preserving one shared bottom timeline axis. Lane's have backgrounds which are created as DOM elements underneath the timeline canvas so they can easily be styled via CSS if preferred.

Define explicit lanes with options.lane.data or timeline.loadLanes, then load articles usingtimeline.loadLaneArticles. Alternatively, use the standard timeline.load method with a lane key on each article. Articles without a lane use options.lane.defaultId. If an article references a lane id that has not been defined yet, HistropediaJS automatically creates an implicit lane for that id.

You can also move an article between lanes after loading it with article.setOption("lane", laneId).

API reference: Lane Options, Lane Schema, Lane Methods

Time Band new

A Time Band is a background band used to mark broad periods or eras, shown beneath the main timeline line by default.

Time Bands are loaded using the timeBand.data option or the timeline.loadTimeBands method, following the Time Band schema.

API reference: Load Time Bands Method, Time Band Schema, Time Band Options, Time Band Style

Configuration

Control initialization and behavior via Timeline options, and nested options for Lanes, Articles, and Time Bands.

Timeline Options

An object containing all settings supported by the timeline. Any option not specified will use the default value.

The timeline options are the main root for all configuration. They include nested settings for controlling zoom, panning, Lanes, Articles, Time Bands, image loading, and styling (shown below with links in the comments).

All timeline options, including nested options, can be set at timeline initialization by passing the object to the Timeline constructor. They can also be set at runtime using the setOption timeline method.

JavaScript
// Core timeline options (defaults)
{
  width: 1000,
  height: 500,
  verticalOffset: 40,
  enableUserControl: true,
  enableCursor: true,
  draggingVicinity: true,
  shiftBceDates: false,
  initialDate: {
    year: 1990,
    month: 1,
    day: 1,
  },
  canvas: { // new
    dpr: 'auto',
    dprMode: 'stable',
    maxDpr: 3,
  },
  zoom:     { /* See: Zoom Options */ },
  pan:      { /* See: Pan Options */ }, // new
  article:  { /* See: Article Options */ },
  lane:     { /* See: Lane Options */ }, // new
  timeBand: { /* See: Time Band Options */ }, // new
  image:    { /* See: Image Options */ },     // new
  style:    { /* See: Timeline Style */ },

  // Additional optional event handling:
  // - on: { 'event-name': (...args) => { /* handler */ } } // new

  //  deprecated Legacy event handlers (since v1.3.0):
  // - onRedraw
  // - onArticleClick
  // - onArticleDoubleClick
  // - onSave
}

Zoom Options

Control the zoom behavior of the timeline, including initial level, limits and wheel behaviour.

These options live under options.zoom.*. The values shown below are the defaults.

JavaScript
// Zoom options (defaults)
{
  initial: 34,
  minimum: 0,
  maximum: 123,
  wheelStep: 0.2, // changed default
  wheelSpeed: 3,
  allowCtrlWheel: false,     // new
  wheelMode: 'auto',         // new
  discreteWheelAnimation: { // new
    active: true,
    duration: 250
  },
  proportionalGain: 2,       // new
  proportionalExponent: 1.1, // new
  ratio: 0.8,
  unitSize: {
    initial: 200,
    showMinorLabels: 48,
    minimum: 8,
  }
};

Pan Options new

Control drag-release momentum after a user pans the timeline viewport.

These options live under options.pan.*. The values shown below are the defaults.

JavaScript
// Pan options (defaults)
{
  momentum: {
    active: true,
    sampleWindow: 100,
    minVelocity: 0.01,
    stopVelocity: 0.005,
    friction: 0.005,
    maxDuration: 5600
  }
};

Article Options

Configure how articles (event cards) look and behave: stacking, period lines, animations, and default styles for normal, hover, and active states.

These options live under options.article.*. Defaults are shown below.

💡

Tip

Exported constants and functions like DENSITY_ALL, RANGE_ALL, and ARTICLE_FROM_SORTER are available in both build types:

  • ESM: import { DENSITY_ALL, RANGE_ALL } from 'histropediajs';
  • UMD: const { DENSITY_ALL, RANGE_ALL } = Histropedia;

JavaScript
// Article options (defaults)
{
  density: DENSITY_ALL,
  rendering: { // new
    pixelSnap: 'device'
  },
  draggable: true,
  distanceToBaseline: { // changed
    value: 350,
    responsive: {
      active: true,
      lanesOnly: true,
      byCardLayout: {
        portrait: { ratio: 0.6, min: 310, max: 410 },
        landscape: { ratio: 0.6, min: 100, max: 160 }
      }
    }
  },
  // distanceToMainLine: 350, // deprecated Use distanceToBaseline.value
  collectOngoing: false,
  autoStacking: {
    active: true,
    rowSpacing: 50,
    range: RANGE_ALL,
    fitToHeight: true,
    topGap: 10
  },
  periodLine: {
    position: 'lane', // new
    baselineGap: 0, // new
    spacing: 4,
    thickness: 10,
    stacking: {
      sorter: ARTICLE_FROM_SORTER,
      reverseOrder: false
    }
  },
  animation: {
    fade: {
      active: true,
      duration: 1500,
      easing: 'swing' // new values
    },
    move: {
      active: true,
      duration: 1500,
      easing: 'swing' // new values
    }
  },
  star: { // new
    visible: true
  },
  defaultData: { // new
    from: {
      precision: PRECISION_DAY
    },
    to: {
      precision: PRECISION_DAY
    },
    rank: 0,
    starred: false,
    hidePeriodLine: false,
    hiddenByFilter: false
  },
  defaultCardLayout: 'portrait', // new
  cardLayoutBreakpoints: [ // new
    { maxHeight: 320, layout: 'landscape' }
  ],
  defaultStyle:       {/* See: Article Default StyleOptions */ },
  defaultHoverStyle:  {/* See: Article Default Hover StyleOptions */ },
  defaultActiveStyle: {/* See: Article Default Active StyleOptions */ },
  layoutStyles:       {/* See: Article Layout StylesOptions */ } // new
};

Lane Options new

Configure multi-lane timelines where related articles sit in separate horizontal lanes while sharing one bottom axis.

These options live under options.lane.*. The values shown below are the defaults.

Lane layout controls lane chrome. Article options control article placement. See Lane Article Overrides for the subset of article options supported by each lane's article object. For a minimal runnable setup, see the simple timeline lanes CodePen.

JavaScript
// Lane options (defaults)
{
  visible: true,
  defaultId: 'default',
  gap: 12,
  topGap: 0,
  axisGap: 24,
  defaultLayout: {/* See: Lane Layout */ },
  defaultStyle: {/* See: Lane Style */ },
  defaultClassName: '',
  defaultHeaderClassName: '',
  defaultBodyClassName: '',
  defaultTitleClassName: '',
  data: [
    /* see Lane Schema; each lane can include
       article: { ... } - see Lane Article Overrides */
  ]
};

Lane Article Overrides

Set LaneData.article to override the timeline-wide article defaults from options.article for one lane. It supports a focused subset of Article Options; each value merges over the timeline article options for articles in that lane.

Use the Article Options section for the full descriptions and value shapes. The links below point to the matching option descriptions.

Merge order

Timeline article options apply first. Lane article overrides apply next for that lane, then individual article data and article-level style overrides apply last.

Supported keys

Other article keys, including cardLayoutBreakpoints, rendering, animation, star, periodLine.position, periodLine.stacking, and autoStacking.range, remain timeline-wide options.

Time Band Options new

Control visibility, layout, and defaults for background eras rendered behind the main timeline line.

These options live under options.timeBand.*. The values shown below are the defaults.

JavaScript
// Time Band options (defaults)
{
  visible: true,
  reserveSpace: true,
  reserveSpacePixels: 20,
  area: { up: 0, down: 'edge' },
  defaultStyle: { /* see Time Band Style */ },
  data: [ /* see Time Band Schema */ ]
};

Image Options new

Configure built-in image loading, caching, and sanitization. This only affects images loaded automatically from the imageUrl property in each article's data. Images are queued for loading when required to render an article. Images are evicted from the cache when the configured image.maxCacheBytes limit has been exceeded, or an image's dimensions have changed.

These options live under options.image.*. The values shown below are the defaults.

JavaScript
// Image options (defaults)
{
  maxConcurrent: 6,
  maxCacheBytes: 64 * 1024 * 1024,
  requireCORS: false,
  decodeMode: 'auto',
  sanitizer: {
    allowedSchemes: ['http', 'https', 'data', 'blob'],
    // allowedOrigins: ['*.example.com'],
  },
  // customSanitizer: (url, options) => url,
};

Debugging and Logging new

HistropediaJS uses a centralized Logger service to control all debug output. Logging is disabled by default so it will not spam your console unless you explicitly turn it on.

You can toggle logging globally via the default Histropedia export, or work directly with the Logger class in ESM/bundler setups. UMD/script builds expose the same helpers on the global Histropedia namespace.

Enable or disable debug logging (default export helpers)

When using the default export, call the convenience helpers below to enable or disable debug output across the library. These methods internally delegate to the shared Logger instance.

JavaScript
import Histropedia from 'histropediajs';
// Or use the global Histropedia object directly for UMD/script-tag usage

// Turn on all HistropediaJS logging
Histropedia.enableDebug();

// Or explicitly set the flag
Histropedia.setDebug(true);

// Later, turn logging off again
Histropedia.disableDebug();
// Equivalent:
Histropedia.setDebug(false);

// Check current state
const isOn = Histropedia.isDebugEnabled(); // boolean

Using the Logger directly (ESM / bundlers)

In module-based builds you can import the Logger class directly. This gives you fine-grained control over the debug flag and lets you emit structured messages at different levels.

JavaScript
import { Logger } from 'histropediajs';

Logger.setEnabled(true); // enable logging
Logger.debug('Timeline initialized');
Logger.info('Loaded articles', articles);
Logger.warn('Something looks odd');
Logger.error('Something went wrong', err);

UMD / script-tag usage

When using the UMD build via a <script> tag, the same helpers are available on the global Histropedia object. You can either toggle logging via Histropedia.enableDebug() or work with Histropedia.Logger directly.

HTML
<script src="https://cdn.jsdelivr.net/npm/histropediajs@1/dist/histropedia.umd.min.js"></script>
<script>
  // Enable debug logging
  Histropedia.enableDebug();

  // Or via the Logger instance
  Histropedia.Logger.setEnabled(true);
  Histropedia.Logger.debug('Timeline ready');
</script>

Changing the debug label (console prefix)

All log messages are prefixed with a label (by default [Histropedia]) so you can easily spot them in the console. You can change this prefix to include your app name, environment, or any other marker.

JavaScript
import { Logger } from 'histropediajs';

// Set a custom label that will appear in front of every log message
Logger.setPrefix('[MyApp Timeline]');

Logger.setEnabled(true);
Logger.debug('Loading articles...');
// Output: [MyApp Timeline] Loading articles...

For script-tag/UMD usage you can configure the same prefix via the global Logger instance:

JavaScript
Histropedia.Logger.setPrefix('[MyApp Timeline]');
Histropedia.enableDebug();
Histropedia.Logger.info('Timeline is ready');
// Output: [MyApp Timeline] Timeline is ready

The prefix is applied to all standard console-style methods exposed by the logger (log, info, warn, error, debug, group, groupCollapsed, groupEnd).

Styling

Customize the default appearance and lane layout of Timelines, Articles, Lanes, and Time Bands across your project.

Timeline Style

Define the base styling for the timeline canvas. Override these defaults per instance as needed.

These options live under options.style.*. The values shown below are the defaults.

JavaScript
// Timeline style options (defaults)
{
  mainLine: {
    visible: true,
    size: 8
  },
  draggingHighlight: {
    visible: true,
    area: { up: 0, down: 'edge' }, // changed default new values
    color: 'rgba(237, 247, 255, 0.5)'
  },
  marker: {
    minor: {
      height: 12,
      color: '#6097f2',
      futureColor: '#ccc'
    },
    major: {
      height: 30,
      color: '#0c3a88',
      futureColor: '#ccc'
    }
  },
  dateLabel: {
    minor: {
      font: 'normal 10px Calibri',
      color: '#333',
      futureColor: '#ccc',
      textAlign: 'start',
      offset: {
        x: 4,
        y: 0
      },
      bceText: '',
      thousandsSeparator: ',',
      yearPrefixes: {
        ka: { label: 'ka', value: 1000, minDivision: 1000 },
        Ma: { label: 'Ma', value: 1e6, minDivision: 1e5 },
        Ga: { label: 'Ga', value: 1e9, minDivision: 1e8 }
      }
    },
    major: {
      font: 'normal 16px Calibri',
      color: '#000',
      futureColor: '#ccc',
      textAlign: 'start',
      offset: {
        x: 4,
        y: 0
      },
      bceText: ' ʙᴄᴇ',
      thousandsSeparator: ',',
      yearPrefixes: {
        ka: { label: 'ka', value: 1000, minDivision: 1e5 },
        Ma: { label: 'Ma', value: 1e6, minDivision: 1e6 },
        Ga: { label: 'Ga', value: 1e9, minDivision: 1e9 }
      }
    }
  }
};

Article Style

Article styles control the appearance of article cards on the timeline. You can define the default style, hover style, and active style for all articles in the Article Options, or override them per article in the Article Data.

Styles can also be changed at runtime:
Timeline defaults: timeline.setOption
Individual articles: article.setStyle(), article.setHoverStyle(), article.setActiveStyle()

⚠️

Caution: If a change to the default styles doesn’t take effect, it may have been overridden by layout styles (for example, the landscape layout).
Update the property in layoutStyles.<layout>.style (or the corresponding hover/active override).

Default Style

The object below lists the complete set of available properties for styling article cards. The values shown for each property are the system defaults. Click on any property to see a description.

These properties can be used anywhere an article style object is used, such as the default style, hoverStyle, and activeStyle, or the layoutStyles object. However, some properties are only supported for specific card layouts, and will be ignored for other layouts. This is indicated with a callout in the description for the property.

defaultStyle in the article options object.

JavaScript
// Default style
{
  color: '#e9e9e9',
  width: 150,
  height: 70,
  backgroundColor: '#fff',
  topRadius: 3,
  borderRadius: 0,
  maxImageHeight: 400, // deprecated Use image.maxHeight instead
  image: { // new
    shape: 'natural',
    margin: 0,
    maxHeight: 400,
    borderRadius: 4
  },
  header: {
    height: 50,
    text: {
      font: "normal 14px 'Segoe UI'",
      color: "#333",
      align: "left",
      baseline: "middle",
      margin: 10,
      lineHeight: 18,
      numberOfLines: 2,
      offsetY: 0 // new
    }
  },
  subheader: {
    height: 30,
    color: '#555',
    text: {
      font: "normal 11px 'Segoe UI'",
      color: "#eee",
      align: "left",
      baseline: "middle",
      margin: 10,
      lineHeight: 6,
      offsetY: 0 // new
    }
  },
  shadow: {
    x: 0,
    y: 0,
    amount: 0,
    color: '#000'
  },
  border: {
    color: '#ddd',
    width: 1
  },
  connectorLine: {
    visible: true,
    offsetX: 18,
    offsetY: -20,
    thickness: 1,
    arrow: { width: 16, height: 45 }
  },
  star: {
    width: 16,
    margin: 3
  }
}

Default Hover Style

Define hover styles as overrides to the normal style. All of the same properties as the main style are supported. See all all fields with descriptions in the default style section above.

defaultHoverStyle in the article options object.

JavaScript
// Default hoverStyle
{
  color: "#a6c6e2"
}

Default Active Style

Define active styles as overrides to the normal style. All of the same properties as the main style are supported. See all all fields with descriptions in the default style section above.

defaultActiveStyle in the article options object.

JavaScript
// Default activeStyle
{
  color: "#337ab7",
  header: { 
    text: { color: "#fff" }
  },
  subheader: { color: '#333' },
  shadow: { x: 3, y: 3, amount: 5, color: '#333' },
  border: { width: 2, color: "#2e6da4" },
  connectorLine: { thickness: 2 }
}

Layout Styles

Layout styles override the normal style, hoverStyle, and activeStyle objects. They are applied only when a specific card layout is used. HistropediaJS currently includes two built-in layouts — “portrait” and “landscape” — with more coming soon (along with guidance for defining custom layouts).

You can define or override layout-specific styles using the layoutStyles key in the article options object, where each layout name acts as a key. Each layout style object supports the same properties as the main article style. See the Default Style section above for the complete list of available fields.

The portrait layout (the default) has no additional overrides. The landscape layout includes the following differences:

JavaScript
// layoutStyles
{
  // "portrait" has no additional layout style by default
  landscape: {
    style: {
      width: 220,
      height: 70,      // Only used for landscape layout
      borderRadius: 4, // Only used for landscape layout
      image: {
        shape: "circle",
        margin: 10
      },
      header: {
        text: {
          color: "#333",
          baseline: "alphabetic"
        }
      },
      subheader: {
        text: {
          color: "#777",
          baseline: "alphabetic"
        }
      }
    },
   hoverStyle: {
      border: {
        color: "#a6c6e2"
      }
    },
    activeStyle: {
      header: {
        text: {
          color: "#000"
        }
      },
      subheader: {
        text: {
          color: "#333"
        }
      }
    }
  }
}

Lane Layout new

Configure the reusable geometry shape for lane chrome. These fields are used by lane.defaultLayout and LaneData.layout.

Lane layout controls lane chrome height and title placement. Article options still control article placement inside each lane.

JavaScript
// LaneLayout options
{
  // height: 240, // optional fixed lane height in px
  heightWeight: 1,
  header: {
    visible: true,
    height: 24,
    padding: {
      left: 12,
      right: 12
    }
  }
};

Fixed and automatic heights: lanes with height consume fixed pixels first. Lanes without height divide the remaining lane area by heightWeight, excluding hidden lanes.

Lane Style new

Customize the DOM chrome for lane headers, bodies, and titles. These fields are used by lane.defaultStyle and LaneData.style.

Lane style defaults are empty objects, so inline styles are only written for values you explicitly configure.

Lane DOM also has stylesheet hooks for themes that should stay out of inline configuration: histropedia-lane, histropedia-lane-index-N, histropedia-lane-position-top, histropedia-lane-position-middle, histropedia-lane-position-bottom, histropedia-lane-header, histropedia-lane-title, and histropedia-lane-body.

N follows timeline.lanes from the shared axis outward. Lower lanes are given higher z-index values than lanes above them, so CSS shadows can make upper lanes appear tucked behind the lane below.

JavaScript
// LaneStyle options
{
  header: {
    // backgroundColor: 'rgba(219, 234, 254, 0.35)'
  },
  body: {
    // backgroundColor: 'rgba(219, 234, 254, 0.2)',
    // borderColor: 'rgba(30, 58, 138, 0.25)',
    // borderWidth: 1,
    // borderRadius: 4
  },
  title: {
    // color: '#1e3a8a',
    // font: '600 13px Inter, sans-serif',
    // textAlign: 'left'
  }
};

Per-lane overrides: set the style key in Lane data, call lane.setStyle, or provide global defaults with options.lane.defaultStyle. Fields you omit stay stylesheet-controlled.

.histropedia-lane {
  overflow: visible;
}

.histropedia-lane:not(.histropedia-lane-position-top) {
  box-shadow: 0 -14px 22px -20px rgba(15, 23, 42, 0.7);
}

.histropedia-lane-position-bottom {
  box-shadow: none;
}

Time Band Style new

Customize the palette, borders, and typography applied to every band. Per-band overrides merge deeply with this default object.

timeBand.defaultStyle in the Time Band Options object.

JavaScript
// Time Band defaultStyle
{
  backgroundColor: 'rgba(200, 200, 200, 0.25)',
  border: {
    color: 'rgba(120, 120, 120, 0.25)',
    width: 1
  },
  text: {
    font: 'normal 16px Calibri',
    color: '#555',
    align: 'left',
    baseline: 'bottom',
    verticalAlign: 'bottom',
    margin: 4,
    offsetY: 0
  }
};

Per-band overrides: call band.setStyle, or set the style key in the Time Band data with a partial object. Fields you omit fall back to the defaults above.

Data Model

Define the structure for timeline content and how per-entry overrides build on your configuration.

Article Schema

An article object powers a single timeline entry: metadata, span on the timeline, and optional style overrides that plug into the article defaults defined in your timeline options.

At a glance: Required fields — id, title, from.

Schema
// Article Schema (clickable)
// Keys are clickable; annotations are NOT defaults.
{
	  id: /* required: number|string */,
	  title: /* required: string */,
	  subtitle: /* optional: string */,
	  lane: /* optional: number|string */,

	  from: {
    year: /* required: number */,
    month: /* optional: 1–12 */,
    day: /* optional: 1–31 */,
    precision: /* optional: one of the PRECISION_* constants; default: PRECISION_DAY */,
  },

  to: { /* optional */
    year: /* required: number */,
    month: /* optional: 1–12 */,
    day: /* optional: 1–31 */,
    precision: /* optional: one of the PRECISION_* constants; default: PRECISION_DAY */
  },
  isToPresent: /* optional: boolean; default: false */,

  imageUrl: /* optional: string (URL) */,
  rank: /* optional: number */,
  starred: /* optional: boolean; default: false */,
  hiddenByFilter: /* optional: boolean | function(Article): boolean; default: false */,
  hidePeriodLine: /* optional: boolean | function(Article): boolean; default: false */,
  offsetLeft: /* optional: number (px); default: 0 */,
  offsetTop: /* optional: number (px); default: 0 */,
  
  cardLayout: /* optional: 'portrait' | 'landscape' | string */,

  // Per-article style overrides (sparse)
  style: /* optional: ArticleStyle */,
  hoverStyle: /* optional: ArticleStyle */,
  activeStyle: /* optional: ArticleStyle */,
}

Per-article style, hoverStyle, and activeStyle override the timeline's article default styles. See: Article Style.

Lane Schema new

A lane object defines one horizontal section of a multi-lane timeline. Load articles with timeline.load and add a lane key to place them in a lane.

At a glance: Required fields — id. All other fields are optional.

Lane layout controls lane chrome. Article options control article placement. See Lane Article Overrides for the supported article keys.

Schema
// LaneData schema (clickable)
{
  id: /* required: number|string */,
  title: /* optional: string */,
  visibility: /* optional: 'visible' | 'hidden' | function(Lane): 'visible' | 'hidden' */,
  className: /* optional: string */,
  headerClassName: /* optional: string */,
  bodyClassName: /* optional: string */,
  titleClassName: /* optional: string */,
  layout: { /* See: Lane Layout */ },
  style: { /* See: Lane Style */ },
  article: { /* See: Lane Article Overrides */ }
}

Time Band Schema new

Time bands describe the spans rendered behind the main timeline line. They use the same day/month/year precision model as articles.

At a glance: Required fields — id, title, from.

Schema
// Time Band Schema (clickable)
{
  id: /* required: number|string */,
  title: /* required: string */,

  from: {
    year: /* required: number */,
    month: /* optional: 1-12 */,
    day: /* optional: 1-31 */,
    precision: /* optional: one of the PRECISION_* constants; default: PRECISION_DAY */
  },

  to: { /* optional */
    year: /* required: number */,
    month: /* optional: 1-12 */,
    day: /* optional: 1-31 */,
    precision: /* optional: one of the PRECISION_* constants; default: PRECISION_DAY */
  },
  isToPresent: /* optional: boolean; default: false */,

  style: /* optional: TimeBandStyle */,
  visibility: /* optional: 'visible' (default) | 'hidden' | function(TimeBand): 'visible' | 'hidden' */
};

API Reference

Complete reference for every method you can call from a timeline instance.

Timeline Methods

Master these methods to control every aspect of your timeline:

.load(articles)

Data

Load the given array of articles on to the timeline.

Parameters
article ArticleData[]

Array of Article objects. Each entry follows the Article Schema.

Returns

void – Loads the articles in place and updates internal state.

This method is used to populate the timeline with articles. It can be called again at any time to add more articles, provided they have unique id properties.

const timeline = new Histropedia.Timeline(container);

// Load articles on to the timeline
timeline.load([
  {
    id: 1,
    title: 'Moon Landing',
    subtitle: 'Apollo 11',
    from: { year: 1969, month: 7, day: 16 },
    to: { year: 1969, month: 7, day: 24 }
  },
  {
    id: 2,
    title: 'World Wide Web',
    subtitle: 'Tim Berners-Lee proposal',
    from: { year: 1989, month: 3, day: 12 }
  }
]);

.loadLanes(lanes) new

Data

Add or update explicit lane definitions.

Parameters
lanes LaneData[]

Array of Lane objects. Each entry follows the Lane Schema.

Returns

void – Adds or updates lanes and redraws the timeline.

If a lane already exists implicitly because article data referenced its id, loadLanes upgrades it to an explicit lane.

timeline.loadLanes([
  {
    id: 'people',
    title: 'People',
    layout: { heightWeight: 2 },
    article: {
      defaultCardLayout: 'landscape',
      defaultStyle: { width: 220 }
    }
  },
  {
    id: 'projects',
    title: 'Projects'
  }
]);

.loadLaneArticles(laneId, articles) new

Data

Stamp a lane id onto a batch of articles and load them onto the timeline.

Parameters
laneId string | number

Lane identifier to assign to every article in the batch.

articles ArticleData[]

Article objects. Existing conflicting lane values are overwritten by laneId.

Returns

void – Loads the articles and redraws the timeline.

timeline.loadLaneArticles('projects', [
  {
    id: 'analytical-engine',
    title: 'Analytical Engine',
    from: { year: 1837 }
  },
  {
    id: 'difference-engine',
    title: 'Difference Engine',
    from: { year: 1822 }
  }
]);

.loadTimeBands(bands) new

Data

Load the given array of Time Bands on to the timeline.

Parameters
bands TimeBandData[]

Array of Time Band objects. Each entry follows the Time Band Schema.

Returns

void – Loads the bands in place and updates internal state.

This method is used to populate the timeline with Time Bands. It can be called again at any time to add more bands, provided they have unique id properties.

const timeline = new Histropedia.Timeline(container);

// Load bands on to the timeline
timeline.loadTimeBands([
  {
    id: 1,
    title: "18th Century",
    from: { year: 1800, precision: Histropedia.PRECISION_CENTURY }
  },
  {
    id: 2,
    title: "Presidency of John F. Kennedy",
    from: { year: 1961, month: 1, day: 20 },
    to: { year: 1963, month: 1, day: 22 }
  },
  {
    id: 3,
    title: "Digital Age (1970s - present)",
    from: { year: 1970, precision: Histropedia.PRECISION_DECADE },
    isToPresent: true
  }
]);

.setOption(option, value?)

Configuration

Set any timeline option, or retrieve its current value when called with a dot-notation path.

Parameters
option string | object

Either a full timeline options object, or a dot-notation string pointing at a specific option.

value any

New value for the option when using a string path. Omit to read the current value instead.

Returns

any – Current option value when reading via a string path without a value argument; otherwise void.

For large inspections it is more efficient to use the timeline.options object directly (e.g. timeline.options.style).

// set new width and height
timeline.setOption({ width: 700, height: 400 });

// set mainLine size
timeline.setOption('style.mainLine.size', 10);

// set default article subheader height and color
timeline.setOption('article.defaultStyle.subheader', { height: 20, color: '#EEE' });

// get current animation settings
const animSettings = timeline.setOption('article.animation');

.setSize(width, height) new

Configuration

Resize the timeline canvas and reflow article layout to the given dimensions (CSS pixels).

Parameters
width number

New canvas width in pixels.

height number

New canvas height in pixels.

Returns

void – Resizes the canvas and triggers any necessary redraw.

Useful when the container resizes after initialisation. Call it from your own resize logic or a ResizeObserver.

const container = document.getElementById('timeline');
const timeline = new Histropedia.Timeline(container);

// Keep the timeline sized with the container
const resize = () => {
  timeline.setSize(container.clientWidth, container.clientHeight);
};

window.addEventListener('resize', resize);
resize();

.on(event, handler) new

Events

Register a runtime event listener for timeline interactions and updates.

Parameters
event string

Name of the timeline event to listen for (e.g. 'article-select').

handler function

Callback invoked with the event payload and, when available, the original DOM event.

Returns

void – Attaches the listener without returning a value.

See the Events & Handlers reference for the complete list of events and payload signatures.

const onArticleSelect = (article) => {
  console.log('Selected article:', article.title);
};

timeline.on('article-select', onArticleSelect);

timeline.on('viewport-drag-start', (dragPayload, pointerEvent) => {
  console.log('Viewport drag started', dragPayload, pointerEvent);
  console.log(this); // Always the timeline instance for all handlers
});

.off(event, handler)

Events

Unregister a previously added event listener.

Parameters
event string

Event name that was originally passed to timeline.on.

handler function

The exact callback reference that was used when registering the listener.

Returns

void – Removes the listener and returns nothing.

const onZoom = ({ zoom }) => {
  console.log('Zoom level:', zoom);
};

timeline.on('zoom', onZoom);

// stop listening when the UI panel closes
timeline.off('zoom', onZoom);

.getArticleById(id)

Query

Retrieve the article currently loaded on the timeline with the matching identifier.

Parameters
id string | number

Unique article identifier, as provided in your timeline article data.

Returns

Article | undefined – The matching article object, or undefined when no article is found.

// get the article with id = 1
const article = timeline.getArticleById(1);

// check article data (see article options for structure)
console.log(article.data);

// call article methods
article.setOption('hidePeriodLine', true);

.getActiveArticle()

Query

Return the article currently selected by the user in the timeline UI.

Returns

Article | null – The active article object, if one is selected.

// get the currently active article
const article = timeline.getActiveArticle();

// check article data
console.log(article?.data);

// call article methods when available
article?.setOption('hidePeriodLine', true);

.getLaneById(id) new

Query

Retrieve the lane currently loaded on the timeline with the matching identifier.

Parameters
id string | number

Lane identifier, as provided in options.lane.data, timeline.loadLanes, or article data.

Returns

Lane | undefined – The matching lane object, if one exists.

const peopleLane = timeline.getLaneById('people');

peopleLane?.setStyle('title.color', '#1e3a8a');
peopleLane?.hide();

.moveLaneToIndex(lane, index) and lane reorder helpers new

Ordering

Reorder lanes from the timeline instance. Public lane index 0 is nearest the shared axis.

Parameters
lane Lane | string | number

Lane instance or lane id to move.

index number

Target public index for moveLaneToIndex. Out-of-range values are clamped.

Returns

Lane – The lane that was moved.

Related helpers: moveLaneBefore, moveLaneAfter, moveLaneUp, and moveLaneDown.

timeline.moveLaneToIndex('people', 0);
timeline.moveLaneAfter('projects', 'people');
timeline.moveLaneUp('reference');
timeline.moveLaneDown('people');

.goToDateAnim(dmy, options?)

Navigation

Animate the timeline viewport so the supplied date scrolls into view.

Parameters
dmy Histropedia.Dmy

Destination date (e.g. new Histropedia.Dmy(year, month, day)). The target date lands on the left edge by default.

options object

Optional animation settings:

  • duration number – Animation length in milliseconds (default 2000).
  • easing string – Easing name (default 'swing'). Supported names: 'linear', 'swing', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic'.
  • offsetX number – Pixel offset to position the date within the viewport (default 0).
  • complete function – Callback invoked when the animation finishes.
Returns

void – Performs an animated pan without returning a value.

// create Dmy for 5th Jan 1970
const date = new Histropedia.Dmy(1970, 1, 5);

// pan to date, with date located on left edge of canvas
timeline.goToDateAnim(date);

// ... with date located in centre of the canvas
timeline.goToDateAnim(date, { offsetX: timeline.width / 2 });

// ... with all options set
const options = {
    duration: 400,
    offsetX: 50,
    complete: () => console.log('done!')
};
timeline.goToDateAnim(date, options);

.fitDateRange(start, end, options?) new

Navigation

Zoom and pan the viewport so a supplied date range fits inside the timeline width.

Parameters
start Dmy | DateParts

Start date as a Dmy instance or plain object such as { year: 1900 }.

end Dmy | DateParts

End date. Dates may be passed in either order.

options object

Optional fit settings:

  • padding number | { left?: number, right?: number } – Space in pixels between the fitted range and the viewport edge (default 0).
  • animation object – Optional animation settings: active, duration, and easing. Supported easing names: 'linear', 'swing', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic'.
Returns

void – Updates the viewport in place.

Year-only and month-only inputs are treated as full periods for fit calculations.

timeline.fitDateRange(
  { year: 1961, month: 1, day: 20 },
  { year: 1963, month: 11, day: 22 },
  {
    padding: { left: 80, right: 80 },
    animation: { active: true, duration: 500 }
  }
);

.fitArticleRange(article, options?) new

Navigation

Zoom and pan the viewport so a single article's full date range fits inside the timeline width.

Parameters
article Article

Article instance to fit, using its computed period.from and period.to dates.

options object

Optional fit settings:

  • padding number | { left?: number, right?: number } – Space in pixels between the fitted article range and the viewport edge (default 0).
  • animation object – Optional animation settings using the same shape as fitDateRange, including easing.
Returns

booleantrue when the article has a range that can be fitted; otherwise false.

The options object uses the same padding and animation keys as fitDateRange.

const article = timeline.getArticleById('apollo-11');

if (article) {
  timeline.fitArticleRange(article, {
    padding: 80,
    animation: { active: true, duration: 500 }
  });
}

.fitArticles(options?) new

Navigation

Zoom and pan the viewport so the currently unfiltered article cards fit inside the timeline width.

Parameters
options object

Optional fit settings:

  • padding number | { left?: number, right?: number } – Space in pixels between the outermost fitted article cards and the viewport edge (default 40).
  • articleFilter function – Optional predicate for choosing which articles to fit. By default, articles hidden by filters are excluded.
  • animation object – Optional animation settings using the same shape as fitDateRange, including easing.
Returns

booleantrue when at least one article can be fitted; otherwise false.

The fit uses each article's start date, card width, and connector offset rather than only the article date range.

// Fit all currently unfiltered articles
timeline.fitArticles();

// Fit only articles in a specific lane
timeline.fitArticles({
  padding: { left: 60, right: 60 },
  articleFilter: article => article.data.lane === 'projects',
  animation: { active: true, duration: 500 }
});

.goToPixelAnim(pixel, options?)

Navigation

Pan the timeline by a fixed number of pixels with smooth animation.

Parameters
pixel number

Pixels to move the timeline. Positive values go forward in time; negative values go backward.

options object

Optional animation settings:

  • duration number – Animation length in milliseconds (default 2000).
  • easing string – Easing name (default 'swing'). Supported names: 'linear', 'swing', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic'.
  • complete function – Callback invoked when the animation finishes.
Returns

void – Performs an animated pan without returning a value.

// 50 pixels backward in time (viewport moves left)
timeline.goToPixelAnim(-50);

// 1 million pixels forward in time (viewport moves right)
timeline.goToPixelAnim(1e6);

// whole canvas width, useful for next/previous navigation arrows
timeline.goToPixelAnim(timeline.width);

// ... with all available options set
const options = {
    duration: 400,
    easing: 'linear',
    complete: () => console.log('done!')
};
timeline.goToPixelAnim(timeline.width, options);

.setStartDate(date, offsetX?)

Navigation

Jump directly to a date on the timeline without animation.

Parameters
date string | Histropedia.Dmy

Destination date as 'yyyy-mm-dd' (month/day optional) or a Histropedia.Dmy instance. Defaults to the left edge of the canvas.

offsetX number

Pixel offset positioning the date within the viewport (default 0).

Returns

void – Updates the viewport start date in place.

// create Dmy for 5th Jan 1970
const date = new Histropedia.Dmy(1970, 1, 5);

// jump to date, with date located on left edge of canvas
timeline.setStartDate(date);

// ... with date located in centre of the canvas
timeline.setStartDate(date, timeline.width / 2);

// set date using string notation
timeline.setStartDate('1970-6'); // 1st June 1970

// set BC date using string notation
timeline.setStartDate('-500-3-25'); // 25th March 500 BC

.getZoom() new

Navigation

Retrieve the current zoom level applied to the timeline viewport.

Returns

number – Current zoom value (lower values are more zoomed in, higher values more zoomed out).

// read the current zoom
const currentZoom = timeline.getZoom();

// zoom out by a small amount
timeline.setZoom(currentZoom + 0.5);

// or, zoom in by a small amount
timeline.setZoom(currentZoom - 0.5);

.setZoom(zoom, centrePixel?)

Navigation

Apply a new zoom level while optionally specifying the point that stays anchored on screen.

Parameters
zoom number

Zoom level between 0 (most zoomed in) and 123 (most zoomed out). Values are clamped to timeline.options.zoom.minimum/maximum.

centrePixel number

Pixel position from the left edge that remains fixed during zoom. Defaults to half of the timeline width.

Returns

void – Updates the timeline zoom level in place.

// set zoom level 13.5, zooming from the centre of the canvas
timeline.setZoom(13.5);

// ... zooming from the left edge of the canvas
timeline.setZoom(13.5, 0);

// ... zooming from the right edge of the canvas
timeline.setZoom(13.5, timeline.width);

.requestRedraw(redrawFunction?)

Rendering

Queue a redraw so it runs at the optimal time, even while animations are in progress.

Parameters
redrawFunction function

Specific redraw function to run (timeline.redraw, timeline.repositionRedraw, timeline.defaultRedraw, or a custom function). Defaults to timeline.repositionRedraw.

Returns

void – Schedules the supplied redraw without returning a value.

Details

Use this after dynamic changes to avoid interrupting animations. Requests are coalesced with any in-flight animation work for a major performance boost.

// hide currently active article and set date labels to green
timeline.getActiveArticle().hiddenByFilter = true;
timeline.options.style.dateLabel.major.color = 'green';

// redraw the timeline using the default `repositionRedraw`
timeline.requestRedraw();

// specify the most basic redraw for extra performance
timeline.requestRedraw(timeline.redraw);

// or request a full restack of articles
timeline.requestRedraw(timeline.defaultRedraw);

.redraw()

Rendering

Run the fastest, most lightweight timeline redraw.

Returns

void – Applies the basic redraw immediately.

Details

Best used when the start date and zoom level are unchanged. Prefer requestRedraw to orchestrate redraw timing automatically.

// hide currently active article and set date labels to green
timeline.getActiveArticle().hiddenByFilter = true;
timeline.options.style.dateLabel.major.color = 'green';

// redraw to see the results
timeline.redraw();

// For best performance call via requestRedraw instead
timeline.requestRedraw(timeline.redraw);

.repositionRedraw()

Rendering

Redraw the timeline while recalculating article positions for new start dates or zoom levels.

Returns

void – Performs the repositioning redraw immediately.

Details

Calls all steps of .redraw and additionally re-computes article origins. Also the default function used by requestRedraw.

// hide currently active article and set date labels to green
timeline.getActiveArticle().hiddenByFilter = true;
timeline.options.style.dateLabel.major.color = 'green';

// redraw to see the changes
timeline.repositionRedraw();

// For best performance call via requestRedraw instead
timeline.requestRedraw(); // defaults to repositionRedraw

.defaultRedraw()

Rendering

Perform the most thorough timeline redraw, including article restacking.

Returns

void – Executes the full redraw immediately.

Details

Runs every step of .repositionRedraw and also re-stacks articles when options.article.autoStacking.active is enabled. Called automatically after user zoom or scroll actions.

// hide currently active article and set date labels to green
timeline.getActiveArticle().hiddenByFilter = true;
timeline.options.style.dateLabel.major.color = 'green';

// redraw to see the changes with restacked articles
timeline.defaultRedraw();

// For best performance call via requestRedraw instead
timeline.requestRedraw(timeline.defaultRedraw);

Article Methods

Control any individual article on your timeline with these focused helpers:

Tip: Retrieve articles with timeline.getArticleById, timeline.getActiveArticle, or by reading the timeline.articles array before calling these methods.

.setOption(option, value?)

Configuration

Set article data fields or read them by providing a dot-notation path.

Parameters
option string | object

Either a full article options object or a dot-notation path into the article options.

value any

Value to assign when using a string path. Omit to read the current value.

Returns

any – Current option value when reading via a string path without a value argument; otherwise void.

For broad inspection prefer the article.data object (e.g. article.data.style).

Use article.setOption("lane", laneId) to move an article to another lane. If the lane id does not already exist, HistropediaJS creates an implicit lane automatically.

// get an article to work with from your timeline
const article = myTimeline.getActiveArticle();

// set a group of options
article.setOption({
    title: 'New title',
    subtitle: '2005 - 2007',
    from: { year: 2005 },
    to: { month: 3, day: 16 }
});

// set a single field using a path string
article.setOption('from.year', 2005);

// move the article to another lane
article.setOption('lane', 'projects');

// read the current rank without changing it
const rank = article.setOption('rank');

.setStyle(option, value?)

Styling

Override the per-article style or query an override value.

Parameters
option string | object

Style overrides object or dot-notation path into the article style options.

value any

Value to apply when using a string path. Omit to read the current override.

Returns

any – Current article-specific style value when reading via a string path without a value argument; otherwise void.

This reads and writes only the article's individual overrides. Use article.style to inspect the final computed style after defaults are applied.

const article = myTimeline.getArticleById(1);

// update a single style property
article.setStyle('border.width', 3);

// update several properties at once
article.setStyle({
    color: '#9b1000',
    header: { height: 60 },
    shadow: { x: 5, y: 10, color: 'blue' }
});

// read a specific override
const borderColor = article.setStyle('border.color');

// inspect the computed style including defaults
const computedStyle = article.style;

.setHoverStyle(option, value?)

Styling

Customize hover state styling introduced in HistropediaJS 1.2.0 or read its overrides.

Parameters
option string | object

Hover style overrides object or dot-notation path into the hover style options.

value any

Value to apply when using a string path. Omit to read the current override.

Returns

any – Current hover-style value when reading via a string path without a value argument; otherwise void.

Use article.hoverStyle to inspect the computed hover appearance including defaults.

const article = myTimeline.getActiveArticle();

// change a single hover property
article.setHoverStyle('star.width', 25);

// apply multiple hover overrides
article.setHoverStyle({
    color: '#9b1000',
    subheader: { height: 60 },
    shadow: { x: 5, y: 10, color: 'green' }
});

// read a hover override
const hoverBorderColor = article.setHoverStyle('border.color');

// inspect the computed hover style
const computedHoverStyle = article.hoverStyle;

.setActiveStyle(option, value?)

Styling

Adjust the styling used while the article is active (selected) or read its overrides.

Parameters
option string | object

Active style overrides object or dot-notation path into the active style options.

value any

Value to apply when using a string path. Omit to read the current override.

Returns

any – Current active-style value when reading via a string path without a value argument; otherwise void.

Access article.activeStyle to inspect the fully computed style when the article is selected.

const article = myTimeline.getActiveArticle();

// tweak a single active-state property
article.setActiveStyle('border.width', 3);

// provide several active-state overrides
article.setActiveStyle({
    color: '#9b1000',
    header: { height: 60 },
    shadow: { x: 5, y: 10, color: 'blue' }
});

// read an active-state override
const activeBorderColor = article.setActiveStyle('border.color');

// inspect the computed active style
const computedActiveStyle = article.activeStyle;

.moveTo(position)

Layout

Place the article's event card at specific canvas coordinates.

Parameters
position object

Object with left and/or top numbers defining the card's new top-left coordinates. Omitted properties keep their current value.

Returns

void – Updates the stored position without drawing immediately.

Details

Use this to pin an event card anywhere on the canvas while it remains linked to its timeline date. Call timeline.redraw() (or requestRedraw) to render the new placement.

If timeline auto-stacking is enabled, the card will return to its stacked position when the user scrolls or zooms.

const article = myTimeline.getActiveArticle();

// move the card to the top-left corner
article.moveTo({ left: 0, top: 0 });
myTimeline.redraw();

// move horizontally only
article.moveTo({ left: 60 });
myTimeline.redraw();

// move vertically only
article.moveTo({ top: 100 });
myTimeline.redraw();

.moveToOffset(offset)

Layout

Shift the event card relative to its origin position.

Parameters
offset object

Object with left and/or top numbers describing the offset from the origin (directly above the start date at the default height). Omitted properties keep their current value.

Returns

void – Updates the stored offset without drawing immediately.

Details

Offset coordinates are relative to the article's origin position. left: 0 keeps the card centered above its date; top: 0 keeps it at the default height from article.distanceToBaseline.value, or the resolved responsive baseline distance when enabled.

Call timeline.redraw() (or requestRedraw) to show the new placement. With auto-stacking enabled the card may snap back after user interactions.

const article = myTimeline.getActiveArticle();

// return to the origin position
article.moveToOffset({ left: 0, top: 0 });
myTimeline.redraw();

// keep the connector vertical but raise the card
article.moveToOffset({ left: 0, top: 60 });
myTimeline.redraw();

// apply both horizontal and vertical offsets
article.moveToOffset({ left: 100, top: -250 });
myTimeline.redraw();

Lane Methods new

Manage lane data, styles, visibility, and order after your timeline is initialized.

Tip: Loaded lanes are stored as Lane instances in timeline.lanes. Retrieve one with timeline.getLaneById(id) before calling the instance methods below.

.setOption(option, value?)

Configuration

Update lane data fields using objects or dot-notation paths.

Parameters
option string | object

Full lane object for batch updates, or a dot-notation path such as 'layout.heightWeight'.

value any

New value when using a string path. Omit this argument to read the current value.

Returns

any when called as a getter; otherwise void.

const lane = timeline.getLaneById('people');

lane.setOption({
  title: 'People & biographies',
  article: {
    defaultCardLayout: 'landscape',
    defaultStyle: { width: 220 }
  }
});

const layout = lane.setOption('layout');

.setStyle(option, value?)

Styling

Override lane chrome styling or query a style value.

Parameters
option string | object

Partial style object or dot-notation path such as 'title.color'.

value any

New value when using a string path. Omit to read the current override.

Returns

any when reading; otherwise void.

const lane = timeline.getLaneById('projects');

lane.setStyle('title.color', '#155e75');
lane.setStyle({
  body: {
    backgroundColor: 'rgba(207, 250, 254, 0.35)',
    borderColor: 'rgba(14, 116, 144, 0.35)'
  }
});

.hide() / .show()

Visibility

Hide or show a lane without unloading its data.

Returns

void – Updates visibility and redraws the timeline.

Hidden lanes are excluded from lane layout and hide their articles while lane layout is active.

const lane = timeline.getLaneById('reference');

lane.hide();
lane.show();

.moveToIndex(index) / .moveUp() / .moveDown()

Ordering

Reorder lanes by public lane index, where 0 is nearest the shared axis.

Parameters
index number

Target public lane index for moveToIndex. Out-of-range values are clamped.

Returns

Lane – The lane that was moved.

const peopleLane = timeline.getLaneById('people');

peopleLane.moveToIndex(0);
peopleLane.moveUp();
peopleLane.moveDown();

.moveBefore(targetLane) / .moveAfter(targetLane)

Ordering

Move a lane relative to another lane instance or lane id.

Parameters
targetLane Lane | string | number

Lane instance or lane id to move before or after.

Returns

Lane – The lane that was moved.

const projectsLane = timeline.getLaneById('projects');

projectsLane.moveBefore('people');
projectsLane.moveAfter('reference');

Time Band Methods new

Manage broad eras and background spans after your timeline is initialized.

Tip: Loaded bands are stored as TimeBand instances in timeline.timeBands. TimeBand is also exported as Histropedia.TimeBand for UMD and as a named ESM export.

.setOption(option, value?)

Configuration

Update Time Band data fields using objects or dot-notation paths.

Parameters
option string | object

Full band object for batch updates, or a dot-notation path such as 'to.year'.

value any

New value when using a string path. Omit this argument to read the current value.

Returns

any – Current value when called as a getter; otherwise void.

Use this method for making changes to Time Band data fields after they have been loaded. The available fields are defined in the Time Band Schema.

const band = timeline.timeBands.find(b => b.id === 2);

// Batch update fields
band.setOption({
  title: 'Reagan Presidency',
  to: { year: 1989, month: 1, day: 20, precision: Histropedia.PRECISION_DAY }
});

// Read the current end date
const end = band.setOption('to');

.setStyle(option, value?)

Styling

Override the visual style for a specific band or query an override value.

Parameters
option string | object

Partial style object or dot-notation path (e.g. 'text.color').

value any

New value when using a string path. Omit to read the current override.

Returns

any – Current override value when reading; otherwise void.

Overrides merge deeply with timeBand.defaultStyle, so supply only the properties you want to change.

const spotlight = timeline.timeBands.find(b => b.id === 3);

// Update a single field
spotlight.setStyle('backgroundColor', 'rgba(12, 74, 110, 0.35)');

// Apply multiple overrides
spotlight.setStyle({
  text: {
    color: '#0f172a',
    align: 'center'
  }
});

// Read the current override
const labelColor = spotlight.setStyle('text.color');

Events & Handlers new

Subscribe prior to initialization with options.on, or at runtime with timeline.on(event, handler). Unsubscribe with timeline.off(event, handler). Some handlers receive the originating DOM event as the last argument.

Timeline

Lifecycle

Background interactions and notifications affecting the whole timeline.

  • timeline-click: TimelineClickPayload, originalEvent
  • timeline-dblclick: TimelineClickPayload, originalEvent – fires after timeline-click when the background receives a double-click.
  • timeline-render-start: RedrawContext – emitted before each draw cycle; drawCycleContext is not yet set.
  • timeline-render-end: RedrawContext – emitted after each draw cycle with drawCycleContext populated when available.
  • timeline-state-change: SerializedState:string
timeline.on('timeline-click', ({ viewport }, evt) => {
  console.log('timeline-click', viewport, evt);
});

timeline.on('timeline-dblclick', ({ viewport }, evt) => {
  console.log('timeline-dblclick', viewport, evt);
});

timeline.on('timeline-render-start', (redrawCtx) => {
  const { canvasContext, top } = redrawCtx;
  // canvasContext is the actual CanvasRenderingContext2D used to draw the timeline
  console.log('render-start', top, canvasContext);
});

timeline.on('timeline-render-end', ({ canvasContext, drawCycleContext }) => {
  console.log('render-end', drawCycleContext, canvasContext);
});

timeline.on('timeline-state-change', (stateJson) => {
  console.log('timeline-state-change', JSON.parse(stateJson));
});
Payload
  • TimelineClickPayload
    • viewport: { x:number, y:number } – coordinates relative to the timeline canvas

  • RedrawContext
    • canvasContext: CanvasRenderingContext2D – the context used to draw the timeline.
    • top: number – vertical position of the timeline main line relative to the canvas.
    • drawCycleContext?: object – data about the current draw cycle (e.g. cached date coordinates).

Article

Interaction

Pointer entry/exit, clicks, and dragging on individual articles.

  • article-pointerenter / article-pointermove / article-pointerleave: article: Article, originalEvent
  • article-click: article: Article, originalEvent
  • article-dblclick: article: Article, originalEvent
  • article-select: article: Article – When a new article is selected on the timeline
  • article-drag-start / article-drag-end: article: Article, originalEvent
  • article-drag: article: Article, delta: DragDelta, originalEvent
timeline.on('article-pointerenter', (article, evt) => console.log('enter', article, evt));
timeline.on('article-pointerleave', (article) => console.log('leave', article));

timeline.on('article-click', (article, evt) => console.log('click', article, evt));

timeline.on('article-select', (article) => console.log('select', article));

timeline.on('article-drag', (article, { dx, dy, totalDx, totalDy }) => {
  console.log('drag', article, { dx, dy, totalDx, totalDy });
});
Payload
  • DragDelta
    • dx: number
    • dy: number
    • totalDx: number
    • totalDy: number

Zoom

Interaction

Track unified zoom changes and specific wheel/pinch gestures.

  • zoom-wheel: WheelPayload, originalEvent
  • zoom-pinch-start: PinchPayload, originalEvent
  • zoom-pinch: PinchPayload, originalEvent
  • zoom-pinch-end: PinchPayload, originalEvent
  • zoom: ZoomPayload
// Unified zoom stream
timeline.on('zoom', ({ zoom, zoomDelta }) => {
  console.log('zoom', zoom, zoomDelta);
});

// Pinch lifecycle
timeline.on('zoom-pinch-start', ({ centre, zoom }) => console.log('pinch start', centre, zoom));
timeline.on('zoom-pinch', ({ centre, zoomDelta, totalZoomDelta }) => console.log('pinch', centre, zoomDelta, totalZoomDelta));
timeline.on('zoom-pinch-end', () => console.log('pinch end'));

// Wheel steps
timeline.on('zoom-wheel', ({ centre, zoom, zoomDelta }, evt) => {
  console.log('wheel', centre, zoom, zoomDelta, evt);
});
Payloads
  • ZoomPayload
    • zoom: number – current zoom level
    • zoomDelta: number – change since previous update
  • WheelPayload
    • centre: { x:number, y:number } – canvas pivot
    • zoom: number
    • zoomDelta: number – change from before the wheel step
  • PinchPayload
    • centre: { x:number, y:number } – pinch centre (canvas coords)
    • scale: number – distance / startDistance
    • distance: number – current finger distance (px)
    • zoom: number
    • zoomDelta: number – per-frame delta
    • totalZoomDelta: number – accumulated since zoom-pinch-start
    • dx?: number – centre.x delta since previous frame
    • pointers: PointerEvent[]

Viewport

Interaction

Pan the visible window by dragging the canvas.

  • viewport-drag-start: ViewportDragPayload, originalEvent
  • viewport-drag: ViewportDragPayload, originalEvent
  • viewport-drag-end: ViewportDragPayload, originalEvent
timeline.on('viewport-drag-start', (payload) => console.log('drag-start', payload));
timeline.on('viewport-drag', ({ dx, totalDx }) => console.log('drag', dx, totalDx));
timeline.on('viewport-drag-end', (payload) => console.log('drag-end', payload));

// Legacy helper (prefer viewport-drag-end)
timeline.on('drag-end', (totalDx) => console.log('drag-end (legacy)', totalDx));
Payload
  • ViewportDragPayload
    • startToken: { unit:number, value:Histropedia.Dmy, length:number } – left edge token
    • offsetX: number – current internal horizontal offset (px)
    • dx?: number – per-frame horizontal delta (px; left positive)
    • totalDx?: number – accumulated since viewport-drag-start

Conventions & guarantees

Notes
  • Event names follow subject-action-phase: zoom-pinch-start, viewport-drag.
  • High-frequency interactions emit *-start, mid *, and *-end.
  • Payloads include only relevant keys. Per-frame deltas are dx, dy, zoomDelta.
  • Totals accumulate from the corresponding *-start (e.g. totalDx).
  • When provided, the original DOM event is always the last argument.
  • startToken is an internal timescale token; treat as opaque unless using Histropedia.Dmy.

Need More Help?

Our documentation is constantly evolving. If you can't find what you're looking for, we're here to help!

💡
🚀
🎯