@kendawson-online/vantl 2.0.0 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +256 -468
- package/package.json +7 -3
- package/src/css/timeline.css +746 -0
- package/src/images/alert.svg +50 -0
- package/src/images/arrow-left.svg +1 -0
- package/src/images/arrow-right.svg +1 -0
- package/src/images/missing-image.svg +29 -0
- package/src/images/spinner.gif +0 -0
package/README.md
CHANGED
|
@@ -1,468 +1,256 @@
|
|
|
1
|
-
# Vanilla JS Timeline
|
|
2
|
-
|
|
3
|
-
A vanilla
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
<div class="
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
**When using the timeline in horizontal mode, this defines whether the timeline should start from the right. This overrides the startIndex setting.**
|
|
258
|
-
|
|
259
|
-
JavaScript/jQuery
|
|
260
|
-
````javascript
|
|
261
|
-
default: false
|
|
262
|
-
options: true / false
|
|
263
|
-
````
|
|
264
|
-
|
|
265
|
-
Data attribute
|
|
266
|
-
````html
|
|
267
|
-
<div class="timeline" data-rtl-mode="true">
|
|
268
|
-
...
|
|
269
|
-
</div>
|
|
270
|
-
````
|
|
271
|
-
<br />
|
|
272
|
-
|
|
273
|
-
------
|
|
274
|
-
|
|
275
|
-
<br />
|
|
276
|
-
|
|
277
|
-
`startIndex`
|
|
278
|
-
|
|
279
|
-
**When using the timeline in horizontal mode, define which item the timeline should start at**
|
|
280
|
-
|
|
281
|
-
JavaScript/jQuery
|
|
282
|
-
````javascript
|
|
283
|
-
default: 0
|
|
284
|
-
options: integer
|
|
285
|
-
````
|
|
286
|
-
|
|
287
|
-
Data attribute
|
|
288
|
-
````html
|
|
289
|
-
<div class="timeline" data-start-index="0">
|
|
290
|
-
...
|
|
291
|
-
</div>
|
|
292
|
-
````
|
|
293
|
-
|
|
294
|
-
<br />
|
|
295
|
-
|
|
296
|
-
------
|
|
297
|
-
|
|
298
|
-
<br />
|
|
299
|
-
|
|
300
|
-
`verticalStartPosition`
|
|
301
|
-
|
|
302
|
-
**When using the timeline in vertical mode, define the alignment of the first item**
|
|
303
|
-
|
|
304
|
-
JavaScript/jQuery
|
|
305
|
-
|
|
306
|
-
```javascript
|
|
307
|
-
default: 'left'
|
|
308
|
-
options: 'left', 'right'
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
Data attribute
|
|
312
|
-
|
|
313
|
-
```html
|
|
314
|
-
<div class="timeline" data-vertical-start-position="right">
|
|
315
|
-
...
|
|
316
|
-
</div>
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
<br />
|
|
320
|
-
|
|
321
|
-
------
|
|
322
|
-
|
|
323
|
-
<br />
|
|
324
|
-
|
|
325
|
-
`verticalTrigger`
|
|
326
|
-
|
|
327
|
-
**When using the timeline in vertical mode, define the distance from the bottom of the screen, in percent or pixels, that the items slide into view**
|
|
328
|
-
|
|
329
|
-
JavaScript/jQuery
|
|
330
|
-
|
|
331
|
-
```javascript
|
|
332
|
-
default: '15%'
|
|
333
|
-
options: percentage or pixel value e.g. '20%' or '150px'
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
Data attribute
|
|
337
|
-
|
|
338
|
-
```html
|
|
339
|
-
<div class="timeline" data-vertical-trigger="150px">
|
|
340
|
-
...
|
|
341
|
-
</div>
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
<br />
|
|
345
|
-
|
|
346
|
-
------
|
|
347
|
-
|
|
348
|
-
<br />
|
|
349
|
-
|
|
350
|
-
`visibleItems`
|
|
351
|
-
|
|
352
|
-
**For horizontal mode: Controls the scrolling range and when navigation arrows appear. Note: With fixed-width timeline items, the actual number of visible items is determined by the container width**
|
|
353
|
-
|
|
354
|
-
JavaScript/jQuery
|
|
355
|
-
|
|
356
|
-
```javascript
|
|
357
|
-
default: 3
|
|
358
|
-
options: integer
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
Data attribute
|
|
362
|
-
|
|
363
|
-
```html
|
|
364
|
-
<div class="timeline" data-visible-items="3">
|
|
365
|
-
...
|
|
366
|
-
</div>
|
|
367
|
-
```
|
|
368
|
-
<br />
|
|
369
|
-
|
|
370
|
-
------
|
|
371
|
-
|
|
372
|
-
<br />
|
|
373
|
-
|
|
374
|
-
`nodeColor`, `lineColor`, `navColor`
|
|
375
|
-
|
|
376
|
-
**Set theme colors for nodes, center line, and navigation buttons (horizontal)**
|
|
377
|
-
|
|
378
|
-
JavaScript/jQuery
|
|
379
|
-
|
|
380
|
-
```javascript
|
|
381
|
-
// any subset can be provided
|
|
382
|
-
jQuery('.timeline').timeline({
|
|
383
|
-
nodeColor: '#2d6cdf',
|
|
384
|
-
lineColor: '#2d6cdf',
|
|
385
|
-
navColor: '#f2f2f2'
|
|
386
|
-
});
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
Data attributes (container)
|
|
390
|
-
|
|
391
|
-
```html
|
|
392
|
-
<div class="timeline"
|
|
393
|
-
data-node-color="#2d6cdf"
|
|
394
|
-
data-line-color="#2d6cdf"
|
|
395
|
-
data-nav-color="#f2f2f2">
|
|
396
|
-
...
|
|
397
|
-
</div>
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
JSON (top-level)
|
|
401
|
-
|
|
402
|
-
```json
|
|
403
|
-
{
|
|
404
|
-
"nodeColor": "#2d6cdf",
|
|
405
|
-
"lineColor": "#2d6cdf",
|
|
406
|
-
"navColor": "#f2f2f2"
|
|
407
|
-
}
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
Notes:
|
|
411
|
-
- If only one of `nodeColor` or `lineColor` is set, it is used for both.
|
|
412
|
-
- `navColor` automatically sets a contrasting border and arrow color.
|
|
413
|
-
|
|
414
|
-
------
|
|
415
|
-
|
|
416
|
-
<br />
|
|
417
|
-
|
|
418
|
-
Deep Linking and Node IDs
|
|
419
|
-
|
|
420
|
-
**Link to a specific node by ID using `?timeline=<containerId>&id=<nodeId>`**
|
|
421
|
-
|
|
422
|
-
- JSON nodes: set `id` on each node; the renderer adds `data-node-id` to items.
|
|
423
|
-
- Inline markup: add `data-node-id` to each `.timeline__item` you want addressable.
|
|
424
|
-
- On click modals: inline items can optionally declare `data-modal-title`, `data-modal-content`, `data-modal-image`, or `data-modal-html`. If absent, the library derives reasonable defaults from the markup (first heading, first paragraph, first image).
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
## Server Upload Workflow
|
|
428
|
-
|
|
429
|
-
This repository includes a small PHP utility under the `server-tools/` folder that converts CSV / Excel / Google Sheets into the timeline JSON format used by the demo. The basic flow is:
|
|
430
|
-
|
|
431
|
-
1. Open `server-tools/upload.html` in a browser (or host the `server-tools/` folder on a PHP-capable host).
|
|
432
|
-
2. Upload a CSV or `.xls/.xlsx` file, or provide a public Google Sheets URL. The server runs `convert.php` to parse the sheet and produce JSON.
|
|
433
|
-
3. If conversion succeeds the JSON is saved to `server-tools/tmp/` with a unique filename and you are redirected to `server-tools/done.php` which shows a preview and a download link.
|
|
434
|
-
4. Temporary files are cleaned up automatically by `server-tools/cleanup_tmp.php` (24-hour TTL). Run that as a cron job on the server.
|
|
435
|
-
|
|
436
|
-
Quick local test (from project root):
|
|
437
|
-
|
|
438
|
-
```bash
|
|
439
|
-
php -S localhost:8000 -t .
|
|
440
|
-
# then visit http://localhost:8000/server/upload.html
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
Notes:
|
|
444
|
-
- The converter will set a `lastupdated` timestamp in the JSON if none is provided — this integrates with the client's caching behavior.
|
|
445
|
-
- Excel parsing requires `phpoffice/phpspreadsheet` (installed via Composer). `convert.php` auto-loads `vendor/autoload.php` if available in `server/` or project root.
|
|
446
|
-
|
|
447
|
-
## Security Notes (important)
|
|
448
|
-
|
|
449
|
-
This upload utility is a convenience tool and not hardened for untrusted public hosting. If you plan to run it on a public server, consider the following safeguards:
|
|
450
|
-
|
|
451
|
-
- Validate uploads: restrict accepted MIME types / extensions (`.csv`, `.xls`, `.xlsx`) and enforce a reasonable maximum file size.
|
|
452
|
-
- Run file parsing in a controlled environment; avoid executing any uploaded content.
|
|
453
|
-
- Store temporary files outside the web root or restrict direct listing/access; `server/done.php` only exposes the saved JSON filename.
|
|
454
|
-
- Sanitize all filenames and never use user-supplied filenames for server paths without cleaning.
|
|
455
|
-
- Limit rate and require authentication if the endpoint will be public to avoid abuse.
|
|
456
|
-
- Use HTTPS to protect uploads in transit.
|
|
457
|
-
- Keep Composer dependencies up-to-date and audit for security issues.
|
|
458
|
-
- Consider additional input validation on fields extracted from the spreadsheet (e.g., URLs, image paths) before including them in output JSON.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
## License & Credits
|
|
462
|
-
|
|
463
|
-
This app is released under the [MIT License](LICENSE)
|
|
464
|
-
|
|
465
|
-
The original `timeline` project was created by Mike Collins and was also released under the MIT License. His project can be found on GitHub here: [https://github.com/squarechip/timeline](https://github.com/squarechip/timeline)
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
Last updated: Jan. 5, 2026
|
|
1
|
+
# Vantl - Vanilla (JS) Timeline
|
|
2
|
+
|
|
3
|
+
A lightweight, responsive timeline library created with vanilla Javascript for creating beautiful horizontal and vertical timelines with zero dependencies. Inspired by [timeline](https://github.com/squarechip/timeline) originally created by [squarechip](https://github.com/squarechip) in 2018.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- ✨ **Zero dependencies** - Pure vanilla JavaScript (jQuery optional)
|
|
9
|
+
- 📱 **Fully responsive** - Auto-switches between horizontal/vertical layouts
|
|
10
|
+
- 🎨 **Customizable colors** - Theme nodes, lines, and navigation
|
|
11
|
+
- 🖼️ **Rich content** - Support for images, HTML, and modal popups
|
|
12
|
+
- 🔗 **Deep linking** - Link directly to specific timeline nodes via URL
|
|
13
|
+
- 📦 **Multiple layouts** - Vertical scroll or horizontal carousel modes
|
|
14
|
+
- 💾 **Smart caching** - LocalStorage caching for JSON data
|
|
15
|
+
- 🚀 **Auto-init** - Just add a data attribute to load from JSON
|
|
16
|
+
- 📏 **Small footprint** - Minified and tree-shakeable
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Via CDN
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<!DOCTYPE html>
|
|
24
|
+
<html>
|
|
25
|
+
<head>
|
|
26
|
+
<!-- timeline stylesheet -->
|
|
27
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@kendawson-online/vantl@2/src/css/timeline.css">
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
|
|
31
|
+
<!-- your timeline code here -->
|
|
32
|
+
<div id="timeline" class="timeline" data-json-config="/path/to/your/data.json"></div>
|
|
33
|
+
|
|
34
|
+
<!-- timeline Javascript -->
|
|
35
|
+
<script src="https://cdn.jsdelivr.net/npm/@kendawson-online/vantl@2/dist/timeline.min.js"></script>
|
|
36
|
+
</body>
|
|
37
|
+
</html>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Via npm
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install @kendawson-online/vantl
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
import { timeline } from '@kendawson-online/vantl';
|
|
48
|
+
import '@kendawson-online/vantl/src/css/timeline.css';
|
|
49
|
+
|
|
50
|
+
timeline(document.querySelectorAll('.timeline'), {
|
|
51
|
+
mode: 'vertical',
|
|
52
|
+
nodeColor: '#2d6cdf'
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage Examples
|
|
57
|
+
|
|
58
|
+
### 1. Auto-Init with JSON (Easiest)
|
|
59
|
+
|
|
60
|
+
The timeline auto-initializes when you add a `data-json-config` attribute:
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<div class="timeline" data-json-config="/path/to/timeline.json"></div>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**JSON Format:**
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"timelineName": "My Timeline",
|
|
70
|
+
"layoutMode": "vertical",
|
|
71
|
+
"lastupdated": "2026-01-08T20:15:34.873Z",
|
|
72
|
+
"nodes": [
|
|
73
|
+
{
|
|
74
|
+
"id": 1,
|
|
75
|
+
"title": "Event Title",
|
|
76
|
+
"content": "Event description...",
|
|
77
|
+
"image": "/path/to/image.jpg"
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2. Inline HTML with Data Attributes
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<div class="timeline" data-mode="horizontal">
|
|
87
|
+
<div class="timeline__wrap">
|
|
88
|
+
<div class="timeline__items">
|
|
89
|
+
<div class="timeline__item">
|
|
90
|
+
<div class="timeline__content">
|
|
91
|
+
<h5>2001</h5>
|
|
92
|
+
<p>Lorem ipsum dolor sit amet, qui <a href="#">minim</a> labore adipisicing minim sint cillum sint consectetur cupidatat.</p>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="timeline__item">
|
|
96
|
+
<div class="timeline__content">
|
|
97
|
+
<h5>2002</h5>
|
|
98
|
+
<p>Lorem ipsum <a href="#">dolor sit amet</a>, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.</p>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="timeline__item">
|
|
102
|
+
<div class="timeline__content">
|
|
103
|
+
<h5>2003</h5>
|
|
104
|
+
<p>Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<script>
|
|
112
|
+
timeline(document.querySelectorAll('.timeline'));
|
|
113
|
+
</script>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 3. JavaScript API
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Vanilla JS
|
|
120
|
+
timeline(document.querySelectorAll('.timeline'), {
|
|
121
|
+
mode: 'horizontal',
|
|
122
|
+
visibleItems: 3,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// jQuery (if available)
|
|
126
|
+
$('.timeline').timeline({
|
|
127
|
+
mode: 'vertical',
|
|
128
|
+
verticalTrigger: '20%'
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## API Options
|
|
133
|
+
|
|
134
|
+
All options can be set via JavaScript API, data attributes, or JSON config.
|
|
135
|
+
|
|
136
|
+
| Option | Type | Default | Description |
|
|
137
|
+
|--------|------|---------|-------------|
|
|
138
|
+
| `mode` | string | `'vertical'` | Layout mode: `'vertical'` or `'horizontal'` |
|
|
139
|
+
| `minWidth` | number | `600` | Min viewport width (px) to maintain horizontal mode |
|
|
140
|
+
| `visibleItems` | number | `3` | Number of items in horizontal viewport |
|
|
141
|
+
| `moveItems` | number | `1` | Items to scroll per navigation click (horizontal) |
|
|
142
|
+
| `startIndex` | number | `0` | Initial item index (horizontal mode) |
|
|
143
|
+
| `horizontalStartPosition` | string | `'top'` | First item alignment: `'top'` or `'bottom'` |
|
|
144
|
+
| `verticalStartPosition` | string | `'left'` | First item alignment: `'left'` or `'right'` |
|
|
145
|
+
| `verticalTrigger` | string | `'15%'` | Scroll trigger distance: percentage or px (e.g., `'20%'` or `'150px'`) |
|
|
146
|
+
| `rtlMode` | boolean | `false` | Right-to-left mode (horizontal) |
|
|
147
|
+
| `nodeColor` | string | — | Node circle color (hex/rgb/hsl) |
|
|
148
|
+
| `lineColor` | string | — | Center line color (hex/rgb/hsl) |
|
|
149
|
+
| `navColor` | string | — | Navigation button color (hex/rgb/hsl) |
|
|
150
|
+
|
|
151
|
+
**Setting Options:**
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
// JavaScript
|
|
155
|
+
timeline(el, { mode: 'horizontal', nodeColor: '#2d6cdf' });
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```html
|
|
159
|
+
<!-- Data attributes -->
|
|
160
|
+
<div class="timeline" data-mode="horizontal" data-node-color="#2d6cdf">
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
// JSON
|
|
165
|
+
{ "layoutMode": "horizontal", "nodeColor": "#2d6cdf" }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Deep Linking
|
|
169
|
+
|
|
170
|
+
Link to a specific timeline node using URL parameters:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
https://example.com/page.html?timeline=myTimelineId&id=3
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- Add `id` attribute to timeline container
|
|
177
|
+
- Add `data-node-id` to each item you want to link to
|
|
178
|
+
- Works automatically with JSON-loaded timelines
|
|
179
|
+
|
|
180
|
+
## Advanced Features
|
|
181
|
+
|
|
182
|
+
### Custom Image Path
|
|
183
|
+
|
|
184
|
+
Override the auto-detected image path:
|
|
185
|
+
|
|
186
|
+
```html
|
|
187
|
+
<script>
|
|
188
|
+
window.TimelineConfig = {
|
|
189
|
+
basePath: '/custom/path/to/images'
|
|
190
|
+
};
|
|
191
|
+
</script>
|
|
192
|
+
<script src="dist/timeline.min.js"></script>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Modal Content
|
|
196
|
+
|
|
197
|
+
Each timeline item can display a modal popup on click:
|
|
198
|
+
|
|
199
|
+
```html
|
|
200
|
+
<div class="timeline__item"
|
|
201
|
+
data-modal-title="Full Title"
|
|
202
|
+
data-modal-content="Extended description..."
|
|
203
|
+
data-modal-image="/img/large.jpg"
|
|
204
|
+
data-modal-html="<p>Custom HTML content</p>">
|
|
205
|
+
...
|
|
206
|
+
</div>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
JSON items automatically support modals with the `title`, `content`, `image`, and `html` fields.
|
|
210
|
+
|
|
211
|
+
### Programmatic Control
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
// Load from JSON programmatically
|
|
215
|
+
loadDataFromJson('/data/timeline.json', '#myTimeline');
|
|
216
|
+
|
|
217
|
+
// Clear cache
|
|
218
|
+
clearTimelineCache(); // Clear all
|
|
219
|
+
clearTimelineCache('timelineId'); // Clear specific
|
|
220
|
+
|
|
221
|
+
// Navigate to node (horizontal mode)
|
|
222
|
+
navigateTimelineToNodeIndex(containerElement, 5);
|
|
223
|
+
|
|
224
|
+
// Open modal
|
|
225
|
+
openTimelineModal(itemElement);
|
|
226
|
+
|
|
227
|
+
// Close modal
|
|
228
|
+
closeTimelineModal();
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Browser Support
|
|
232
|
+
|
|
233
|
+
- Chrome/Edge (2018+)
|
|
234
|
+
- Firefox (2018+)
|
|
235
|
+
- Safari (2018+)
|
|
236
|
+
- Requires: ES6, IntersectionObserver, CSS Custom Properties
|
|
237
|
+
|
|
238
|
+
## Contributing
|
|
239
|
+
|
|
240
|
+
See [DEVELOPMENT.md](DEVELOPMENT.md) for build instructions and architecture overview.
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
245
|
+
|
|
246
|
+
## Credits
|
|
247
|
+
|
|
248
|
+
Originally inspired by [timeline](https://github.com/squarechip/timeline) by [Mike Collins](https://github.com/squarechip) (2018).
|
|
249
|
+
|
|
250
|
+
Refactored and maintained by [Ken Dawson](https://github.com/kendawson-online) (2026).
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
**Package:** [@kendawson-online/vantl](https://www.npmjs.com/package/@kendawson-online/vantl)
|
|
255
|
+
**Repository:** [github.com/kendawson-online/vantl](https://github.com/kendawson-online/vantl)
|
|
256
|
+
**CDN:** [cdn.jsdelivr.net/npm/@kendawson-online/vantl](https://cdn.jsdelivr.net/npm/@kendawson-online/vantl)
|