@authsignal/browser 0.1.0 → 0.1.2
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/dist/index.js +4 -8
- package/package.json +4 -4
- package/dist/index.mjs +0 -4520
package/dist/index.mjs
DELETED
|
@@ -1,4520 +0,0 @@
|
|
|
1
|
-
// Unique ID creation requires a high quality random # generator. In the browser we therefore
|
|
2
|
-
// require the crypto API and do not support built-in fallback to lower quality random number
|
|
3
|
-
// generators (like Math.random()).
|
|
4
|
-
let getRandomValues;
|
|
5
|
-
const rnds8 = new Uint8Array(16);
|
|
6
|
-
function rng() {
|
|
7
|
-
// lazy load so that environments that need to polyfill have a chance to do so
|
|
8
|
-
if (!getRandomValues) {
|
|
9
|
-
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
|
|
10
|
-
getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
|
11
|
-
|
|
12
|
-
if (!getRandomValues) {
|
|
13
|
-
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return getRandomValues(rnds8);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Convert array of 16 byte values to UUID string format of the form:
|
|
22
|
-
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
const byteToHex = [];
|
|
26
|
-
|
|
27
|
-
for (let i = 0; i < 256; ++i) {
|
|
28
|
-
byteToHex.push((i + 0x100).toString(16).slice(1));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function unsafeStringify(arr, offset = 0) {
|
|
32
|
-
// Note: Be careful editing this code! It's been tuned for performance
|
|
33
|
-
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
|
|
34
|
-
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
38
|
-
var native = {
|
|
39
|
-
randomUUID
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
function v4(options, buf, offset) {
|
|
43
|
-
if (native.randomUUID && !buf && !options) {
|
|
44
|
-
return native.randomUUID();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
options = options || {};
|
|
48
|
-
const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
|
49
|
-
|
|
50
|
-
rnds[6] = rnds[6] & 0x0f | 0x40;
|
|
51
|
-
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
|
|
52
|
-
|
|
53
|
-
if (buf) {
|
|
54
|
-
offset = offset || 0;
|
|
55
|
-
|
|
56
|
-
for (let i = 0; i < 16; ++i) {
|
|
57
|
-
buf[offset + i] = rnds[i];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return buf;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return unsafeStringify(rnds);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
var setCookie = function (_a) {
|
|
67
|
-
var name = _a.name, value = _a.value, expire = _a.expire, domain = _a.domain, secure = _a.secure;
|
|
68
|
-
var expireString = expire === Infinity ? " expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + expire;
|
|
69
|
-
document.cookie =
|
|
70
|
-
encodeURIComponent(name) +
|
|
71
|
-
"=" +
|
|
72
|
-
value +
|
|
73
|
-
"; path=/;" +
|
|
74
|
-
expireString +
|
|
75
|
-
(domain ? "; domain=" + domain : "") +
|
|
76
|
-
(secure ? "; secure" : "");
|
|
77
|
-
};
|
|
78
|
-
var getCookieDomain = function () {
|
|
79
|
-
return document.location.hostname.replace("www.", "");
|
|
80
|
-
};
|
|
81
|
-
var getCookie = function (name) {
|
|
82
|
-
if (!name) {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
return (decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(name).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
var AuthsignalWindowMessage;
|
|
89
|
-
(function (AuthsignalWindowMessage) {
|
|
90
|
-
AuthsignalWindowMessage["AUTHSIGNAL_CLOSE_POPUP"] = "AUTHSIGNAL_CLOSE_POPUP";
|
|
91
|
-
})(AuthsignalWindowMessage || (AuthsignalWindowMessage = {}));
|
|
92
|
-
|
|
93
|
-
var focusableSelectors = [
|
|
94
|
-
'a[href]:not([tabindex^="-"])',
|
|
95
|
-
'area[href]:not([tabindex^="-"])',
|
|
96
|
-
'input:not([type="hidden"]):not([type="radio"]):not([disabled]):not([tabindex^="-"])',
|
|
97
|
-
'input[type="radio"]:not([disabled]):not([tabindex^="-"])',
|
|
98
|
-
'select:not([disabled]):not([tabindex^="-"])',
|
|
99
|
-
'textarea:not([disabled]):not([tabindex^="-"])',
|
|
100
|
-
'button:not([disabled]):not([tabindex^="-"])',
|
|
101
|
-
'iframe:not([tabindex^="-"])',
|
|
102
|
-
'audio[controls]:not([tabindex^="-"])',
|
|
103
|
-
'video[controls]:not([tabindex^="-"])',
|
|
104
|
-
'[contenteditable]:not([tabindex^="-"])',
|
|
105
|
-
'[tabindex]:not([tabindex^="-"])',
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
var TAB_KEY = 'Tab';
|
|
109
|
-
var ESCAPE_KEY = 'Escape';
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Define the constructor to instantiate a dialog
|
|
113
|
-
*
|
|
114
|
-
* @constructor
|
|
115
|
-
* @param {Element} element
|
|
116
|
-
*/
|
|
117
|
-
function A11yDialog(element) {
|
|
118
|
-
// Prebind the functions that will be bound in addEventListener and
|
|
119
|
-
// removeEventListener to avoid losing references
|
|
120
|
-
this._show = this.show.bind(this);
|
|
121
|
-
this._hide = this.hide.bind(this);
|
|
122
|
-
this._maintainFocus = this._maintainFocus.bind(this);
|
|
123
|
-
this._bindKeypress = this._bindKeypress.bind(this);
|
|
124
|
-
|
|
125
|
-
this.$el = element;
|
|
126
|
-
this.shown = false;
|
|
127
|
-
this._id = this.$el.getAttribute('data-a11y-dialog') || this.$el.id;
|
|
128
|
-
this._previouslyFocused = null;
|
|
129
|
-
this._listeners = {};
|
|
130
|
-
|
|
131
|
-
// Initialise everything needed for the dialog to work properly
|
|
132
|
-
this.create();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Set up everything necessary for the dialog to be functioning
|
|
137
|
-
*
|
|
138
|
-
* @param {(NodeList | Element | string)} targets
|
|
139
|
-
* @return {this}
|
|
140
|
-
*/
|
|
141
|
-
A11yDialog.prototype.create = function () {
|
|
142
|
-
this.$el.setAttribute('aria-hidden', true);
|
|
143
|
-
this.$el.setAttribute('aria-modal', true);
|
|
144
|
-
this.$el.setAttribute('tabindex', -1);
|
|
145
|
-
|
|
146
|
-
if (!this.$el.hasAttribute('role')) {
|
|
147
|
-
this.$el.setAttribute('role', 'dialog');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Keep a collection of dialog openers, each of which will be bound a click
|
|
151
|
-
// event listener to open the dialog
|
|
152
|
-
this._openers = $$('[data-a11y-dialog-show="' + this._id + '"]');
|
|
153
|
-
this._openers.forEach(
|
|
154
|
-
function (opener) {
|
|
155
|
-
opener.addEventListener('click', this._show);
|
|
156
|
-
}.bind(this)
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
// Keep a collection of dialog closers, each of which will be bound a click
|
|
160
|
-
// event listener to close the dialog
|
|
161
|
-
const $el = this.$el;
|
|
162
|
-
|
|
163
|
-
this._closers = $$('[data-a11y-dialog-hide]', this.$el)
|
|
164
|
-
// This filter is necessary in case there are nested dialogs, so that
|
|
165
|
-
// only closers from the current dialog are retrieved and effective
|
|
166
|
-
.filter(function (closer) {
|
|
167
|
-
// Testing for `[aria-modal="true"]` is not enough since this attribute
|
|
168
|
-
// and the collect of closers is done at instantation time, when nested
|
|
169
|
-
// dialogs might not have yet been instantiated. Note that if the dialogs
|
|
170
|
-
// are manually instantiated, this could still fail because none of these
|
|
171
|
-
// selectors would match; this would cause closers to close all parent
|
|
172
|
-
// dialogs instead of just the current one
|
|
173
|
-
return closer.closest('[aria-modal="true"], [data-a11y-dialog]') === $el
|
|
174
|
-
})
|
|
175
|
-
.concat($$('[data-a11y-dialog-hide="' + this._id + '"]'));
|
|
176
|
-
|
|
177
|
-
this._closers.forEach(
|
|
178
|
-
function (closer) {
|
|
179
|
-
closer.addEventListener('click', this._hide);
|
|
180
|
-
}.bind(this)
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
// Execute all callbacks registered for the `create` event
|
|
184
|
-
this._fire('create');
|
|
185
|
-
|
|
186
|
-
return this
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Show the dialog element, disable all the targets (siblings), trap the
|
|
191
|
-
* current focus within it, listen for some specific key presses and fire all
|
|
192
|
-
* registered callbacks for `show` event
|
|
193
|
-
*
|
|
194
|
-
* @param {CustomEvent} event
|
|
195
|
-
* @return {this}
|
|
196
|
-
*/
|
|
197
|
-
A11yDialog.prototype.show = function (event) {
|
|
198
|
-
// If the dialog is already open, abort
|
|
199
|
-
if (this.shown) {
|
|
200
|
-
return this
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Keep a reference to the currently focused element to be able to restore
|
|
204
|
-
// it later
|
|
205
|
-
this._previouslyFocused = document.activeElement;
|
|
206
|
-
this.$el.removeAttribute('aria-hidden');
|
|
207
|
-
this.shown = true;
|
|
208
|
-
|
|
209
|
-
// Set the focus to the dialog element
|
|
210
|
-
moveFocusToDialog(this.$el);
|
|
211
|
-
|
|
212
|
-
// Bind a focus event listener to the body element to make sure the focus
|
|
213
|
-
// stays trapped inside the dialog while open, and start listening for some
|
|
214
|
-
// specific key presses (TAB and ESC)
|
|
215
|
-
document.body.addEventListener('focus', this._maintainFocus, true);
|
|
216
|
-
document.addEventListener('keydown', this._bindKeypress);
|
|
217
|
-
|
|
218
|
-
// Execute all callbacks registered for the `show` event
|
|
219
|
-
this._fire('show', event);
|
|
220
|
-
|
|
221
|
-
return this
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Hide the dialog element, enable all the targets (siblings), restore the
|
|
226
|
-
* focus to the previously active element, stop listening for some specific
|
|
227
|
-
* key presses and fire all registered callbacks for `hide` event
|
|
228
|
-
*
|
|
229
|
-
* @param {CustomEvent} event
|
|
230
|
-
* @return {this}
|
|
231
|
-
*/
|
|
232
|
-
A11yDialog.prototype.hide = function (event) {
|
|
233
|
-
// If the dialog is already closed, abort
|
|
234
|
-
if (!this.shown) {
|
|
235
|
-
return this
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
this.shown = false;
|
|
239
|
-
this.$el.setAttribute('aria-hidden', 'true');
|
|
240
|
-
|
|
241
|
-
// If there was a focused element before the dialog was opened (and it has a
|
|
242
|
-
// `focus` method), restore the focus back to it
|
|
243
|
-
// See: https://github.com/KittyGiraudel/a11y-dialog/issues/108
|
|
244
|
-
if (this._previouslyFocused && this._previouslyFocused.focus) {
|
|
245
|
-
this._previouslyFocused.focus();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Remove the focus event listener to the body element and stop listening
|
|
249
|
-
// for specific key presses
|
|
250
|
-
document.body.removeEventListener('focus', this._maintainFocus, true);
|
|
251
|
-
document.removeEventListener('keydown', this._bindKeypress);
|
|
252
|
-
|
|
253
|
-
// Execute all callbacks registered for the `hide` event
|
|
254
|
-
this._fire('hide', event);
|
|
255
|
-
|
|
256
|
-
return this
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Destroy the current instance (after making sure the dialog has been hidden)
|
|
261
|
-
* and remove all associated listeners from dialog openers and closers
|
|
262
|
-
*
|
|
263
|
-
* @return {this}
|
|
264
|
-
*/
|
|
265
|
-
A11yDialog.prototype.destroy = function () {
|
|
266
|
-
// Hide the dialog to avoid destroying an open instance
|
|
267
|
-
this.hide();
|
|
268
|
-
|
|
269
|
-
// Remove the click event listener from all dialog openers
|
|
270
|
-
this._openers.forEach(
|
|
271
|
-
function (opener) {
|
|
272
|
-
opener.removeEventListener('click', this._show);
|
|
273
|
-
}.bind(this)
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
// Remove the click event listener from all dialog closers
|
|
277
|
-
this._closers.forEach(
|
|
278
|
-
function (closer) {
|
|
279
|
-
closer.removeEventListener('click', this._hide);
|
|
280
|
-
}.bind(this)
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
// Execute all callbacks registered for the `destroy` event
|
|
284
|
-
this._fire('destroy');
|
|
285
|
-
|
|
286
|
-
// Keep an object of listener types mapped to callback functions
|
|
287
|
-
this._listeners = {};
|
|
288
|
-
|
|
289
|
-
return this
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Register a new callback for the given event type
|
|
294
|
-
*
|
|
295
|
-
* @param {string} type
|
|
296
|
-
* @param {Function} handler
|
|
297
|
-
*/
|
|
298
|
-
A11yDialog.prototype.on = function (type, handler) {
|
|
299
|
-
if (typeof this._listeners[type] === 'undefined') {
|
|
300
|
-
this._listeners[type] = [];
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
this._listeners[type].push(handler);
|
|
304
|
-
|
|
305
|
-
return this
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Unregister an existing callback for the given event type
|
|
310
|
-
*
|
|
311
|
-
* @param {string} type
|
|
312
|
-
* @param {Function} handler
|
|
313
|
-
*/
|
|
314
|
-
A11yDialog.prototype.off = function (type, handler) {
|
|
315
|
-
var index = (this._listeners[type] || []).indexOf(handler);
|
|
316
|
-
|
|
317
|
-
if (index > -1) {
|
|
318
|
-
this._listeners[type].splice(index, 1);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return this
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Iterate over all registered handlers for given type and call them all with
|
|
326
|
-
* the dialog element as first argument, event as second argument (if any). Also
|
|
327
|
-
* dispatch a custom event on the DOM element itself to make it possible to
|
|
328
|
-
* react to the lifecycle of auto-instantiated dialogs.
|
|
329
|
-
*
|
|
330
|
-
* @access private
|
|
331
|
-
* @param {string} type
|
|
332
|
-
* @param {CustomEvent} event
|
|
333
|
-
*/
|
|
334
|
-
A11yDialog.prototype._fire = function (type, event) {
|
|
335
|
-
var listeners = this._listeners[type] || [];
|
|
336
|
-
var domEvent = new CustomEvent(type, { detail: event });
|
|
337
|
-
|
|
338
|
-
this.$el.dispatchEvent(domEvent);
|
|
339
|
-
|
|
340
|
-
listeners.forEach(
|
|
341
|
-
function (listener) {
|
|
342
|
-
listener(this.$el, event);
|
|
343
|
-
}.bind(this)
|
|
344
|
-
);
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Private event handler used when listening to some specific key presses
|
|
349
|
-
* (namely ESCAPE and TAB)
|
|
350
|
-
*
|
|
351
|
-
* @access private
|
|
352
|
-
* @param {Event} event
|
|
353
|
-
*/
|
|
354
|
-
A11yDialog.prototype._bindKeypress = function (event) {
|
|
355
|
-
// This is an escape hatch in case there are nested dialogs, so the keypresses
|
|
356
|
-
// are only reacted to for the most recent one
|
|
357
|
-
const focused = document.activeElement;
|
|
358
|
-
if (focused && focused.closest('[aria-modal="true"]') !== this.$el) return
|
|
359
|
-
|
|
360
|
-
// If the dialog is shown and the ESCAPE key is being pressed, prevent any
|
|
361
|
-
// further effects from the ESCAPE key and hide the dialog, unless its role
|
|
362
|
-
// is 'alertdialog', which should be modal
|
|
363
|
-
if (
|
|
364
|
-
this.shown &&
|
|
365
|
-
event.key === ESCAPE_KEY &&
|
|
366
|
-
this.$el.getAttribute('role') !== 'alertdialog'
|
|
367
|
-
) {
|
|
368
|
-
event.preventDefault();
|
|
369
|
-
this.hide(event);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// If the dialog is shown and the TAB key is being pressed, make sure the
|
|
373
|
-
// focus stays trapped within the dialog element
|
|
374
|
-
if (this.shown && event.key === TAB_KEY) {
|
|
375
|
-
trapTabKey(this.$el, event);
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Private event handler used when making sure the focus stays within the
|
|
381
|
-
* currently open dialog
|
|
382
|
-
*
|
|
383
|
-
* @access private
|
|
384
|
-
* @param {Event} event
|
|
385
|
-
*/
|
|
386
|
-
A11yDialog.prototype._maintainFocus = function (event) {
|
|
387
|
-
// If the dialog is shown and the focus is not within a dialog element (either
|
|
388
|
-
// this one or another one in case of nested dialogs) or within an element
|
|
389
|
-
// with the `data-a11y-dialog-focus-trap-ignore` attribute, move it back to
|
|
390
|
-
// its first focusable child.
|
|
391
|
-
// See: https://github.com/KittyGiraudel/a11y-dialog/issues/177
|
|
392
|
-
if (
|
|
393
|
-
this.shown &&
|
|
394
|
-
!event.target.closest('[aria-modal="true"]') &&
|
|
395
|
-
!event.target.closest('[data-a11y-dialog-ignore-focus-trap]')
|
|
396
|
-
) {
|
|
397
|
-
moveFocusToDialog(this.$el);
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Convert a NodeList into an array
|
|
403
|
-
*
|
|
404
|
-
* @param {NodeList} collection
|
|
405
|
-
* @return {Array<Element>}
|
|
406
|
-
*/
|
|
407
|
-
function toArray(collection) {
|
|
408
|
-
return Array.prototype.slice.call(collection)
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* Query the DOM for nodes matching the given selector, scoped to context (or
|
|
413
|
-
* the whole document)
|
|
414
|
-
*
|
|
415
|
-
* @param {String} selector
|
|
416
|
-
* @param {Element} [context = document]
|
|
417
|
-
* @return {Array<Element>}
|
|
418
|
-
*/
|
|
419
|
-
function $$(selector, context) {
|
|
420
|
-
return toArray((context || document).querySelectorAll(selector))
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Set the focus to the first element with `autofocus` with the element or the
|
|
425
|
-
* element itself
|
|
426
|
-
*
|
|
427
|
-
* @param {Element} node
|
|
428
|
-
*/
|
|
429
|
-
function moveFocusToDialog(node) {
|
|
430
|
-
var focused = node.querySelector('[autofocus]') || node;
|
|
431
|
-
|
|
432
|
-
focused.focus();
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Get the focusable children of the given element
|
|
437
|
-
*
|
|
438
|
-
* @param {Element} node
|
|
439
|
-
* @return {Array<Element>}
|
|
440
|
-
*/
|
|
441
|
-
function getFocusableChildren(node) {
|
|
442
|
-
return $$(focusableSelectors.join(','), node).filter(function (child) {
|
|
443
|
-
return !!(
|
|
444
|
-
child.offsetWidth ||
|
|
445
|
-
child.offsetHeight ||
|
|
446
|
-
child.getClientRects().length
|
|
447
|
-
)
|
|
448
|
-
})
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* Trap the focus inside the given element
|
|
453
|
-
*
|
|
454
|
-
* @param {Element} node
|
|
455
|
-
* @param {Event} event
|
|
456
|
-
*/
|
|
457
|
-
function trapTabKey(node, event) {
|
|
458
|
-
var focusableChildren = getFocusableChildren(node);
|
|
459
|
-
var focusedItemIndex = focusableChildren.indexOf(document.activeElement);
|
|
460
|
-
|
|
461
|
-
// If the SHIFT key is being pressed while tabbing (moving backwards) and
|
|
462
|
-
// the currently focused item is the first one, move the focus to the last
|
|
463
|
-
// focusable item from the dialog element
|
|
464
|
-
if (event.shiftKey && focusedItemIndex === 0) {
|
|
465
|
-
focusableChildren[focusableChildren.length - 1].focus();
|
|
466
|
-
event.preventDefault();
|
|
467
|
-
// If the SHIFT key is not being pressed (moving forwards) and the currently
|
|
468
|
-
// focused item is the last one, move the focus to the first focusable item
|
|
469
|
-
// from the dialog element
|
|
470
|
-
} else if (
|
|
471
|
-
!event.shiftKey &&
|
|
472
|
-
focusedItemIndex === focusableChildren.length - 1
|
|
473
|
-
) {
|
|
474
|
-
focusableChildren[0].focus();
|
|
475
|
-
event.preventDefault();
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function instantiateDialogs() {
|
|
480
|
-
$$('[data-a11y-dialog]').forEach(function (node) {
|
|
481
|
-
new A11yDialog(node);
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
if (typeof document !== 'undefined') {
|
|
486
|
-
if (document.readyState === 'loading') {
|
|
487
|
-
document.addEventListener('DOMContentLoaded', instantiateDialogs);
|
|
488
|
-
} else {
|
|
489
|
-
if (window.requestAnimationFrame) {
|
|
490
|
-
window.requestAnimationFrame(instantiateDialogs);
|
|
491
|
-
} else {
|
|
492
|
-
window.setTimeout(instantiateDialogs, 16);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/*
|
|
498
|
-
* File: iframeResizer.js
|
|
499
|
-
* Desc: Force iframes to size to content.
|
|
500
|
-
* Requires: iframeResizer.contentWindow.js to be loaded into the target frame.
|
|
501
|
-
* Doc: https://github.com/davidjbradshaw/iframe-resizer
|
|
502
|
-
* Author: David J. Bradshaw - dave@bradshaw.net
|
|
503
|
-
* Contributor: Jure Mav - jure.mav@gmail.com
|
|
504
|
-
* Contributor: Reed Dadoune - reed@dadoune.com
|
|
505
|
-
*/
|
|
506
|
-
(function (undefined$1) {
|
|
507
|
-
if (typeof window === 'undefined') return // don't run for server side render
|
|
508
|
-
|
|
509
|
-
var count = 0,
|
|
510
|
-
logEnabled = false,
|
|
511
|
-
hiddenCheckEnabled = false,
|
|
512
|
-
msgHeader = 'message',
|
|
513
|
-
msgHeaderLen = msgHeader.length,
|
|
514
|
-
msgId = '[iFrameSizer]', // Must match iframe msg ID
|
|
515
|
-
msgIdLen = msgId.length,
|
|
516
|
-
pagePosition = null,
|
|
517
|
-
requestAnimationFrame = window.requestAnimationFrame,
|
|
518
|
-
resetRequiredMethods = Object.freeze({
|
|
519
|
-
max: 1,
|
|
520
|
-
scroll: 1,
|
|
521
|
-
bodyScroll: 1,
|
|
522
|
-
documentElementScroll: 1
|
|
523
|
-
}),
|
|
524
|
-
settings = {},
|
|
525
|
-
timer = null,
|
|
526
|
-
defaults = Object.freeze({
|
|
527
|
-
autoResize: true,
|
|
528
|
-
bodyBackground: null,
|
|
529
|
-
bodyMargin: null,
|
|
530
|
-
bodyMarginV1: 8,
|
|
531
|
-
bodyPadding: null,
|
|
532
|
-
checkOrigin: true,
|
|
533
|
-
inPageLinks: false,
|
|
534
|
-
enablePublicMethods: true,
|
|
535
|
-
heightCalculationMethod: 'bodyOffset',
|
|
536
|
-
id: 'iFrameResizer',
|
|
537
|
-
interval: 32,
|
|
538
|
-
log: false,
|
|
539
|
-
maxHeight: Infinity,
|
|
540
|
-
maxWidth: Infinity,
|
|
541
|
-
minHeight: 0,
|
|
542
|
-
minWidth: 0,
|
|
543
|
-
mouseEvents: true,
|
|
544
|
-
resizeFrom: 'parent',
|
|
545
|
-
scrolling: false,
|
|
546
|
-
sizeHeight: true,
|
|
547
|
-
sizeWidth: false,
|
|
548
|
-
warningTimeout: 5000,
|
|
549
|
-
tolerance: 0,
|
|
550
|
-
widthCalculationMethod: 'scroll',
|
|
551
|
-
onClose: function () {
|
|
552
|
-
return true
|
|
553
|
-
},
|
|
554
|
-
onClosed: function () {},
|
|
555
|
-
onInit: function () {},
|
|
556
|
-
onMessage: function () {
|
|
557
|
-
warn('onMessage function not defined');
|
|
558
|
-
},
|
|
559
|
-
onMouseEnter: function () {},
|
|
560
|
-
onMouseLeave: function () {},
|
|
561
|
-
onResized: function () {},
|
|
562
|
-
onScroll: function () {
|
|
563
|
-
return true
|
|
564
|
-
}
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
function getMutationObserver() {
|
|
568
|
-
return (
|
|
569
|
-
window.MutationObserver ||
|
|
570
|
-
window.WebKitMutationObserver ||
|
|
571
|
-
window.MozMutationObserver
|
|
572
|
-
)
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
function addEventListener(el, evt, func) {
|
|
576
|
-
el.addEventListener(evt, func, false);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
function removeEventListener(el, evt, func) {
|
|
580
|
-
el.removeEventListener(evt, func, false);
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
function setupRequestAnimationFrame() {
|
|
584
|
-
var vendors = ['moz', 'webkit', 'o', 'ms'];
|
|
585
|
-
var x;
|
|
586
|
-
|
|
587
|
-
// Remove vendor prefixing if prefixed and break early if not
|
|
588
|
-
for (x = 0; x < vendors.length && !requestAnimationFrame; x += 1) {
|
|
589
|
-
requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
if (requestAnimationFrame) {
|
|
593
|
-
// Firefox extension content-scripts have a globalThis object that is not the same as window.
|
|
594
|
-
// Binding `requestAnimationFrame` to window allows the function to work and prevents errors
|
|
595
|
-
// being thrown when run in that context, and should be a no-op in every other context.
|
|
596
|
-
requestAnimationFrame = requestAnimationFrame.bind(window);
|
|
597
|
-
} else {
|
|
598
|
-
log('setup', 'RequestAnimationFrame not supported');
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
function getMyID(iframeId) {
|
|
603
|
-
var retStr = 'Host page: ' + iframeId;
|
|
604
|
-
|
|
605
|
-
if (window.top !== window.self) {
|
|
606
|
-
retStr =
|
|
607
|
-
window.parentIFrame && window.parentIFrame.getId
|
|
608
|
-
? window.parentIFrame.getId() + ': ' + iframeId
|
|
609
|
-
: 'Nested host page: ' + iframeId;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
return retStr
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
function formatLogHeader(iframeId) {
|
|
616
|
-
return msgId + '[' + getMyID(iframeId) + ']'
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
function isLogEnabled(iframeId) {
|
|
620
|
-
return settings[iframeId] ? settings[iframeId].log : logEnabled
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
function log(iframeId, msg) {
|
|
624
|
-
output('log', iframeId, msg, isLogEnabled(iframeId));
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
function info(iframeId, msg) {
|
|
628
|
-
output('info', iframeId, msg, isLogEnabled(iframeId));
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
function warn(iframeId, msg) {
|
|
632
|
-
output('warn', iframeId, msg, true);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
function output(type, iframeId, msg, enabled) {
|
|
636
|
-
if (true === enabled && 'object' === typeof window.console) {
|
|
637
|
-
// eslint-disable-next-line no-console
|
|
638
|
-
console[type](formatLogHeader(iframeId), msg);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
function iFrameListener(event) {
|
|
643
|
-
function resizeIFrame() {
|
|
644
|
-
function resize() {
|
|
645
|
-
setSize(messageData);
|
|
646
|
-
setPagePosition(iframeId);
|
|
647
|
-
on('onResized', messageData);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
ensureInRange('Height');
|
|
651
|
-
ensureInRange('Width');
|
|
652
|
-
|
|
653
|
-
syncResize(resize, messageData, 'init');
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
function processMsg() {
|
|
657
|
-
var data = msg.slice(msgIdLen).split(':');
|
|
658
|
-
var height = data[1] ? parseInt(data[1], 10) : 0;
|
|
659
|
-
var iframe = settings[data[0]] && settings[data[0]].iframe;
|
|
660
|
-
var compStyle = getComputedStyle(iframe);
|
|
661
|
-
|
|
662
|
-
return {
|
|
663
|
-
iframe: iframe,
|
|
664
|
-
id: data[0],
|
|
665
|
-
height: height + getPaddingEnds(compStyle) + getBorderEnds(compStyle),
|
|
666
|
-
width: data[2],
|
|
667
|
-
type: data[3]
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
function getPaddingEnds(compStyle) {
|
|
672
|
-
if (compStyle.boxSizing !== 'border-box') {
|
|
673
|
-
return 0
|
|
674
|
-
}
|
|
675
|
-
var top = compStyle.paddingTop ? parseInt(compStyle.paddingTop, 10) : 0;
|
|
676
|
-
var bot = compStyle.paddingBottom
|
|
677
|
-
? parseInt(compStyle.paddingBottom, 10)
|
|
678
|
-
: 0;
|
|
679
|
-
return top + bot
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
function getBorderEnds(compStyle) {
|
|
683
|
-
if (compStyle.boxSizing !== 'border-box') {
|
|
684
|
-
return 0
|
|
685
|
-
}
|
|
686
|
-
var top = compStyle.borderTopWidth
|
|
687
|
-
? parseInt(compStyle.borderTopWidth, 10)
|
|
688
|
-
: 0;
|
|
689
|
-
var bot = compStyle.borderBottomWidth
|
|
690
|
-
? parseInt(compStyle.borderBottomWidth, 10)
|
|
691
|
-
: 0;
|
|
692
|
-
return top + bot
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
function ensureInRange(Dimension) {
|
|
696
|
-
var max = Number(settings[iframeId]['max' + Dimension]),
|
|
697
|
-
min = Number(settings[iframeId]['min' + Dimension]),
|
|
698
|
-
dimension = Dimension.toLowerCase(),
|
|
699
|
-
size = Number(messageData[dimension]);
|
|
700
|
-
|
|
701
|
-
log(iframeId, 'Checking ' + dimension + ' is in range ' + min + '-' + max);
|
|
702
|
-
|
|
703
|
-
if (size < min) {
|
|
704
|
-
size = min;
|
|
705
|
-
log(iframeId, 'Set ' + dimension + ' to min value');
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
if (size > max) {
|
|
709
|
-
size = max;
|
|
710
|
-
log(iframeId, 'Set ' + dimension + ' to max value');
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
messageData[dimension] = '' + size;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
function isMessageFromIFrame() {
|
|
717
|
-
function checkAllowedOrigin() {
|
|
718
|
-
function checkList() {
|
|
719
|
-
var i = 0,
|
|
720
|
-
retCode = false;
|
|
721
|
-
|
|
722
|
-
log(
|
|
723
|
-
iframeId,
|
|
724
|
-
'Checking connection is from allowed list of origins: ' +
|
|
725
|
-
checkOrigin
|
|
726
|
-
);
|
|
727
|
-
|
|
728
|
-
for (; i < checkOrigin.length; i++) {
|
|
729
|
-
if (checkOrigin[i] === origin) {
|
|
730
|
-
retCode = true;
|
|
731
|
-
break
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
return retCode
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
function checkSingle() {
|
|
738
|
-
var remoteHost = settings[iframeId] && settings[iframeId].remoteHost;
|
|
739
|
-
log(iframeId, 'Checking connection is from: ' + remoteHost);
|
|
740
|
-
return origin === remoteHost
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
return checkOrigin.constructor === Array ? checkList() : checkSingle()
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
var origin = event.origin,
|
|
747
|
-
checkOrigin = settings[iframeId] && settings[iframeId].checkOrigin;
|
|
748
|
-
|
|
749
|
-
if (checkOrigin && '' + origin !== 'null' && !checkAllowedOrigin()) {
|
|
750
|
-
throw new Error(
|
|
751
|
-
'Unexpected message received from: ' +
|
|
752
|
-
origin +
|
|
753
|
-
' for ' +
|
|
754
|
-
messageData.iframe.id +
|
|
755
|
-
'. Message was: ' +
|
|
756
|
-
event.data +
|
|
757
|
-
'. This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains.'
|
|
758
|
-
)
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
return true
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
function isMessageForUs() {
|
|
765
|
-
return (
|
|
766
|
-
msgId === ('' + msg).slice(0, msgIdLen) &&
|
|
767
|
-
msg.slice(msgIdLen).split(':')[0] in settings
|
|
768
|
-
) // ''+Protects against non-string msg
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
function isMessageFromMetaParent() {
|
|
772
|
-
// Test if this message is from a parent above us. This is an ugly test, however, updating
|
|
773
|
-
// the message format would break backwards compatibility.
|
|
774
|
-
var retCode = messageData.type in { true: 1, false: 1, undefined: 1 };
|
|
775
|
-
|
|
776
|
-
if (retCode) {
|
|
777
|
-
log(iframeId, 'Ignoring init message from meta parent page');
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
return retCode
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
function getMsgBody(offset) {
|
|
784
|
-
return msg.slice(msg.indexOf(':') + msgHeaderLen + offset)
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
function forwardMsgFromIFrame(msgBody) {
|
|
788
|
-
log(
|
|
789
|
-
iframeId,
|
|
790
|
-
'onMessage passed: {iframe: ' +
|
|
791
|
-
messageData.iframe.id +
|
|
792
|
-
', message: ' +
|
|
793
|
-
msgBody +
|
|
794
|
-
'}'
|
|
795
|
-
);
|
|
796
|
-
|
|
797
|
-
on('onMessage', {
|
|
798
|
-
iframe: messageData.iframe,
|
|
799
|
-
message: JSON.parse(msgBody)
|
|
800
|
-
});
|
|
801
|
-
|
|
802
|
-
log(iframeId, '--');
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
function getPageInfo() {
|
|
806
|
-
var bodyPosition = document.body.getBoundingClientRect(),
|
|
807
|
-
iFramePosition = messageData.iframe.getBoundingClientRect();
|
|
808
|
-
|
|
809
|
-
return JSON.stringify({
|
|
810
|
-
iframeHeight: iFramePosition.height,
|
|
811
|
-
iframeWidth: iFramePosition.width,
|
|
812
|
-
clientHeight: Math.max(
|
|
813
|
-
document.documentElement.clientHeight,
|
|
814
|
-
window.innerHeight || 0
|
|
815
|
-
),
|
|
816
|
-
clientWidth: Math.max(
|
|
817
|
-
document.documentElement.clientWidth,
|
|
818
|
-
window.innerWidth || 0
|
|
819
|
-
),
|
|
820
|
-
offsetTop: parseInt(iFramePosition.top - bodyPosition.top, 10),
|
|
821
|
-
offsetLeft: parseInt(iFramePosition.left - bodyPosition.left, 10),
|
|
822
|
-
scrollTop: window.pageYOffset,
|
|
823
|
-
scrollLeft: window.pageXOffset,
|
|
824
|
-
documentHeight: document.documentElement.clientHeight,
|
|
825
|
-
documentWidth: document.documentElement.clientWidth,
|
|
826
|
-
windowHeight: window.innerHeight,
|
|
827
|
-
windowWidth: window.innerWidth
|
|
828
|
-
})
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
function sendPageInfoToIframe(iframe, iframeId) {
|
|
832
|
-
function debouncedTrigger() {
|
|
833
|
-
trigger('Send Page Info', 'pageInfo:' + getPageInfo(), iframe, iframeId);
|
|
834
|
-
}
|
|
835
|
-
debounceFrameEvents(debouncedTrigger, 32, iframeId);
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
function startPageInfoMonitor() {
|
|
839
|
-
function setListener(type, func) {
|
|
840
|
-
function sendPageInfo() {
|
|
841
|
-
if (settings[id]) {
|
|
842
|
-
sendPageInfoToIframe(settings[id].iframe, id);
|
|
843
|
-
} else {
|
|
844
|
-
stop();
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
['scroll', 'resize'].forEach(function (evt) {
|
|
848
|
-
log(id, type + evt + ' listener for sendPageInfo');
|
|
849
|
-
func(window, evt, sendPageInfo);
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
function stop() {
|
|
854
|
-
setListener('Remove ', removeEventListener);
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
function start() {
|
|
858
|
-
setListener('Add ', addEventListener);
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
var id = iframeId; // Create locally scoped copy of iFrame ID
|
|
862
|
-
|
|
863
|
-
start();
|
|
864
|
-
|
|
865
|
-
if (settings[id]) {
|
|
866
|
-
settings[id].stopPageInfo = stop;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
function stopPageInfoMonitor() {
|
|
871
|
-
if (settings[iframeId] && settings[iframeId].stopPageInfo) {
|
|
872
|
-
settings[iframeId].stopPageInfo();
|
|
873
|
-
delete settings[iframeId].stopPageInfo;
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
function checkIFrameExists() {
|
|
878
|
-
var retBool = true;
|
|
879
|
-
|
|
880
|
-
if (null === messageData.iframe) {
|
|
881
|
-
warn(iframeId, 'IFrame (' + messageData.id + ') not found');
|
|
882
|
-
retBool = false;
|
|
883
|
-
}
|
|
884
|
-
return retBool
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
function getElementPosition(target) {
|
|
888
|
-
var iFramePosition = target.getBoundingClientRect();
|
|
889
|
-
|
|
890
|
-
getPagePosition(iframeId);
|
|
891
|
-
|
|
892
|
-
return {
|
|
893
|
-
x: Math.floor(Number(iFramePosition.left) + Number(pagePosition.x)),
|
|
894
|
-
y: Math.floor(Number(iFramePosition.top) + Number(pagePosition.y))
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
function scrollRequestFromChild(addOffset) {
|
|
899
|
-
/* istanbul ignore next */ // Not testable in Karma
|
|
900
|
-
function reposition() {
|
|
901
|
-
pagePosition = newPosition;
|
|
902
|
-
scrollTo();
|
|
903
|
-
log(iframeId, '--');
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
function calcOffset() {
|
|
907
|
-
return {
|
|
908
|
-
x: Number(messageData.width) + offset.x,
|
|
909
|
-
y: Number(messageData.height) + offset.y
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
function scrollParent() {
|
|
914
|
-
if (window.parentIFrame) {
|
|
915
|
-
window.parentIFrame['scrollTo' + (addOffset ? 'Offset' : '')](
|
|
916
|
-
newPosition.x,
|
|
917
|
-
newPosition.y
|
|
918
|
-
);
|
|
919
|
-
} else {
|
|
920
|
-
warn(
|
|
921
|
-
iframeId,
|
|
922
|
-
'Unable to scroll to requested position, window.parentIFrame not found'
|
|
923
|
-
);
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
var offset = addOffset
|
|
928
|
-
? getElementPosition(messageData.iframe)
|
|
929
|
-
: { x: 0, y: 0 },
|
|
930
|
-
newPosition = calcOffset();
|
|
931
|
-
|
|
932
|
-
log(
|
|
933
|
-
iframeId,
|
|
934
|
-
'Reposition requested from iFrame (offset x:' +
|
|
935
|
-
offset.x +
|
|
936
|
-
' y:' +
|
|
937
|
-
offset.y +
|
|
938
|
-
')'
|
|
939
|
-
);
|
|
940
|
-
|
|
941
|
-
if (window.top === window.self) {
|
|
942
|
-
reposition();
|
|
943
|
-
} else {
|
|
944
|
-
scrollParent();
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
function scrollTo() {
|
|
949
|
-
if (false === on('onScroll', pagePosition)) {
|
|
950
|
-
unsetPagePosition();
|
|
951
|
-
} else {
|
|
952
|
-
setPagePosition(iframeId);
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
function findTarget(location) {
|
|
957
|
-
function jumpToTarget() {
|
|
958
|
-
var jumpPosition = getElementPosition(target);
|
|
959
|
-
|
|
960
|
-
log(
|
|
961
|
-
iframeId,
|
|
962
|
-
'Moving to in page link (#' +
|
|
963
|
-
hash +
|
|
964
|
-
') at x: ' +
|
|
965
|
-
jumpPosition.x +
|
|
966
|
-
' y: ' +
|
|
967
|
-
jumpPosition.y
|
|
968
|
-
);
|
|
969
|
-
pagePosition = {
|
|
970
|
-
x: jumpPosition.x,
|
|
971
|
-
y: jumpPosition.y
|
|
972
|
-
};
|
|
973
|
-
|
|
974
|
-
scrollTo();
|
|
975
|
-
log(iframeId, '--');
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
function jumpToParent() {
|
|
979
|
-
if (window.parentIFrame) {
|
|
980
|
-
window.parentIFrame.moveToAnchor(hash);
|
|
981
|
-
} else {
|
|
982
|
-
log(
|
|
983
|
-
iframeId,
|
|
984
|
-
'In page link #' +
|
|
985
|
-
hash +
|
|
986
|
-
' not found and window.parentIFrame not found'
|
|
987
|
-
);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
var hash = location.split('#')[1] || '',
|
|
992
|
-
hashData = decodeURIComponent(hash),
|
|
993
|
-
target =
|
|
994
|
-
document.getElementById(hashData) ||
|
|
995
|
-
document.getElementsByName(hashData)[0];
|
|
996
|
-
|
|
997
|
-
if (target) {
|
|
998
|
-
jumpToTarget();
|
|
999
|
-
} else if (window.top === window.self) {
|
|
1000
|
-
log(iframeId, 'In page link #' + hash + ' not found');
|
|
1001
|
-
} else {
|
|
1002
|
-
jumpToParent();
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
function onMouse(event) {
|
|
1007
|
-
var mousePos = {};
|
|
1008
|
-
|
|
1009
|
-
if (Number(messageData.width) === 0 && Number(messageData.height) === 0) {
|
|
1010
|
-
var data = getMsgBody(9).split(':');
|
|
1011
|
-
mousePos = {
|
|
1012
|
-
x: data[1],
|
|
1013
|
-
y: data[0]
|
|
1014
|
-
};
|
|
1015
|
-
} else {
|
|
1016
|
-
mousePos = {
|
|
1017
|
-
x: messageData.width,
|
|
1018
|
-
y: messageData.height
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
on(event, {
|
|
1023
|
-
iframe: messageData.iframe,
|
|
1024
|
-
screenX: Number(mousePos.x),
|
|
1025
|
-
screenY: Number(mousePos.y),
|
|
1026
|
-
type: messageData.type
|
|
1027
|
-
});
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
function on(funcName, val) {
|
|
1031
|
-
return chkEvent(iframeId, funcName, val)
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
function actionMsg() {
|
|
1035
|
-
if (settings[iframeId] && settings[iframeId].firstRun) firstRun();
|
|
1036
|
-
|
|
1037
|
-
switch (messageData.type) {
|
|
1038
|
-
case 'close': {
|
|
1039
|
-
closeIFrame(messageData.iframe);
|
|
1040
|
-
break
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
case 'message': {
|
|
1044
|
-
forwardMsgFromIFrame(getMsgBody(6));
|
|
1045
|
-
break
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
case 'mouseenter': {
|
|
1049
|
-
onMouse('onMouseEnter');
|
|
1050
|
-
break
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
case 'mouseleave': {
|
|
1054
|
-
onMouse('onMouseLeave');
|
|
1055
|
-
break
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
case 'autoResize': {
|
|
1059
|
-
settings[iframeId].autoResize = JSON.parse(getMsgBody(9));
|
|
1060
|
-
break
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
case 'scrollTo': {
|
|
1064
|
-
scrollRequestFromChild(false);
|
|
1065
|
-
break
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
case 'scrollToOffset': {
|
|
1069
|
-
scrollRequestFromChild(true);
|
|
1070
|
-
break
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
case 'pageInfo': {
|
|
1074
|
-
sendPageInfoToIframe(
|
|
1075
|
-
settings[iframeId] && settings[iframeId].iframe,
|
|
1076
|
-
iframeId
|
|
1077
|
-
);
|
|
1078
|
-
startPageInfoMonitor();
|
|
1079
|
-
break
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
case 'pageInfoStop': {
|
|
1083
|
-
stopPageInfoMonitor();
|
|
1084
|
-
break
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
case 'inPageLink': {
|
|
1088
|
-
findTarget(getMsgBody(9));
|
|
1089
|
-
break
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
case 'reset': {
|
|
1093
|
-
resetIFrame(messageData);
|
|
1094
|
-
break
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
case 'init': {
|
|
1098
|
-
resizeIFrame();
|
|
1099
|
-
on('onInit', messageData.iframe);
|
|
1100
|
-
break
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
default: {
|
|
1104
|
-
if (
|
|
1105
|
-
Number(messageData.width) === 0 &&
|
|
1106
|
-
Number(messageData.height) === 0
|
|
1107
|
-
) {
|
|
1108
|
-
warn(
|
|
1109
|
-
'Unsupported message received (' +
|
|
1110
|
-
messageData.type +
|
|
1111
|
-
'), this is likely due to the iframe containing a later ' +
|
|
1112
|
-
'version of iframe-resizer than the parent page'
|
|
1113
|
-
);
|
|
1114
|
-
} else {
|
|
1115
|
-
resizeIFrame();
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
function hasSettings(iframeId) {
|
|
1122
|
-
var retBool = true;
|
|
1123
|
-
|
|
1124
|
-
if (!settings[iframeId]) {
|
|
1125
|
-
retBool = false;
|
|
1126
|
-
warn(
|
|
1127
|
-
messageData.type +
|
|
1128
|
-
' No settings for ' +
|
|
1129
|
-
iframeId +
|
|
1130
|
-
'. Message was: ' +
|
|
1131
|
-
msg
|
|
1132
|
-
);
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
return retBool
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
function iFrameReadyMsgReceived() {
|
|
1139
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
1140
|
-
for (var iframeId in settings) {
|
|
1141
|
-
trigger(
|
|
1142
|
-
'iFrame requested init',
|
|
1143
|
-
createOutgoingMsg(iframeId),
|
|
1144
|
-
settings[iframeId].iframe,
|
|
1145
|
-
iframeId
|
|
1146
|
-
);
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
function firstRun() {
|
|
1151
|
-
if (settings[iframeId]) {
|
|
1152
|
-
settings[iframeId].firstRun = false;
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
var msg = event.data,
|
|
1157
|
-
messageData = {},
|
|
1158
|
-
iframeId = null;
|
|
1159
|
-
|
|
1160
|
-
if ('[iFrameResizerChild]Ready' === msg) {
|
|
1161
|
-
iFrameReadyMsgReceived();
|
|
1162
|
-
} else if (isMessageForUs()) {
|
|
1163
|
-
messageData = processMsg();
|
|
1164
|
-
iframeId = messageData.id;
|
|
1165
|
-
if (settings[iframeId]) {
|
|
1166
|
-
settings[iframeId].loaded = true;
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
|
-
if (!isMessageFromMetaParent() && hasSettings(iframeId)) {
|
|
1170
|
-
log(iframeId, 'Received: ' + msg);
|
|
1171
|
-
|
|
1172
|
-
if (checkIFrameExists() && isMessageFromIFrame()) {
|
|
1173
|
-
actionMsg();
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
} else {
|
|
1177
|
-
info(iframeId, 'Ignored: ' + msg);
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
function chkEvent(iframeId, funcName, val) {
|
|
1182
|
-
var func = null,
|
|
1183
|
-
retVal = null;
|
|
1184
|
-
|
|
1185
|
-
if (settings[iframeId]) {
|
|
1186
|
-
func = settings[iframeId][funcName];
|
|
1187
|
-
|
|
1188
|
-
if ('function' === typeof func) {
|
|
1189
|
-
retVal = func(val);
|
|
1190
|
-
} else {
|
|
1191
|
-
throw new TypeError(
|
|
1192
|
-
funcName + ' on iFrame[' + iframeId + '] is not a function'
|
|
1193
|
-
)
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
return retVal
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
function removeIframeListeners(iframe) {
|
|
1201
|
-
var iframeId = iframe.id;
|
|
1202
|
-
delete settings[iframeId];
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
function closeIFrame(iframe) {
|
|
1206
|
-
var iframeId = iframe.id;
|
|
1207
|
-
if (chkEvent(iframeId, 'onClose', iframeId) === false) {
|
|
1208
|
-
log(iframeId, 'Close iframe cancelled by onClose event');
|
|
1209
|
-
return
|
|
1210
|
-
}
|
|
1211
|
-
log(iframeId, 'Removing iFrame: ' + iframeId);
|
|
1212
|
-
|
|
1213
|
-
try {
|
|
1214
|
-
// Catch race condition error with React
|
|
1215
|
-
if (iframe.parentNode) {
|
|
1216
|
-
iframe.parentNode.removeChild(iframe);
|
|
1217
|
-
}
|
|
1218
|
-
} catch (error) {
|
|
1219
|
-
warn(error);
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
chkEvent(iframeId, 'onClosed', iframeId);
|
|
1223
|
-
log(iframeId, '--');
|
|
1224
|
-
removeIframeListeners(iframe);
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
function getPagePosition(iframeId) {
|
|
1228
|
-
if (null === pagePosition) {
|
|
1229
|
-
pagePosition = {
|
|
1230
|
-
x:
|
|
1231
|
-
window.pageXOffset === undefined$1
|
|
1232
|
-
? document.documentElement.scrollLeft
|
|
1233
|
-
: window.pageXOffset,
|
|
1234
|
-
y:
|
|
1235
|
-
window.pageYOffset === undefined$1
|
|
1236
|
-
? document.documentElement.scrollTop
|
|
1237
|
-
: window.pageYOffset
|
|
1238
|
-
};
|
|
1239
|
-
log(
|
|
1240
|
-
iframeId,
|
|
1241
|
-
'Get page position: ' + pagePosition.x + ',' + pagePosition.y
|
|
1242
|
-
);
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
function setPagePosition(iframeId) {
|
|
1247
|
-
if (null !== pagePosition) {
|
|
1248
|
-
window.scrollTo(pagePosition.x, pagePosition.y);
|
|
1249
|
-
log(
|
|
1250
|
-
iframeId,
|
|
1251
|
-
'Set page position: ' + pagePosition.x + ',' + pagePosition.y
|
|
1252
|
-
);
|
|
1253
|
-
unsetPagePosition();
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
function unsetPagePosition() {
|
|
1258
|
-
pagePosition = null;
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
function resetIFrame(messageData) {
|
|
1262
|
-
function reset() {
|
|
1263
|
-
setSize(messageData);
|
|
1264
|
-
trigger('reset', 'reset', messageData.iframe, messageData.id);
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
log(
|
|
1268
|
-
messageData.id,
|
|
1269
|
-
'Size reset requested by ' +
|
|
1270
|
-
('init' === messageData.type ? 'host page' : 'iFrame')
|
|
1271
|
-
);
|
|
1272
|
-
getPagePosition(messageData.id);
|
|
1273
|
-
syncResize(reset, messageData, 'reset');
|
|
1274
|
-
}
|
|
1275
|
-
|
|
1276
|
-
function setSize(messageData) {
|
|
1277
|
-
function setDimension(dimension) {
|
|
1278
|
-
if (!messageData.id) {
|
|
1279
|
-
log('undefined', 'messageData id not set');
|
|
1280
|
-
return
|
|
1281
|
-
}
|
|
1282
|
-
messageData.iframe.style[dimension] = messageData[dimension] + 'px';
|
|
1283
|
-
log(
|
|
1284
|
-
messageData.id,
|
|
1285
|
-
'IFrame (' +
|
|
1286
|
-
iframeId +
|
|
1287
|
-
') ' +
|
|
1288
|
-
dimension +
|
|
1289
|
-
' set to ' +
|
|
1290
|
-
messageData[dimension] +
|
|
1291
|
-
'px'
|
|
1292
|
-
);
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
function chkZero(dimension) {
|
|
1296
|
-
// FireFox sets dimension of hidden iFrames to zero.
|
|
1297
|
-
// So if we detect that set up an event to check for
|
|
1298
|
-
// when iFrame becomes visible.
|
|
1299
|
-
|
|
1300
|
-
/* istanbul ignore next */ // Not testable in PhantomJS
|
|
1301
|
-
if (!hiddenCheckEnabled && '0' === messageData[dimension]) {
|
|
1302
|
-
hiddenCheckEnabled = true;
|
|
1303
|
-
log(iframeId, 'Hidden iFrame detected, creating visibility listener');
|
|
1304
|
-
fixHiddenIFrames();
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
function processDimension(dimension) {
|
|
1309
|
-
setDimension(dimension);
|
|
1310
|
-
chkZero(dimension);
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
var iframeId = messageData.iframe.id;
|
|
1314
|
-
|
|
1315
|
-
if (settings[iframeId]) {
|
|
1316
|
-
if (settings[iframeId].sizeHeight) {
|
|
1317
|
-
processDimension('height');
|
|
1318
|
-
}
|
|
1319
|
-
if (settings[iframeId].sizeWidth) {
|
|
1320
|
-
processDimension('width');
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
|
-
function syncResize(func, messageData, doNotSync) {
|
|
1326
|
-
/* istanbul ignore if */ // Not testable in PhantomJS
|
|
1327
|
-
if (
|
|
1328
|
-
doNotSync !== messageData.type &&
|
|
1329
|
-
requestAnimationFrame &&
|
|
1330
|
-
// including check for jasmine because had trouble getting spy to work in unit test using requestAnimationFrame
|
|
1331
|
-
!window.jasmine
|
|
1332
|
-
) {
|
|
1333
|
-
log(messageData.id, 'Requesting animation frame');
|
|
1334
|
-
requestAnimationFrame(func);
|
|
1335
|
-
} else {
|
|
1336
|
-
func();
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
function trigger(calleeMsg, msg, iframe, id, noResponseWarning) {
|
|
1341
|
-
function postMessageToIFrame() {
|
|
1342
|
-
var target = settings[id] && settings[id].targetOrigin;
|
|
1343
|
-
log(
|
|
1344
|
-
id,
|
|
1345
|
-
'[' +
|
|
1346
|
-
calleeMsg +
|
|
1347
|
-
'] Sending msg to iframe[' +
|
|
1348
|
-
id +
|
|
1349
|
-
'] (' +
|
|
1350
|
-
msg +
|
|
1351
|
-
') targetOrigin: ' +
|
|
1352
|
-
target
|
|
1353
|
-
);
|
|
1354
|
-
iframe.contentWindow.postMessage(msgId + msg, target);
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
function iFrameNotFound() {
|
|
1358
|
-
warn(id, '[' + calleeMsg + '] IFrame(' + id + ') not found');
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
function chkAndSend() {
|
|
1362
|
-
if (
|
|
1363
|
-
iframe &&
|
|
1364
|
-
'contentWindow' in iframe &&
|
|
1365
|
-
null !== iframe.contentWindow
|
|
1366
|
-
) {
|
|
1367
|
-
// Null test for PhantomJS
|
|
1368
|
-
postMessageToIFrame();
|
|
1369
|
-
} else {
|
|
1370
|
-
iFrameNotFound();
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
function warnOnNoResponse() {
|
|
1375
|
-
function warning() {
|
|
1376
|
-
if (settings[id] && !settings[id].loaded && !errorShown) {
|
|
1377
|
-
errorShown = true;
|
|
1378
|
-
warn(
|
|
1379
|
-
id,
|
|
1380
|
-
'IFrame has not responded within ' +
|
|
1381
|
-
settings[id].warningTimeout / 1000 +
|
|
1382
|
-
' seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ignored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning.'
|
|
1383
|
-
);
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
if (
|
|
1388
|
-
!!noResponseWarning &&
|
|
1389
|
-
settings[id] &&
|
|
1390
|
-
!!settings[id].warningTimeout
|
|
1391
|
-
) {
|
|
1392
|
-
settings[id].msgTimeout = setTimeout(
|
|
1393
|
-
warning,
|
|
1394
|
-
settings[id].warningTimeout
|
|
1395
|
-
);
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
var errorShown = false;
|
|
1400
|
-
|
|
1401
|
-
id = id || iframe.id;
|
|
1402
|
-
|
|
1403
|
-
if (settings[id]) {
|
|
1404
|
-
chkAndSend();
|
|
1405
|
-
warnOnNoResponse();
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
function createOutgoingMsg(iframeId) {
|
|
1410
|
-
return (
|
|
1411
|
-
iframeId +
|
|
1412
|
-
':' +
|
|
1413
|
-
settings[iframeId].bodyMarginV1 +
|
|
1414
|
-
':' +
|
|
1415
|
-
settings[iframeId].sizeWidth +
|
|
1416
|
-
':' +
|
|
1417
|
-
settings[iframeId].log +
|
|
1418
|
-
':' +
|
|
1419
|
-
settings[iframeId].interval +
|
|
1420
|
-
':' +
|
|
1421
|
-
settings[iframeId].enablePublicMethods +
|
|
1422
|
-
':' +
|
|
1423
|
-
settings[iframeId].autoResize +
|
|
1424
|
-
':' +
|
|
1425
|
-
settings[iframeId].bodyMargin +
|
|
1426
|
-
':' +
|
|
1427
|
-
settings[iframeId].heightCalculationMethod +
|
|
1428
|
-
':' +
|
|
1429
|
-
settings[iframeId].bodyBackground +
|
|
1430
|
-
':' +
|
|
1431
|
-
settings[iframeId].bodyPadding +
|
|
1432
|
-
':' +
|
|
1433
|
-
settings[iframeId].tolerance +
|
|
1434
|
-
':' +
|
|
1435
|
-
settings[iframeId].inPageLinks +
|
|
1436
|
-
':' +
|
|
1437
|
-
settings[iframeId].resizeFrom +
|
|
1438
|
-
':' +
|
|
1439
|
-
settings[iframeId].widthCalculationMethod +
|
|
1440
|
-
':' +
|
|
1441
|
-
settings[iframeId].mouseEvents
|
|
1442
|
-
)
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
function isNumber(value) {
|
|
1446
|
-
return typeof value === 'number'
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
function setupIFrame(iframe, options) {
|
|
1450
|
-
function setLimits() {
|
|
1451
|
-
function addStyle(style) {
|
|
1452
|
-
var styleValue = settings[iframeId][style];
|
|
1453
|
-
if (Infinity !== styleValue && 0 !== styleValue) {
|
|
1454
|
-
iframe.style[style] = isNumber(styleValue)
|
|
1455
|
-
? styleValue + 'px'
|
|
1456
|
-
: styleValue;
|
|
1457
|
-
log(iframeId, 'Set ' + style + ' = ' + iframe.style[style]);
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
function chkMinMax(dimension) {
|
|
1462
|
-
if (
|
|
1463
|
-
settings[iframeId]['min' + dimension] >
|
|
1464
|
-
settings[iframeId]['max' + dimension]
|
|
1465
|
-
) {
|
|
1466
|
-
throw new Error(
|
|
1467
|
-
'Value for min' +
|
|
1468
|
-
dimension +
|
|
1469
|
-
' can not be greater than max' +
|
|
1470
|
-
dimension
|
|
1471
|
-
)
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
chkMinMax('Height');
|
|
1476
|
-
chkMinMax('Width');
|
|
1477
|
-
|
|
1478
|
-
addStyle('maxHeight');
|
|
1479
|
-
addStyle('minHeight');
|
|
1480
|
-
addStyle('maxWidth');
|
|
1481
|
-
addStyle('minWidth');
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
function newId() {
|
|
1485
|
-
var id = (options && options.id) || defaults.id + count++;
|
|
1486
|
-
if (null !== document.getElementById(id)) {
|
|
1487
|
-
id += count++;
|
|
1488
|
-
}
|
|
1489
|
-
return id
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
|
-
function ensureHasId(iframeId) {
|
|
1493
|
-
if (typeof iframeId !== 'string') {
|
|
1494
|
-
throw new TypeError('Invaild id for iFrame. Expected String')
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
if ('' === iframeId) {
|
|
1498
|
-
// eslint-disable-next-line no-multi-assign
|
|
1499
|
-
iframe.id = iframeId = newId();
|
|
1500
|
-
logEnabled = (options || {}).log;
|
|
1501
|
-
log(
|
|
1502
|
-
iframeId,
|
|
1503
|
-
'Added missing iframe ID: ' + iframeId + ' (' + iframe.src + ')'
|
|
1504
|
-
);
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
return iframeId
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
function setScrolling() {
|
|
1511
|
-
log(
|
|
1512
|
-
iframeId,
|
|
1513
|
-
'IFrame scrolling ' +
|
|
1514
|
-
(settings[iframeId] && settings[iframeId].scrolling
|
|
1515
|
-
? 'enabled'
|
|
1516
|
-
: 'disabled') +
|
|
1517
|
-
' for ' +
|
|
1518
|
-
iframeId
|
|
1519
|
-
);
|
|
1520
|
-
iframe.style.overflow =
|
|
1521
|
-
false === (settings[iframeId] && settings[iframeId].scrolling)
|
|
1522
|
-
? 'hidden'
|
|
1523
|
-
: 'auto';
|
|
1524
|
-
switch (settings[iframeId] && settings[iframeId].scrolling) {
|
|
1525
|
-
case 'omit': {
|
|
1526
|
-
break
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
case true: {
|
|
1530
|
-
iframe.scrolling = 'yes';
|
|
1531
|
-
break
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
case false: {
|
|
1535
|
-
iframe.scrolling = 'no';
|
|
1536
|
-
break
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
|
-
default: {
|
|
1540
|
-
iframe.scrolling = settings[iframeId]
|
|
1541
|
-
? settings[iframeId].scrolling
|
|
1542
|
-
: 'no';
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
// The V1 iFrame script expects an int, where as in V2 expects a CSS
|
|
1548
|
-
// string value such as '1px 3em', so if we have an int for V2, set V1=V2
|
|
1549
|
-
// and then convert V2 to a string PX value.
|
|
1550
|
-
function setupBodyMarginValues() {
|
|
1551
|
-
if (
|
|
1552
|
-
'number' ===
|
|
1553
|
-
typeof (settings[iframeId] && settings[iframeId].bodyMargin) ||
|
|
1554
|
-
'0' === (settings[iframeId] && settings[iframeId].bodyMargin)
|
|
1555
|
-
) {
|
|
1556
|
-
settings[iframeId].bodyMarginV1 = settings[iframeId].bodyMargin;
|
|
1557
|
-
settings[iframeId].bodyMargin =
|
|
1558
|
-
'' + settings[iframeId].bodyMargin + 'px';
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
function checkReset() {
|
|
1563
|
-
// Reduce scope of firstRun to function, because IE8's JS execution
|
|
1564
|
-
// context stack is borked and this value gets externally
|
|
1565
|
-
// changed midway through running this function!!!
|
|
1566
|
-
var firstRun = settings[iframeId] && settings[iframeId].firstRun,
|
|
1567
|
-
resetRequertMethod =
|
|
1568
|
-
settings[iframeId] &&
|
|
1569
|
-
settings[iframeId].heightCalculationMethod in resetRequiredMethods;
|
|
1570
|
-
|
|
1571
|
-
if (!firstRun && resetRequertMethod) {
|
|
1572
|
-
resetIFrame({ iframe: iframe, height: 0, width: 0, type: 'init' });
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
function setupIFrameObject() {
|
|
1577
|
-
if (settings[iframeId]) {
|
|
1578
|
-
settings[iframeId].iframe.iFrameResizer = {
|
|
1579
|
-
close: closeIFrame.bind(null, settings[iframeId].iframe),
|
|
1580
|
-
|
|
1581
|
-
removeListeners: removeIframeListeners.bind(
|
|
1582
|
-
null,
|
|
1583
|
-
settings[iframeId].iframe
|
|
1584
|
-
),
|
|
1585
|
-
|
|
1586
|
-
resize: trigger.bind(
|
|
1587
|
-
null,
|
|
1588
|
-
'Window resize',
|
|
1589
|
-
'resize',
|
|
1590
|
-
settings[iframeId].iframe
|
|
1591
|
-
),
|
|
1592
|
-
|
|
1593
|
-
moveToAnchor: function (anchor) {
|
|
1594
|
-
trigger(
|
|
1595
|
-
'Move to anchor',
|
|
1596
|
-
'moveToAnchor:' + anchor,
|
|
1597
|
-
settings[iframeId].iframe,
|
|
1598
|
-
iframeId
|
|
1599
|
-
);
|
|
1600
|
-
},
|
|
1601
|
-
|
|
1602
|
-
sendMessage: function (message) {
|
|
1603
|
-
message = JSON.stringify(message);
|
|
1604
|
-
trigger(
|
|
1605
|
-
'Send Message',
|
|
1606
|
-
'message:' + message,
|
|
1607
|
-
settings[iframeId].iframe,
|
|
1608
|
-
iframeId
|
|
1609
|
-
);
|
|
1610
|
-
}
|
|
1611
|
-
};
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
// We have to call trigger twice, as we can not be sure if all
|
|
1616
|
-
// iframes have completed loading when this code runs. The
|
|
1617
|
-
// event listener also catches the page changing in the iFrame.
|
|
1618
|
-
function init(msg) {
|
|
1619
|
-
function iFrameLoaded() {
|
|
1620
|
-
trigger('iFrame.onload', msg, iframe, undefined$1, true);
|
|
1621
|
-
checkReset();
|
|
1622
|
-
}
|
|
1623
|
-
|
|
1624
|
-
function createDestroyObserver(MutationObserver) {
|
|
1625
|
-
if (!iframe.parentNode) {
|
|
1626
|
-
return
|
|
1627
|
-
}
|
|
1628
|
-
|
|
1629
|
-
var destroyObserver = new MutationObserver(function (mutations) {
|
|
1630
|
-
mutations.forEach(function (mutation) {
|
|
1631
|
-
var removedNodes = Array.prototype.slice.call(mutation.removedNodes); // Transform NodeList into an Array
|
|
1632
|
-
removedNodes.forEach(function (removedNode) {
|
|
1633
|
-
if (removedNode === iframe) {
|
|
1634
|
-
closeIFrame(iframe);
|
|
1635
|
-
}
|
|
1636
|
-
});
|
|
1637
|
-
});
|
|
1638
|
-
});
|
|
1639
|
-
destroyObserver.observe(iframe.parentNode, {
|
|
1640
|
-
childList: true
|
|
1641
|
-
});
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
var MutationObserver = getMutationObserver();
|
|
1645
|
-
if (MutationObserver) {
|
|
1646
|
-
createDestroyObserver(MutationObserver);
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
|
-
addEventListener(iframe, 'load', iFrameLoaded);
|
|
1650
|
-
trigger('init', msg, iframe, undefined$1, true);
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
function checkOptions(options) {
|
|
1654
|
-
if ('object' !== typeof options) {
|
|
1655
|
-
throw new TypeError('Options is not an object')
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
function copyOptions(options) {
|
|
1660
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
1661
|
-
for (var option in defaults) {
|
|
1662
|
-
if (Object.prototype.hasOwnProperty.call(defaults, option)) {
|
|
1663
|
-
settings[iframeId][option] = Object.prototype.hasOwnProperty.call(
|
|
1664
|
-
options,
|
|
1665
|
-
option
|
|
1666
|
-
)
|
|
1667
|
-
? options[option]
|
|
1668
|
-
: defaults[option];
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
function getTargetOrigin(remoteHost) {
|
|
1674
|
-
return '' === remoteHost ||
|
|
1675
|
-
null !== remoteHost.match(/^(about:blank|javascript:|file:\/\/)/)
|
|
1676
|
-
? '*'
|
|
1677
|
-
: remoteHost
|
|
1678
|
-
}
|
|
1679
|
-
|
|
1680
|
-
function depricate(key) {
|
|
1681
|
-
var splitName = key.split('Callback');
|
|
1682
|
-
|
|
1683
|
-
if (splitName.length === 2) {
|
|
1684
|
-
var name =
|
|
1685
|
-
'on' + splitName[0].charAt(0).toUpperCase() + splitName[0].slice(1);
|
|
1686
|
-
this[name] = this[key];
|
|
1687
|
-
delete this[key];
|
|
1688
|
-
warn(
|
|
1689
|
-
iframeId,
|
|
1690
|
-
"Deprecated: '" +
|
|
1691
|
-
key +
|
|
1692
|
-
"' has been renamed '" +
|
|
1693
|
-
name +
|
|
1694
|
-
"'. The old method will be removed in the next major version."
|
|
1695
|
-
);
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
|
|
1699
|
-
function processOptions(options) {
|
|
1700
|
-
options = options || {};
|
|
1701
|
-
|
|
1702
|
-
settings[iframeId] = Object.create(null); // Protect against prototype attacks
|
|
1703
|
-
settings[iframeId].iframe = iframe;
|
|
1704
|
-
settings[iframeId].firstRun = true;
|
|
1705
|
-
settings[iframeId].remoteHost =
|
|
1706
|
-
iframe.src && iframe.src.split('/').slice(0, 3).join('/');
|
|
1707
|
-
|
|
1708
|
-
checkOptions(options);
|
|
1709
|
-
Object.keys(options).forEach(depricate, options);
|
|
1710
|
-
copyOptions(options);
|
|
1711
|
-
|
|
1712
|
-
if (settings[iframeId]) {
|
|
1713
|
-
settings[iframeId].targetOrigin =
|
|
1714
|
-
true === settings[iframeId].checkOrigin
|
|
1715
|
-
? getTargetOrigin(settings[iframeId].remoteHost)
|
|
1716
|
-
: '*';
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
|
|
1720
|
-
function beenHere() {
|
|
1721
|
-
return iframeId in settings && 'iFrameResizer' in iframe
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
var iframeId = ensureHasId(iframe.id);
|
|
1725
|
-
|
|
1726
|
-
if (beenHere()) {
|
|
1727
|
-
warn(iframeId, 'Ignored iFrame, already setup.');
|
|
1728
|
-
} else {
|
|
1729
|
-
processOptions(options);
|
|
1730
|
-
setScrolling();
|
|
1731
|
-
setLimits();
|
|
1732
|
-
setupBodyMarginValues();
|
|
1733
|
-
init(createOutgoingMsg(iframeId));
|
|
1734
|
-
setupIFrameObject();
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
function debouce(fn, time) {
|
|
1739
|
-
if (null === timer) {
|
|
1740
|
-
timer = setTimeout(function () {
|
|
1741
|
-
timer = null;
|
|
1742
|
-
fn();
|
|
1743
|
-
}, time);
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
var frameTimer = {};
|
|
1748
|
-
function debounceFrameEvents(fn, time, frameId) {
|
|
1749
|
-
if (!frameTimer[frameId]) {
|
|
1750
|
-
frameTimer[frameId] = setTimeout(function () {
|
|
1751
|
-
frameTimer[frameId] = null;
|
|
1752
|
-
fn();
|
|
1753
|
-
}, time);
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
|
-
// Not testable in PhantomJS
|
|
1758
|
-
/* istanbul ignore next */
|
|
1759
|
-
|
|
1760
|
-
function fixHiddenIFrames() {
|
|
1761
|
-
function checkIFrames() {
|
|
1762
|
-
function checkIFrame(settingId) {
|
|
1763
|
-
function chkDimension(dimension) {
|
|
1764
|
-
return (
|
|
1765
|
-
'0px' ===
|
|
1766
|
-
(settings[settingId] && settings[settingId].iframe.style[dimension])
|
|
1767
|
-
)
|
|
1768
|
-
}
|
|
1769
|
-
|
|
1770
|
-
function isVisible(el) {
|
|
1771
|
-
return null !== el.offsetParent
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
if (
|
|
1775
|
-
settings[settingId] &&
|
|
1776
|
-
isVisible(settings[settingId].iframe) &&
|
|
1777
|
-
(chkDimension('height') || chkDimension('width'))
|
|
1778
|
-
) {
|
|
1779
|
-
trigger(
|
|
1780
|
-
'Visibility change',
|
|
1781
|
-
'resize',
|
|
1782
|
-
settings[settingId].iframe,
|
|
1783
|
-
settingId
|
|
1784
|
-
);
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
Object.keys(settings).forEach(function (key) {
|
|
1789
|
-
checkIFrame(key);
|
|
1790
|
-
});
|
|
1791
|
-
}
|
|
1792
|
-
|
|
1793
|
-
function mutationObserved(mutations) {
|
|
1794
|
-
log(
|
|
1795
|
-
'window',
|
|
1796
|
-
'Mutation observed: ' + mutations[0].target + ' ' + mutations[0].type
|
|
1797
|
-
);
|
|
1798
|
-
debouce(checkIFrames, 16);
|
|
1799
|
-
}
|
|
1800
|
-
|
|
1801
|
-
function createMutationObserver() {
|
|
1802
|
-
var target = document.querySelector('body'),
|
|
1803
|
-
config = {
|
|
1804
|
-
attributes: true,
|
|
1805
|
-
attributeOldValue: false,
|
|
1806
|
-
characterData: true,
|
|
1807
|
-
characterDataOldValue: false,
|
|
1808
|
-
childList: true,
|
|
1809
|
-
subtree: true
|
|
1810
|
-
},
|
|
1811
|
-
observer = new MutationObserver(mutationObserved);
|
|
1812
|
-
|
|
1813
|
-
observer.observe(target, config);
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
var MutationObserver = getMutationObserver();
|
|
1817
|
-
if (MutationObserver) {
|
|
1818
|
-
createMutationObserver();
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
function resizeIFrames(event) {
|
|
1823
|
-
function resize() {
|
|
1824
|
-
sendTriggerMsg('Window ' + event, 'resize');
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
|
-
log('window', 'Trigger event: ' + event);
|
|
1828
|
-
debouce(resize, 16);
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
// Not testable in PhantomJS
|
|
1832
|
-
/* istanbul ignore next */
|
|
1833
|
-
function tabVisible() {
|
|
1834
|
-
function resize() {
|
|
1835
|
-
sendTriggerMsg('Tab Visible', 'resize');
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
if ('hidden' !== document.visibilityState) {
|
|
1839
|
-
log('document', 'Trigger event: Visibility change');
|
|
1840
|
-
debouce(resize, 16);
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
function sendTriggerMsg(eventName, event) {
|
|
1845
|
-
function isIFrameResizeEnabled(iframeId) {
|
|
1846
|
-
return (
|
|
1847
|
-
settings[iframeId] &&
|
|
1848
|
-
'parent' === settings[iframeId].resizeFrom &&
|
|
1849
|
-
settings[iframeId].autoResize &&
|
|
1850
|
-
!settings[iframeId].firstRun
|
|
1851
|
-
)
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
Object.keys(settings).forEach(function (iframeId) {
|
|
1855
|
-
if (isIFrameResizeEnabled(iframeId)) {
|
|
1856
|
-
trigger(eventName, event, settings[iframeId].iframe, iframeId);
|
|
1857
|
-
}
|
|
1858
|
-
});
|
|
1859
|
-
}
|
|
1860
|
-
|
|
1861
|
-
function setupEventListeners() {
|
|
1862
|
-
addEventListener(window, 'message', iFrameListener);
|
|
1863
|
-
|
|
1864
|
-
addEventListener(window, 'resize', function () {
|
|
1865
|
-
resizeIFrames('resize');
|
|
1866
|
-
});
|
|
1867
|
-
|
|
1868
|
-
addEventListener(document, 'visibilitychange', tabVisible);
|
|
1869
|
-
|
|
1870
|
-
addEventListener(document, '-webkit-visibilitychange', tabVisible);
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
function factory() {
|
|
1874
|
-
function init(options, element) {
|
|
1875
|
-
function chkType() {
|
|
1876
|
-
if (!element.tagName) {
|
|
1877
|
-
throw new TypeError('Object is not a valid DOM element')
|
|
1878
|
-
} else if ('IFRAME' !== element.tagName.toUpperCase()) {
|
|
1879
|
-
throw new TypeError(
|
|
1880
|
-
'Expected <IFRAME> tag, found <' + element.tagName + '>'
|
|
1881
|
-
)
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
|
|
1885
|
-
if (element) {
|
|
1886
|
-
chkType();
|
|
1887
|
-
setupIFrame(element, options);
|
|
1888
|
-
iFrames.push(element);
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
|
|
1892
|
-
function warnDeprecatedOptions(options) {
|
|
1893
|
-
if (options && options.enablePublicMethods) {
|
|
1894
|
-
warn(
|
|
1895
|
-
'enablePublicMethods option has been removed, public methods are now always available in the iFrame'
|
|
1896
|
-
);
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
|
|
1900
|
-
var iFrames;
|
|
1901
|
-
|
|
1902
|
-
setupRequestAnimationFrame();
|
|
1903
|
-
setupEventListeners();
|
|
1904
|
-
|
|
1905
|
-
return function iFrameResizeF(options, target) {
|
|
1906
|
-
iFrames = []; // Only return iFrames past in on this call
|
|
1907
|
-
|
|
1908
|
-
warnDeprecatedOptions(options);
|
|
1909
|
-
|
|
1910
|
-
switch (typeof target) {
|
|
1911
|
-
case 'undefined':
|
|
1912
|
-
case 'string': {
|
|
1913
|
-
Array.prototype.forEach.call(
|
|
1914
|
-
document.querySelectorAll(target || 'iframe'),
|
|
1915
|
-
init.bind(undefined$1, options)
|
|
1916
|
-
);
|
|
1917
|
-
break
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
|
-
case 'object': {
|
|
1921
|
-
init(options, target);
|
|
1922
|
-
break
|
|
1923
|
-
}
|
|
1924
|
-
|
|
1925
|
-
default: {
|
|
1926
|
-
throw new TypeError('Unexpected data type (' + typeof target + ')')
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
return iFrames
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
function createJQueryPublicMethod($) {
|
|
1935
|
-
if (!$.fn) {
|
|
1936
|
-
info('', 'Unable to bind to jQuery, it is not fully loaded.');
|
|
1937
|
-
} else if (!$.fn.iFrameResize) {
|
|
1938
|
-
$.fn.iFrameResize = function $iFrameResizeF(options) {
|
|
1939
|
-
function init(index, element) {
|
|
1940
|
-
setupIFrame(element, options);
|
|
1941
|
-
}
|
|
1942
|
-
|
|
1943
|
-
return this.filter('iframe').each(init).end()
|
|
1944
|
-
};
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
|
|
1948
|
-
if (window.jQuery !== undefined$1) {
|
|
1949
|
-
createJQueryPublicMethod(window.jQuery);
|
|
1950
|
-
}
|
|
1951
|
-
|
|
1952
|
-
if (typeof define === 'function' && define.amd) {
|
|
1953
|
-
define([], factory);
|
|
1954
|
-
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
|
1955
|
-
// Node for browserfy
|
|
1956
|
-
module.exports = factory();
|
|
1957
|
-
}
|
|
1958
|
-
window.iFrameResize = window.iFrameResize || factory();
|
|
1959
|
-
})();
|
|
1960
|
-
|
|
1961
|
-
/*
|
|
1962
|
-
* File: iframeResizer.contentWindow.js
|
|
1963
|
-
* Desc: Include this file in any page being loaded into an iframe
|
|
1964
|
-
* to force the iframe to resize to the content size.
|
|
1965
|
-
* Requires: iframeResizer.js on host page.
|
|
1966
|
-
* Doc: https://github.com/davidjbradshaw/iframe-resizer
|
|
1967
|
-
* Author: David J. Bradshaw - dave@bradshaw.net
|
|
1968
|
-
*
|
|
1969
|
-
*/
|
|
1970
|
-
(function (undefined$1) {
|
|
1971
|
-
if (typeof window === 'undefined') return // don't run for server side render
|
|
1972
|
-
|
|
1973
|
-
var autoResize = true,
|
|
1974
|
-
base = 10,
|
|
1975
|
-
bodyBackground = '',
|
|
1976
|
-
bodyMargin = 0,
|
|
1977
|
-
bodyMarginStr = '',
|
|
1978
|
-
bodyObserver = null,
|
|
1979
|
-
bodyPadding = '',
|
|
1980
|
-
calculateWidth = false,
|
|
1981
|
-
doubleEventList = { resize: 1, click: 1 },
|
|
1982
|
-
eventCancelTimer = 128,
|
|
1983
|
-
firstRun = true,
|
|
1984
|
-
height = 1,
|
|
1985
|
-
heightCalcModeDefault = 'bodyOffset',
|
|
1986
|
-
heightCalcMode = heightCalcModeDefault,
|
|
1987
|
-
initLock = true,
|
|
1988
|
-
initMsg = '',
|
|
1989
|
-
inPageLinks = {},
|
|
1990
|
-
interval = 32,
|
|
1991
|
-
intervalTimer = null,
|
|
1992
|
-
logging = false,
|
|
1993
|
-
mouseEvents = false,
|
|
1994
|
-
msgID = '[iFrameSizer]', // Must match host page msg ID
|
|
1995
|
-
msgIdLen = msgID.length,
|
|
1996
|
-
myID = '',
|
|
1997
|
-
resetRequiredMethods = {
|
|
1998
|
-
max: 1,
|
|
1999
|
-
min: 1,
|
|
2000
|
-
bodyScroll: 1,
|
|
2001
|
-
documentElementScroll: 1
|
|
2002
|
-
},
|
|
2003
|
-
resizeFrom = 'child',
|
|
2004
|
-
target = window.parent,
|
|
2005
|
-
targetOriginDefault = '*',
|
|
2006
|
-
tolerance = 0,
|
|
2007
|
-
triggerLocked = false,
|
|
2008
|
-
triggerLockedTimer = null,
|
|
2009
|
-
throttledTimer = 16,
|
|
2010
|
-
width = 1,
|
|
2011
|
-
widthCalcModeDefault = 'scroll',
|
|
2012
|
-
widthCalcMode = widthCalcModeDefault,
|
|
2013
|
-
win = window,
|
|
2014
|
-
onMessage = function () {
|
|
2015
|
-
warn('onMessage function not defined');
|
|
2016
|
-
},
|
|
2017
|
-
onReady = function () {},
|
|
2018
|
-
onPageInfo = function () {},
|
|
2019
|
-
customCalcMethods = {
|
|
2020
|
-
height: function () {
|
|
2021
|
-
warn('Custom height calculation function not defined');
|
|
2022
|
-
return document.documentElement.offsetHeight
|
|
2023
|
-
},
|
|
2024
|
-
width: function () {
|
|
2025
|
-
warn('Custom width calculation function not defined');
|
|
2026
|
-
return document.body.scrollWidth
|
|
2027
|
-
}
|
|
2028
|
-
},
|
|
2029
|
-
eventHandlersByName = {},
|
|
2030
|
-
passiveSupported = false;
|
|
2031
|
-
|
|
2032
|
-
function noop() {}
|
|
2033
|
-
|
|
2034
|
-
try {
|
|
2035
|
-
var options = Object.create(
|
|
2036
|
-
{},
|
|
2037
|
-
{
|
|
2038
|
-
passive: {
|
|
2039
|
-
// eslint-disable-next-line getter-return
|
|
2040
|
-
get: function () {
|
|
2041
|
-
passiveSupported = true;
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
}
|
|
2045
|
-
);
|
|
2046
|
-
window.addEventListener('test', noop, options);
|
|
2047
|
-
window.removeEventListener('test', noop, options);
|
|
2048
|
-
} catch (error) {
|
|
2049
|
-
/* */
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
function addEventListener(el, evt, func, options) {
|
|
2053
|
-
el.addEventListener(evt, func, passiveSupported ? options || {} : false);
|
|
2054
|
-
}
|
|
2055
|
-
|
|
2056
|
-
function removeEventListener(el, evt, func) {
|
|
2057
|
-
el.removeEventListener(evt, func, false);
|
|
2058
|
-
}
|
|
2059
|
-
|
|
2060
|
-
function capitalizeFirstLetter(string) {
|
|
2061
|
-
return string.charAt(0).toUpperCase() + string.slice(1)
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
// Based on underscore.js
|
|
2065
|
-
function throttle(func) {
|
|
2066
|
-
var context,
|
|
2067
|
-
args,
|
|
2068
|
-
result,
|
|
2069
|
-
timeout = null,
|
|
2070
|
-
previous = 0,
|
|
2071
|
-
later = function () {
|
|
2072
|
-
previous = Date.now();
|
|
2073
|
-
timeout = null;
|
|
2074
|
-
result = func.apply(context, args);
|
|
2075
|
-
if (!timeout) {
|
|
2076
|
-
// eslint-disable-next-line no-multi-assign
|
|
2077
|
-
context = args = null;
|
|
2078
|
-
}
|
|
2079
|
-
};
|
|
2080
|
-
|
|
2081
|
-
return function () {
|
|
2082
|
-
var now = Date.now();
|
|
2083
|
-
|
|
2084
|
-
if (!previous) {
|
|
2085
|
-
previous = now;
|
|
2086
|
-
}
|
|
2087
|
-
|
|
2088
|
-
var remaining = throttledTimer - (now - previous);
|
|
2089
|
-
|
|
2090
|
-
context = this;
|
|
2091
|
-
args = arguments;
|
|
2092
|
-
|
|
2093
|
-
if (remaining <= 0 || remaining > throttledTimer) {
|
|
2094
|
-
if (timeout) {
|
|
2095
|
-
clearTimeout(timeout);
|
|
2096
|
-
timeout = null;
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
|
-
previous = now;
|
|
2100
|
-
result = func.apply(context, args);
|
|
2101
|
-
|
|
2102
|
-
if (!timeout) {
|
|
2103
|
-
// eslint-disable-next-line no-multi-assign
|
|
2104
|
-
context = args = null;
|
|
2105
|
-
}
|
|
2106
|
-
} else if (!timeout) {
|
|
2107
|
-
timeout = setTimeout(later, remaining);
|
|
2108
|
-
}
|
|
2109
|
-
|
|
2110
|
-
return result
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
function formatLogMsg(msg) {
|
|
2115
|
-
return msgID + '[' + myID + '] ' + msg
|
|
2116
|
-
}
|
|
2117
|
-
|
|
2118
|
-
function log(msg) {
|
|
2119
|
-
if (logging && 'object' === typeof window.console) {
|
|
2120
|
-
// eslint-disable-next-line no-console
|
|
2121
|
-
console.log(formatLogMsg(msg));
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2125
|
-
function warn(msg) {
|
|
2126
|
-
if ('object' === typeof window.console) {
|
|
2127
|
-
// eslint-disable-next-line no-console
|
|
2128
|
-
console.warn(formatLogMsg(msg));
|
|
2129
|
-
}
|
|
2130
|
-
}
|
|
2131
|
-
|
|
2132
|
-
function init() {
|
|
2133
|
-
readDataFromParent();
|
|
2134
|
-
log('Initialising iFrame (' + window.location.href + ')');
|
|
2135
|
-
readDataFromPage();
|
|
2136
|
-
setMargin();
|
|
2137
|
-
setBodyStyle('background', bodyBackground);
|
|
2138
|
-
setBodyStyle('padding', bodyPadding);
|
|
2139
|
-
injectClearFixIntoBodyElement();
|
|
2140
|
-
checkHeightMode();
|
|
2141
|
-
checkWidthMode();
|
|
2142
|
-
stopInfiniteResizingOfIFrame();
|
|
2143
|
-
setupPublicMethods();
|
|
2144
|
-
setupMouseEvents();
|
|
2145
|
-
startEventListeners();
|
|
2146
|
-
inPageLinks = setupInPageLinks();
|
|
2147
|
-
sendSize('init', 'Init message from host page');
|
|
2148
|
-
onReady();
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
function readDataFromParent() {
|
|
2152
|
-
function strBool(str) {
|
|
2153
|
-
return 'true' === str
|
|
2154
|
-
}
|
|
2155
|
-
|
|
2156
|
-
var data = initMsg.slice(msgIdLen).split(':');
|
|
2157
|
-
|
|
2158
|
-
myID = data[0];
|
|
2159
|
-
bodyMargin = undefined$1 === data[1] ? bodyMargin : Number(data[1]); // For V1 compatibility
|
|
2160
|
-
calculateWidth = undefined$1 === data[2] ? calculateWidth : strBool(data[2]);
|
|
2161
|
-
logging = undefined$1 === data[3] ? logging : strBool(data[3]);
|
|
2162
|
-
interval = undefined$1 === data[4] ? interval : Number(data[4]);
|
|
2163
|
-
autoResize = undefined$1 === data[6] ? autoResize : strBool(data[6]);
|
|
2164
|
-
bodyMarginStr = data[7];
|
|
2165
|
-
heightCalcMode = undefined$1 === data[8] ? heightCalcMode : data[8];
|
|
2166
|
-
bodyBackground = data[9];
|
|
2167
|
-
bodyPadding = data[10];
|
|
2168
|
-
tolerance = undefined$1 === data[11] ? tolerance : Number(data[11]);
|
|
2169
|
-
inPageLinks.enable = undefined$1 === data[12] ? false : strBool(data[12]);
|
|
2170
|
-
resizeFrom = undefined$1 === data[13] ? resizeFrom : data[13];
|
|
2171
|
-
widthCalcMode = undefined$1 === data[14] ? widthCalcMode : data[14];
|
|
2172
|
-
mouseEvents = undefined$1 === data[15] ? mouseEvents : strBool(data[15]);
|
|
2173
|
-
}
|
|
2174
|
-
|
|
2175
|
-
function depricate(key) {
|
|
2176
|
-
var splitName = key.split('Callback');
|
|
2177
|
-
|
|
2178
|
-
if (splitName.length === 2) {
|
|
2179
|
-
var name =
|
|
2180
|
-
'on' + splitName[0].charAt(0).toUpperCase() + splitName[0].slice(1);
|
|
2181
|
-
this[name] = this[key];
|
|
2182
|
-
delete this[key];
|
|
2183
|
-
warn(
|
|
2184
|
-
"Deprecated: '" +
|
|
2185
|
-
key +
|
|
2186
|
-
"' has been renamed '" +
|
|
2187
|
-
name +
|
|
2188
|
-
"'. The old method will be removed in the next major version."
|
|
2189
|
-
);
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
|
|
2193
|
-
function readDataFromPage() {
|
|
2194
|
-
function readData() {
|
|
2195
|
-
var data = window.iFrameResizer;
|
|
2196
|
-
|
|
2197
|
-
log('Reading data from page: ' + JSON.stringify(data));
|
|
2198
|
-
Object.keys(data).forEach(depricate, data);
|
|
2199
|
-
|
|
2200
|
-
onMessage = 'onMessage' in data ? data.onMessage : onMessage;
|
|
2201
|
-
onReady = 'onReady' in data ? data.onReady : onReady;
|
|
2202
|
-
targetOriginDefault =
|
|
2203
|
-
'targetOrigin' in data ? data.targetOrigin : targetOriginDefault;
|
|
2204
|
-
heightCalcMode =
|
|
2205
|
-
'heightCalculationMethod' in data
|
|
2206
|
-
? data.heightCalculationMethod
|
|
2207
|
-
: heightCalcMode;
|
|
2208
|
-
widthCalcMode =
|
|
2209
|
-
'widthCalculationMethod' in data
|
|
2210
|
-
? data.widthCalculationMethod
|
|
2211
|
-
: widthCalcMode;
|
|
2212
|
-
}
|
|
2213
|
-
|
|
2214
|
-
function setupCustomCalcMethods(calcMode, calcFunc) {
|
|
2215
|
-
if ('function' === typeof calcMode) {
|
|
2216
|
-
log('Setup custom ' + calcFunc + 'CalcMethod');
|
|
2217
|
-
customCalcMethods[calcFunc] = calcMode;
|
|
2218
|
-
calcMode = 'custom';
|
|
2219
|
-
}
|
|
2220
|
-
|
|
2221
|
-
return calcMode
|
|
2222
|
-
}
|
|
2223
|
-
|
|
2224
|
-
if (
|
|
2225
|
-
'iFrameResizer' in window &&
|
|
2226
|
-
Object === window.iFrameResizer.constructor
|
|
2227
|
-
) {
|
|
2228
|
-
readData();
|
|
2229
|
-
heightCalcMode = setupCustomCalcMethods(heightCalcMode, 'height');
|
|
2230
|
-
widthCalcMode = setupCustomCalcMethods(widthCalcMode, 'width');
|
|
2231
|
-
}
|
|
2232
|
-
|
|
2233
|
-
log('TargetOrigin for parent set to: ' + targetOriginDefault);
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2236
|
-
function chkCSS(attr, value) {
|
|
2237
|
-
if (-1 !== value.indexOf('-')) {
|
|
2238
|
-
warn('Negative CSS value ignored for ' + attr);
|
|
2239
|
-
value = '';
|
|
2240
|
-
}
|
|
2241
|
-
return value
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
|
-
function setBodyStyle(attr, value) {
|
|
2245
|
-
if (undefined$1 !== value && '' !== value && 'null' !== value) {
|
|
2246
|
-
document.body.style[attr] = value;
|
|
2247
|
-
log('Body ' + attr + ' set to "' + value + '"');
|
|
2248
|
-
}
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
function setMargin() {
|
|
2252
|
-
// If called via V1 script, convert bodyMargin from int to str
|
|
2253
|
-
if (undefined$1 === bodyMarginStr) {
|
|
2254
|
-
bodyMarginStr = bodyMargin + 'px';
|
|
2255
|
-
}
|
|
2256
|
-
|
|
2257
|
-
setBodyStyle('margin', chkCSS('margin', bodyMarginStr));
|
|
2258
|
-
}
|
|
2259
|
-
|
|
2260
|
-
function stopInfiniteResizingOfIFrame() {
|
|
2261
|
-
document.documentElement.style.height = '';
|
|
2262
|
-
document.body.style.height = '';
|
|
2263
|
-
log('HTML & body height set to "auto"');
|
|
2264
|
-
}
|
|
2265
|
-
|
|
2266
|
-
function manageTriggerEvent(options) {
|
|
2267
|
-
var listener = {
|
|
2268
|
-
add: function (eventName) {
|
|
2269
|
-
function handleEvent() {
|
|
2270
|
-
sendSize(options.eventName, options.eventType);
|
|
2271
|
-
}
|
|
2272
|
-
|
|
2273
|
-
eventHandlersByName[eventName] = handleEvent;
|
|
2274
|
-
|
|
2275
|
-
addEventListener(window, eventName, handleEvent, { passive: true });
|
|
2276
|
-
},
|
|
2277
|
-
remove: function (eventName) {
|
|
2278
|
-
var handleEvent = eventHandlersByName[eventName];
|
|
2279
|
-
delete eventHandlersByName[eventName];
|
|
2280
|
-
|
|
2281
|
-
removeEventListener(window, eventName, handleEvent);
|
|
2282
|
-
}
|
|
2283
|
-
};
|
|
2284
|
-
|
|
2285
|
-
if (options.eventNames && Array.prototype.map) {
|
|
2286
|
-
options.eventName = options.eventNames[0];
|
|
2287
|
-
options.eventNames.map(listener[options.method]);
|
|
2288
|
-
} else {
|
|
2289
|
-
listener[options.method](options.eventName);
|
|
2290
|
-
}
|
|
2291
|
-
|
|
2292
|
-
log(
|
|
2293
|
-
capitalizeFirstLetter(options.method) +
|
|
2294
|
-
' event listener: ' +
|
|
2295
|
-
options.eventType
|
|
2296
|
-
);
|
|
2297
|
-
}
|
|
2298
|
-
|
|
2299
|
-
function manageEventListeners(method) {
|
|
2300
|
-
manageTriggerEvent({
|
|
2301
|
-
method: method,
|
|
2302
|
-
eventType: 'Animation Start',
|
|
2303
|
-
eventNames: ['animationstart', 'webkitAnimationStart']
|
|
2304
|
-
});
|
|
2305
|
-
manageTriggerEvent({
|
|
2306
|
-
method: method,
|
|
2307
|
-
eventType: 'Animation Iteration',
|
|
2308
|
-
eventNames: ['animationiteration', 'webkitAnimationIteration']
|
|
2309
|
-
});
|
|
2310
|
-
manageTriggerEvent({
|
|
2311
|
-
method: method,
|
|
2312
|
-
eventType: 'Animation End',
|
|
2313
|
-
eventNames: ['animationend', 'webkitAnimationEnd']
|
|
2314
|
-
});
|
|
2315
|
-
manageTriggerEvent({
|
|
2316
|
-
method: method,
|
|
2317
|
-
eventType: 'Input',
|
|
2318
|
-
eventName: 'input'
|
|
2319
|
-
});
|
|
2320
|
-
manageTriggerEvent({
|
|
2321
|
-
method: method,
|
|
2322
|
-
eventType: 'Mouse Up',
|
|
2323
|
-
eventName: 'mouseup'
|
|
2324
|
-
});
|
|
2325
|
-
manageTriggerEvent({
|
|
2326
|
-
method: method,
|
|
2327
|
-
eventType: 'Mouse Down',
|
|
2328
|
-
eventName: 'mousedown'
|
|
2329
|
-
});
|
|
2330
|
-
manageTriggerEvent({
|
|
2331
|
-
method: method,
|
|
2332
|
-
eventType: 'Orientation Change',
|
|
2333
|
-
eventName: 'orientationchange'
|
|
2334
|
-
});
|
|
2335
|
-
manageTriggerEvent({
|
|
2336
|
-
method: method,
|
|
2337
|
-
eventType: 'Print',
|
|
2338
|
-
eventNames: ['afterprint', 'beforeprint']
|
|
2339
|
-
});
|
|
2340
|
-
manageTriggerEvent({
|
|
2341
|
-
method: method,
|
|
2342
|
-
eventType: 'Ready State Change',
|
|
2343
|
-
eventName: 'readystatechange'
|
|
2344
|
-
});
|
|
2345
|
-
manageTriggerEvent({
|
|
2346
|
-
method: method,
|
|
2347
|
-
eventType: 'Touch Start',
|
|
2348
|
-
eventName: 'touchstart'
|
|
2349
|
-
});
|
|
2350
|
-
manageTriggerEvent({
|
|
2351
|
-
method: method,
|
|
2352
|
-
eventType: 'Touch End',
|
|
2353
|
-
eventName: 'touchend'
|
|
2354
|
-
});
|
|
2355
|
-
manageTriggerEvent({
|
|
2356
|
-
method: method,
|
|
2357
|
-
eventType: 'Touch Cancel',
|
|
2358
|
-
eventName: 'touchcancel'
|
|
2359
|
-
});
|
|
2360
|
-
manageTriggerEvent({
|
|
2361
|
-
method: method,
|
|
2362
|
-
eventType: 'Transition Start',
|
|
2363
|
-
eventNames: [
|
|
2364
|
-
'transitionstart',
|
|
2365
|
-
'webkitTransitionStart',
|
|
2366
|
-
'MSTransitionStart',
|
|
2367
|
-
'oTransitionStart',
|
|
2368
|
-
'otransitionstart'
|
|
2369
|
-
]
|
|
2370
|
-
});
|
|
2371
|
-
manageTriggerEvent({
|
|
2372
|
-
method: method,
|
|
2373
|
-
eventType: 'Transition Iteration',
|
|
2374
|
-
eventNames: [
|
|
2375
|
-
'transitioniteration',
|
|
2376
|
-
'webkitTransitionIteration',
|
|
2377
|
-
'MSTransitionIteration',
|
|
2378
|
-
'oTransitionIteration',
|
|
2379
|
-
'otransitioniteration'
|
|
2380
|
-
]
|
|
2381
|
-
});
|
|
2382
|
-
manageTriggerEvent({
|
|
2383
|
-
method: method,
|
|
2384
|
-
eventType: 'Transition End',
|
|
2385
|
-
eventNames: [
|
|
2386
|
-
'transitionend',
|
|
2387
|
-
'webkitTransitionEnd',
|
|
2388
|
-
'MSTransitionEnd',
|
|
2389
|
-
'oTransitionEnd',
|
|
2390
|
-
'otransitionend'
|
|
2391
|
-
]
|
|
2392
|
-
});
|
|
2393
|
-
if ('child' === resizeFrom) {
|
|
2394
|
-
manageTriggerEvent({
|
|
2395
|
-
method: method,
|
|
2396
|
-
eventType: 'IFrame Resized',
|
|
2397
|
-
eventName: 'resize'
|
|
2398
|
-
});
|
|
2399
|
-
}
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
function checkCalcMode(calcMode, calcModeDefault, modes, type) {
|
|
2403
|
-
if (calcModeDefault !== calcMode) {
|
|
2404
|
-
if (!(calcMode in modes)) {
|
|
2405
|
-
warn(
|
|
2406
|
-
calcMode + ' is not a valid option for ' + type + 'CalculationMethod.'
|
|
2407
|
-
);
|
|
2408
|
-
calcMode = calcModeDefault;
|
|
2409
|
-
}
|
|
2410
|
-
log(type + ' calculation method set to "' + calcMode + '"');
|
|
2411
|
-
}
|
|
2412
|
-
|
|
2413
|
-
return calcMode
|
|
2414
|
-
}
|
|
2415
|
-
|
|
2416
|
-
function checkHeightMode() {
|
|
2417
|
-
heightCalcMode = checkCalcMode(
|
|
2418
|
-
heightCalcMode,
|
|
2419
|
-
heightCalcModeDefault,
|
|
2420
|
-
getHeight,
|
|
2421
|
-
'height'
|
|
2422
|
-
);
|
|
2423
|
-
}
|
|
2424
|
-
|
|
2425
|
-
function checkWidthMode() {
|
|
2426
|
-
widthCalcMode = checkCalcMode(
|
|
2427
|
-
widthCalcMode,
|
|
2428
|
-
widthCalcModeDefault,
|
|
2429
|
-
getWidth,
|
|
2430
|
-
'width'
|
|
2431
|
-
);
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
|
-
function startEventListeners() {
|
|
2435
|
-
if (true === autoResize) {
|
|
2436
|
-
manageEventListeners('add');
|
|
2437
|
-
setupMutationObserver();
|
|
2438
|
-
} else {
|
|
2439
|
-
log('Auto Resize disabled');
|
|
2440
|
-
}
|
|
2441
|
-
}
|
|
2442
|
-
|
|
2443
|
-
// function stopMsgsToParent() {
|
|
2444
|
-
// log('Disable outgoing messages')
|
|
2445
|
-
// sendPermit = false
|
|
2446
|
-
// }
|
|
2447
|
-
|
|
2448
|
-
// function removeMsgListener() {
|
|
2449
|
-
// log('Remove event listener: Message')
|
|
2450
|
-
// removeEventListener(window, 'message', receiver)
|
|
2451
|
-
// }
|
|
2452
|
-
|
|
2453
|
-
function disconnectMutationObserver() {
|
|
2454
|
-
if (null !== bodyObserver) {
|
|
2455
|
-
/* istanbul ignore next */ // Not testable in PhantonJS
|
|
2456
|
-
bodyObserver.disconnect();
|
|
2457
|
-
}
|
|
2458
|
-
}
|
|
2459
|
-
|
|
2460
|
-
function stopEventListeners() {
|
|
2461
|
-
manageEventListeners('remove');
|
|
2462
|
-
disconnectMutationObserver();
|
|
2463
|
-
clearInterval(intervalTimer);
|
|
2464
|
-
}
|
|
2465
|
-
|
|
2466
|
-
// function teardown() {
|
|
2467
|
-
// stopMsgsToParent()
|
|
2468
|
-
// removeMsgListener()
|
|
2469
|
-
// if (true === autoResize) stopEventListeners()
|
|
2470
|
-
// }
|
|
2471
|
-
|
|
2472
|
-
function injectClearFixIntoBodyElement() {
|
|
2473
|
-
var clearFix = document.createElement('div');
|
|
2474
|
-
clearFix.style.clear = 'both';
|
|
2475
|
-
// Guard against the following having been globally redefined in CSS.
|
|
2476
|
-
clearFix.style.display = 'block';
|
|
2477
|
-
clearFix.style.height = '0';
|
|
2478
|
-
document.body.appendChild(clearFix);
|
|
2479
|
-
}
|
|
2480
|
-
|
|
2481
|
-
function setupInPageLinks() {
|
|
2482
|
-
function getPagePosition() {
|
|
2483
|
-
return {
|
|
2484
|
-
x:
|
|
2485
|
-
window.pageXOffset === undefined$1
|
|
2486
|
-
? document.documentElement.scrollLeft
|
|
2487
|
-
: window.pageXOffset,
|
|
2488
|
-
y:
|
|
2489
|
-
window.pageYOffset === undefined$1
|
|
2490
|
-
? document.documentElement.scrollTop
|
|
2491
|
-
: window.pageYOffset
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
|
|
2495
|
-
function getElementPosition(el) {
|
|
2496
|
-
var elPosition = el.getBoundingClientRect(),
|
|
2497
|
-
pagePosition = getPagePosition();
|
|
2498
|
-
|
|
2499
|
-
return {
|
|
2500
|
-
x: parseInt(elPosition.left, 10) + parseInt(pagePosition.x, 10),
|
|
2501
|
-
y: parseInt(elPosition.top, 10) + parseInt(pagePosition.y, 10)
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
|
|
2505
|
-
function findTarget(location) {
|
|
2506
|
-
function jumpToTarget(target) {
|
|
2507
|
-
var jumpPosition = getElementPosition(target);
|
|
2508
|
-
|
|
2509
|
-
log(
|
|
2510
|
-
'Moving to in page link (#' +
|
|
2511
|
-
hash +
|
|
2512
|
-
') at x: ' +
|
|
2513
|
-
jumpPosition.x +
|
|
2514
|
-
' y: ' +
|
|
2515
|
-
jumpPosition.y
|
|
2516
|
-
);
|
|
2517
|
-
sendMsg(jumpPosition.y, jumpPosition.x, 'scrollToOffset'); // X&Y reversed at sendMsg uses height/width
|
|
2518
|
-
}
|
|
2519
|
-
|
|
2520
|
-
var hash = location.split('#')[1] || location, // Remove # if present
|
|
2521
|
-
hashData = decodeURIComponent(hash),
|
|
2522
|
-
target =
|
|
2523
|
-
document.getElementById(hashData) ||
|
|
2524
|
-
document.getElementsByName(hashData)[0];
|
|
2525
|
-
|
|
2526
|
-
if (undefined$1 === target) {
|
|
2527
|
-
log(
|
|
2528
|
-
'In page link (#' +
|
|
2529
|
-
hash +
|
|
2530
|
-
') not found in iFrame, so sending to parent'
|
|
2531
|
-
);
|
|
2532
|
-
sendMsg(0, 0, 'inPageLink', '#' + hash);
|
|
2533
|
-
} else {
|
|
2534
|
-
jumpToTarget(target);
|
|
2535
|
-
}
|
|
2536
|
-
}
|
|
2537
|
-
|
|
2538
|
-
function checkLocationHash() {
|
|
2539
|
-
var hash = window.location.hash;
|
|
2540
|
-
var href = window.location.href;
|
|
2541
|
-
|
|
2542
|
-
if ('' !== hash && '#' !== hash) {
|
|
2543
|
-
findTarget(href);
|
|
2544
|
-
}
|
|
2545
|
-
}
|
|
2546
|
-
|
|
2547
|
-
function bindAnchors() {
|
|
2548
|
-
function setupLink(el) {
|
|
2549
|
-
function linkClicked(e) {
|
|
2550
|
-
e.preventDefault();
|
|
2551
|
-
|
|
2552
|
-
/* jshint validthis:true */
|
|
2553
|
-
findTarget(this.getAttribute('href'));
|
|
2554
|
-
}
|
|
2555
|
-
|
|
2556
|
-
if ('#' !== el.getAttribute('href')) {
|
|
2557
|
-
addEventListener(el, 'click', linkClicked);
|
|
2558
|
-
}
|
|
2559
|
-
}
|
|
2560
|
-
|
|
2561
|
-
Array.prototype.forEach.call(
|
|
2562
|
-
document.querySelectorAll('a[href^="#"]'),
|
|
2563
|
-
setupLink
|
|
2564
|
-
);
|
|
2565
|
-
}
|
|
2566
|
-
|
|
2567
|
-
function bindLocationHash() {
|
|
2568
|
-
addEventListener(window, 'hashchange', checkLocationHash);
|
|
2569
|
-
}
|
|
2570
|
-
|
|
2571
|
-
function initCheck() {
|
|
2572
|
-
// Check if page loaded with location hash after init resize
|
|
2573
|
-
setTimeout(checkLocationHash, eventCancelTimer);
|
|
2574
|
-
}
|
|
2575
|
-
|
|
2576
|
-
function enableInPageLinks() {
|
|
2577
|
-
/* istanbul ignore else */ // Not testable in phantonJS
|
|
2578
|
-
if (Array.prototype.forEach && document.querySelectorAll) {
|
|
2579
|
-
log('Setting up location.hash handlers');
|
|
2580
|
-
bindAnchors();
|
|
2581
|
-
bindLocationHash();
|
|
2582
|
-
initCheck();
|
|
2583
|
-
} else {
|
|
2584
|
-
warn(
|
|
2585
|
-
'In page linking not fully supported in this browser! (See README.md for IE8 workaround)'
|
|
2586
|
-
);
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
|
|
2590
|
-
if (inPageLinks.enable) {
|
|
2591
|
-
enableInPageLinks();
|
|
2592
|
-
} else {
|
|
2593
|
-
log('In page linking not enabled');
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
|
-
return {
|
|
2597
|
-
findTarget: findTarget
|
|
2598
|
-
}
|
|
2599
|
-
}
|
|
2600
|
-
|
|
2601
|
-
function setupMouseEvents() {
|
|
2602
|
-
if (mouseEvents !== true) return
|
|
2603
|
-
|
|
2604
|
-
function sendMouse(e) {
|
|
2605
|
-
sendMsg(0, 0, e.type, e.screenY + ':' + e.screenX);
|
|
2606
|
-
}
|
|
2607
|
-
|
|
2608
|
-
function addMouseListener(evt, name) {
|
|
2609
|
-
log('Add event listener: ' + name);
|
|
2610
|
-
addEventListener(window.document, evt, sendMouse);
|
|
2611
|
-
}
|
|
2612
|
-
|
|
2613
|
-
addMouseListener('mouseenter', 'Mouse Enter');
|
|
2614
|
-
addMouseListener('mouseleave', 'Mouse Leave');
|
|
2615
|
-
}
|
|
2616
|
-
|
|
2617
|
-
function setupPublicMethods() {
|
|
2618
|
-
log('Enable public methods');
|
|
2619
|
-
|
|
2620
|
-
win.parentIFrame = {
|
|
2621
|
-
autoResize: function autoResizeF(resize) {
|
|
2622
|
-
if (true === resize && false === autoResize) {
|
|
2623
|
-
autoResize = true;
|
|
2624
|
-
startEventListeners();
|
|
2625
|
-
} else if (false === resize && true === autoResize) {
|
|
2626
|
-
autoResize = false;
|
|
2627
|
-
stopEventListeners();
|
|
2628
|
-
}
|
|
2629
|
-
sendMsg(0, 0, 'autoResize', JSON.stringify(autoResize));
|
|
2630
|
-
return autoResize
|
|
2631
|
-
},
|
|
2632
|
-
|
|
2633
|
-
close: function closeF() {
|
|
2634
|
-
sendMsg(0, 0, 'close');
|
|
2635
|
-
// teardown()
|
|
2636
|
-
},
|
|
2637
|
-
|
|
2638
|
-
getId: function getIdF() {
|
|
2639
|
-
return myID
|
|
2640
|
-
},
|
|
2641
|
-
|
|
2642
|
-
getPageInfo: function getPageInfoF(callback) {
|
|
2643
|
-
if ('function' === typeof callback) {
|
|
2644
|
-
onPageInfo = callback;
|
|
2645
|
-
sendMsg(0, 0, 'pageInfo');
|
|
2646
|
-
} else {
|
|
2647
|
-
onPageInfo = function () {};
|
|
2648
|
-
sendMsg(0, 0, 'pageInfoStop');
|
|
2649
|
-
}
|
|
2650
|
-
},
|
|
2651
|
-
|
|
2652
|
-
moveToAnchor: function moveToAnchorF(hash) {
|
|
2653
|
-
inPageLinks.findTarget(hash);
|
|
2654
|
-
},
|
|
2655
|
-
|
|
2656
|
-
reset: function resetF() {
|
|
2657
|
-
resetIFrame('parentIFrame.reset');
|
|
2658
|
-
},
|
|
2659
|
-
|
|
2660
|
-
scrollTo: function scrollToF(x, y) {
|
|
2661
|
-
sendMsg(y, x, 'scrollTo'); // X&Y reversed at sendMsg uses height/width
|
|
2662
|
-
},
|
|
2663
|
-
|
|
2664
|
-
scrollToOffset: function scrollToF(x, y) {
|
|
2665
|
-
sendMsg(y, x, 'scrollToOffset'); // X&Y reversed at sendMsg uses height/width
|
|
2666
|
-
},
|
|
2667
|
-
|
|
2668
|
-
sendMessage: function sendMessageF(msg, targetOrigin) {
|
|
2669
|
-
sendMsg(0, 0, 'message', JSON.stringify(msg), targetOrigin);
|
|
2670
|
-
},
|
|
2671
|
-
|
|
2672
|
-
setHeightCalculationMethod: function setHeightCalculationMethodF(
|
|
2673
|
-
heightCalculationMethod
|
|
2674
|
-
) {
|
|
2675
|
-
heightCalcMode = heightCalculationMethod;
|
|
2676
|
-
checkHeightMode();
|
|
2677
|
-
},
|
|
2678
|
-
|
|
2679
|
-
setWidthCalculationMethod: function setWidthCalculationMethodF(
|
|
2680
|
-
widthCalculationMethod
|
|
2681
|
-
) {
|
|
2682
|
-
widthCalcMode = widthCalculationMethod;
|
|
2683
|
-
checkWidthMode();
|
|
2684
|
-
},
|
|
2685
|
-
|
|
2686
|
-
setTargetOrigin: function setTargetOriginF(targetOrigin) {
|
|
2687
|
-
log('Set targetOrigin: ' + targetOrigin);
|
|
2688
|
-
targetOriginDefault = targetOrigin;
|
|
2689
|
-
},
|
|
2690
|
-
|
|
2691
|
-
size: function sizeF(customHeight, customWidth) {
|
|
2692
|
-
var valString =
|
|
2693
|
-
'' + (customHeight || '') + (customWidth ? ',' + customWidth : '');
|
|
2694
|
-
sendSize(
|
|
2695
|
-
'size',
|
|
2696
|
-
'parentIFrame.size(' + valString + ')',
|
|
2697
|
-
customHeight,
|
|
2698
|
-
customWidth
|
|
2699
|
-
);
|
|
2700
|
-
}
|
|
2701
|
-
};
|
|
2702
|
-
}
|
|
2703
|
-
|
|
2704
|
-
function initInterval() {
|
|
2705
|
-
if (0 !== interval) {
|
|
2706
|
-
log('setInterval: ' + interval + 'ms');
|
|
2707
|
-
intervalTimer = setInterval(function () {
|
|
2708
|
-
sendSize('interval', 'setInterval: ' + interval);
|
|
2709
|
-
}, Math.abs(interval));
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
|
|
2713
|
-
// Not testable in PhantomJS
|
|
2714
|
-
/* istanbul ignore next */
|
|
2715
|
-
function setupBodyMutationObserver() {
|
|
2716
|
-
function addImageLoadListners(mutation) {
|
|
2717
|
-
function addImageLoadListener(element) {
|
|
2718
|
-
if (false === element.complete) {
|
|
2719
|
-
log('Attach listeners to ' + element.src);
|
|
2720
|
-
element.addEventListener('load', imageLoaded, false);
|
|
2721
|
-
element.addEventListener('error', imageError, false);
|
|
2722
|
-
elements.push(element);
|
|
2723
|
-
}
|
|
2724
|
-
}
|
|
2725
|
-
|
|
2726
|
-
if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
|
|
2727
|
-
addImageLoadListener(mutation.target);
|
|
2728
|
-
} else if (mutation.type === 'childList') {
|
|
2729
|
-
Array.prototype.forEach.call(
|
|
2730
|
-
mutation.target.querySelectorAll('img'),
|
|
2731
|
-
addImageLoadListener
|
|
2732
|
-
);
|
|
2733
|
-
}
|
|
2734
|
-
}
|
|
2735
|
-
|
|
2736
|
-
function removeFromArray(element) {
|
|
2737
|
-
elements.splice(elements.indexOf(element), 1);
|
|
2738
|
-
}
|
|
2739
|
-
|
|
2740
|
-
function removeImageLoadListener(element) {
|
|
2741
|
-
log('Remove listeners from ' + element.src);
|
|
2742
|
-
element.removeEventListener('load', imageLoaded, false);
|
|
2743
|
-
element.removeEventListener('error', imageError, false);
|
|
2744
|
-
removeFromArray(element);
|
|
2745
|
-
}
|
|
2746
|
-
|
|
2747
|
-
function imageEventTriggered(event, type, typeDesc) {
|
|
2748
|
-
removeImageLoadListener(event.target);
|
|
2749
|
-
sendSize(type, typeDesc + ': ' + event.target.src);
|
|
2750
|
-
}
|
|
2751
|
-
|
|
2752
|
-
function imageLoaded(event) {
|
|
2753
|
-
imageEventTriggered(event, 'imageLoad', 'Image loaded');
|
|
2754
|
-
}
|
|
2755
|
-
|
|
2756
|
-
function imageError(event) {
|
|
2757
|
-
imageEventTriggered(event, 'imageLoadFailed', 'Image load failed');
|
|
2758
|
-
}
|
|
2759
|
-
|
|
2760
|
-
function mutationObserved(mutations) {
|
|
2761
|
-
sendSize(
|
|
2762
|
-
'mutationObserver',
|
|
2763
|
-
'mutationObserver: ' + mutations[0].target + ' ' + mutations[0].type
|
|
2764
|
-
);
|
|
2765
|
-
|
|
2766
|
-
// Deal with WebKit / Blink asyncing image loading when tags are injected into the page
|
|
2767
|
-
mutations.forEach(addImageLoadListners);
|
|
2768
|
-
}
|
|
2769
|
-
|
|
2770
|
-
function createMutationObserver() {
|
|
2771
|
-
var target = document.querySelector('body'),
|
|
2772
|
-
config = {
|
|
2773
|
-
attributes: true,
|
|
2774
|
-
attributeOldValue: false,
|
|
2775
|
-
characterData: true,
|
|
2776
|
-
characterDataOldValue: false,
|
|
2777
|
-
childList: true,
|
|
2778
|
-
subtree: true
|
|
2779
|
-
};
|
|
2780
|
-
|
|
2781
|
-
observer = new MutationObserver(mutationObserved);
|
|
2782
|
-
|
|
2783
|
-
log('Create body MutationObserver');
|
|
2784
|
-
observer.observe(target, config);
|
|
2785
|
-
|
|
2786
|
-
return observer
|
|
2787
|
-
}
|
|
2788
|
-
|
|
2789
|
-
var elements = [],
|
|
2790
|
-
MutationObserver =
|
|
2791
|
-
window.MutationObserver || window.WebKitMutationObserver,
|
|
2792
|
-
observer = createMutationObserver();
|
|
2793
|
-
|
|
2794
|
-
return {
|
|
2795
|
-
disconnect: function () {
|
|
2796
|
-
if ('disconnect' in observer) {
|
|
2797
|
-
log('Disconnect body MutationObserver');
|
|
2798
|
-
observer.disconnect();
|
|
2799
|
-
elements.forEach(removeImageLoadListener);
|
|
2800
|
-
}
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2803
|
-
}
|
|
2804
|
-
|
|
2805
|
-
function setupMutationObserver() {
|
|
2806
|
-
var forceIntervalTimer = 0 > interval;
|
|
2807
|
-
|
|
2808
|
-
// Not testable in PhantomJS
|
|
2809
|
-
/* istanbul ignore if */ if (
|
|
2810
|
-
window.MutationObserver ||
|
|
2811
|
-
window.WebKitMutationObserver
|
|
2812
|
-
) {
|
|
2813
|
-
if (forceIntervalTimer) {
|
|
2814
|
-
initInterval();
|
|
2815
|
-
} else {
|
|
2816
|
-
bodyObserver = setupBodyMutationObserver();
|
|
2817
|
-
}
|
|
2818
|
-
} else {
|
|
2819
|
-
log('MutationObserver not supported in this browser!');
|
|
2820
|
-
initInterval();
|
|
2821
|
-
}
|
|
2822
|
-
}
|
|
2823
|
-
|
|
2824
|
-
// document.documentElement.offsetHeight is not reliable, so
|
|
2825
|
-
// we have to jump through hoops to get a better value.
|
|
2826
|
-
function getComputedStyle(prop, el) {
|
|
2827
|
-
var retVal = 0;
|
|
2828
|
-
el = el || document.body; // Not testable in phantonJS
|
|
2829
|
-
|
|
2830
|
-
retVal = document.defaultView.getComputedStyle(el, null);
|
|
2831
|
-
retVal = null === retVal ? 0 : retVal[prop];
|
|
2832
|
-
|
|
2833
|
-
return parseInt(retVal, base)
|
|
2834
|
-
}
|
|
2835
|
-
|
|
2836
|
-
function chkEventThottle(timer) {
|
|
2837
|
-
if (timer > throttledTimer / 2) {
|
|
2838
|
-
throttledTimer = 2 * timer;
|
|
2839
|
-
log('Event throttle increased to ' + throttledTimer + 'ms');
|
|
2840
|
-
}
|
|
2841
|
-
}
|
|
2842
|
-
|
|
2843
|
-
// Idea from https://github.com/guardian/iframe-messenger
|
|
2844
|
-
function getMaxElement(side, elements) {
|
|
2845
|
-
var elementsLength = elements.length,
|
|
2846
|
-
elVal = 0,
|
|
2847
|
-
maxVal = 0,
|
|
2848
|
-
Side = capitalizeFirstLetter(side),
|
|
2849
|
-
timer = Date.now();
|
|
2850
|
-
|
|
2851
|
-
for (var i = 0; i < elementsLength; i++) {
|
|
2852
|
-
elVal =
|
|
2853
|
-
elements[i].getBoundingClientRect()[side] +
|
|
2854
|
-
getComputedStyle('margin' + Side, elements[i]);
|
|
2855
|
-
if (elVal > maxVal) {
|
|
2856
|
-
maxVal = elVal;
|
|
2857
|
-
}
|
|
2858
|
-
}
|
|
2859
|
-
|
|
2860
|
-
timer = Date.now() - timer;
|
|
2861
|
-
|
|
2862
|
-
log('Parsed ' + elementsLength + ' HTML elements');
|
|
2863
|
-
log('Element position calculated in ' + timer + 'ms');
|
|
2864
|
-
|
|
2865
|
-
chkEventThottle(timer);
|
|
2866
|
-
|
|
2867
|
-
return maxVal
|
|
2868
|
-
}
|
|
2869
|
-
|
|
2870
|
-
function getAllMeasurements(dimensions) {
|
|
2871
|
-
return [
|
|
2872
|
-
dimensions.bodyOffset(),
|
|
2873
|
-
dimensions.bodyScroll(),
|
|
2874
|
-
dimensions.documentElementOffset(),
|
|
2875
|
-
dimensions.documentElementScroll()
|
|
2876
|
-
]
|
|
2877
|
-
}
|
|
2878
|
-
|
|
2879
|
-
function getTaggedElements(side, tag) {
|
|
2880
|
-
function noTaggedElementsFound() {
|
|
2881
|
-
warn('No tagged elements (' + tag + ') found on page');
|
|
2882
|
-
return document.querySelectorAll('body *')
|
|
2883
|
-
}
|
|
2884
|
-
|
|
2885
|
-
var elements = document.querySelectorAll('[' + tag + ']');
|
|
2886
|
-
|
|
2887
|
-
if (elements.length === 0) noTaggedElementsFound();
|
|
2888
|
-
|
|
2889
|
-
return getMaxElement(side, elements)
|
|
2890
|
-
}
|
|
2891
|
-
|
|
2892
|
-
function getAllElements() {
|
|
2893
|
-
return document.querySelectorAll('body *')
|
|
2894
|
-
}
|
|
2895
|
-
|
|
2896
|
-
var getHeight = {
|
|
2897
|
-
bodyOffset: function getBodyOffsetHeight() {
|
|
2898
|
-
return (
|
|
2899
|
-
document.body.offsetHeight +
|
|
2900
|
-
getComputedStyle('marginTop') +
|
|
2901
|
-
getComputedStyle('marginBottom')
|
|
2902
|
-
)
|
|
2903
|
-
},
|
|
2904
|
-
|
|
2905
|
-
offset: function () {
|
|
2906
|
-
return getHeight.bodyOffset() // Backwards compatibility
|
|
2907
|
-
},
|
|
2908
|
-
|
|
2909
|
-
bodyScroll: function getBodyScrollHeight() {
|
|
2910
|
-
return document.body.scrollHeight
|
|
2911
|
-
},
|
|
2912
|
-
|
|
2913
|
-
custom: function getCustomWidth() {
|
|
2914
|
-
return customCalcMethods.height()
|
|
2915
|
-
},
|
|
2916
|
-
|
|
2917
|
-
documentElementOffset: function getDEOffsetHeight() {
|
|
2918
|
-
return document.documentElement.offsetHeight
|
|
2919
|
-
},
|
|
2920
|
-
|
|
2921
|
-
documentElementScroll: function getDEScrollHeight() {
|
|
2922
|
-
return document.documentElement.scrollHeight
|
|
2923
|
-
},
|
|
2924
|
-
|
|
2925
|
-
max: function getMaxHeight() {
|
|
2926
|
-
return Math.max.apply(null, getAllMeasurements(getHeight))
|
|
2927
|
-
},
|
|
2928
|
-
|
|
2929
|
-
min: function getMinHeight() {
|
|
2930
|
-
return Math.min.apply(null, getAllMeasurements(getHeight))
|
|
2931
|
-
},
|
|
2932
|
-
|
|
2933
|
-
grow: function growHeight() {
|
|
2934
|
-
return getHeight.max() // Run max without the forced downsizing
|
|
2935
|
-
},
|
|
2936
|
-
|
|
2937
|
-
lowestElement: function getBestHeight() {
|
|
2938
|
-
return Math.max(
|
|
2939
|
-
getHeight.bodyOffset() || getHeight.documentElementOffset(),
|
|
2940
|
-
getMaxElement('bottom', getAllElements())
|
|
2941
|
-
)
|
|
2942
|
-
},
|
|
2943
|
-
|
|
2944
|
-
taggedElement: function getTaggedElementsHeight() {
|
|
2945
|
-
return getTaggedElements('bottom', 'data-iframe-height')
|
|
2946
|
-
}
|
|
2947
|
-
},
|
|
2948
|
-
getWidth = {
|
|
2949
|
-
bodyScroll: function getBodyScrollWidth() {
|
|
2950
|
-
return document.body.scrollWidth
|
|
2951
|
-
},
|
|
2952
|
-
|
|
2953
|
-
bodyOffset: function getBodyOffsetWidth() {
|
|
2954
|
-
return document.body.offsetWidth
|
|
2955
|
-
},
|
|
2956
|
-
|
|
2957
|
-
custom: function getCustomWidth() {
|
|
2958
|
-
return customCalcMethods.width()
|
|
2959
|
-
},
|
|
2960
|
-
|
|
2961
|
-
documentElementScroll: function getDEScrollWidth() {
|
|
2962
|
-
return document.documentElement.scrollWidth
|
|
2963
|
-
},
|
|
2964
|
-
|
|
2965
|
-
documentElementOffset: function getDEOffsetWidth() {
|
|
2966
|
-
return document.documentElement.offsetWidth
|
|
2967
|
-
},
|
|
2968
|
-
|
|
2969
|
-
scroll: function getMaxWidth() {
|
|
2970
|
-
return Math.max(getWidth.bodyScroll(), getWidth.documentElementScroll())
|
|
2971
|
-
},
|
|
2972
|
-
|
|
2973
|
-
max: function getMaxWidth() {
|
|
2974
|
-
return Math.max.apply(null, getAllMeasurements(getWidth))
|
|
2975
|
-
},
|
|
2976
|
-
|
|
2977
|
-
min: function getMinWidth() {
|
|
2978
|
-
return Math.min.apply(null, getAllMeasurements(getWidth))
|
|
2979
|
-
},
|
|
2980
|
-
|
|
2981
|
-
rightMostElement: function rightMostElement() {
|
|
2982
|
-
return getMaxElement('right', getAllElements())
|
|
2983
|
-
},
|
|
2984
|
-
|
|
2985
|
-
taggedElement: function getTaggedElementsWidth() {
|
|
2986
|
-
return getTaggedElements('right', 'data-iframe-width')
|
|
2987
|
-
}
|
|
2988
|
-
};
|
|
2989
|
-
|
|
2990
|
-
function sizeIFrame(
|
|
2991
|
-
triggerEvent,
|
|
2992
|
-
triggerEventDesc,
|
|
2993
|
-
customHeight,
|
|
2994
|
-
customWidth
|
|
2995
|
-
) {
|
|
2996
|
-
function resizeIFrame() {
|
|
2997
|
-
height = currentHeight;
|
|
2998
|
-
width = currentWidth;
|
|
2999
|
-
|
|
3000
|
-
sendMsg(height, width, triggerEvent);
|
|
3001
|
-
}
|
|
3002
|
-
|
|
3003
|
-
function isSizeChangeDetected() {
|
|
3004
|
-
function checkTolarance(a, b) {
|
|
3005
|
-
var retVal = Math.abs(a - b) <= tolerance;
|
|
3006
|
-
return !retVal
|
|
3007
|
-
}
|
|
3008
|
-
|
|
3009
|
-
currentHeight =
|
|
3010
|
-
undefined$1 === customHeight ? getHeight[heightCalcMode]() : customHeight;
|
|
3011
|
-
currentWidth =
|
|
3012
|
-
undefined$1 === customWidth ? getWidth[widthCalcMode]() : customWidth;
|
|
3013
|
-
|
|
3014
|
-
return (
|
|
3015
|
-
checkTolarance(height, currentHeight) ||
|
|
3016
|
-
(calculateWidth && checkTolarance(width, currentWidth))
|
|
3017
|
-
)
|
|
3018
|
-
}
|
|
3019
|
-
|
|
3020
|
-
function isForceResizableEvent() {
|
|
3021
|
-
return !(triggerEvent in { init: 1, interval: 1, size: 1 })
|
|
3022
|
-
}
|
|
3023
|
-
|
|
3024
|
-
function isForceResizableCalcMode() {
|
|
3025
|
-
return (
|
|
3026
|
-
heightCalcMode in resetRequiredMethods ||
|
|
3027
|
-
(calculateWidth && widthCalcMode in resetRequiredMethods)
|
|
3028
|
-
)
|
|
3029
|
-
}
|
|
3030
|
-
|
|
3031
|
-
function logIgnored() {
|
|
3032
|
-
log('No change in size detected');
|
|
3033
|
-
}
|
|
3034
|
-
|
|
3035
|
-
function checkDownSizing() {
|
|
3036
|
-
if (isForceResizableEvent() && isForceResizableCalcMode()) {
|
|
3037
|
-
resetIFrame(triggerEventDesc);
|
|
3038
|
-
} else if (!(triggerEvent in { interval: 1 })) {
|
|
3039
|
-
logIgnored();
|
|
3040
|
-
}
|
|
3041
|
-
}
|
|
3042
|
-
|
|
3043
|
-
var currentHeight, currentWidth;
|
|
3044
|
-
|
|
3045
|
-
if (isSizeChangeDetected() || 'init' === triggerEvent) {
|
|
3046
|
-
lockTrigger();
|
|
3047
|
-
resizeIFrame();
|
|
3048
|
-
} else {
|
|
3049
|
-
checkDownSizing();
|
|
3050
|
-
}
|
|
3051
|
-
}
|
|
3052
|
-
|
|
3053
|
-
var sizeIFrameThrottled = throttle(sizeIFrame);
|
|
3054
|
-
|
|
3055
|
-
function sendSize(triggerEvent, triggerEventDesc, customHeight, customWidth) {
|
|
3056
|
-
function recordTrigger() {
|
|
3057
|
-
if (!(triggerEvent in { reset: 1, resetPage: 1, init: 1 })) {
|
|
3058
|
-
log('Trigger event: ' + triggerEventDesc);
|
|
3059
|
-
}
|
|
3060
|
-
}
|
|
3061
|
-
|
|
3062
|
-
function isDoubleFiredEvent() {
|
|
3063
|
-
return triggerLocked && triggerEvent in doubleEventList
|
|
3064
|
-
}
|
|
3065
|
-
|
|
3066
|
-
if (isDoubleFiredEvent()) {
|
|
3067
|
-
log('Trigger event cancelled: ' + triggerEvent);
|
|
3068
|
-
} else {
|
|
3069
|
-
recordTrigger();
|
|
3070
|
-
if (triggerEvent === 'init') {
|
|
3071
|
-
sizeIFrame(triggerEvent, triggerEventDesc, customHeight, customWidth);
|
|
3072
|
-
} else {
|
|
3073
|
-
sizeIFrameThrottled(
|
|
3074
|
-
triggerEvent,
|
|
3075
|
-
triggerEventDesc,
|
|
3076
|
-
customHeight,
|
|
3077
|
-
customWidth
|
|
3078
|
-
);
|
|
3079
|
-
}
|
|
3080
|
-
}
|
|
3081
|
-
}
|
|
3082
|
-
|
|
3083
|
-
function lockTrigger() {
|
|
3084
|
-
if (!triggerLocked) {
|
|
3085
|
-
triggerLocked = true;
|
|
3086
|
-
log('Trigger event lock on');
|
|
3087
|
-
}
|
|
3088
|
-
clearTimeout(triggerLockedTimer);
|
|
3089
|
-
triggerLockedTimer = setTimeout(function () {
|
|
3090
|
-
triggerLocked = false;
|
|
3091
|
-
log('Trigger event lock off');
|
|
3092
|
-
log('--');
|
|
3093
|
-
}, eventCancelTimer);
|
|
3094
|
-
}
|
|
3095
|
-
|
|
3096
|
-
function triggerReset(triggerEvent) {
|
|
3097
|
-
height = getHeight[heightCalcMode]();
|
|
3098
|
-
width = getWidth[widthCalcMode]();
|
|
3099
|
-
|
|
3100
|
-
sendMsg(height, width, triggerEvent);
|
|
3101
|
-
}
|
|
3102
|
-
|
|
3103
|
-
function resetIFrame(triggerEventDesc) {
|
|
3104
|
-
var hcm = heightCalcMode;
|
|
3105
|
-
heightCalcMode = heightCalcModeDefault;
|
|
3106
|
-
|
|
3107
|
-
log('Reset trigger event: ' + triggerEventDesc);
|
|
3108
|
-
lockTrigger();
|
|
3109
|
-
triggerReset('reset');
|
|
3110
|
-
|
|
3111
|
-
heightCalcMode = hcm;
|
|
3112
|
-
}
|
|
3113
|
-
|
|
3114
|
-
function sendMsg(height, width, triggerEvent, msg, targetOrigin) {
|
|
3115
|
-
function setTargetOrigin() {
|
|
3116
|
-
if (undefined$1 === targetOrigin) {
|
|
3117
|
-
targetOrigin = targetOriginDefault;
|
|
3118
|
-
} else {
|
|
3119
|
-
log('Message targetOrigin: ' + targetOrigin);
|
|
3120
|
-
}
|
|
3121
|
-
}
|
|
3122
|
-
|
|
3123
|
-
function sendToParent() {
|
|
3124
|
-
var size = height + ':' + width,
|
|
3125
|
-
message =
|
|
3126
|
-
myID +
|
|
3127
|
-
':' +
|
|
3128
|
-
size +
|
|
3129
|
-
':' +
|
|
3130
|
-
triggerEvent +
|
|
3131
|
-
(undefined$1 === msg ? '' : ':' + msg);
|
|
3132
|
-
|
|
3133
|
-
log('Sending message to host page (' + message + ')');
|
|
3134
|
-
target.postMessage(msgID + message, targetOrigin);
|
|
3135
|
-
}
|
|
3136
|
-
|
|
3137
|
-
{
|
|
3138
|
-
setTargetOrigin();
|
|
3139
|
-
sendToParent();
|
|
3140
|
-
}
|
|
3141
|
-
}
|
|
3142
|
-
|
|
3143
|
-
function receiver(event) {
|
|
3144
|
-
var processRequestFromParent = {
|
|
3145
|
-
init: function initFromParent() {
|
|
3146
|
-
initMsg = event.data;
|
|
3147
|
-
target = event.source;
|
|
3148
|
-
|
|
3149
|
-
init();
|
|
3150
|
-
firstRun = false;
|
|
3151
|
-
setTimeout(function () {
|
|
3152
|
-
initLock = false;
|
|
3153
|
-
}, eventCancelTimer);
|
|
3154
|
-
},
|
|
3155
|
-
|
|
3156
|
-
reset: function resetFromParent() {
|
|
3157
|
-
if (initLock) {
|
|
3158
|
-
log('Page reset ignored by init');
|
|
3159
|
-
} else {
|
|
3160
|
-
log('Page size reset by host page');
|
|
3161
|
-
triggerReset('resetPage');
|
|
3162
|
-
}
|
|
3163
|
-
},
|
|
3164
|
-
|
|
3165
|
-
resize: function resizeFromParent() {
|
|
3166
|
-
sendSize('resizeParent', 'Parent window requested size check');
|
|
3167
|
-
},
|
|
3168
|
-
|
|
3169
|
-
moveToAnchor: function moveToAnchorF() {
|
|
3170
|
-
inPageLinks.findTarget(getData());
|
|
3171
|
-
},
|
|
3172
|
-
inPageLink: function inPageLinkF() {
|
|
3173
|
-
this.moveToAnchor();
|
|
3174
|
-
}, // Backward compatibility
|
|
3175
|
-
|
|
3176
|
-
pageInfo: function pageInfoFromParent() {
|
|
3177
|
-
var msgBody = getData();
|
|
3178
|
-
log('PageInfoFromParent called from parent: ' + msgBody);
|
|
3179
|
-
onPageInfo(JSON.parse(msgBody));
|
|
3180
|
-
log(' --');
|
|
3181
|
-
},
|
|
3182
|
-
|
|
3183
|
-
message: function messageFromParent() {
|
|
3184
|
-
var msgBody = getData();
|
|
3185
|
-
|
|
3186
|
-
log('onMessage called from parent: ' + msgBody);
|
|
3187
|
-
// eslint-disable-next-line sonarjs/no-extra-arguments
|
|
3188
|
-
onMessage(JSON.parse(msgBody));
|
|
3189
|
-
log(' --');
|
|
3190
|
-
}
|
|
3191
|
-
};
|
|
3192
|
-
|
|
3193
|
-
function isMessageForUs() {
|
|
3194
|
-
return msgID === ('' + event.data).slice(0, msgIdLen) // ''+ Protects against non-string messages
|
|
3195
|
-
}
|
|
3196
|
-
|
|
3197
|
-
function getMessageType() {
|
|
3198
|
-
return event.data.split(']')[1].split(':')[0]
|
|
3199
|
-
}
|
|
3200
|
-
|
|
3201
|
-
function getData() {
|
|
3202
|
-
return event.data.slice(event.data.indexOf(':') + 1)
|
|
3203
|
-
}
|
|
3204
|
-
|
|
3205
|
-
function isMiddleTier() {
|
|
3206
|
-
return (
|
|
3207
|
-
(!(typeof module !== 'undefined' && module.exports) &&
|
|
3208
|
-
'iFrameResize' in window) ||
|
|
3209
|
-
(window.jQuery !== undefined$1 &&
|
|
3210
|
-
'iFrameResize' in window.jQuery.prototype)
|
|
3211
|
-
)
|
|
3212
|
-
}
|
|
3213
|
-
|
|
3214
|
-
function isInitMsg() {
|
|
3215
|
-
// Test if this message is from a child below us. This is an ugly test, however, updating
|
|
3216
|
-
// the message format would break backwards compatibility.
|
|
3217
|
-
return event.data.split(':')[2] in { true: 1, false: 1 }
|
|
3218
|
-
}
|
|
3219
|
-
|
|
3220
|
-
function callFromParent() {
|
|
3221
|
-
var messageType = getMessageType();
|
|
3222
|
-
|
|
3223
|
-
if (messageType in processRequestFromParent) {
|
|
3224
|
-
processRequestFromParent[messageType]();
|
|
3225
|
-
} else if (!isMiddleTier() && !isInitMsg()) {
|
|
3226
|
-
warn('Unexpected message (' + event.data + ')');
|
|
3227
|
-
}
|
|
3228
|
-
}
|
|
3229
|
-
|
|
3230
|
-
function processMessage() {
|
|
3231
|
-
if (false === firstRun) {
|
|
3232
|
-
callFromParent();
|
|
3233
|
-
} else if (isInitMsg()) {
|
|
3234
|
-
processRequestFromParent.init();
|
|
3235
|
-
} else {
|
|
3236
|
-
log(
|
|
3237
|
-
'Ignored message of type "' +
|
|
3238
|
-
getMessageType() +
|
|
3239
|
-
'". Received before initialization.'
|
|
3240
|
-
);
|
|
3241
|
-
}
|
|
3242
|
-
}
|
|
3243
|
-
|
|
3244
|
-
if (isMessageForUs()) {
|
|
3245
|
-
processMessage();
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
|
|
3249
|
-
// Normally the parent kicks things off when it detects the iFrame has loaded.
|
|
3250
|
-
// If this script is async-loaded, then tell parent page to retry init.
|
|
3251
|
-
function chkLateLoaded() {
|
|
3252
|
-
if ('loading' !== document.readyState) {
|
|
3253
|
-
window.parent.postMessage('[iFrameResizerChild]Ready', '*');
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
|
-
|
|
3257
|
-
addEventListener(window, 'message', receiver);
|
|
3258
|
-
addEventListener(window, 'readystatechange', chkLateLoaded);
|
|
3259
|
-
chkLateLoaded();
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
})();
|
|
3263
|
-
|
|
3264
|
-
var CONTAINER_ID = "__authsignal-popup-container";
|
|
3265
|
-
var CONTENT_ID = "__authsignal-popup-content";
|
|
3266
|
-
var OVERLAY_ID = "__authsignal-popup-overlay";
|
|
3267
|
-
var STYLE_ID = "__authsignal-popup-style";
|
|
3268
|
-
var IFRAME_ID = "__authsignal-popup-iframe";
|
|
3269
|
-
var DEFAULT_WIDTH = "385px";
|
|
3270
|
-
var PopupHandler = /** @class */ (function () {
|
|
3271
|
-
function PopupHandler(_a) {
|
|
3272
|
-
var width = _a.width;
|
|
3273
|
-
this.popup = null;
|
|
3274
|
-
this.isHeightAutoResized = true;
|
|
3275
|
-
if (document.querySelector("#".concat(CONTAINER_ID))) {
|
|
3276
|
-
throw new Error("Multiple instances of Authsignal popup is not supported.");
|
|
3277
|
-
}
|
|
3278
|
-
this.create({ width: width });
|
|
3279
|
-
}
|
|
3280
|
-
PopupHandler.prototype.create = function (_a) {
|
|
3281
|
-
var _this = this;
|
|
3282
|
-
var _b = _a.width, width = _b === void 0 ? DEFAULT_WIDTH : _b;
|
|
3283
|
-
var isWidthValidCSSValue = CSS.supports("width", width);
|
|
3284
|
-
var popupWidth = width;
|
|
3285
|
-
if (!isWidthValidCSSValue) {
|
|
3286
|
-
console.warn("Invalid CSS value for `popupOptions.width`. Using default value instead.");
|
|
3287
|
-
popupWidth = DEFAULT_WIDTH;
|
|
3288
|
-
}
|
|
3289
|
-
// Create dialog container
|
|
3290
|
-
var container = document.createElement("div");
|
|
3291
|
-
container.setAttribute("id", CONTAINER_ID);
|
|
3292
|
-
container.setAttribute("aria-hidden", "true");
|
|
3293
|
-
// Create dialog overlay
|
|
3294
|
-
var overlay = document.createElement("div");
|
|
3295
|
-
overlay.setAttribute("id", OVERLAY_ID);
|
|
3296
|
-
overlay.setAttribute("data-a11y-dialog-hide", "true");
|
|
3297
|
-
// Create dialog content
|
|
3298
|
-
var content = document.createElement("div");
|
|
3299
|
-
content.setAttribute("id", CONTENT_ID);
|
|
3300
|
-
document.body.appendChild(container);
|
|
3301
|
-
// Create CSS for dialog
|
|
3302
|
-
var style = document.createElement("style");
|
|
3303
|
-
style.setAttribute("id", STYLE_ID);
|
|
3304
|
-
style.textContent = "\n #".concat(CONTAINER_ID, ",\n #").concat(OVERLAY_ID, " {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n\n #").concat(CONTAINER_ID, " {\n z-index: 2147483647;\n display: flex;\n }\n\n #").concat(CONTAINER_ID, "[aria-hidden='true'] {\n display: none;\n }\n\n #").concat(OVERLAY_ID, " {\n background-color: rgba(0, 0, 0, 0.18);\n }\n\n #").concat(CONTENT_ID, " {\n margin: auto;\n z-index: 2147483647;\n position: relative;\n background-color: transparent;\n border-radius: 8px;\n width: ").concat(popupWidth, ";\n }\n\n #").concat(CONTENT_ID, " iframe {\n width: 1px;\n min-width: 100%;\n border-radius: inherit;\n max-height: 65vh;\n }\n ");
|
|
3305
|
-
// Attach the created elements
|
|
3306
|
-
document.head.insertAdjacentElement("beforeend", style);
|
|
3307
|
-
container.appendChild(overlay);
|
|
3308
|
-
container.appendChild(content);
|
|
3309
|
-
this.popup = new A11yDialog(container);
|
|
3310
|
-
// Make sure to remove any trace of the dialog on hide
|
|
3311
|
-
this.popup.on("hide", function () {
|
|
3312
|
-
_this.destroy();
|
|
3313
|
-
});
|
|
3314
|
-
};
|
|
3315
|
-
PopupHandler.prototype.destroy = function () {
|
|
3316
|
-
var dialogEl = document.querySelector("#".concat(CONTAINER_ID));
|
|
3317
|
-
var styleEl = document.querySelector("#".concat(STYLE_ID));
|
|
3318
|
-
if (dialogEl && styleEl) {
|
|
3319
|
-
document.body.removeChild(dialogEl);
|
|
3320
|
-
document.head.removeChild(styleEl);
|
|
3321
|
-
}
|
|
3322
|
-
};
|
|
3323
|
-
PopupHandler.prototype.show = function (_a) {
|
|
3324
|
-
var _this = this;
|
|
3325
|
-
var url = _a.url;
|
|
3326
|
-
if (!this.popup) {
|
|
3327
|
-
throw new Error("Popup is not initialized");
|
|
3328
|
-
}
|
|
3329
|
-
var iframe = document.createElement("iframe");
|
|
3330
|
-
iframe.setAttribute("id", IFRAME_ID);
|
|
3331
|
-
iframe.setAttribute("name", "authsignal");
|
|
3332
|
-
iframe.setAttribute("title", "Authsignal multi-factor authentication");
|
|
3333
|
-
iframe.setAttribute("src", url);
|
|
3334
|
-
iframe.setAttribute("frameborder", "0");
|
|
3335
|
-
iframe.setAttribute("allow", "publickey-credentials-get *; clipboard-write");
|
|
3336
|
-
var dialogContent = document.querySelector("#".concat(CONTENT_ID));
|
|
3337
|
-
if (dialogContent) {
|
|
3338
|
-
dialogContent.appendChild(iframe);
|
|
3339
|
-
}
|
|
3340
|
-
// @ts-expect-error can't get typescript import to behave nicely, this works though
|
|
3341
|
-
iFrameResize({
|
|
3342
|
-
checkOrigin: false,
|
|
3343
|
-
scrolling: true,
|
|
3344
|
-
onInit: function () {
|
|
3345
|
-
var _a;
|
|
3346
|
-
(_a = _this.popup) === null || _a === void 0 ? void 0 : _a.show();
|
|
3347
|
-
}
|
|
3348
|
-
}, iframe);
|
|
3349
|
-
};
|
|
3350
|
-
PopupHandler.prototype.close = function () {
|
|
3351
|
-
if (!this.popup) {
|
|
3352
|
-
throw new Error("Popup is not initialized");
|
|
3353
|
-
}
|
|
3354
|
-
this.popup.hide();
|
|
3355
|
-
};
|
|
3356
|
-
PopupHandler.prototype.on = function (event, handler) {
|
|
3357
|
-
if (!this.popup) {
|
|
3358
|
-
throw new Error("Popup is not initialized");
|
|
3359
|
-
}
|
|
3360
|
-
this.popup.on(event, handler);
|
|
3361
|
-
};
|
|
3362
|
-
return PopupHandler;
|
|
3363
|
-
}());
|
|
3364
|
-
|
|
3365
|
-
/******************************************************************************
|
|
3366
|
-
Copyright (c) Microsoft Corporation.
|
|
3367
|
-
|
|
3368
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
3369
|
-
purpose with or without fee is hereby granted.
|
|
3370
|
-
|
|
3371
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
3372
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
3373
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
3374
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
3375
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
3376
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
3377
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
3378
|
-
***************************************************************************** */
|
|
3379
|
-
|
|
3380
|
-
function __rest(s, e) {
|
|
3381
|
-
var t = {};
|
|
3382
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
3383
|
-
t[p] = s[p];
|
|
3384
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
3385
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
3386
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
3387
|
-
t[p[i]] = s[p[i]];
|
|
3388
|
-
}
|
|
3389
|
-
return t;
|
|
3390
|
-
}
|
|
3391
|
-
|
|
3392
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
3393
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3394
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
3395
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
3396
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
3397
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
3398
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
3399
|
-
});
|
|
3400
|
-
}
|
|
3401
|
-
|
|
3402
|
-
function __generator(thisArg, body) {
|
|
3403
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
3404
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
3405
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
3406
|
-
function step(op) {
|
|
3407
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
3408
|
-
while (_) try {
|
|
3409
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
3410
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
3411
|
-
switch (op[0]) {
|
|
3412
|
-
case 0: case 1: t = op; break;
|
|
3413
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
3414
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
3415
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
3416
|
-
default:
|
|
3417
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
3418
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
3419
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
3420
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
3421
|
-
if (t[2]) _.ops.pop();
|
|
3422
|
-
_.trys.pop(); continue;
|
|
3423
|
-
}
|
|
3424
|
-
op = body.call(thisArg, _);
|
|
3425
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
3426
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
3427
|
-
}
|
|
3428
|
-
}
|
|
3429
|
-
|
|
3430
|
-
/* [@simplewebauthn/browser@7.2.0] */
|
|
3431
|
-
function utf8StringToBuffer(value) {
|
|
3432
|
-
return new TextEncoder().encode(value);
|
|
3433
|
-
}
|
|
3434
|
-
|
|
3435
|
-
function bufferToBase64URLString(buffer) {
|
|
3436
|
-
const bytes = new Uint8Array(buffer);
|
|
3437
|
-
let str = '';
|
|
3438
|
-
for (const charCode of bytes) {
|
|
3439
|
-
str += String.fromCharCode(charCode);
|
|
3440
|
-
}
|
|
3441
|
-
const base64String = btoa(str);
|
|
3442
|
-
return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
3443
|
-
}
|
|
3444
|
-
|
|
3445
|
-
function base64URLStringToBuffer(base64URLString) {
|
|
3446
|
-
const base64 = base64URLString.replace(/-/g, '+').replace(/_/g, '/');
|
|
3447
|
-
const padLength = (4 - (base64.length % 4)) % 4;
|
|
3448
|
-
const padded = base64.padEnd(base64.length + padLength, '=');
|
|
3449
|
-
const binary = atob(padded);
|
|
3450
|
-
const buffer = new ArrayBuffer(binary.length);
|
|
3451
|
-
const bytes = new Uint8Array(buffer);
|
|
3452
|
-
for (let i = 0; i < binary.length; i++) {
|
|
3453
|
-
bytes[i] = binary.charCodeAt(i);
|
|
3454
|
-
}
|
|
3455
|
-
return buffer;
|
|
3456
|
-
}
|
|
3457
|
-
|
|
3458
|
-
function browserSupportsWebAuthn() {
|
|
3459
|
-
return (window?.PublicKeyCredential !== undefined && typeof window.PublicKeyCredential === 'function');
|
|
3460
|
-
}
|
|
3461
|
-
|
|
3462
|
-
function toPublicKeyCredentialDescriptor(descriptor) {
|
|
3463
|
-
const { id } = descriptor;
|
|
3464
|
-
return {
|
|
3465
|
-
...descriptor,
|
|
3466
|
-
id: base64URLStringToBuffer(id),
|
|
3467
|
-
transports: descriptor.transports,
|
|
3468
|
-
};
|
|
3469
|
-
}
|
|
3470
|
-
|
|
3471
|
-
function isValidDomain(hostname) {
|
|
3472
|
-
return (hostname === 'localhost' || /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(hostname));
|
|
3473
|
-
}
|
|
3474
|
-
|
|
3475
|
-
class WebAuthnError extends Error {
|
|
3476
|
-
code;
|
|
3477
|
-
constructor({ message, code, cause, name, }) {
|
|
3478
|
-
super(message, { cause });
|
|
3479
|
-
this.name = name ?? cause.name;
|
|
3480
|
-
this.code = code;
|
|
3481
|
-
}
|
|
3482
|
-
}
|
|
3483
|
-
|
|
3484
|
-
function identifyRegistrationError({ error, options, }) {
|
|
3485
|
-
const { publicKey } = options;
|
|
3486
|
-
if (!publicKey) {
|
|
3487
|
-
throw Error('options was missing required publicKey property');
|
|
3488
|
-
}
|
|
3489
|
-
if (error.name === 'AbortError') {
|
|
3490
|
-
if (options.signal instanceof AbortSignal) {
|
|
3491
|
-
return new WebAuthnError({
|
|
3492
|
-
message: 'Registration ceremony was sent an abort signal',
|
|
3493
|
-
code: 'ERROR_CEREMONY_ABORTED',
|
|
3494
|
-
cause: error,
|
|
3495
|
-
});
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
else if (error.name === 'ConstraintError') {
|
|
3499
|
-
if (publicKey.authenticatorSelection?.requireResidentKey === true) {
|
|
3500
|
-
return new WebAuthnError({
|
|
3501
|
-
message: 'Discoverable credentials were required but no available authenticator supported it',
|
|
3502
|
-
code: 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT',
|
|
3503
|
-
cause: error,
|
|
3504
|
-
});
|
|
3505
|
-
}
|
|
3506
|
-
else if (publicKey.authenticatorSelection?.userVerification === 'required') {
|
|
3507
|
-
return new WebAuthnError({
|
|
3508
|
-
message: 'User verification was required but no available authenticator supported it',
|
|
3509
|
-
code: 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT',
|
|
3510
|
-
cause: error,
|
|
3511
|
-
});
|
|
3512
|
-
}
|
|
3513
|
-
}
|
|
3514
|
-
else if (error.name === 'InvalidStateError') {
|
|
3515
|
-
return new WebAuthnError({
|
|
3516
|
-
message: 'The authenticator was previously registered',
|
|
3517
|
-
code: 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED',
|
|
3518
|
-
cause: error
|
|
3519
|
-
});
|
|
3520
|
-
}
|
|
3521
|
-
else if (error.name === 'NotAllowedError') {
|
|
3522
|
-
return new WebAuthnError({
|
|
3523
|
-
message: error.message,
|
|
3524
|
-
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
|
|
3525
|
-
cause: error,
|
|
3526
|
-
});
|
|
3527
|
-
}
|
|
3528
|
-
else if (error.name === 'NotSupportedError') {
|
|
3529
|
-
const validPubKeyCredParams = publicKey.pubKeyCredParams.filter(param => param.type === 'public-key');
|
|
3530
|
-
if (validPubKeyCredParams.length === 0) {
|
|
3531
|
-
return new WebAuthnError({
|
|
3532
|
-
message: 'No entry in pubKeyCredParams was of type "public-key"',
|
|
3533
|
-
code: 'ERROR_MALFORMED_PUBKEYCREDPARAMS',
|
|
3534
|
-
cause: error,
|
|
3535
|
-
});
|
|
3536
|
-
}
|
|
3537
|
-
return new WebAuthnError({
|
|
3538
|
-
message: 'No available authenticator supported any of the specified pubKeyCredParams algorithms',
|
|
3539
|
-
code: 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG',
|
|
3540
|
-
cause: error,
|
|
3541
|
-
});
|
|
3542
|
-
}
|
|
3543
|
-
else if (error.name === 'SecurityError') {
|
|
3544
|
-
const effectiveDomain = window.location.hostname;
|
|
3545
|
-
if (!isValidDomain(effectiveDomain)) {
|
|
3546
|
-
return new WebAuthnError({
|
|
3547
|
-
message: `${window.location.hostname} is an invalid domain`,
|
|
3548
|
-
code: 'ERROR_INVALID_DOMAIN',
|
|
3549
|
-
cause: error
|
|
3550
|
-
});
|
|
3551
|
-
}
|
|
3552
|
-
else if (publicKey.rp.id !== effectiveDomain) {
|
|
3553
|
-
return new WebAuthnError({
|
|
3554
|
-
message: `The RP ID "${publicKey.rp.id}" is invalid for this domain`,
|
|
3555
|
-
code: 'ERROR_INVALID_RP_ID',
|
|
3556
|
-
cause: error,
|
|
3557
|
-
});
|
|
3558
|
-
}
|
|
3559
|
-
}
|
|
3560
|
-
else if (error.name === 'TypeError') {
|
|
3561
|
-
if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {
|
|
3562
|
-
return new WebAuthnError({
|
|
3563
|
-
message: 'User ID was not between 1 and 64 characters',
|
|
3564
|
-
code: 'ERROR_INVALID_USER_ID_LENGTH',
|
|
3565
|
-
cause: error,
|
|
3566
|
-
});
|
|
3567
|
-
}
|
|
3568
|
-
}
|
|
3569
|
-
else if (error.name === 'UnknownError') {
|
|
3570
|
-
return new WebAuthnError({
|
|
3571
|
-
message: 'The authenticator was unable to process the specified options, or could not create a new credential',
|
|
3572
|
-
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
|
|
3573
|
-
cause: error,
|
|
3574
|
-
});
|
|
3575
|
-
}
|
|
3576
|
-
return error;
|
|
3577
|
-
}
|
|
3578
|
-
|
|
3579
|
-
class WebAuthnAbortService {
|
|
3580
|
-
controller;
|
|
3581
|
-
createNewAbortSignal() {
|
|
3582
|
-
if (this.controller) {
|
|
3583
|
-
const abortError = new Error('Cancelling existing WebAuthn API call for new one');
|
|
3584
|
-
abortError.name = 'AbortError';
|
|
3585
|
-
this.controller.abort(abortError);
|
|
3586
|
-
}
|
|
3587
|
-
const newController = new AbortController();
|
|
3588
|
-
this.controller = newController;
|
|
3589
|
-
return newController.signal;
|
|
3590
|
-
}
|
|
3591
|
-
}
|
|
3592
|
-
const webauthnAbortService = new WebAuthnAbortService();
|
|
3593
|
-
|
|
3594
|
-
const attachments = ['cross-platform', 'platform'];
|
|
3595
|
-
function toAuthenticatorAttachment(attachment) {
|
|
3596
|
-
if (!attachment) {
|
|
3597
|
-
return;
|
|
3598
|
-
}
|
|
3599
|
-
if (attachments.indexOf(attachment) < 0) {
|
|
3600
|
-
return;
|
|
3601
|
-
}
|
|
3602
|
-
return attachment;
|
|
3603
|
-
}
|
|
3604
|
-
|
|
3605
|
-
async function startRegistration(creationOptionsJSON) {
|
|
3606
|
-
if (!browserSupportsWebAuthn()) {
|
|
3607
|
-
throw new Error('WebAuthn is not supported in this browser');
|
|
3608
|
-
}
|
|
3609
|
-
const publicKey = {
|
|
3610
|
-
...creationOptionsJSON,
|
|
3611
|
-
challenge: base64URLStringToBuffer(creationOptionsJSON.challenge),
|
|
3612
|
-
user: {
|
|
3613
|
-
...creationOptionsJSON.user,
|
|
3614
|
-
id: utf8StringToBuffer(creationOptionsJSON.user.id),
|
|
3615
|
-
},
|
|
3616
|
-
excludeCredentials: creationOptionsJSON.excludeCredentials?.map(toPublicKeyCredentialDescriptor),
|
|
3617
|
-
};
|
|
3618
|
-
const options = { publicKey };
|
|
3619
|
-
options.signal = webauthnAbortService.createNewAbortSignal();
|
|
3620
|
-
let credential;
|
|
3621
|
-
try {
|
|
3622
|
-
credential = (await navigator.credentials.create(options));
|
|
3623
|
-
}
|
|
3624
|
-
catch (err) {
|
|
3625
|
-
throw identifyRegistrationError({ error: err, options });
|
|
3626
|
-
}
|
|
3627
|
-
if (!credential) {
|
|
3628
|
-
throw new Error('Registration was not completed');
|
|
3629
|
-
}
|
|
3630
|
-
const { id, rawId, response, type } = credential;
|
|
3631
|
-
let transports = undefined;
|
|
3632
|
-
if (typeof response.getTransports === 'function') {
|
|
3633
|
-
transports = response.getTransports();
|
|
3634
|
-
}
|
|
3635
|
-
return {
|
|
3636
|
-
id,
|
|
3637
|
-
rawId: bufferToBase64URLString(rawId),
|
|
3638
|
-
response: {
|
|
3639
|
-
attestationObject: bufferToBase64URLString(response.attestationObject),
|
|
3640
|
-
clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
|
|
3641
|
-
transports,
|
|
3642
|
-
},
|
|
3643
|
-
type,
|
|
3644
|
-
clientExtensionResults: credential.getClientExtensionResults(),
|
|
3645
|
-
authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment),
|
|
3646
|
-
};
|
|
3647
|
-
}
|
|
3648
|
-
|
|
3649
|
-
function bufferToUTF8String(value) {
|
|
3650
|
-
return new TextDecoder('utf-8').decode(value);
|
|
3651
|
-
}
|
|
3652
|
-
|
|
3653
|
-
async function browserSupportsWebAuthnAutofill() {
|
|
3654
|
-
const globalPublicKeyCredential = window.PublicKeyCredential;
|
|
3655
|
-
return (globalPublicKeyCredential.isConditionalMediationAvailable !== undefined &&
|
|
3656
|
-
globalPublicKeyCredential.isConditionalMediationAvailable());
|
|
3657
|
-
}
|
|
3658
|
-
|
|
3659
|
-
function identifyAuthenticationError({ error, options, }) {
|
|
3660
|
-
const { publicKey } = options;
|
|
3661
|
-
if (!publicKey) {
|
|
3662
|
-
throw Error('options was missing required publicKey property');
|
|
3663
|
-
}
|
|
3664
|
-
if (error.name === 'AbortError') {
|
|
3665
|
-
if (options.signal instanceof AbortSignal) {
|
|
3666
|
-
return new WebAuthnError({
|
|
3667
|
-
message: 'Authentication ceremony was sent an abort signal',
|
|
3668
|
-
code: 'ERROR_CEREMONY_ABORTED',
|
|
3669
|
-
cause: error,
|
|
3670
|
-
});
|
|
3671
|
-
}
|
|
3672
|
-
}
|
|
3673
|
-
else if (error.name === 'NotAllowedError') {
|
|
3674
|
-
return new WebAuthnError({
|
|
3675
|
-
message: error.message,
|
|
3676
|
-
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
|
|
3677
|
-
cause: error,
|
|
3678
|
-
});
|
|
3679
|
-
}
|
|
3680
|
-
else if (error.name === 'SecurityError') {
|
|
3681
|
-
const effectiveDomain = window.location.hostname;
|
|
3682
|
-
if (!isValidDomain(effectiveDomain)) {
|
|
3683
|
-
return new WebAuthnError({
|
|
3684
|
-
message: `${window.location.hostname} is an invalid domain`,
|
|
3685
|
-
code: 'ERROR_INVALID_DOMAIN',
|
|
3686
|
-
cause: error,
|
|
3687
|
-
});
|
|
3688
|
-
}
|
|
3689
|
-
else if (publicKey.rpId !== effectiveDomain) {
|
|
3690
|
-
return new WebAuthnError({
|
|
3691
|
-
message: `The RP ID "${publicKey.rpId}" is invalid for this domain`,
|
|
3692
|
-
code: 'ERROR_INVALID_RP_ID',
|
|
3693
|
-
cause: error,
|
|
3694
|
-
});
|
|
3695
|
-
}
|
|
3696
|
-
}
|
|
3697
|
-
else if (error.name === 'UnknownError') {
|
|
3698
|
-
return new WebAuthnError({
|
|
3699
|
-
message: 'The authenticator was unable to process the specified options, or could not create a new assertion signature',
|
|
3700
|
-
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
|
|
3701
|
-
cause: error,
|
|
3702
|
-
});
|
|
3703
|
-
}
|
|
3704
|
-
return error;
|
|
3705
|
-
}
|
|
3706
|
-
|
|
3707
|
-
async function startAuthentication(requestOptionsJSON, useBrowserAutofill = false) {
|
|
3708
|
-
if (!browserSupportsWebAuthn()) {
|
|
3709
|
-
throw new Error('WebAuthn is not supported in this browser');
|
|
3710
|
-
}
|
|
3711
|
-
let allowCredentials;
|
|
3712
|
-
if (requestOptionsJSON.allowCredentials?.length !== 0) {
|
|
3713
|
-
allowCredentials = requestOptionsJSON.allowCredentials?.map(toPublicKeyCredentialDescriptor);
|
|
3714
|
-
}
|
|
3715
|
-
const publicKey = {
|
|
3716
|
-
...requestOptionsJSON,
|
|
3717
|
-
challenge: base64URLStringToBuffer(requestOptionsJSON.challenge),
|
|
3718
|
-
allowCredentials,
|
|
3719
|
-
};
|
|
3720
|
-
const options = {};
|
|
3721
|
-
if (useBrowserAutofill) {
|
|
3722
|
-
if (!(await browserSupportsWebAuthnAutofill())) {
|
|
3723
|
-
throw Error('Browser does not support WebAuthn autofill');
|
|
3724
|
-
}
|
|
3725
|
-
const eligibleInputs = document.querySelectorAll("input[autocomplete*='webauthn']");
|
|
3726
|
-
if (eligibleInputs.length < 1) {
|
|
3727
|
-
throw Error('No <input> with `"webauthn"` in its `autocomplete` attribute was detected');
|
|
3728
|
-
}
|
|
3729
|
-
options.mediation = 'conditional';
|
|
3730
|
-
publicKey.allowCredentials = [];
|
|
3731
|
-
}
|
|
3732
|
-
options.publicKey = publicKey;
|
|
3733
|
-
options.signal = webauthnAbortService.createNewAbortSignal();
|
|
3734
|
-
let credential;
|
|
3735
|
-
try {
|
|
3736
|
-
credential = (await navigator.credentials.get(options));
|
|
3737
|
-
}
|
|
3738
|
-
catch (err) {
|
|
3739
|
-
throw identifyAuthenticationError({ error: err, options });
|
|
3740
|
-
}
|
|
3741
|
-
if (!credential) {
|
|
3742
|
-
throw new Error('Authentication was not completed');
|
|
3743
|
-
}
|
|
3744
|
-
const { id, rawId, response, type } = credential;
|
|
3745
|
-
let userHandle = undefined;
|
|
3746
|
-
if (response.userHandle) {
|
|
3747
|
-
userHandle = bufferToUTF8String(response.userHandle);
|
|
3748
|
-
}
|
|
3749
|
-
return {
|
|
3750
|
-
id,
|
|
3751
|
-
rawId: bufferToBase64URLString(rawId),
|
|
3752
|
-
response: {
|
|
3753
|
-
authenticatorData: bufferToBase64URLString(response.authenticatorData),
|
|
3754
|
-
clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
|
|
3755
|
-
signature: bufferToBase64URLString(response.signature),
|
|
3756
|
-
userHandle,
|
|
3757
|
-
},
|
|
3758
|
-
type,
|
|
3759
|
-
clientExtensionResults: credential.getClientExtensionResults(),
|
|
3760
|
-
authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment),
|
|
3761
|
-
};
|
|
3762
|
-
}
|
|
3763
|
-
|
|
3764
|
-
// eslint-lint-disable-next-line @typescript-eslint/naming-convention
|
|
3765
|
-
class HTTPError extends Error {
|
|
3766
|
-
constructor(response, request, options) {
|
|
3767
|
-
const code = (response.status || response.status === 0) ? response.status : '';
|
|
3768
|
-
const title = response.statusText || '';
|
|
3769
|
-
const status = `${code} ${title}`.trim();
|
|
3770
|
-
const reason = status ? `status code ${status}` : 'an unknown error';
|
|
3771
|
-
super(`Request failed with ${reason}`);
|
|
3772
|
-
Object.defineProperty(this, "response", {
|
|
3773
|
-
enumerable: true,
|
|
3774
|
-
configurable: true,
|
|
3775
|
-
writable: true,
|
|
3776
|
-
value: void 0
|
|
3777
|
-
});
|
|
3778
|
-
Object.defineProperty(this, "request", {
|
|
3779
|
-
enumerable: true,
|
|
3780
|
-
configurable: true,
|
|
3781
|
-
writable: true,
|
|
3782
|
-
value: void 0
|
|
3783
|
-
});
|
|
3784
|
-
Object.defineProperty(this, "options", {
|
|
3785
|
-
enumerable: true,
|
|
3786
|
-
configurable: true,
|
|
3787
|
-
writable: true,
|
|
3788
|
-
value: void 0
|
|
3789
|
-
});
|
|
3790
|
-
this.name = 'HTTPError';
|
|
3791
|
-
this.response = response;
|
|
3792
|
-
this.request = request;
|
|
3793
|
-
this.options = options;
|
|
3794
|
-
}
|
|
3795
|
-
}
|
|
3796
|
-
|
|
3797
|
-
class TimeoutError extends Error {
|
|
3798
|
-
constructor(request) {
|
|
3799
|
-
super('Request timed out');
|
|
3800
|
-
Object.defineProperty(this, "request", {
|
|
3801
|
-
enumerable: true,
|
|
3802
|
-
configurable: true,
|
|
3803
|
-
writable: true,
|
|
3804
|
-
value: void 0
|
|
3805
|
-
});
|
|
3806
|
-
this.name = 'TimeoutError';
|
|
3807
|
-
this.request = request;
|
|
3808
|
-
}
|
|
3809
|
-
}
|
|
3810
|
-
|
|
3811
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
3812
|
-
const isObject = (value) => value !== null && typeof value === 'object';
|
|
3813
|
-
|
|
3814
|
-
const validateAndMerge = (...sources) => {
|
|
3815
|
-
for (const source of sources) {
|
|
3816
|
-
if ((!isObject(source) || Array.isArray(source)) && typeof source !== 'undefined') {
|
|
3817
|
-
throw new TypeError('The `options` argument must be an object');
|
|
3818
|
-
}
|
|
3819
|
-
}
|
|
3820
|
-
return deepMerge({}, ...sources);
|
|
3821
|
-
};
|
|
3822
|
-
const mergeHeaders = (source1 = {}, source2 = {}) => {
|
|
3823
|
-
const result = new globalThis.Headers(source1);
|
|
3824
|
-
const isHeadersInstance = source2 instanceof globalThis.Headers;
|
|
3825
|
-
const source = new globalThis.Headers(source2);
|
|
3826
|
-
for (const [key, value] of source.entries()) {
|
|
3827
|
-
if ((isHeadersInstance && value === 'undefined') || value === undefined) {
|
|
3828
|
-
result.delete(key);
|
|
3829
|
-
}
|
|
3830
|
-
else {
|
|
3831
|
-
result.set(key, value);
|
|
3832
|
-
}
|
|
3833
|
-
}
|
|
3834
|
-
return result;
|
|
3835
|
-
};
|
|
3836
|
-
// TODO: Make this strongly-typed (no `any`).
|
|
3837
|
-
const deepMerge = (...sources) => {
|
|
3838
|
-
let returnValue = {};
|
|
3839
|
-
let headers = {};
|
|
3840
|
-
for (const source of sources) {
|
|
3841
|
-
if (Array.isArray(source)) {
|
|
3842
|
-
if (!Array.isArray(returnValue)) {
|
|
3843
|
-
returnValue = [];
|
|
3844
|
-
}
|
|
3845
|
-
returnValue = [...returnValue, ...source];
|
|
3846
|
-
}
|
|
3847
|
-
else if (isObject(source)) {
|
|
3848
|
-
for (let [key, value] of Object.entries(source)) {
|
|
3849
|
-
if (isObject(value) && key in returnValue) {
|
|
3850
|
-
value = deepMerge(returnValue[key], value);
|
|
3851
|
-
}
|
|
3852
|
-
returnValue = { ...returnValue, [key]: value };
|
|
3853
|
-
}
|
|
3854
|
-
if (isObject(source.headers)) {
|
|
3855
|
-
headers = mergeHeaders(headers, source.headers);
|
|
3856
|
-
returnValue.headers = headers;
|
|
3857
|
-
}
|
|
3858
|
-
}
|
|
3859
|
-
}
|
|
3860
|
-
return returnValue;
|
|
3861
|
-
};
|
|
3862
|
-
|
|
3863
|
-
const supportsRequestStreams = (() => {
|
|
3864
|
-
let duplexAccessed = false;
|
|
3865
|
-
let hasContentType = false;
|
|
3866
|
-
const supportsReadableStream = typeof globalThis.ReadableStream === 'function';
|
|
3867
|
-
const supportsRequest = typeof globalThis.Request === 'function';
|
|
3868
|
-
if (supportsReadableStream && supportsRequest) {
|
|
3869
|
-
hasContentType = new globalThis.Request('https://a.com', {
|
|
3870
|
-
body: new globalThis.ReadableStream(),
|
|
3871
|
-
method: 'POST',
|
|
3872
|
-
// @ts-expect-error - Types are outdated.
|
|
3873
|
-
get duplex() {
|
|
3874
|
-
duplexAccessed = true;
|
|
3875
|
-
return 'half';
|
|
3876
|
-
},
|
|
3877
|
-
}).headers.has('Content-Type');
|
|
3878
|
-
}
|
|
3879
|
-
return duplexAccessed && !hasContentType;
|
|
3880
|
-
})();
|
|
3881
|
-
const supportsAbortController = typeof globalThis.AbortController === 'function';
|
|
3882
|
-
const supportsResponseStreams = typeof globalThis.ReadableStream === 'function';
|
|
3883
|
-
const supportsFormData = typeof globalThis.FormData === 'function';
|
|
3884
|
-
const requestMethods = ['get', 'post', 'put', 'patch', 'head', 'delete'];
|
|
3885
|
-
const responseTypes = {
|
|
3886
|
-
json: 'application/json',
|
|
3887
|
-
text: 'text/*',
|
|
3888
|
-
formData: 'multipart/form-data',
|
|
3889
|
-
arrayBuffer: '*/*',
|
|
3890
|
-
blob: '*/*',
|
|
3891
|
-
};
|
|
3892
|
-
// The maximum value of a 32bit int (see issue #117)
|
|
3893
|
-
const maxSafeTimeout = 2147483647;
|
|
3894
|
-
const stop = Symbol('stop');
|
|
3895
|
-
|
|
3896
|
-
const normalizeRequestMethod = (input) => requestMethods.includes(input) ? input.toUpperCase() : input;
|
|
3897
|
-
const retryMethods = ['get', 'put', 'head', 'delete', 'options', 'trace'];
|
|
3898
|
-
const retryStatusCodes = [408, 413, 429, 500, 502, 503, 504];
|
|
3899
|
-
const retryAfterStatusCodes = [413, 429, 503];
|
|
3900
|
-
const defaultRetryOptions = {
|
|
3901
|
-
limit: 2,
|
|
3902
|
-
methods: retryMethods,
|
|
3903
|
-
statusCodes: retryStatusCodes,
|
|
3904
|
-
afterStatusCodes: retryAfterStatusCodes,
|
|
3905
|
-
maxRetryAfter: Number.POSITIVE_INFINITY,
|
|
3906
|
-
backoffLimit: Number.POSITIVE_INFINITY,
|
|
3907
|
-
};
|
|
3908
|
-
const normalizeRetryOptions = (retry = {}) => {
|
|
3909
|
-
if (typeof retry === 'number') {
|
|
3910
|
-
return {
|
|
3911
|
-
...defaultRetryOptions,
|
|
3912
|
-
limit: retry,
|
|
3913
|
-
};
|
|
3914
|
-
}
|
|
3915
|
-
if (retry.methods && !Array.isArray(retry.methods)) {
|
|
3916
|
-
throw new Error('retry.methods must be an array');
|
|
3917
|
-
}
|
|
3918
|
-
if (retry.statusCodes && !Array.isArray(retry.statusCodes)) {
|
|
3919
|
-
throw new Error('retry.statusCodes must be an array');
|
|
3920
|
-
}
|
|
3921
|
-
return {
|
|
3922
|
-
...defaultRetryOptions,
|
|
3923
|
-
...retry,
|
|
3924
|
-
afterStatusCodes: retryAfterStatusCodes,
|
|
3925
|
-
};
|
|
3926
|
-
};
|
|
3927
|
-
|
|
3928
|
-
// `Promise.race()` workaround (#91)
|
|
3929
|
-
async function timeout(request, abortController, options) {
|
|
3930
|
-
return new Promise((resolve, reject) => {
|
|
3931
|
-
const timeoutId = setTimeout(() => {
|
|
3932
|
-
if (abortController) {
|
|
3933
|
-
abortController.abort();
|
|
3934
|
-
}
|
|
3935
|
-
reject(new TimeoutError(request));
|
|
3936
|
-
}, options.timeout);
|
|
3937
|
-
void options
|
|
3938
|
-
.fetch(request)
|
|
3939
|
-
.then(resolve)
|
|
3940
|
-
.catch(reject)
|
|
3941
|
-
.then(() => {
|
|
3942
|
-
clearTimeout(timeoutId);
|
|
3943
|
-
});
|
|
3944
|
-
});
|
|
3945
|
-
}
|
|
3946
|
-
|
|
3947
|
-
// DOMException is supported on most modern browsers and Node.js 18+.
|
|
3948
|
-
// @see https://developer.mozilla.org/en-US/docs/Web/API/DOMException#browser_compatibility
|
|
3949
|
-
const isDomExceptionSupported = Boolean(globalThis.DOMException);
|
|
3950
|
-
// TODO: When targeting Node.js 18, use `signal.throwIfAborted()` (https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/throwIfAborted)
|
|
3951
|
-
function composeAbortError(signal) {
|
|
3952
|
-
/*
|
|
3953
|
-
NOTE: Use DomException with AbortError name as specified in MDN docs (https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort)
|
|
3954
|
-
> When abort() is called, the fetch() promise rejects with an Error of type DOMException, with name AbortError.
|
|
3955
|
-
*/
|
|
3956
|
-
if (isDomExceptionSupported) {
|
|
3957
|
-
return new DOMException(signal?.reason ?? 'The operation was aborted.', 'AbortError');
|
|
3958
|
-
}
|
|
3959
|
-
// DOMException not supported. Fall back to use of error and override name.
|
|
3960
|
-
const error = new Error(signal?.reason ?? 'The operation was aborted.');
|
|
3961
|
-
error.name = 'AbortError';
|
|
3962
|
-
return error;
|
|
3963
|
-
}
|
|
3964
|
-
|
|
3965
|
-
// https://github.com/sindresorhus/delay/tree/ab98ae8dfcb38e1593286c94d934e70d14a4e111
|
|
3966
|
-
async function delay(ms, { signal }) {
|
|
3967
|
-
return new Promise((resolve, reject) => {
|
|
3968
|
-
if (signal) {
|
|
3969
|
-
if (signal.aborted) {
|
|
3970
|
-
reject(composeAbortError(signal));
|
|
3971
|
-
return;
|
|
3972
|
-
}
|
|
3973
|
-
signal.addEventListener('abort', handleAbort, { once: true });
|
|
3974
|
-
}
|
|
3975
|
-
function handleAbort() {
|
|
3976
|
-
reject(composeAbortError(signal));
|
|
3977
|
-
clearTimeout(timeoutId);
|
|
3978
|
-
}
|
|
3979
|
-
const timeoutId = setTimeout(() => {
|
|
3980
|
-
signal?.removeEventListener('abort', handleAbort);
|
|
3981
|
-
resolve();
|
|
3982
|
-
}, ms);
|
|
3983
|
-
});
|
|
3984
|
-
}
|
|
3985
|
-
|
|
3986
|
-
class Ky {
|
|
3987
|
-
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
3988
|
-
static create(input, options) {
|
|
3989
|
-
const ky = new Ky(input, options);
|
|
3990
|
-
const fn = async () => {
|
|
3991
|
-
if (ky._options.timeout > maxSafeTimeout) {
|
|
3992
|
-
throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`);
|
|
3993
|
-
}
|
|
3994
|
-
// Delay the fetch so that body method shortcuts can set the Accept header
|
|
3995
|
-
await Promise.resolve();
|
|
3996
|
-
let response = await ky._fetch();
|
|
3997
|
-
for (const hook of ky._options.hooks.afterResponse) {
|
|
3998
|
-
// eslint-disable-next-line no-await-in-loop
|
|
3999
|
-
const modifiedResponse = await hook(ky.request, ky._options, ky._decorateResponse(response.clone()));
|
|
4000
|
-
if (modifiedResponse instanceof globalThis.Response) {
|
|
4001
|
-
response = modifiedResponse;
|
|
4002
|
-
}
|
|
4003
|
-
}
|
|
4004
|
-
ky._decorateResponse(response);
|
|
4005
|
-
if (!response.ok && ky._options.throwHttpErrors) {
|
|
4006
|
-
let error = new HTTPError(response, ky.request, ky._options);
|
|
4007
|
-
for (const hook of ky._options.hooks.beforeError) {
|
|
4008
|
-
// eslint-disable-next-line no-await-in-loop
|
|
4009
|
-
error = await hook(error);
|
|
4010
|
-
}
|
|
4011
|
-
throw error;
|
|
4012
|
-
}
|
|
4013
|
-
// If `onDownloadProgress` is passed, it uses the stream API internally
|
|
4014
|
-
/* istanbul ignore next */
|
|
4015
|
-
if (ky._options.onDownloadProgress) {
|
|
4016
|
-
if (typeof ky._options.onDownloadProgress !== 'function') {
|
|
4017
|
-
throw new TypeError('The `onDownloadProgress` option must be a function');
|
|
4018
|
-
}
|
|
4019
|
-
if (!supportsResponseStreams) {
|
|
4020
|
-
throw new Error('Streams are not supported in your environment. `ReadableStream` is missing.');
|
|
4021
|
-
}
|
|
4022
|
-
return ky._stream(response.clone(), ky._options.onDownloadProgress);
|
|
4023
|
-
}
|
|
4024
|
-
return response;
|
|
4025
|
-
};
|
|
4026
|
-
const isRetriableMethod = ky._options.retry.methods.includes(ky.request.method.toLowerCase());
|
|
4027
|
-
const result = (isRetriableMethod ? ky._retry(fn) : fn());
|
|
4028
|
-
for (const [type, mimeType] of Object.entries(responseTypes)) {
|
|
4029
|
-
result[type] = async () => {
|
|
4030
|
-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
4031
|
-
ky.request.headers.set('accept', ky.request.headers.get('accept') || mimeType);
|
|
4032
|
-
const awaitedResult = await result;
|
|
4033
|
-
const response = awaitedResult.clone();
|
|
4034
|
-
if (type === 'json') {
|
|
4035
|
-
if (response.status === 204) {
|
|
4036
|
-
return '';
|
|
4037
|
-
}
|
|
4038
|
-
const arrayBuffer = await response.clone().arrayBuffer();
|
|
4039
|
-
const responseSize = arrayBuffer.byteLength;
|
|
4040
|
-
if (responseSize === 0) {
|
|
4041
|
-
return '';
|
|
4042
|
-
}
|
|
4043
|
-
if (options.parseJson) {
|
|
4044
|
-
return options.parseJson(await response.text());
|
|
4045
|
-
}
|
|
4046
|
-
}
|
|
4047
|
-
return response[type]();
|
|
4048
|
-
};
|
|
4049
|
-
}
|
|
4050
|
-
return result;
|
|
4051
|
-
}
|
|
4052
|
-
// eslint-disable-next-line complexity
|
|
4053
|
-
constructor(input, options = {}) {
|
|
4054
|
-
Object.defineProperty(this, "request", {
|
|
4055
|
-
enumerable: true,
|
|
4056
|
-
configurable: true,
|
|
4057
|
-
writable: true,
|
|
4058
|
-
value: void 0
|
|
4059
|
-
});
|
|
4060
|
-
Object.defineProperty(this, "abortController", {
|
|
4061
|
-
enumerable: true,
|
|
4062
|
-
configurable: true,
|
|
4063
|
-
writable: true,
|
|
4064
|
-
value: void 0
|
|
4065
|
-
});
|
|
4066
|
-
Object.defineProperty(this, "_retryCount", {
|
|
4067
|
-
enumerable: true,
|
|
4068
|
-
configurable: true,
|
|
4069
|
-
writable: true,
|
|
4070
|
-
value: 0
|
|
4071
|
-
});
|
|
4072
|
-
Object.defineProperty(this, "_input", {
|
|
4073
|
-
enumerable: true,
|
|
4074
|
-
configurable: true,
|
|
4075
|
-
writable: true,
|
|
4076
|
-
value: void 0
|
|
4077
|
-
});
|
|
4078
|
-
Object.defineProperty(this, "_options", {
|
|
4079
|
-
enumerable: true,
|
|
4080
|
-
configurable: true,
|
|
4081
|
-
writable: true,
|
|
4082
|
-
value: void 0
|
|
4083
|
-
});
|
|
4084
|
-
this._input = input;
|
|
4085
|
-
this._options = {
|
|
4086
|
-
// TODO: credentials can be removed when the spec change is implemented in all browsers. Context: https://www.chromestatus.com/feature/4539473312350208
|
|
4087
|
-
credentials: this._input.credentials || 'same-origin',
|
|
4088
|
-
...options,
|
|
4089
|
-
headers: mergeHeaders(this._input.headers, options.headers),
|
|
4090
|
-
hooks: deepMerge({
|
|
4091
|
-
beforeRequest: [],
|
|
4092
|
-
beforeRetry: [],
|
|
4093
|
-
beforeError: [],
|
|
4094
|
-
afterResponse: [],
|
|
4095
|
-
}, options.hooks),
|
|
4096
|
-
method: normalizeRequestMethod(options.method ?? this._input.method),
|
|
4097
|
-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
4098
|
-
prefixUrl: String(options.prefixUrl || ''),
|
|
4099
|
-
retry: normalizeRetryOptions(options.retry),
|
|
4100
|
-
throwHttpErrors: options.throwHttpErrors !== false,
|
|
4101
|
-
timeout: typeof options.timeout === 'undefined' ? 10000 : options.timeout,
|
|
4102
|
-
fetch: options.fetch ?? globalThis.fetch.bind(globalThis),
|
|
4103
|
-
};
|
|
4104
|
-
if (typeof this._input !== 'string' && !(this._input instanceof URL || this._input instanceof globalThis.Request)) {
|
|
4105
|
-
throw new TypeError('`input` must be a string, URL, or Request');
|
|
4106
|
-
}
|
|
4107
|
-
if (this._options.prefixUrl && typeof this._input === 'string') {
|
|
4108
|
-
if (this._input.startsWith('/')) {
|
|
4109
|
-
throw new Error('`input` must not begin with a slash when using `prefixUrl`');
|
|
4110
|
-
}
|
|
4111
|
-
if (!this._options.prefixUrl.endsWith('/')) {
|
|
4112
|
-
this._options.prefixUrl += '/';
|
|
4113
|
-
}
|
|
4114
|
-
this._input = this._options.prefixUrl + this._input;
|
|
4115
|
-
}
|
|
4116
|
-
if (supportsAbortController) {
|
|
4117
|
-
this.abortController = new globalThis.AbortController();
|
|
4118
|
-
if (this._options.signal) {
|
|
4119
|
-
const originalSignal = this._options.signal;
|
|
4120
|
-
this._options.signal.addEventListener('abort', () => {
|
|
4121
|
-
this.abortController.abort(originalSignal.reason);
|
|
4122
|
-
});
|
|
4123
|
-
}
|
|
4124
|
-
this._options.signal = this.abortController.signal;
|
|
4125
|
-
}
|
|
4126
|
-
if (supportsRequestStreams) {
|
|
4127
|
-
// @ts-expect-error - Types are outdated.
|
|
4128
|
-
this._options.duplex = 'half';
|
|
4129
|
-
}
|
|
4130
|
-
this.request = new globalThis.Request(this._input, this._options);
|
|
4131
|
-
if (this._options.searchParams) {
|
|
4132
|
-
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
4133
|
-
const textSearchParams = typeof this._options.searchParams === 'string'
|
|
4134
|
-
? this._options.searchParams.replace(/^\?/, '')
|
|
4135
|
-
: new URLSearchParams(this._options.searchParams).toString();
|
|
4136
|
-
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
4137
|
-
const searchParams = '?' + textSearchParams;
|
|
4138
|
-
const url = this.request.url.replace(/(?:\?.*?)?(?=#|$)/, searchParams);
|
|
4139
|
-
// To provide correct form boundary, Content-Type header should be deleted each time when new Request instantiated from another one
|
|
4140
|
-
if (((supportsFormData && this._options.body instanceof globalThis.FormData)
|
|
4141
|
-
|| this._options.body instanceof URLSearchParams) && !(this._options.headers && this._options.headers['content-type'])) {
|
|
4142
|
-
this.request.headers.delete('content-type');
|
|
4143
|
-
}
|
|
4144
|
-
// The spread of `this.request` is required as otherwise it misses the `duplex` option for some reason and throws.
|
|
4145
|
-
this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options);
|
|
4146
|
-
}
|
|
4147
|
-
if (this._options.json !== undefined) {
|
|
4148
|
-
this._options.body = JSON.stringify(this._options.json);
|
|
4149
|
-
this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
|
|
4150
|
-
this.request = new globalThis.Request(this.request, { body: this._options.body });
|
|
4151
|
-
}
|
|
4152
|
-
}
|
|
4153
|
-
_calculateRetryDelay(error) {
|
|
4154
|
-
this._retryCount++;
|
|
4155
|
-
if (this._retryCount < this._options.retry.limit && !(error instanceof TimeoutError)) {
|
|
4156
|
-
if (error instanceof HTTPError) {
|
|
4157
|
-
if (!this._options.retry.statusCodes.includes(error.response.status)) {
|
|
4158
|
-
return 0;
|
|
4159
|
-
}
|
|
4160
|
-
const retryAfter = error.response.headers.get('Retry-After');
|
|
4161
|
-
if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
|
|
4162
|
-
let after = Number(retryAfter);
|
|
4163
|
-
if (Number.isNaN(after)) {
|
|
4164
|
-
after = Date.parse(retryAfter) - Date.now();
|
|
4165
|
-
}
|
|
4166
|
-
else {
|
|
4167
|
-
after *= 1000;
|
|
4168
|
-
}
|
|
4169
|
-
if (typeof this._options.retry.maxRetryAfter !== 'undefined' && after > this._options.retry.maxRetryAfter) {
|
|
4170
|
-
return 0;
|
|
4171
|
-
}
|
|
4172
|
-
return after;
|
|
4173
|
-
}
|
|
4174
|
-
if (error.response.status === 413) {
|
|
4175
|
-
return 0;
|
|
4176
|
-
}
|
|
4177
|
-
}
|
|
4178
|
-
const BACKOFF_FACTOR = 0.3;
|
|
4179
|
-
return Math.min(this._options.retry.backoffLimit, BACKOFF_FACTOR * (2 ** (this._retryCount - 1)) * 1000);
|
|
4180
|
-
}
|
|
4181
|
-
return 0;
|
|
4182
|
-
}
|
|
4183
|
-
_decorateResponse(response) {
|
|
4184
|
-
if (this._options.parseJson) {
|
|
4185
|
-
response.json = async () => this._options.parseJson(await response.text());
|
|
4186
|
-
}
|
|
4187
|
-
return response;
|
|
4188
|
-
}
|
|
4189
|
-
async _retry(fn) {
|
|
4190
|
-
try {
|
|
4191
|
-
return await fn();
|
|
4192
|
-
// eslint-disable-next-line @typescript-eslint/no-implicit-any-catch
|
|
4193
|
-
}
|
|
4194
|
-
catch (error) {
|
|
4195
|
-
const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
|
|
4196
|
-
if (ms !== 0 && this._retryCount > 0) {
|
|
4197
|
-
await delay(ms, { signal: this._options.signal });
|
|
4198
|
-
for (const hook of this._options.hooks.beforeRetry) {
|
|
4199
|
-
// eslint-disable-next-line no-await-in-loop
|
|
4200
|
-
const hookResult = await hook({
|
|
4201
|
-
request: this.request,
|
|
4202
|
-
options: this._options,
|
|
4203
|
-
error: error,
|
|
4204
|
-
retryCount: this._retryCount,
|
|
4205
|
-
});
|
|
4206
|
-
// If `stop` is returned from the hook, the retry process is stopped
|
|
4207
|
-
if (hookResult === stop) {
|
|
4208
|
-
return;
|
|
4209
|
-
}
|
|
4210
|
-
}
|
|
4211
|
-
return this._retry(fn);
|
|
4212
|
-
}
|
|
4213
|
-
throw error;
|
|
4214
|
-
}
|
|
4215
|
-
}
|
|
4216
|
-
async _fetch() {
|
|
4217
|
-
for (const hook of this._options.hooks.beforeRequest) {
|
|
4218
|
-
// eslint-disable-next-line no-await-in-loop
|
|
4219
|
-
const result = await hook(this.request, this._options);
|
|
4220
|
-
if (result instanceof Request) {
|
|
4221
|
-
this.request = result;
|
|
4222
|
-
break;
|
|
4223
|
-
}
|
|
4224
|
-
if (result instanceof Response) {
|
|
4225
|
-
return result;
|
|
4226
|
-
}
|
|
4227
|
-
}
|
|
4228
|
-
if (this._options.timeout === false) {
|
|
4229
|
-
return this._options.fetch(this.request.clone());
|
|
4230
|
-
}
|
|
4231
|
-
return timeout(this.request.clone(), this.abortController, this._options);
|
|
4232
|
-
}
|
|
4233
|
-
/* istanbul ignore next */
|
|
4234
|
-
_stream(response, onDownloadProgress) {
|
|
4235
|
-
const totalBytes = Number(response.headers.get('content-length')) || 0;
|
|
4236
|
-
let transferredBytes = 0;
|
|
4237
|
-
if (response.status === 204) {
|
|
4238
|
-
if (onDownloadProgress) {
|
|
4239
|
-
onDownloadProgress({ percent: 1, totalBytes, transferredBytes }, new Uint8Array());
|
|
4240
|
-
}
|
|
4241
|
-
return new globalThis.Response(null, {
|
|
4242
|
-
status: response.status,
|
|
4243
|
-
statusText: response.statusText,
|
|
4244
|
-
headers: response.headers,
|
|
4245
|
-
});
|
|
4246
|
-
}
|
|
4247
|
-
return new globalThis.Response(new globalThis.ReadableStream({
|
|
4248
|
-
async start(controller) {
|
|
4249
|
-
const reader = response.body.getReader();
|
|
4250
|
-
if (onDownloadProgress) {
|
|
4251
|
-
onDownloadProgress({ percent: 0, transferredBytes: 0, totalBytes }, new Uint8Array());
|
|
4252
|
-
}
|
|
4253
|
-
async function read() {
|
|
4254
|
-
const { done, value } = await reader.read();
|
|
4255
|
-
if (done) {
|
|
4256
|
-
controller.close();
|
|
4257
|
-
return;
|
|
4258
|
-
}
|
|
4259
|
-
if (onDownloadProgress) {
|
|
4260
|
-
transferredBytes += value.byteLength;
|
|
4261
|
-
const percent = totalBytes === 0 ? 0 : transferredBytes / totalBytes;
|
|
4262
|
-
onDownloadProgress({ percent, transferredBytes, totalBytes }, value);
|
|
4263
|
-
}
|
|
4264
|
-
controller.enqueue(value);
|
|
4265
|
-
await read();
|
|
4266
|
-
}
|
|
4267
|
-
await read();
|
|
4268
|
-
},
|
|
4269
|
-
}), {
|
|
4270
|
-
status: response.status,
|
|
4271
|
-
statusText: response.statusText,
|
|
4272
|
-
headers: response.headers,
|
|
4273
|
-
});
|
|
4274
|
-
}
|
|
4275
|
-
}
|
|
4276
|
-
|
|
4277
|
-
/*! MIT License © Sindre Sorhus */
|
|
4278
|
-
const createInstance = (defaults) => {
|
|
4279
|
-
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
4280
|
-
const ky = (input, options) => Ky.create(input, validateAndMerge(defaults, options));
|
|
4281
|
-
for (const method of requestMethods) {
|
|
4282
|
-
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
4283
|
-
ky[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }));
|
|
4284
|
-
}
|
|
4285
|
-
ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
|
|
4286
|
-
ky.extend = (newDefaults) => createInstance(validateAndMerge(defaults, newDefaults));
|
|
4287
|
-
ky.stop = stop;
|
|
4288
|
-
return ky;
|
|
4289
|
-
};
|
|
4290
|
-
const ky = createInstance();
|
|
4291
|
-
var ky$1 = ky;
|
|
4292
|
-
|
|
4293
|
-
var PasskeyApiClient = /** @class */ (function () {
|
|
4294
|
-
function PasskeyApiClient(_a) {
|
|
4295
|
-
var baseUrl = _a.baseUrl, tenantId = _a.tenantId;
|
|
4296
|
-
this.tenantId = tenantId;
|
|
4297
|
-
this.api = ky$1.create({
|
|
4298
|
-
prefixUrl: baseUrl
|
|
4299
|
-
});
|
|
4300
|
-
}
|
|
4301
|
-
PasskeyApiClient.prototype.registrationOptions = function (_a) {
|
|
4302
|
-
var token = _a.token, userName = _a.userName;
|
|
4303
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
4304
|
-
var response;
|
|
4305
|
-
return __generator(this, function (_b) {
|
|
4306
|
-
switch (_b.label) {
|
|
4307
|
-
case 0: return [4 /*yield*/, this.api.post("user-authenticators/passkey/registration-options", {
|
|
4308
|
-
json: { userName: userName },
|
|
4309
|
-
headers: {
|
|
4310
|
-
Authorization: "Bearer ".concat(token)
|
|
4311
|
-
}
|
|
4312
|
-
})];
|
|
4313
|
-
case 1:
|
|
4314
|
-
response = _b.sent();
|
|
4315
|
-
return [2 /*return*/, response.json()];
|
|
4316
|
-
}
|
|
4317
|
-
});
|
|
4318
|
-
});
|
|
4319
|
-
};
|
|
4320
|
-
PasskeyApiClient.prototype.authenticationOptions = function (_a) {
|
|
4321
|
-
var token = _a.token;
|
|
4322
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
4323
|
-
var authorizationHeader, response;
|
|
4324
|
-
return __generator(this, function (_b) {
|
|
4325
|
-
switch (_b.label) {
|
|
4326
|
-
case 0:
|
|
4327
|
-
authorizationHeader = token ? "Bearer ".concat(token) : "Basic ".concat(Buffer.from(this.tenantId).toString("base64"));
|
|
4328
|
-
return [4 /*yield*/, this.api.post("user-authenticators/passkey/authentication-options", {
|
|
4329
|
-
json: {},
|
|
4330
|
-
headers: {
|
|
4331
|
-
Authorization: authorizationHeader
|
|
4332
|
-
}
|
|
4333
|
-
})];
|
|
4334
|
-
case 1:
|
|
4335
|
-
response = _b.sent();
|
|
4336
|
-
return [2 /*return*/, response.json()];
|
|
4337
|
-
}
|
|
4338
|
-
});
|
|
4339
|
-
});
|
|
4340
|
-
};
|
|
4341
|
-
PasskeyApiClient.prototype.addAuthenticator = function (_a) {
|
|
4342
|
-
var token = _a.token, rest = __rest(_a, ["token"]);
|
|
4343
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
4344
|
-
var response;
|
|
4345
|
-
return __generator(this, function (_b) {
|
|
4346
|
-
switch (_b.label) {
|
|
4347
|
-
case 0: return [4 /*yield*/, this.api.post("user-authenticators/passkey", {
|
|
4348
|
-
json: rest,
|
|
4349
|
-
headers: {
|
|
4350
|
-
Authorization: "Bearer ".concat(token)
|
|
4351
|
-
}
|
|
4352
|
-
})];
|
|
4353
|
-
case 1:
|
|
4354
|
-
response = _b.sent();
|
|
4355
|
-
return [2 /*return*/, response.json()];
|
|
4356
|
-
}
|
|
4357
|
-
});
|
|
4358
|
-
});
|
|
4359
|
-
};
|
|
4360
|
-
PasskeyApiClient.prototype.verify = function (_a) {
|
|
4361
|
-
var token = _a.token, rest = __rest(_a, ["token"]);
|
|
4362
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
4363
|
-
var authorizationHeader, response;
|
|
4364
|
-
return __generator(this, function (_b) {
|
|
4365
|
-
switch (_b.label) {
|
|
4366
|
-
case 0:
|
|
4367
|
-
authorizationHeader = token ? "Bearer ".concat(token) : "Basic ".concat(Buffer.from(this.tenantId).toString("base64"));
|
|
4368
|
-
return [4 /*yield*/, this.api.post("verify/passkey", {
|
|
4369
|
-
json: rest,
|
|
4370
|
-
headers: {
|
|
4371
|
-
Authorization: authorizationHeader
|
|
4372
|
-
}
|
|
4373
|
-
})];
|
|
4374
|
-
case 1:
|
|
4375
|
-
response = _b.sent();
|
|
4376
|
-
return [2 /*return*/, response.json()];
|
|
4377
|
-
}
|
|
4378
|
-
});
|
|
4379
|
-
});
|
|
4380
|
-
};
|
|
4381
|
-
return PasskeyApiClient;
|
|
4382
|
-
}());
|
|
4383
|
-
|
|
4384
|
-
var Passkey = /** @class */ (function () {
|
|
4385
|
-
function Passkey(_a) {
|
|
4386
|
-
var baseUrl = _a.baseUrl, tenantId = _a.tenantId;
|
|
4387
|
-
this.api = new PasskeyApiClient({ baseUrl: baseUrl, tenantId: tenantId });
|
|
4388
|
-
}
|
|
4389
|
-
Passkey.prototype.signUp = function (_a) {
|
|
4390
|
-
var userName = _a.userName, token = _a.token;
|
|
4391
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
4392
|
-
var optionsResponse, registrationResponse, addAuthenticatorResponse, error_1;
|
|
4393
|
-
return __generator(this, function (_b) {
|
|
4394
|
-
switch (_b.label) {
|
|
4395
|
-
case 0: return [4 /*yield*/, this.api.registrationOptions({ userName: userName, token: token })];
|
|
4396
|
-
case 1:
|
|
4397
|
-
optionsResponse = _b.sent();
|
|
4398
|
-
_b.label = 2;
|
|
4399
|
-
case 2:
|
|
4400
|
-
_b.trys.push([2, 5, , 6]);
|
|
4401
|
-
return [4 /*yield*/, startRegistration(optionsResponse.options)];
|
|
4402
|
-
case 3:
|
|
4403
|
-
registrationResponse = _b.sent();
|
|
4404
|
-
return [4 /*yield*/, this.api.addAuthenticator({
|
|
4405
|
-
challengeId: optionsResponse.challengeId,
|
|
4406
|
-
registrationCredential: registrationResponse,
|
|
4407
|
-
token: token
|
|
4408
|
-
})];
|
|
4409
|
-
case 4:
|
|
4410
|
-
addAuthenticatorResponse = _b.sent();
|
|
4411
|
-
return [2 /*return*/, addAuthenticatorResponse === null || addAuthenticatorResponse === void 0 ? void 0 : addAuthenticatorResponse.accessToken];
|
|
4412
|
-
case 5:
|
|
4413
|
-
error_1 = _b.sent();
|
|
4414
|
-
console.error(error_1);
|
|
4415
|
-
return [3 /*break*/, 6];
|
|
4416
|
-
case 6: return [2 /*return*/];
|
|
4417
|
-
}
|
|
4418
|
-
});
|
|
4419
|
-
});
|
|
4420
|
-
};
|
|
4421
|
-
Passkey.prototype.signIn = function (params) {
|
|
4422
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
4423
|
-
var optionsResponse, authenticationResponse, verifyResponse, error_2;
|
|
4424
|
-
return __generator(this, function (_a) {
|
|
4425
|
-
switch (_a.label) {
|
|
4426
|
-
case 0:
|
|
4427
|
-
if ((params === null || params === void 0 ? void 0 : params.token) && params.autofill) {
|
|
4428
|
-
throw new Error("Autofill is not supported when providing a token");
|
|
4429
|
-
}
|
|
4430
|
-
return [4 /*yield*/, this.api.authenticationOptions({ token: params === null || params === void 0 ? void 0 : params.token })];
|
|
4431
|
-
case 1:
|
|
4432
|
-
optionsResponse = _a.sent();
|
|
4433
|
-
_a.label = 2;
|
|
4434
|
-
case 2:
|
|
4435
|
-
_a.trys.push([2, 5, , 6]);
|
|
4436
|
-
return [4 /*yield*/, startAuthentication(optionsResponse.options, params === null || params === void 0 ? void 0 : params.autofill)];
|
|
4437
|
-
case 3:
|
|
4438
|
-
authenticationResponse = _a.sent();
|
|
4439
|
-
return [4 /*yield*/, this.api.verify({
|
|
4440
|
-
challengeId: optionsResponse.challengeId,
|
|
4441
|
-
authenticationCredential: authenticationResponse,
|
|
4442
|
-
token: params === null || params === void 0 ? void 0 : params.token
|
|
4443
|
-
})];
|
|
4444
|
-
case 4:
|
|
4445
|
-
verifyResponse = _a.sent();
|
|
4446
|
-
return [2 /*return*/, verifyResponse === null || verifyResponse === void 0 ? void 0 : verifyResponse.accessToken];
|
|
4447
|
-
case 5:
|
|
4448
|
-
error_2 = _a.sent();
|
|
4449
|
-
console.error(error_2);
|
|
4450
|
-
return [3 /*break*/, 6];
|
|
4451
|
-
case 6: return [2 /*return*/];
|
|
4452
|
-
}
|
|
4453
|
-
});
|
|
4454
|
-
});
|
|
4455
|
-
};
|
|
4456
|
-
return Passkey;
|
|
4457
|
-
}());
|
|
4458
|
-
|
|
4459
|
-
var DEFAULT_COOKIE_NAME = "__as_aid";
|
|
4460
|
-
var DEFAULT_BASE_URL = "https://challenge.authsignal.com/v1";
|
|
4461
|
-
var Authsignal = /** @class */ (function () {
|
|
4462
|
-
function Authsignal(_a) {
|
|
4463
|
-
var cookieDomain = _a.cookieDomain, _b = _a.cookieName, cookieName = _b === void 0 ? DEFAULT_COOKIE_NAME : _b, _c = _a.baseUrl, baseUrl = _c === void 0 ? DEFAULT_BASE_URL : _c, tenantId = _a.tenantId;
|
|
4464
|
-
this.anonymousId = "";
|
|
4465
|
-
this.cookieDomain = "";
|
|
4466
|
-
this.anonymousIdCookieName = "";
|
|
4467
|
-
this._token = undefined;
|
|
4468
|
-
this.cookieDomain = cookieDomain || getCookieDomain();
|
|
4469
|
-
this.anonymousIdCookieName = cookieName;
|
|
4470
|
-
this.passkey = new Passkey({ tenantId: tenantId, baseUrl: baseUrl });
|
|
4471
|
-
var idCookie = getCookie(this.anonymousIdCookieName);
|
|
4472
|
-
if (idCookie) {
|
|
4473
|
-
this.anonymousId = idCookie;
|
|
4474
|
-
}
|
|
4475
|
-
else {
|
|
4476
|
-
this.anonymousId = v4();
|
|
4477
|
-
setCookie({
|
|
4478
|
-
name: this.anonymousIdCookieName,
|
|
4479
|
-
value: this.anonymousId,
|
|
4480
|
-
expire: Infinity,
|
|
4481
|
-
domain: this.cookieDomain,
|
|
4482
|
-
secure: document.location.protocol !== "http:"
|
|
4483
|
-
});
|
|
4484
|
-
}
|
|
4485
|
-
}
|
|
4486
|
-
Authsignal.prototype.launch = function (url, options) {
|
|
4487
|
-
var _this = this;
|
|
4488
|
-
if (!(options === null || options === void 0 ? void 0 : options.mode) || options.mode === "redirect") {
|
|
4489
|
-
window.location.href = url;
|
|
4490
|
-
}
|
|
4491
|
-
else {
|
|
4492
|
-
var popupOptions = options.popupOptions;
|
|
4493
|
-
var Popup_1 = new PopupHandler({ width: popupOptions === null || popupOptions === void 0 ? void 0 : popupOptions.width });
|
|
4494
|
-
var popupUrl = "".concat(url, "&mode=popup");
|
|
4495
|
-
Popup_1.show({ url: popupUrl });
|
|
4496
|
-
return new Promise(function (resolve) {
|
|
4497
|
-
var onMessage = function (event) {
|
|
4498
|
-
var data = null;
|
|
4499
|
-
try {
|
|
4500
|
-
data = JSON.parse(event.data);
|
|
4501
|
-
}
|
|
4502
|
-
catch (_a) {
|
|
4503
|
-
// Ignore if the event data is not valid JSON
|
|
4504
|
-
}
|
|
4505
|
-
if ((data === null || data === void 0 ? void 0 : data.event) === AuthsignalWindowMessage.AUTHSIGNAL_CLOSE_POPUP) {
|
|
4506
|
-
_this._token = data.token;
|
|
4507
|
-
Popup_1.close();
|
|
4508
|
-
}
|
|
4509
|
-
};
|
|
4510
|
-
Popup_1.on("hide", function () {
|
|
4511
|
-
resolve({ token: _this._token });
|
|
4512
|
-
});
|
|
4513
|
-
window.addEventListener("message", onMessage, false);
|
|
4514
|
-
});
|
|
4515
|
-
}
|
|
4516
|
-
};
|
|
4517
|
-
return Authsignal;
|
|
4518
|
-
}());
|
|
4519
|
-
|
|
4520
|
-
export { Authsignal, AuthsignalWindowMessage };
|