@knight-lab/timelinejs 3.8.21 → 3.9.1

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.
Files changed (216) hide show
  1. package/.nvmrc +1 -1
  2. package/API_TEST.html +0 -5
  3. package/CHANGELOG.md +12 -0
  4. package/dist/css/fonts/font.amatic-andika.css +1 -1
  5. package/dist/css/fonts/font.bitter-raleway.css +4 -4
  6. package/dist/css/fonts/font.clicker-garamond.css +1 -1
  7. package/dist/css/fonts/font.dancing-ledger.css +2 -2
  8. package/dist/css/fonts/font.oldstandard.css +2 -2
  9. package/dist/css/fonts/font.opensans-gentiumbook.css +2 -2
  10. package/dist/css/fonts/font.playfair-faunaone.css +2 -2
  11. package/dist/css/fonts/font.playfair.css +2 -2
  12. package/dist/css/fonts/font.roboto-megrim.css +2 -2
  13. package/dist/css/fonts/font.unicaone-vollkorn.css +2 -2
  14. package/dist/css/icons/tl-icons.eot +0 -0
  15. package/dist/css/icons/tl-icons.svg +58 -55
  16. package/dist/css/icons/tl-icons.ttf +0 -0
  17. package/dist/css/icons/tl-icons.woff +0 -0
  18. package/dist/css/icons/tl-icons.woff2 +0 -0
  19. package/dist/css/themes/timeline.theme.contrast.css +157 -319
  20. package/dist/css/themes/timeline.theme.dark.css +146 -308
  21. package/dist/css/timeline.css +155 -317
  22. package/dist/css/timeline.css.map +1 -1
  23. package/dist/embed/compare.html +4 -4
  24. package/dist/embed/index.html +3 -6
  25. package/dist/embed/old-index.html +2 -5
  26. package/dist/embed/popular_timelines.json +5989 -1
  27. package/dist/js/locale/af.json +54 -56
  28. package/dist/js/locale/ar.json +54 -56
  29. package/dist/js/locale/be.json +71 -73
  30. package/dist/js/locale/bg.json +54 -56
  31. package/dist/js/locale/ca.json +54 -56
  32. package/dist/js/locale/cz.json +56 -63
  33. package/dist/js/locale/da.json +54 -56
  34. package/dist/js/locale/de.json +1 -3
  35. package/dist/js/locale/el.json +54 -56
  36. package/dist/js/locale/en-24hr.json +51 -57
  37. package/dist/js/locale/en-week.json +51 -57
  38. package/dist/js/locale/en.json +3 -8
  39. package/dist/js/locale/eo.json +54 -56
  40. package/dist/js/locale/es.json +55 -57
  41. package/dist/js/locale/et.json +54 -56
  42. package/dist/js/locale/eu.json +54 -56
  43. package/dist/js/locale/fa.json +52 -54
  44. package/dist/js/locale/fi.json +73 -75
  45. package/dist/js/locale/fo.json +54 -56
  46. package/dist/js/locale/fr.json +1 -8
  47. package/dist/js/locale/fy.json +71 -73
  48. package/dist/js/locale/ga.json +54 -56
  49. package/dist/js/locale/gl.json +54 -56
  50. package/dist/js/locale/he.json +54 -56
  51. package/dist/js/locale/hi.json +72 -74
  52. package/dist/js/locale/hr.json +54 -56
  53. package/dist/js/locale/hu.json +91 -93
  54. package/dist/js/locale/hy.json +54 -56
  55. package/dist/js/locale/id.json +54 -56
  56. package/dist/js/locale/is.json +54 -56
  57. package/dist/js/locale/it.json +18 -20
  58. package/dist/js/locale/iw.json +54 -56
  59. package/dist/js/locale/ja.json +54 -56
  60. package/dist/js/locale/ka.json +54 -56
  61. package/dist/js/locale/ko.json +54 -56
  62. package/dist/js/locale/lb.json +54 -56
  63. package/dist/js/locale/lt.json +54 -56
  64. package/dist/js/locale/lv.json +54 -56
  65. package/dist/js/locale/ms.json +54 -56
  66. package/dist/js/locale/my.json +31 -38
  67. package/dist/js/locale/nb.json +54 -56
  68. package/dist/js/locale/ne.json +54 -56
  69. package/dist/js/locale/nl.json +54 -56
  70. package/dist/js/locale/nn.json +54 -56
  71. package/dist/js/locale/no.json +54 -56
  72. package/dist/js/locale/pl.json +54 -56
  73. package/dist/js/locale/pt-br.json +45 -47
  74. package/dist/js/locale/pt.json +57 -59
  75. package/dist/js/locale/rm.json +54 -56
  76. package/dist/js/locale/ro.json +54 -56
  77. package/dist/js/locale/ru.json +54 -56
  78. package/dist/js/locale/si.json +53 -55
  79. package/dist/js/locale/sk.json +54 -56
  80. package/dist/js/locale/sl.json +54 -56
  81. package/dist/js/locale/sr-cy.json +54 -56
  82. package/dist/js/locale/sr.json +54 -56
  83. package/dist/js/locale/sv.json +11 -13
  84. package/dist/js/locale/ta.json +54 -56
  85. package/dist/js/locale/te.json +53 -55
  86. package/dist/js/locale/th.json +55 -62
  87. package/dist/js/locale/tl.json +54 -56
  88. package/dist/js/locale/tr.json +54 -56
  89. package/dist/js/locale/uk.json +54 -56
  90. package/dist/js/locale/ur.json +2 -9
  91. package/dist/js/locale/vi.json +33 -35
  92. package/dist/js/locale/zh-cn.json +1 -3
  93. package/dist/js/locale/zh-tw.json +54 -56
  94. package/dist/js/timeline.js +2 -3
  95. package/dist/js/timeline.js.LICENSE.txt +1 -0
  96. package/dist/js/timeline.js.map +1 -1
  97. package/package.json +20 -18
  98. package/src/css/icons/icons.html +49 -1
  99. package/src/css/icons/tl-icons.eot +0 -0
  100. package/src/css/icons/tl-icons.svg +58 -55
  101. package/src/css/icons/tl-icons.ttf +0 -0
  102. package/src/css/icons/tl-icons.woff +0 -0
  103. package/src/css/icons/tl-icons.woff2 +0 -0
  104. package/src/embed/compare.html +4 -4
  105. package/src/embed/index.html +3 -6
  106. package/src/embed/old-index.html +2 -5
  107. package/src/embed/popular_timelines.json +5989 -1
  108. package/src/js/core/TimelineConfig.js +0 -1
  109. package/src/js/date/TLDate.js +32 -1
  110. package/src/js/date/__tests__/TLDate.test.js +10 -0
  111. package/src/js/dom/DOMUtil.js +12 -12
  112. package/src/js/language/I18NMixins.js +13 -3
  113. package/src/js/language/Language.js +50 -23
  114. package/src/js/language/__tests__/Language.test.js +32 -0
  115. package/src/js/language/locale/af.json +54 -56
  116. package/src/js/language/locale/ar.json +54 -56
  117. package/src/js/language/locale/be.json +71 -73
  118. package/src/js/language/locale/bg.json +54 -56
  119. package/src/js/language/locale/ca.json +54 -56
  120. package/src/js/language/locale/cz.json +56 -63
  121. package/src/js/language/locale/da.json +54 -56
  122. package/src/js/language/locale/de.json +1 -3
  123. package/src/js/language/locale/el.json +54 -56
  124. package/src/js/language/locale/en-24hr.json +51 -57
  125. package/src/js/language/locale/en-week.json +51 -57
  126. package/src/js/language/locale/en.json +3 -8
  127. package/src/js/language/locale/eo.json +54 -56
  128. package/src/js/language/locale/es.json +55 -57
  129. package/src/js/language/locale/et.json +54 -56
  130. package/src/js/language/locale/eu.json +54 -56
  131. package/src/js/language/locale/fa.json +52 -54
  132. package/src/js/language/locale/fi.json +73 -75
  133. package/src/js/language/locale/fo.json +54 -56
  134. package/src/js/language/locale/fr.json +1 -8
  135. package/src/js/language/locale/fy.json +71 -73
  136. package/src/js/language/locale/ga.json +54 -56
  137. package/src/js/language/locale/gl.json +54 -56
  138. package/src/js/language/locale/he.json +54 -56
  139. package/src/js/language/locale/hi.json +72 -74
  140. package/src/js/language/locale/hr.json +54 -56
  141. package/src/js/language/locale/hu.json +91 -93
  142. package/src/js/language/locale/hy.json +54 -56
  143. package/src/js/language/locale/id.json +54 -56
  144. package/src/js/language/locale/is.json +54 -56
  145. package/src/js/language/locale/it.json +18 -20
  146. package/src/js/language/locale/iw.json +54 -56
  147. package/src/js/language/locale/ja.json +54 -56
  148. package/src/js/language/locale/ka.json +54 -56
  149. package/src/js/language/locale/ko.json +54 -56
  150. package/src/js/language/locale/lb.json +54 -56
  151. package/src/js/language/locale/lt.json +54 -56
  152. package/src/js/language/locale/lv.json +54 -56
  153. package/src/js/language/locale/ms.json +54 -56
  154. package/src/js/language/locale/my.json +31 -38
  155. package/src/js/language/locale/nb.json +54 -56
  156. package/src/js/language/locale/ne.json +54 -56
  157. package/src/js/language/locale/nl.json +54 -56
  158. package/src/js/language/locale/nn.json +54 -56
  159. package/src/js/language/locale/no.json +54 -56
  160. package/src/js/language/locale/pl.json +54 -56
  161. package/src/js/language/locale/pt-br.json +45 -47
  162. package/src/js/language/locale/pt.json +57 -59
  163. package/src/js/language/locale/rm.json +54 -56
  164. package/src/js/language/locale/ro.json +54 -56
  165. package/src/js/language/locale/ru.json +54 -56
  166. package/src/js/language/locale/si.json +53 -55
  167. package/src/js/language/locale/sk.json +54 -56
  168. package/src/js/language/locale/sl.json +54 -56
  169. package/src/js/language/locale/sr-cy.json +54 -56
  170. package/src/js/language/locale/sr.json +54 -56
  171. package/src/js/language/locale/sv.json +11 -13
  172. package/src/js/language/locale/ta.json +54 -56
  173. package/src/js/language/locale/te.json +53 -55
  174. package/src/js/language/locale/th.json +55 -62
  175. package/src/js/language/locale/tl.json +54 -56
  176. package/src/js/language/locale/tr.json +54 -56
  177. package/src/js/language/locale/uk.json +54 -56
  178. package/src/js/language/locale/ur.json +2 -9
  179. package/src/js/language/locale/vi.json +33 -35
  180. package/src/js/language/locale/zh-cn.json +1 -3
  181. package/src/js/language/locale/zh-tw.json +54 -56
  182. package/src/js/media/Media.js +6 -2
  183. package/src/js/media/MediaType.js +3 -3
  184. package/src/js/media/types/DailyMotion.js +9 -1
  185. package/src/js/media/types/Text.js +33 -31
  186. package/src/js/media/types/Vimeo.js +58 -57
  187. package/src/js/slider/Slide.js +17 -2
  188. package/src/js/slider/SlideNav.js +12 -7
  189. package/src/js/slider/StorySlider.js +8 -12
  190. package/src/js/timeline/Timeline.js +47 -13
  191. package/src/js/timenav/TimeAxis.js +20 -1
  192. package/src/js/timenav/TimeMarker.js +48 -3
  193. package/src/js/timenav/TimeNav.js +143 -16
  194. package/src/js/ui/MenuBar.js +202 -149
  195. package/src/js/ui/Swipable.js +1 -1
  196. package/src/less/TL.Timeline.Base.less +38 -1
  197. package/src/less/Typography.less +2 -3
  198. package/src/less/Variables.less +4 -1
  199. package/src/less/icons/Icons.less +9 -0
  200. package/src/less/media/types/TL.Media.Text.less +5 -0
  201. package/src/less/slider/TL.Slide.less +40 -45
  202. package/src/less/slider/TL.SlideNav.less +82 -55
  203. package/src/less/themes/contrast/Variables.less +7 -4
  204. package/src/less/themes/dark/TL.Theme.Dark.less +2 -2
  205. package/src/less/themes/dark/Variables.less +4 -1
  206. package/src/less/timenav/TL.TimeMarker.less +16 -10
  207. package/src/less/timenav/TL.TimeNav.less +2 -50
  208. package/src/less/ui/TL.MenuBar.Button.less +8 -6
  209. package/src/template/all-media-types.json +53 -3
  210. package/src/template/cosmo.json +113 -0
  211. package/src/template/index.html +5 -3
  212. package/webpack.common.js +13 -10
  213. package/webpack.dev.js +16 -6
  214. package/dist/js/timeline-min.js +0 -4
  215. package/dist/timeline3.zip +0 -0
  216. package/src/less/core/Reset.less +0 -115
