@flourish/sdk 4.2.0 → 4.2.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.
@@ -1,5 +0,0 @@
1
- export function createFlourishCredit(credit_url: any, query_string: any, public_url: any, credit_text: any): any;
2
- export function getLocalizedCreditTextAndUrl(lang: any, credit_key: any): {
3
- credit_text: any;
4
- credit_url: any;
5
- };
@@ -1,47 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getLocalizedCreditTextAndUrl = exports.createFlourishCredit = void 0;
7
- const localizations_1 = __importDefault(require("./localizations"));
8
- function createFlourishCredit(credit_url, query_string, public_url, credit_text) {
9
- credit_url = credit_url || "https://flourish.studio",
10
- query_string = query_string || "?utm_source=api&utm_campaign=" + window.location.href,
11
- public_url = public_url || "https://public.flourish.studio/",
12
- credit_text = credit_text || "A Flourish data visualization";
13
- var credit = document.createElement("div");
14
- credit.setAttribute("class", "flourish-credit");
15
- credit.setAttribute("style", "width:100%!important;margin:0 0 4px!important;text-align:right!important;font-family:Helvetica,sans-serif!important;color:#888!important;font-size:11px!important;font-weight:bold!important;font-style:normal!important;-webkit-font-smoothing:antialiased!important;box-shadow:none!important;");
16
- var a = document.createElement("a");
17
- a.setAttribute("href", credit_url + query_string);
18
- a.setAttribute("target", "_top");
19
- a.setAttribute("style", "display:inline-block!important;text-decoration:none!important;font:inherit!important;color:inherit!important;border:none!important;margin:0 5px!important;box-shadow:none!important;");
20
- credit.appendChild(a);
21
- var img = document.createElement("img");
22
- img.setAttribute("alt", "Flourish logo");
23
- img.setAttribute("src", public_url + "resources/bosh.svg");
24
- img.setAttribute("style", "font:inherit!important;width:auto!important;height:12px!important;border:none!important;margin:0 2px 0!important;vertical-align:middle!important;display:inline-block!important;box-shadow:none!important;");
25
- a.appendChild(img);
26
- var span = document.createElement("span");
27
- span.setAttribute("style", "font:inherit!important;color:#888!important;vertical-align:middle!important;display:inline-block!important;box-shadow:none!important;");
28
- span.appendChild(document.createTextNode(credit_text));
29
- a.appendChild(span);
30
- return credit;
31
- }
32
- exports.createFlourishCredit = createFlourishCredit;
33
- function getLocalizedCreditTextAndUrl(lang, credit_key) {
34
- var credit_text, credit_url;
35
- lang = lang || "en", credit_key = credit_key || "";
36
- credit_text = localizations_1.default[lang].credits[credit_key] || localizations_1.default.en.credits[credit_key] || localizations_1.default.en.credits.default;
37
- if (typeof credit_text == "object") {
38
- if (credit_text.url)
39
- credit_url = credit_text.url;
40
- credit_text = credit_text.text;
41
- }
42
- return {
43
- credit_text: credit_text,
44
- credit_url: credit_url
45
- };
46
- }
47
- exports.getLocalizedCreditTextAndUrl = getLocalizedCreditTextAndUrl;
@@ -1,5 +0,0 @@
1
- export function sendCustomerAnalyticsMessage(message: any): void;
2
- export function addAnalyticsListener(callback: any): void;
3
- export function removeAnalyticsListener(callback: any): void;
4
- export function dispatchAnalyticsEvent(message: any): void;
5
- export function initCustomerAnalytics(): void;
@@ -1,114 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initCustomerAnalytics = exports.dispatchAnalyticsEvent = exports.removeAnalyticsListener = exports.addAnalyticsListener = exports.sendCustomerAnalyticsMessage = void 0;
4
- // Embedded code - must work in IE
5
- var enabled = false;
6
- function getLocationData() {
7
- var data = {};
8
- if (window._Flourish_template_id) {
9
- data.template_id = window._Flourish_template_id;
10
- }
11
- if (window.Flourish && window.Flourish.app && window.Flourish.app.loaded_template_id) {
12
- data.template_id = window.Flourish.app.loaded_template_id;
13
- }
14
- if (window._Flourish_visualisation_id) {
15
- data.visualisation_id = window._Flourish_visualisation_id;
16
- }
17
- if (window.Flourish && window.Flourish.app && window.Flourish.app.loaded_visualisation) {
18
- data.visualisation_id = window.Flourish.app.loaded_visualisation.id;
19
- }
20
- if (window.Flourish && window.Flourish.app && window.Flourish.app.story) {
21
- data.story_id = window.Flourish.app.story.id;
22
- data.slide_count = window.Flourish.app.story.slides.length;
23
- }
24
- if (window.Flourish && window.Flourish.app && window.Flourish.app.current_slide) {
25
- // One indexed
26
- data.slide_index = window.Flourish.app.current_slide.index + 1;
27
- }
28
- return data;
29
- }
30
- function sendCustomerAnalyticsMessage(message) {
31
- if (!enabled)
32
- return;
33
- if (window.top === window.self)
34
- return;
35
- var embedded_window = window;
36
- if (embedded_window.location.pathname === "srcdoc")
37
- embedded_window = embedded_window.parent;
38
- var location_data = getLocationData();
39
- var message_with_metadata = {
40
- sender: "Flourish",
41
- method: "customerAnalytics"
42
- };
43
- for (var key in location_data) {
44
- if (location_data.hasOwnProperty(key)) {
45
- message_with_metadata[key] = location_data[key];
46
- }
47
- }
48
- for (var key in message) {
49
- if (message.hasOwnProperty(key)) {
50
- message_with_metadata[key] = message[key];
51
- }
52
- }
53
- embedded_window.parent.postMessage(JSON.stringify(message_with_metadata), "*");
54
- }
55
- exports.sendCustomerAnalyticsMessage = sendCustomerAnalyticsMessage;
56
- function addAnalyticsListener(callback) {
57
- if (typeof callback !== "function") {
58
- throw new Error("Analytics callback is not a function");
59
- }
60
- window.Flourish._analytics_listeners.push(callback);
61
- }
62
- exports.addAnalyticsListener = addAnalyticsListener;
63
- function removeAnalyticsListener(callback) {
64
- if (typeof callback !== "function") {
65
- throw new Error("Analytics callback is not a function");
66
- }
67
- window.Flourish._analytics_listeners = window.Flourish._analytics_listeners.filter(function (listener) {
68
- return callback !== listener;
69
- });
70
- }
71
- exports.removeAnalyticsListener = removeAnalyticsListener;
72
- function dispatchAnalyticsEvent(message) {
73
- // If the window.Flourish object hasn't been created by the customer, they
74
- // can't be listening for analytics events
75
- if (!window.Flourish)
76
- return;
77
- window.Flourish._analytics_listeners.forEach(function (listener) {
78
- listener(message);
79
- });
80
- }
81
- exports.dispatchAnalyticsEvent = dispatchAnalyticsEvent;
82
- function initCustomerAnalytics() {
83
- enabled = true;
84
- var events = [
85
- {
86
- event_name: "click",
87
- action_name: "click",
88
- use_capture: true
89
- },
90
- {
91
- event_name: "keydown",
92
- action_name: "key_down",
93
- use_capture: true
94
- },
95
- {
96
- event_name: "mouseenter",
97
- action_name: "mouse_enter",
98
- use_capture: false
99
- },
100
- {
101
- event_name: "mouseleave",
102
- action_name: "mouse_leave",
103
- use_capture: false
104
- }
105
- ];
106
- events.forEach(function (event) {
107
- document.body.addEventListener(event.event_name, function () {
108
- sendCustomerAnalyticsMessage({
109
- action: event.action_name
110
- });
111
- }, event.use_capture);
112
- });
113
- }
114
- exports.initCustomerAnalytics = initCustomerAnalytics;
@@ -1,25 +0,0 @@
1
- export default initEmbedding;
2
- declare function initEmbedding(): {
3
- createEmbedIframe: typeof createEmbedIframe;
4
- isFixedHeight: typeof isFixedHeight;
5
- getHeightForBreakpoint: typeof getHeightForBreakpoint;
6
- startEventListeners: typeof startEventListeners;
7
- notifyParentWindow: typeof notifyParentWindow;
8
- initScrolly: typeof initScrolly;
9
- createScrolly: typeof createScrolly;
10
- isSafari: typeof isSafari;
11
- initCustomerAnalytics: typeof initCustomerAnalytics;
12
- addAnalyticsListener: typeof addAnalyticsListener;
13
- sendCustomerAnalyticsMessage: typeof sendCustomerAnalyticsMessage;
14
- };
15
- declare function createEmbedIframe(embed_url: any, container: any, width: any, height: any, play_on_load: any): any;
16
- declare function isFixedHeight(): any;
17
- declare function getHeightForBreakpoint(width: any): 650 | 575 | 400;
18
- declare function startEventListeners(callback: any, allowed_methods: any, embed_domain: any): void;
19
- declare function notifyParentWindow(height: any, opts: any): void;
20
- declare function initScrolly(opts: any): void;
21
- declare function createScrolly(iframe: any, slides: any): void;
22
- declare function isSafari(): boolean;
23
- import { initCustomerAnalytics } from "./customer_analytics";
24
- import { addAnalyticsListener } from "./customer_analytics";
25
- import { sendCustomerAnalyticsMessage } from "./customer_analytics";
@@ -1,461 +0,0 @@
1
- "use strict";
2
- /* This file is used by the story player, and must be IE-compatible */
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const customer_analytics_1 = require("./customer_analytics");
8
- const parse_query_params_1 = __importDefault(require("./parse_query_params"));
9
- var is_fixed_height;
10
- var is_amp;
11
- function isFixedHeight() {
12
- if (is_fixed_height == undefined) {
13
- var params = (0, parse_query_params_1.default)();
14
- // "referrer" in params implies this is an Embedly embed
15
- // Check whether embedding site is known to support dynamic resizing
16
- if ("referrer" in params)
17
- is_fixed_height = /^https:\/\/medium.com\//.test(params.referrer);
18
- else
19
- is_fixed_height = !("auto" in params);
20
- }
21
- return is_fixed_height;
22
- }
23
- function getHeightForBreakpoint(width) {
24
- var breakpoint_width = width || window.innerWidth;
25
- if (breakpoint_width > 999)
26
- return 650;
27
- if (breakpoint_width > 599)
28
- return 575;
29
- return 400;
30
- }
31
- function initScrolly(opts) {
32
- if (!opts)
33
- return;
34
- if (window.top === window.self)
35
- return;
36
- var embedded_window = window;
37
- if (embedded_window.location.pathname == "srcdoc")
38
- embedded_window = embedded_window.parent;
39
- var message = {
40
- sender: "Flourish",
41
- method: "scrolly",
42
- };
43
- if (opts) {
44
- for (var name in opts)
45
- message[name] = opts[name];
46
- }
47
- embedded_window.parent.postMessage(JSON.stringify(message), "*");
48
- }
49
- function notifyParentWindow(height, opts) {
50
- if (window.top === window.self)
51
- return;
52
- var embedded_window = window;
53
- if (embedded_window.location.pathname == "srcdoc")
54
- embedded_window = embedded_window.parent;
55
- if (is_amp) {
56
- // Message is not stringified for AMP
57
- height = parseInt(height, 10);
58
- embedded_window.parent.postMessage({
59
- sentinel: "amp",
60
- type: "embed-size",
61
- height: height,
62
- }, "*");
63
- return;
64
- }
65
- var message = {
66
- sender: "Flourish",
67
- context: "iframe.resize",
68
- method: "resize",
69
- height: height,
70
- src: embedded_window.location.toString(),
71
- };
72
- if (opts) {
73
- for (var name in opts)
74
- message[name] = opts[name];
75
- }
76
- embedded_window.parent.postMessage(JSON.stringify(message), "*");
77
- }
78
- function isSafari() {
79
- // Some example user agents:
80
- // Safari iOS: Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1
81
- // Chrome OS X: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
82
- // Embedded WkWebview on iOS: Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D5039a
83
- return (navigator.userAgent.indexOf("Safari") !== -1 || navigator.userAgent.indexOf("iPhone") !== -1) && navigator.userAgent.indexOf("Chrome") == -1;
84
- }
85
- function isString(s) {
86
- return typeof s === "string" || s instanceof String;
87
- }
88
- function isPossibleHeight(n) {
89
- if (typeof n === "number") {
90
- return !isNaN(n) && (n >= 0);
91
- }
92
- else if (isString(n)) {
93
- // First regex checks there is at least one digit in n and rejectsedge cases like "" and "px" that would pass second regex
94
- // Given first regex, second regex makes sure that n is either a pure number or a number with a valid CSS unit
95
- // Units based on https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units#lengths plus %
96
- return /\d/.test(n) && /^[0-9]*(\.[0-9]*)?(cm|mm|Q|in|pc|pt|px|em|ex|ch|rem|lh|vw|vh|vmin|vmax|%)?$/i.test(n);
97
- }
98
- return false;
99
- }
100
- function validateWarnMessage(message) {
101
- if (message.method !== "warn") {
102
- console.warn("BUG: validateWarnMessage called for method" + message.method);
103
- return false;
104
- }
105
- if ((message.message != null) && !isString(message.message))
106
- return false;
107
- if ((message.explanation != null) && !isString(message.explanation))
108
- return false;
109
- return true;
110
- }
111
- function validateResizeMessage(message) {
112
- if (message.method !== "resize") {
113
- console.warn("BUG: validateResizeMessage called for method" + message.method);
114
- return false;
115
- }
116
- if (!isString(message.src))
117
- return false;
118
- if (!isString(message.context))
119
- return false;
120
- if (!isPossibleHeight(message.height))
121
- return false;
122
- return true;
123
- }
124
- function validateSetSettingMessage(_message) {
125
- throw new Error("Validation for setSetting is not implemented yet; see issue #4328");
126
- }
127
- function validateScrolly(message) {
128
- if (message.method !== "scrolly") {
129
- console.warn("BUG: validateScrolly called for method" + message.method);
130
- return false;
131
- }
132
- if (!Array.isArray(message.slides))
133
- return false;
134
- return true;
135
- }
136
- function validateCustomerAnalyticsMessage(message) {
137
- if (message.method !== "customerAnalytics") {
138
- console.warn("BUG: validateCustomerAnalyticsMessage called for method" + message.method);
139
- return false;
140
- }
141
- // We don't consume customer analytics messages; they're just passed
142
- // on, and their structure is up to the customer, so there's no
143
- // point in validating them.
144
- return true;
145
- }
146
- function validateRequestUpload(message) {
147
- if (message.method !== "request-upload") {
148
- console.warn("BUG: validateResizeMessage called for method" + message.method);
149
- return false;
150
- }
151
- // FIXME: when adding validation for setSetting (see above) we should
152
- // also validate that this is a valid setting name of appropriate type
153
- if (!isString(message.name))
154
- return false;
155
- if (!(message.accept == null || isString(message.accept)))
156
- return false;
157
- return true;
158
- }
159
- function getMessageValidators(methods) {
160
- var available_message_validators = {
161
- "warn": validateWarnMessage,
162
- "resize": validateResizeMessage,
163
- "setSetting": validateSetSettingMessage,
164
- "customerAnalytics": validateCustomerAnalyticsMessage,
165
- "request-upload": validateRequestUpload,
166
- "scrolly": validateScrolly
167
- };
168
- var validators = {};
169
- for (var i = 0; i < methods.length; i++) {
170
- var method = methods[i];
171
- if (available_message_validators[method]) {
172
- validators[method] = available_message_validators[method];
173
- }
174
- else {
175
- throw new Error("No validator found for method " + method);
176
- }
177
- }
178
- return validators;
179
- }
180
- function startEventListeners(callback, allowed_methods, embed_domain) {
181
- var message_validators = getMessageValidators(allowed_methods);
182
- window.addEventListener("message", function (event) {
183
- var is_accepted_event_origin = (function () {
184
- if (event.origin == document.location.origin) {
185
- return true;
186
- }
187
- // If company has configured a custom origin for downloaded projects, allow it
188
- if (embed_domain) {
189
- const origin = event.origin.toLowerCase();
190
- embed_domain = embed_domain.toLowerCase();
191
- // Allow the domain itself…
192
- if (origin.endsWith("//" + embed_domain))
193
- return true;
194
- // and subdomains
195
- if (origin.endsWith("." + embed_domain))
196
- return true;
197
- }
198
- if (event.origin.match(/\/\/localhost:\d+$|\/\/(?:public|app)\.flourish.devlocal$|\/\/flourish-api\.com$|\.flourish\.(?:local(:\d+)?|net|rocks|studio)$|\.uri\.sh$|\/\/flourish-user-templates\.com$/)) {
199
- return true;
200
- }
201
- return false;
202
- })();
203
- // event.source is null when the message is sent by an extension
204
- // https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Using_window.postMessage_in_extensions
205
- if (event.source == null)
206
- return;
207
- if (!is_accepted_event_origin)
208
- return;
209
- var message;
210
- try {
211
- message = typeof event.data === "object" ? event.data : JSON.parse(event.data);
212
- }
213
- catch (e) {
214
- console.warn("Unexpected non-JSON message: " + JSON.stringify(event.data));
215
- return;
216
- }
217
- if (message.sender !== "Flourish")
218
- return;
219
- if (!message.method) {
220
- console.warn("The 'method' property was missing from message", message);
221
- return;
222
- }
223
- if (!Object.prototype.hasOwnProperty.call(message_validators, message.method)) {
224
- console.warn("No validator implemented for message", message);
225
- return;
226
- }
227
- if (!message_validators[message.method](message)) {
228
- console.warn("Validation failed for the message", message);
229
- return;
230
- }
231
- var frames = document.querySelectorAll("iframe");
232
- for (var i = 0; i < frames.length; i++) {
233
- if (frames[i].contentWindow == event.source || frames[i].contentWindow == event.source.parent) {
234
- callback(message, frames[i]);
235
- return;
236
- }
237
- }
238
- console.warn("could not find frame", message);
239
- });
240
- if (isSafari()) {
241
- window.addEventListener("resize", onSafariWindowResize);
242
- onSafariWindowResize();
243
- }
244
- }
245
- function onSafariWindowResize() {
246
- // Ensure all iframes without explicit width attribute are sized to fit their container
247
- var containers = document.querySelectorAll(".flourish-embed");
248
- for (var i = 0; i < containers.length; i++) {
249
- var container = containers[i];
250
- if (container.getAttribute("data-width"))
251
- continue;
252
- var iframe = container.querySelector("iframe");
253
- // When embeds are dynamically loaded, we might have a container without a
254
- // loaded iframe yet
255
- if (!iframe)
256
- continue;
257
- var computed_style = window.getComputedStyle(container);
258
- var width = container.offsetWidth - parseFloat(computed_style.paddingLeft) - parseFloat(computed_style.paddingRight);
259
- iframe.style.width = width + "px";
260
- }
261
- }
262
- function createScrolly(iframe, slides) {
263
- var parent = iframe.parentNode;
264
- // Fallback to avoid any situation where the scrolly gets initialised twice
265
- if (parent.classList.contains("fl-scrolly-wrapper")) {
266
- console.warn("createScrolly is being called more than once per story. This should not happen.");
267
- return;
268
- }
269
- parent.classList.add("fl-scrolly-wrapper");
270
- parent.style.position = "relative";
271
- parent.style.paddingBottom = "1px";
272
- parent.style.transform = "translate3d(0, 0, 0)"; // Workaround for Safari https://stackoverflow.com/questions/50224855/not-respecting-z-index-on-safari-with-position-sticky
273
- iframe.style.position = "sticky";
274
- var h = parent.getAttribute("data-height") || null;
275
- if (!h) { // Scrollies require fixed height to work well, so if not height set …
276
- h = "80vh"; // … use a sensible fallback
277
- iframe.style.height = h; // And update the iframe height directly
278
- }
279
- iframe.style.top = "calc(50vh - " + h + "/2)";
280
- var credit = parent.querySelector(".flourish-credit");
281
- if (credit) {
282
- credit.style.position = "sticky";
283
- credit.style.top = "calc(50vh + " + h + "/2)";
284
- }
285
- slides.forEach(function (d, i) {
286
- var has_content = typeof d == "string" && d.trim() != "";
287
- var step = document.createElement("div");
288
- step.setAttribute("data-slide", i);
289
- step.classList.add("fl-scrolly-caption");
290
- step.style.position = "relative";
291
- step.style.transform = "translate3d(0,0,0)"; // Workaround for Safari https://stackoverflow.com/questions/50224855/not-respecting-z-index-on-safari-with-position-sticky
292
- step.style.textAlign = "center";
293
- step.style.maxWidth = "500px";
294
- step.style.height = "auto";
295
- step.style.marginTop = "0";
296
- step.style.marginBottom = has_content ? "100vh" : "50vh";
297
- step.style.marginLeft = "auto";
298
- step.style.marginRight = "auto";
299
- var caption = document.createElement("div");
300
- caption.innerHTML = d;
301
- caption.style.visibility = has_content ? "" : "hidden";
302
- caption.style.display = "inline-block";
303
- caption.style.paddingTop = "1.25em";
304
- caption.style.paddingRight = "1.25em";
305
- caption.style.paddingBottom = "1.25em";
306
- caption.style.paddingLeft = "1.25em";
307
- caption.style.background = "rgba(255,255,255,0.9)";
308
- caption.style.boxShadow = "0px 0px 10px rgba(0,0,0,0.2)";
309
- caption.style.borderRadius = "10px";
310
- caption.style.textAlign = "center";
311
- caption.style.maxWidth = "100%";
312
- caption.style.margin = "0 20px";
313
- caption.style.overflowX = "hidden";
314
- step.appendChild(caption);
315
- parent.appendChild(step);
316
- });
317
- initIntersection(parent);
318
- }
319
- function initIntersection(container) {
320
- var t = "0%"; // Trigger when hits viewport; could be set by user in the future
321
- var observer = new IntersectionObserver(function (entries) {
322
- entries.forEach(function (entry) {
323
- if (entry.isIntersecting) {
324
- var iframe = container.querySelector("iframe");
325
- if (iframe)
326
- iframe.src = iframe.src.replace(/#slide-.*/, "") + "#slide-" + entry.target.getAttribute("data-slide");
327
- }
328
- });
329
- }, { rootMargin: "0px 0px -" + t + " 0px" });
330
- var steps = container.querySelectorAll(".fl-scrolly-caption");
331
- for (var i = 0; i < steps.length; i++) {
332
- observer.observe(steps[i]);
333
- }
334
- // Set a max width on any images in the captions, to avoid ugly overflowing
335
- // in the rare cases where the
336
- // This won't happen much, but it is possible to paste an image into a
337
- // story caption, so better to handle this nicely since there's no other
338
- // way for the user to set it.
339
- var images = container.querySelectorAll(".fl-scrolly-caption img");
340
- images.forEach(function (img) { img.style.maxWidth = "100%"; });
341
- }
342
- function createEmbedIframe(embed_url, container, width, height, play_on_load) {
343
- var iframe = document.createElement("iframe");
344
- iframe.setAttribute("scrolling", "no");
345
- iframe.setAttribute("frameborder", "0");
346
- iframe.setAttribute("title", "Interactive or visual content");
347
- iframe.setAttribute("sandbox", "allow-same-origin allow-forms allow-scripts allow-downloads allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation");
348
- container.appendChild(iframe);
349
- // If the iframe doesn't have an offset parent, either the element or a parent
350
- // is set to display: none. This can cause problems with visualisation loading, so
351
- // we need to poll for the iframe being displayed before loading the visualisation.
352
- // FIXME: In Chrome, fixed position elements also return null for `offsetParent`.
353
- // The chances of an embed which is both position: fixed and display: none are
354
- // pretty small, so fuhgeddaboudit . If it's an issue in the future, we'll have to
355
- // recurse through the parent elements to make sure the iframe is displaying.
356
- if (iframe.offsetParent || getComputedStyle(iframe).position === "fixed") {
357
- setIframeContent(embed_url, container, iframe, width, height, play_on_load);
358
- }
359
- else {
360
- var poll_item = {
361
- embed_url: embed_url,
362
- container: container,
363
- iframe: iframe,
364
- width: width,
365
- height: height,
366
- play_on_load: play_on_load
367
- };
368
- // If this is the first embed on the page which is isn't displayed, set up a
369
- // list of hidden iframes to poll
370
- if (!window._flourish_poll_items) {
371
- window._flourish_poll_items = [poll_item];
372
- }
373
- else {
374
- // Otherwise, add this to the list of iframes which are being polled
375
- window._flourish_poll_items.push(poll_item);
376
- }
377
- if (window._flourish_poll_items.length > 1) {
378
- // If there were already items in the array then we have already started
379
- // polling in a different embed script, so we can return. This iframe will
380
- // have its contents set by the other embed script.
381
- return iframe;
382
- }
383
- // Poll to see whether any of the iframes have started displaying
384
- var interval = setInterval(function () {
385
- window._flourish_poll_items = window._flourish_poll_items.filter(function (item) {
386
- if (!item.iframe.offsetParent) {
387
- // It's still not displaying, so return true to leave it in the array
388
- return true;
389
- }
390
- // It's displaying, so set the content, and return false to remove it from
391
- // the array
392
- setIframeContent(item.embed_url, item.container, item.iframe, item.width, item.height, item.play_on_load);
393
- return false;
394
- });
395
- if (!window._flourish_poll_items.length) {
396
- // All of the iframes are displaying, so we can stop polling. If another
397
- // embed is added later, a new interval will be created by that embed script.
398
- clearInterval(interval);
399
- }
400
- }, 500);
401
- }
402
- return iframe;
403
- }
404
- function setIframeContent(embed_url, container, iframe, width, height, play_on_load) {
405
- var width_in_px;
406
- if (width && typeof width === "number") {
407
- width_in_px = width;
408
- width = "" + width + "px";
409
- }
410
- // The regular expression below detects widths that have been explicitly
411
- // expressed in px units. (It turns out CSS is more complicated than you may
412
- // have realised.)
413
- else if (width && width.match(/^[ \t\r\n\f]*([+-]?\d+|\d*\.\d+(?:[eE][+-]?\d+)?)(?:\\?[Pp]|\\0{0,4}[57]0(?:\r\n|[ \t\r\n\f])?)(?:\\?[Xx]|\\0{0,4}[57]8(?:\r\n|[ \t\r\n\f])?)[ \t\r\n\f]*$/)) {
414
- width_in_px = parseFloat(width);
415
- }
416
- if (height && typeof height === "number")
417
- height = "" + height + "px";
418
- // Odd design decision in Safari means need to set fixed width rather than %
419
- // as will try and size iframe to content otherwise. Must also set scrolling=no
420
- if (width)
421
- iframe.style.width = width;
422
- else if (isSafari())
423
- iframe.style.width = container.offsetWidth + "px";
424
- else
425
- iframe.style.width = "100%";
426
- var fixed_height = !!height;
427
- if (!fixed_height) {
428
- if (embed_url.match(/\?/))
429
- embed_url += "&auto=1";
430
- else
431
- embed_url += "?auto=1";
432
- // For initial height, use our standard breakpoints, based on the explicit
433
- // pixel width if we know it, or the iframe's measured width if not.
434
- height = getHeightForBreakpoint(width_in_px || iframe.offsetWidth) + "px";
435
- }
436
- if (height) {
437
- if (height.charAt(height.length - 1) === "%") {
438
- height = (parseFloat(height) / 100) * container.parentNode.offsetHeight + "px";
439
- }
440
- iframe.style.height = height;
441
- }
442
- iframe.setAttribute("src", embed_url + (play_on_load ? "#play-on-load" : ""));
443
- return iframe;
444
- }
445
- function initEmbedding() {
446
- is_amp = window.location.hash == "#amp=1";
447
- return {
448
- createEmbedIframe: createEmbedIframe,
449
- isFixedHeight: isFixedHeight,
450
- getHeightForBreakpoint: getHeightForBreakpoint,
451
- startEventListeners: startEventListeners,
452
- notifyParentWindow: notifyParentWindow,
453
- initScrolly: initScrolly,
454
- createScrolly: createScrolly,
455
- isSafari: isSafari,
456
- initCustomerAnalytics: customer_analytics_1.initCustomerAnalytics,
457
- addAnalyticsListener: customer_analytics_1.addAnalyticsListener,
458
- sendCustomerAnalyticsMessage: customer_analytics_1.sendCustomerAnalyticsMessage
459
- };
460
- }
461
- exports.default = initEmbedding;