@knight-lab/timelinejs 3.9.2 → 3.9.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/css/fonts/font.abril-droidsans.css +1 -1
  3. package/dist/css/fonts/font.amatic-andika.css +3 -3
  4. package/dist/css/fonts/font.bevan-pontanosans.css +2 -2
  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.default.css +3 -3
  9. package/dist/css/fonts/font.fjalla-average.css +1 -1
  10. package/dist/css/fonts/font.lustria-lato.css +2 -2
  11. package/dist/css/fonts/font.medula-lato.css +3 -3
  12. package/dist/css/fonts/font.oldstandard.css +2 -2
  13. package/dist/css/fonts/font.opensans-gentiumbook.css +4 -4
  14. package/dist/css/fonts/font.playfair-faunaone.css +5 -5
  15. package/dist/css/fonts/font.playfair.css +3 -3
  16. package/dist/css/fonts/font.pt.css +3 -3
  17. package/dist/css/fonts/font.roboto-megrim.css +3 -3
  18. package/dist/css/fonts/font.rufina-sintony.css +4 -4
  19. package/dist/css/fonts/font.unicaone-vollkorn.css +3 -3
  20. package/dist/embed/index.html +1 -1
  21. package/dist/js/timeline.js +1 -1
  22. package/dist/js/timeline.js.LICENSE.txt +1 -1
  23. package/dist/js/timeline.js.map +1 -1
  24. package/package.json +2 -2
  25. package/src/embed/index.html +1 -1
  26. package/src/js/core/ConfigFactory.js +11 -4
  27. package/src/js/index.js +3 -6
  28. package/src/js/media/types/WikipediaImage.js +4 -3
  29. package/src/js/slider/Slide.js +3 -4
  30. package/src/js/slider/StorySlider.js +1 -2
  31. package/src/js/timeline/Timeline.js +26 -24
  32. package/src/js/timenav/TimeEra.js +1 -2
  33. package/src/js/timenav/TimeMarker.js +2 -3
  34. package/src/template/all-media-types.json +8 -5
  35. package/src/template/index.html +1 -0
  36. package/src/js/dom/DOMUtil.js +0 -25
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@knight-lab/timelinejs",
3
- "version": "3.9.2",
3
+ "version": "3.9.4",
4
4
  "license": "MPL-2.0",
5
5
  "description": "TimelineJS v3: A Storytelling Timeline built in JavaScript, made by Northwestern University Knight Lab.",
6
6
  "dependencies": {
7
- "dompurify": "^2.2.7",
7
+ "dompurify": "^3.1.7",
8
8
  "wicg-inert": "^3.1.2"
9
9
  },
10
10
  "devDependencies": {
@@ -150,7 +150,7 @@
150
150
  var options = optionsFromUrlParams();
151
151
  createEmbedDiv('timeline-embed', options.width, options.height);
152
152
  // ga_property_id is not something we let users override
153
- options.ga_property_id = 'UA-27829802-4';
153
+ options.ga_measurement_id = 'G-LVEFKMG087'
154
154
  if (typeof(options.source) == 'undefined') {
155
155
  options.source = '1xuY4upIooEeszZ_lCmeNx24eSFWe0rHe9ZdqH2xqVNk' // women in computing
156
156
  }
@@ -65,7 +65,8 @@ function extractEventFromCSVObject(orig_row) {
65
65
  caption: row['Media Caption'] || '',
66
66
  credit: row['Media Credit'] || '',
67
67
  url: row['Media'] || '',
68
- thumbnail: row['Media Thumbnail'] || ''
68
+ thumbnail: row['Media Thumbnail'] || '',
69
+ alt: row['Alt Text'] || ''
69
70
  },
70
71
  text: {
71
72
  headline: row['Headline'] || '',
@@ -154,7 +155,13 @@ export async function readGoogleAsCSV(url, sheets_proxy) {
154
155
  if (error_json.proxy_err_code == 'response_not_csv') {
155
156
  throw new TLError('Timeline could not read the data for your timeline. Make sure you have published it to the web.')
156
157
  }
157
- throw new TLError(error_json.message)
158
+ let msg = "undefined error"
159
+ if (Array.isArray(error_json.message)) {
160
+ msg = error_json.message.join('<br>')
161
+ } else {
162
+ msg = String(error_json.message)
163
+ }
164
+ throw new TLError(msg)
158
165
  })
159
166
 
160
167
  let timeline_config = { 'events': [], 'errors': [], 'warnings': [], 'eras': [] }
@@ -217,7 +224,7 @@ var buildGoogleFeedURL = function(key, api_version) {
217
224
  }
218
225
  }