@@ -1,4 +1,4 @@
1
- import { classMixin, mergeData, unlinkify } from "../core/Util"
1
+ import { classMixin, mergeData, trim, unlinkify } from "../core/Util"
2
2
  import Events from "../core/Events"
3
3
  import { DOMMixins } from "../dom/DOMMixins"
4
4
  import { DOMEvent } from "../dom/DOMEvent"
@@ -9,6 +9,7 @@ import { webkit as BROWSER_WEBKIT } from "../core/Browser";
9
9
  import { easeInSpline } from "../animation/Ease";
10
10
 
11
11
  import { lookupMediaType } from "../media/MediaType"
12
+ import { I18NMixins } from "../language/I18NMixins";
12
13
 
13
14
  export class TimeMarker {
14
15
  constructor(data, options) {
@@ -75,6 +76,9 @@ export class TimeMarker {
75
76
  // End date
76
77
  this.has_end_date = false;
77
78
 
79
+ // Alternative text
80
+ this.ariaLabel = '';
81
+
78
82
  // Merge Data and Options
79
83
  mergeData(this.options, options);
80
84
  mergeData(this.data, data);
@@ -107,8 +111,19 @@ export class TimeMarker {
107
111
  } else {
108
112
  this._el.container.className = 'tl-timemarker';
109
113
  }
114
+
115
+ this._el.container.ariaLabel = this.ariaLabel;
116
+ if (this.active) {
117
+ this._el.container.ariaLabel += ', shown';
118
+ } else {
119
+ this._el.container.ariaLabel += ', press space to show';
120
+ }
110
121
  }
111
122
 
123
+ setFocus(options = { preventScroll: true }) {
124
+ this._el.container.focus(options);
125
+ }
126
+
112
127
  addTo(container) {
113
128
  container.appendChild(this._el.container);
114
129
  }
@@ -216,17 +231,44 @@ export class TimeMarker {
216
231
  this._el.timespan.style.height = remainder + "px";
217
232
  }
218
233
 
234
+ getFormattedDate() {
235
+ if (trim(this.data.display_date).length > 0) {
236
+ return this.data.display_date;
237
+ }
238
+
239
+ let date_text = "";
240
+ if (this.data.end_date) {
241
+ date_text = " to " + this.data.end_date.getDisplayDate(this.getLanguage());
242
+ }
243
+ if (this.data.start_date) {
244
+ date_text = (date_text ? "from " : "") + this.data.start_date.getDisplayDate(this.getLanguage()) + date_text;
245
+ }
246
+ return date_text;
247
+ }
248
+
219
249
  /* Events
220
250
  ================================================== */
221
251
  _onMarkerClick(e) {
222
252
  this.fire("markerclick", { unique_id: this.data.unique_id });
223
253
  }
224
254
 
255
+ _onMarkerKeydown(e) {
256
+ if (/Space|Enter/.test(e.code)) {
257
+ this.fire("markerclick", { unique_id: this.data.unique_id });
258
+ }
259
+ }
260
+
261
+ _onMarkerBlur(e) {
262
+ this.fire("markerblur", { unique_id: this.data.unique_id });
263
+ }
264
+
225
265
  /* Private Methods
226
266
  ================================================== */
227
267
  _initLayout() {
228
268
  // Create Layout
229
269
  this._el.container = DOM.create("div", "tl-timemarker");
270
+ this._el.container.setAttribute('tabindex', '-1');
271
+
230
272
  if (this.data.unique_id) {
231
273
  this._el.container.id = this.data.unique_id + "-marker";
232
274
  }
@@ -277,7 +319,8 @@ export class TimeMarker {
277
319
  this._text.innerHTML = unlinkify(this.data.media.caption);
278
320
  }
279
321
 
280
-
322
+ const date = this.getFormattedDate();
323
+ this.ariaLabel = `${this._text.innerHTML}, ${date}`;
281
324
 
282
325
  // Fire event that the slide is loaded
283
326
  this.onLoaded();
@@ -286,6 +329,8 @@ export class TimeMarker {
286
329
 
287
330
  _initEvents() {
288
331
  DOMEvent.addListener(this._el.container, 'click', this._onMarkerClick, this);
332
+ DOMEvent.addListener(this._el.container, 'keydown', this._onMarkerKeydown, this);
333
+ DOMEvent.addListener(this._el.container, 'blur', this._onMarkerBlur, this);
289
334
  }
290
335
 
291
336
  // Update Display
@@ -304,4 +349,4 @@ export class TimeMarker {
304
349
  }
305
350
 
306
351
 
307
- classMixin(TimeMarker, Events, DOMMixins)
352
+ classMixin(TimeMarker, I18NMixins, Events, DOMMixins)
@@ -11,13 +11,14 @@ import { TimeAxis } from "./TimeAxis"
11
11
  import { TimeMarker } from "./TimeMarker"
12
12
  import Swipable from "../ui/Swipable"
13
13
  import { Animate } from "../animation/Animate"
14
+ import { I18NMixins } from "../language/I18NMixins"
14
15
 
15
16
 
16
17
 
17
18
  export class TimeNav {
18
19
 
19
20
  constructor(elem, timeline_config, options, language) {
20
- this.language = language // just passing through for TimeAxis. Is this a bad code smell?
21
+ this.language = language
21
22
  // DOM ELEMENTS
22
23
  this._el = {
23
24
  parent: {},
@@ -29,8 +30,7 @@ export class TimeNav {
29
30
  marker_container: {},
30
31
  marker_item_container: {},
31
32
  timeaxis: {},
32
- timeaxis_background: {},
33
- attribution: {}
33
+ timeaxis_background: {}
34
34
  };
35
35
 
36
36
  this.collapsed = false;
@@ -40,6 +40,14 @@ export class TimeNav {
40
40
  } else {
41
41
  this._el.container = DOM.get(elem);
42
42
  }
43
+ this._el.container.setAttribute('tabindex', '0');
44
+
45
+ // 'application' role supports predictable control of keyboard input in a complex component
46
+ this._el.container.setAttribute('role', 'application');
47
+ this._el.container.setAttribute('aria-label', this._('aria_label_timeline_navigation'));
48
+ this._el.container.setAttribute('aria-description',
49
+ 'Navigate between markers with arrow keys. Press "Home" for the first and "End" for the last markers'
50
+ );
43
51
 
44
52
  this.config = timeline_config;
45
53
 
@@ -72,7 +80,9 @@ export class TimeNav {
72
80
  this._eras = [];
73
81
  this.has_eras = false;
74
82
 
75
- // Groups Array
83
+ /**
84
+ * @type TimeGroup
85
+ */
76
86
  this._groups = [];
77
87
 
78
88
  // Row Height
@@ -81,6 +91,9 @@ export class TimeNav {
81
91
  // Current Marker
82
92
  this.current_id = "";
83
93
 
94
+ // Current Focused Marker
95
+ this.current_focused_id = "";
96
+
84
97
  // TimeScale
85
98
  this.timescale = {};
86
99
 
@@ -365,7 +378,13 @@ export class TimeNav {
365
378
  _resetMarkersActive() {
366
379
  for (var i = 0; i < this._markers.length; i++) {
367
380
  this._markers[i].setActive(false);
368
- };
381
+ }
382
+ }
383
+
384
+ _resetMarkersBlurListeners() {
385
+ for (var i = 0; i < this._markers.length; i++) {
386
+ this._markers[i].off('markerblur', this._onMarkerBlur, this);
387
+ }
369
388
  }
370
389
 
371
390
  _findMarkerIndex(n) {
@@ -459,6 +478,56 @@ export class TimeNav {
459
478
  if (n >= 0 && n < this._markers.length) {
460
479
  this._markers[n].setActive(true);
461
480
  }
481
+
482
+ this.animateMovement(_n, fast, css_animation, _duration, _ease);
483
+
484
+ if (n >= 0 && n < this._markers.length) {
485
+ this.current_id = this.current_focused_id = this._markers[n].data.unique_id;
486
+ } else {
487
+ this.current_id = this.current_focused_id = '';
488
+ }
489
+
490
+ this._setLabelWithCurrentMarker();
491
+ }
492
+
493
+ goToId(id, fast, css_animation) {
494
+ this.goTo(this._findMarkerIndex(id), fast, css_animation);
495
+ }
496
+
497
+ focusOn(n, fast, css_animation) {
498
+ const _ease = this.options.ease,
499
+ _duration = this.options.duration,
500
+ _n = (n < 0) ? 0 : n;
501
+
502
+ this.animateMovement(_n, fast, css_animation, _duration, _ease);
503
+
504
+ this._resetMarkersBlurListeners();
505
+ if (n >= 0 && n < this._markers.length) {
506
+ this._markers[n].setFocus();
507
+ this.current_focused_id = this._markers[n].data.unique_id;
508
+ this._markers[n].on('markerblur', this._onMarkerBlur, this);
509
+ }
510
+ }
511
+
512
+ focusNext() {
513
+ const n = this._findMarkerIndex(this.current_focused_id);
514
+ if ((n + 1) < this._markers.length) {
515
+ this.focusOn(n + 1);
516
+ } else {
517
+ this.focusOn(n);
518
+ }
519
+ }
520
+
521
+ focusPrevious() {
522
+ const n = this._findMarkerIndex(this.current_focused_id);
523
+ if (n - 1 >= 0) {
524
+ this.focusOn(n - 1);
525
+ } else {
526
+ this.focusOn(n);
527
+ }
528
+ }
529
+
530
+ animateMovement(n, fast, css_animation, duration, ease) {
462
531
  // Stop animation
463
532
  if (this.animator) {
464
533
  this.animator.stop();
@@ -466,18 +535,21 @@ export class TimeNav {
466
535
 
467
536
  if (fast) {
468
537
  this._el.slider.className = "tl-timenav-slider";
469
- this._el.slider.style.left = -this._markers[_n].getLeft() + (this.options.width / 2) + "px";
538
+ this._el.slider.style.left = -this._markers[n].getLeft() +
539
+ (this.options.width / 2) + "px";
470
540
  } else {
471
541
  if (css_animation) {
472
542
  this._el.slider.className = "tl-timenav-slider tl-timenav-slider-animate";
473
543
  this.animate_css = true;
474
- this._el.slider.style.left = -this._markers[_n].getLeft() + (this.options.width / 2) + "px";
544
+ this._el.slider.style.left = -this._markers[n].getLeft() +
545
+ (this.options.width / 2) + "px";
475
546
  } else {
476
547
  this._el.slider.className = "tl-timenav-slider";
477
548
  this.animator = Animate(this._el.slider, {
478
- left: -this._markers[_n].getLeft() + (this.options.width / 2) + "px",
479
- duration: _duration,
480
- easing: _ease
549
+ left: -this._markers[n].getLeft() +
550
+ (this.options.width / 2) + "px",
551
+ duration: duration,
552
+ easing: ease
481
553
  });
482
554
  }
483
555
  }
@@ -487,12 +559,29 @@ export class TimeNav {
487
559
  } else {
488
560
  this.current_id = '';
489
561
  }
562
+
563
+ this._dispatchVisibleTicksChange();
490
564
  }
491
565
 
492
566
  goToId(id, fast, css_animation) {
493
567
  this.goTo(this._findMarkerIndex(id), fast, css_animation);
494
568
  }
495
569
 
570
+ _dispatchVisibleTicksChange() {
571
+ /**
572
+ * The timeout is required to wait till the end of the animation
573
+ * and repositioning of the ticks on the screen
574
+ */
575
+ if (this.ticks_change_timeout) {
576
+ clearTimeout(this.ticks_change_timeout);
577
+ this.ticks_change_timeout = null;
578
+ }
579
+ this.ticks_change_timeout = setTimeout(() => {
580
+ const visible_ticks = this.timeaxis.getVisibleTicks();
581
+ this.fire("visible_ticks_change", { visible_ticks });
582
+ }, this.options.duration);
583
+ }
584
+
496
585
  /* Events
497
586
  ================================================== */
498
587
  _onLoaded() {
@@ -518,6 +607,12 @@ export class TimeNav {
518
607
  this.fire("change", { unique_id: e.unique_id });
519
608
  }
520
609
 
610
+ _onMarkerBlur(e) {
611
+ // Reset the focused marked to the active marker after it lost the focus
612
+ if (this.current_focused_id === this.current_id) return;
613
+ this.focusOn(this._findMarkerIndex(this.current_id));
614
+ }
615
+
521
616
  _onMouseScroll(e) {
522
617
 
523
618
  var delta = 0,
@@ -576,6 +671,35 @@ export class TimeNav {
576
671
 
577
672
  }
578
673
 
674
+ _onKeydown(e) {
675
+ DOMEvent.stopPropagation(e);
676
+
677
+ switch (e.key) {
678
+ case "ArrowUp":
679
+ case "ArrowRight":
680
+ {
681
+ this.focusNext();
682
+ break;
683
+ }
684
+ case "ArrowDown":
685
+ case "ArrowLeft":
686
+ {
687
+ this.focusPrevious();
688
+ break;
689
+ }
690
+ case "Home":
691
+ {
692
+ this.focusOn(0);
693
+ break;
694
+ }
695
+ case "End":
696
+ {
697
+ this.focusOn(this._markers.length - 1);
698
+ break;
699
+ }
700
+ }
701
+ }
702
+
579
703
  /* Private Methods
580
704
  ================================================== */
581
705
 
@@ -633,12 +757,18 @@ export class TimeNav {
633
757
 
634
758
  }
635
759
 
760
+ _setLabelWithCurrentMarker() {
761
+ const currentMarker = this._markers[this._findMarkerIndex(this.current_focused_id)];
762
+ const currentMarkerText = currentMarker && currentMarker.ariaLabel ?
763
+ `, ${currentMarker.ariaLabel}, shown` :
764
+ '';
765
+ this._el.container.setAttribute('aria-label', `Timeline navigation ${currentMarkerText}`);
766
+ }
636
767
 
637
768
  /* Init
638
769
  ================================================== */
639
770
  _initLayout() {
640
771
  // Create Layout
641
- this._el.attribution = DOM.create('div', 'tl-attribution', this._el.container);
642
772
  this._el.line = DOM.create('div', 'tl-timenav-line', this._el.container);
643
773
  this._el.slider = DOM.create('div', 'tl-timenav-slider', this._el.container);
644
774
  this._el.slider_background = DOM.create('div', 'tl-timenav-slider-background', this._el.slider);
@@ -648,10 +778,6 @@ export class TimeNav {
648
778
  this._el.timeaxis = DOM.create('div', 'tl-timeaxis', this._el.slider);
649
779
  this._el.timeaxis_background = DOM.create('div', 'tl-timeaxis-background', this._el.container);
650
780
 
651
-
652
- // Knight Lab Logo
653
- this._el.attribution.innerHTML = "<a href='http://timeline.knightlab.com' target='_blank' rel='noopener'><span class='tl-knightlab-logo'></span>TimelineJS</a>"
654
-
655
781
  // Time Axis
656
782
  this.timeaxis = new TimeAxis(this._el.timeaxis, this.options, this.language);
657
783
 
@@ -672,6 +798,7 @@ export class TimeNav {
672
798
  // Scroll Events
673
799
  DOMEvent.addListener(this._el.container, 'mousewheel', this._onMouseScroll, this);
674
800
  DOMEvent.addListener(this._el.container, 'DOMMouseScroll', this._onMouseScroll, this);
801
+ DOMEvent.addListener(this._el.container, 'keydown', this._onKeydown, this);
675
802
  }
676
803
 
677
804
  _initData() {
@@ -688,4 +815,4 @@ export class TimeNav {
688
815
  }
689
816
  }
690
817
 
691
- classMixin(TimeNav, Events, DOMMixins)
818
+ classMixin(TimeNav, Events, DOMMixins, I18NMixins)