219
226
 
220
- async function jsonFromGoogleURL(google_url, options) {
227
+ export async function jsonFromGoogleURL(google_url, options) {
221
228
 
222
229
  if (!options['sheets_proxy']) {
223
230
  throw new TLError("Proxy option must be set to read data from Google")
@@ -334,4 +341,4 @@ function handleRow(event, timeline_config) {
334
341
  } else {
335
342
  timeline_config.events.push(event);
336
343
  }
337
- }
344
+ }
package/src/js/index.js CHANGED
@@ -1,7 +1,4 @@
1
1
  import "../less/TL.Timeline.less"
2
- export { Timeline }
3
- from "./timeline/Timeline"
4
- export { parseGoogleSpreadsheetURL }
5
- from "./core/ConfigFactory"
6
- export { lookupMediaType }
7
- from "./media/MediaType"
2
+ export { Timeline, exportJSON } from "./timeline/Timeline"
3
+ export { parseGoogleSpreadsheetURL } from "./core/ConfigFactory"
4
+ export { lookupMediaType } from "./media/MediaType"
@@ -44,7 +44,7 @@ export default class WikipediaImage extends Media {
44
44
 
45
45
  _loadMedia() {
46
46
  var api_url,
47
- image_width = this.options.width || 1000,
47
+ image_width = Math.round(this.options.width) || 1000, // value to WP API must be int
48
48
  language_code = this.getLanguage().lang.toLowerCase(),
49
49
  self = this;
50
50
 
@@ -140,8 +140,9 @@ export default class WikipediaImage extends Media {
140
140
 
141
141
  _getImageURL(w, h) {
142
142
  if (w && this.base_image_url) {
143
- let match = this.base_image_url.match(/(\/\d+px-)/)
143
+ let match = this.base_image_url.match(/(\/[\d\.]+px-)/)
144
144
  if (match) {
145
+ w = Math.round(w) // WP image URLS 404 if floats are used so round it.
145
146
  return this.base_image_url.replace(match[1], `/${w}px-`) // Wikipedia will autoscale the image for us
146
147
  }
147
148
  }
@@ -156,4 +157,4 @@ export default class WikipediaImage extends Media {
156
157
  *
157
158
  * https://commons.wikimedia.org/w/api.php?action=query&titles=File:Beryl-Quartz-Emerald-Zambia-33mm_0885.jpg&prop=imageinfo&iiprop=url&&iiurlwidth=1000
158
159
  * https://commons.wikimedia.org/wiki/File:Beryl-Quartz-Emerald-Zambia-33mm_0885.jpg
159
- */
160
+ */
@@ -1,6 +1,5 @@
1
1
  import "wicg-inert";
2
2
 
3
- import { addClass } from "../dom/DOMUtil"
4
3
  import { I18NMixins } from "../language/I18NMixins";
5
4
  import Events from "../core/Events";
6
5
  import { DOMMixins } from "../dom/DOMMixins";
@@ -321,17 +320,17 @@ export class Slide {
321
320
 
322
321
  // Add to DOM
323
322
  if (!this.has.text && !this.has.headline && this.has.media) {
324
- addClass(this._el.container, 'tl-slide-media-only');
323
+ this._el.container.classList.add('tl-slide-media-only');
325
324
  this._media.addTo(this._el.content);
326
325
  } else if (this.has.headline && this.has.media && !this.has.text) {
327
- addClass(this._el.container, 'tl-slide-media-only');
326
+ this._el.container.classList.add('tl-slide-media-only');
328
327
  this._text.addTo(this._el.content);
329
328
  this._media.addTo(this._el.content);
330
329
  } else if (this.has.text && this.has.media) {
331
330
  this._text.addTo(this._el.content);
332
331
  this._media.addTo(this._el.content);
333
332
  } else if (this.has.text || this.has.headline) {
334
- addClass(this._el.container, 'tl-slide-text-only');
333
+ this._el.container.classList.add('tl-slide-text-only');
335
334
  this._text.addTo(this._el.content);
336
335
  }
337
336
 
@@ -6,7 +6,6 @@ import { Animate } from "../animation/Animate"
6
6
  import * as DOM from "../dom/DOM"
7
7
  import { DOMEvent } from "../dom/DOMEvent"
8
8
  import * as Browser from "../core/Browser"
9
- import { addClass } from "../dom/DOMUtil"
10
9
  import Swipable from "../ui/Swipable";
11
10
  import Message from "../ui/Message"
12
11
  import { Slide } from "./Slide"
@@ -394,7 +393,7 @@ export class StorySlider {
394
393
  ================================================== */
395
394
  _initLayout() {
396
395
 
397
- addClass(this._el.container, 'tl-storyslider');
396
+ this._el.container.classList.add('tl-storyslider');
398
397
 
399
398
  // Create Navigation
400
399
  this._nav.previous = new SlideNav({ title: "Previous", description: "description" }, { direction: "previous" }, this._el.container);
@@ -1,12 +1,11 @@
1
1
  import * as DOM from "../dom/DOM"
2
- import { addClass } from "../dom/DOMUtil"
3
2
  import { hexToRgb, mergeData, classMixin, isTrue, trace, addTraceHandler } from "../core/Util";
4
3
  import { easeInOutQuint, easeOutStrong } from "../animation/Ease";
5
4
  import Message from "../ui/Message"
6
5
  import { Language, fallback, loadLanguage } from "../language/Language"
7
6
  import { I18NMixins } from "../language/I18NMixins";
8
7
  import Events from "../core/Events";
9
- import { makeConfig } from "../core/ConfigFactory"
8
+ import { makeConfig, jsonFromGoogleURL } from "../core/ConfigFactory"
10
9
  import { TimelineConfig } from "../core/TimelineConfig"
11
10
  import { TimeNav } from "../timenav/TimeNav"
12
11
  import * as Browser from "../core/Browser"
@@ -134,6 +133,7 @@ class Timeline {
134
133
  slide_default_fade: "0%", // landscape fade
135
134
  zoom_sequence: [0.5, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89], // Array of Fibonacci numbers for TimeNav zoom levels
136
135
  language: "en",
136
+ ga_measurement_id: null,
137
137
  ga_property_id: null,
138
138
  track_events: ['back_to_start', 'nav_next', 'nav_previous', 'zoom_in', 'zoom_out'],
139
139
  theme: null,
@@ -192,17 +192,17 @@ class Timeline {
192
192
  }
193
193
 
194
194
  // Apply base class to container
195
- addClass(this._el.container, 'tl-timeline');
195
+ this._el.container.classList.add('tl-timeline');
196
196
  this._el.container.setAttribute('tabindex', '0');
197
197
  this._el.container.setAttribute('role', 'region');
198
198
  this._el.container.setAttribute('aria-label', this._('aria_label_timeline'));
199
199
 
200
200
  if (this.options.is_embed) {
201
- addClass(this._el.container, 'tl-timeline-embed');
201
+ this._el.container.classList.add('tl-timeline-embed');
202
202
  }
203
203
 
204
204
  if (this.options.is_full_embed) {
205
- addClass(this._el.container, 'tl-timeline-full-embed');
205
+ this._el.container.classList.add('tl-timeline-full-embed');
206
206
  }
207
207
 
208
208
  this._loadLanguage(data);
@@ -992,31 +992,23 @@ class Timeline {
992
992
  this._el.container.focus();
993
993
  }
994
994
 
995
- _initGoogleAnalytics() {
996
- (function(i, s, o, g, r, a, m) {
997
- i['GoogleAnalyticsObject'] = r;
998
- i[r] = i[r] || function() {
999
- (i[r].q = i[r].q || []).push(arguments)
1000
- }, i[r].l = 1 * new Date();
1001
- a = s.createElement(o), m = s.getElementsByTagName(o)[0];
1002
- a.async = 1;
1003
- a.src = g;
1004
- m.parentNode.insertBefore(a, m)
1005
- })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
1006
-
1007
- ga('create', this.options.ga_property_id, 'auto');
1008
- ga('set', 'anonymizeIp', true);
995
+ _initGoogleAnalytics(measurement_id) {
996
+ loadJS(`https://www.googletagmanager.com/gtag/js?id=${measurement_id}`)
997
+ window.dataLayer = window.dataLayer || [];
998
+ window.gtag = function(){dataLayer.push(arguments);}
999
+ gtag('js', new Date());
1000
+ gtag('config', measurement_id);
1009
1001
  }
1010
1002
 
1011
1003
  _initAnalytics() {
1012
- if (this.options.ga_property_id === null) { return; }
1013
- this._initGoogleAnalytics();
1014
- ga('send', 'pageview');
1004
+ let measurement_id = this.options.ga_measurement_id || this.options.ga_property_id || null;
1005
+ if (!measurement_id) { return; }
1006
+ this._initGoogleAnalytics(measurement_id);
1015
1007
  var events = this.options.track_events;
1016
1008
  for (let i = 0; i < events.length; i++) {
1017
1009
  var event_ = events[i];
1018
1010
  this.addEventListener(event_, function(e) {
1019
- ga('send', 'event', e.type, 'clicked');
1011
+ gtag('event', e.type);
1020
1012
  });
1021
1013
  }
1022
1014
  }
@@ -1026,4 +1018,14 @@ class Timeline {
1026
1018
 
1027
1019
  classMixin(Timeline, I18NMixins, Events)
1028
1020
 
1029
- export { Timeline }
1021
+ async function exportJSON(url, proxy_url) {
1022
+
1023
+ if (!proxy_url) {
1024
+ proxy_url = 'https://sheets-proxy.knightlab.com/proxy/'
1025
+ }
1026
+
1027
+ let json = await jsonFromGoogleURL(url, {sheets_proxy: proxy_url})
1028
+ return json
1029
+ }
1030
+
1031
+ export { Timeline, exportJSON }
@@ -2,7 +2,6 @@ import { classMixin, unlinkify, mergeData } from "../core/Util"
2
2
  import Events from "../core/Events"
3
3
  import { DOMMixins } from "../dom/DOMMixins"
4
4
  import * as Browser from "../core/Browser"
5
- import { removeClass } from "../dom/DOMUtil";
6
5
  import { easeInSpline } from "../animation/Ease";
7
6
  import * as DOM from "../dom/DOM"
8
7
 
@@ -156,7 +155,7 @@ export class TimeEra {
156
155
  this.setPosition({ top: n });
157
156
 
158
157
  if (remainder < 56) {
159
- removeClass(this._el.content_container, "tl-timeera-content-container-small");
158
+ this._el.content_container.remove("tl-timeera-content-container-small");
160
159
  }
161
160
  }
162
161
 
@@ -3,7 +3,6 @@ import Events from "../core/Events"
3
3
  import { DOMMixins } from "../dom/DOMMixins"
4
4
  import { DOMEvent } from "../dom/DOMEvent"
5
5
 
6
- import { addClass, removeClass } from "../dom/DOMUtil"
7
6
  import * as DOM from "../dom/DOM"
8
7
  import { webkit as BROWSER_WEBKIT } from "../core/Browser";
9
8
  import { easeInSpline } from "../animation/Ease";
@@ -181,9 +180,9 @@ export class TimeMarker {
181
180
  }
182
181
 
183
182
  if (h <= 56) {
184
- addClass(this._el.content_container, "tl-timemarker-content-container-small");
183
+ this._el.content_container.classList.add("tl-timemarker-content-container-small");
185
184
  } else {
186
- removeClass(this._el.content_container, "tl-timemarker-content-container-small");
185
+ this._el.content_container.classList.remove("tl-timemarker-content-container-small");
187
186
  }
188
187
 
189
188
  // Handle number of lines visible vertically
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "text": {
9
9
  "headline": "TimelineJS Media Types",
10
- "text": "<p>TimelineJS supports many media types. This provides a simple way to test them all. This page tests a simple image on a remote server. Also, if the Timeline was created with the <code>soundcite</code> option set to <code>true</code> then <span class='soundcite' data-url='https://soundcite.knightlab.com/media/bach-cello-suite.mp3' data-start='0' data-end='164000' data-plays='1'>this should be an active SoundCite player.</span></p>"
10
+ "text": "<p>TimelineJS supports many media types. This provides a simple way to test them all. This page tests a simple image on a remote server. Also, if the Timeline was created with the <code>soundcite</code> option set to <code>true</code> then <span class='soundcite' data-url='https://soundcite.knightlab.com/media/bach-cello-suite.mp3' data-start='0' data-end='164000' data-plays='1'>this should be an active SoundCite player.</span></p><p><a target=\"_self\" href=\"#wikipedia-images\">click to jump to Wikipedia Images</a></p>"
11
11
  },
12
12
  "background": {
13
13
  "color": "papayawhip"
@@ -388,10 +388,10 @@
388
388
 
389
389
  {
390
390
  "media": {
391
- "url": "https://en.wikipedia.org/wiki/1997_International_Tennis_Championships_%E2%80%93_Doubles",
391
+ "url": "https://fr.wikipedia.org/wiki/Bataille_de_Champigny#/media/Fichier:Champigny,_le_four_%C3%A0_chaux_(d%C3%A9tail).jpg",
392
392
  "caption": "1997 International Tennis Championships - Doubles",
393
393
  "credit": "Wikipedia",
394
- "link": "https://en.wikipedia.org/wiki/1997_International_Tennis_Championships_%E2%80%93_Doubles"
394
+ "link": "https://fr.wikipedia.org/wiki/Bataille_de_Champigny#/media/Fichier:Champigny,_le_four_%C3%A0_chaux_(d%C3%A9tail).jpg"
395
395
  },
396
396
  "start_date": {
397
397
  "year": "1920"
@@ -519,7 +519,7 @@
519
519
  },
520
520
  {
521
521
  "media": {
522
- "url": "https://file-examples.com/storage/fef12739526267ac9a2b543/2017/04/file_example_MP4_480_1_5MG.mp4",
522
+ "url": "https://file-examples.com/storage/febf69dcf3656dfd992b0fa/2017/04/file_example_MP4_480_1_5MG.mp4",
523
523
  "credit": "file-examples.com"
524
524
  },
525
525
  "start_date": {
@@ -548,6 +548,7 @@
548
548
  "group": "Video"
549
549
  },
550
550
  {
551
+ "unique_id": "wistia",
551
552
  "media": {
552
553
  "url": "https://lakeshore.wistia.com/medias/g2h5ddrucc",
553
554
  "credit": "Wistia"
@@ -562,6 +563,7 @@
562
563
  "group": "Video"
563
564
  },
564
565
  {
566
+ "unique_id": "wikipedia-images",
565
567
  "media": {
566
568
  "url": "https://de.wikipedia.org/wiki/Beryllium#/media/Datei:Beryl-Quartz-Emerald-Zambia-33mm_0885.jpg",
567
569
  "credit": "Wikipedia"
@@ -576,6 +578,7 @@
576
578
  "group": "Image"
577
579
  },
578
580
  {
581
+ "unique_id": "wikipedia-commons",
579
582
  "media": {
580
583
  "url": "https://commons.wikimedia.org/wiki/File:David-Bowie_Chicago_2002-08-08_photoby_Adam-Bielawski-cropped.jpg",
581
584
  "credit": "Wikipedia"
@@ -590,4 +593,4 @@
590
593
  "group": "Image"
591
594
  }
592
595
  ]
593
- }
596
+ }
@@ -13,6 +13,7 @@
13
13
  hash_bookmark: true,
14
14
  start_at_end: false,
15
15
  autolink: false,
16
+ ga_measurement_id: 'G-LVEFKMG087',
16
17
  sheets_proxy: 'https://sheets-proxy.knightlab.com/proxy/'
17
18
  }
18
19
 
@@ -1,25 +0,0 @@
1
- /* DomUtil
2
- Inspired by Leaflet
3
- DomUtil contains various utility functions for working with DOM
4
- Why are they in DOMUtil and not DOM?
5
- ================================================== */
6
-
7
- function hasClass(el, name) {
8
- return (el.className.length > 0) &&
9
- new RegExp("(^|\\s)" + name + "(\\s|$)").test(el.className);
10
- }
11
-
12
- export function addClass(el, name) {
13
- if (!hasClass(el, name)) {
14
- el.className += (el.className ? ' ' : '') + name;
15
- }
16
- }
17
-
18
- export function removeClass(el, name) {
19
- el.className = el.className.replace(/(\S+)\s*/g, function(w, match) {
20
- if (match === name) {
21
- return '';
22
- }
23
- return w;
24
- }).replace(/^\s+/, '');
25
- }