iframe-resizer 4.4.4 → 5.1.5-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,204 +1,246 @@
1
- /*
2
- * File: iframeResizer.js
3
- * Desc: Force iframes to size to content.
4
- * Requires: iframeResizer.contentWindow.js to be loaded into the target frame.
5
- * Doc: https://iframe-resizer.com
6
- * Author: David J. Bradshaw - info@iframe-resizer.com
1
+ /*!
2
+ * @preserve
3
+ *
4
+ * @module iframe-resizer/legacy (parent) 5.1.5-beta.1 (umd) - 2024-07-10
5
+ *
6
+ * @license GPL-3.0 for non-commercial use only.
7
+ * For commercial use, you must purchase a license from
8
+ * https://iframe-resizer.com/pricing
9
+ *
10
+ * @desciption Keep same and cross domain iFrames sized to their content
11
+ *
12
+ * @author David J. Bradshaw <info@iframe-resizer.com>
13
+ *
14
+ * @see {@link https://iframe-resizer.com}
15
+ *
16
+ * @copyright (c) 2013 - 2024, David J. Bradshaw. All rights reserved.
7
17
  */
8
18
 
9
- console.info(`
10
- IFRAME-RESIZER
11
19
 
12
- Iframe-Resizer 5 is now available via the following two packages:
20
+ (function (global, factory) {
21
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
22
+ typeof define === 'function' && define.amd ? define(factory) :
23
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.iframeResize = factory());
24
+ })(this, (function () { 'use strict';
13
25
 
14
- * @iframe-resizer/parent
15
- * @iframe-resizer/child
26
+ const msg = `IFRAME-RESIZER 5
16
27
 
17
- Additionally their are also new versions of iframe-resizer for React, Vue, and jQuery.
28
+ This package has been split into separate packages for Parent and Child pages. Along with new packages for jQuery, React and Vue.
18
29
 
19
30
  Version 5 of iframe-resizer has been extensively rewritten to use modern browser APIs, which has enabled significantly better performance and greater accuracy in the detection of content resizing events.
20
31
 
21
32
  Please see https://iframe-resizer.com/upgrade for more details.
22
- `)
23
-
24
- // eslint-disable-next-line sonarjs/cognitive-complexity, no-shadow-restricted-names
25
- ;(function (undefined) {
26
- if (typeof window === 'undefined') return // don't run for server side render
27
-
28
- // var VERSION = '4.3.11'
29
-
30
- var count = 0,
31
- destroyObserver,
32
- logEnabled = false,
33
- hiddenCheckEnabled = false,
34
- msgHeader = 'message',
35
- msgHeaderLen = msgHeader.length,
36
- msgId = '[iFrameSizer]', // Must match iframe msg ID
37
- msgIdLen = msgId.length,
38
- pagePosition = null,
39
- requestAnimationFrame = window.requestAnimationFrame,
40
- resetRequiredMethods = Object.freeze({
41
- max: 1,
42
- scroll: 1,
43
- bodyScroll: 1,
44
- documentElementScroll: 1
45
- }),
46
- settings = {},
47
- timer = null,
48
- defaults = Object.freeze({
49
- autoResize: true,
50
- bodyBackground: null,
51
- bodyMargin: null,
52
- bodyMarginV1: 8,
53
- bodyPadding: null,
54
- checkOrigin: true,
55
- inPageLinks: false,
56
- enablePublicMethods: true,
57
- heightCalculationMethod: 'bodyOffset',
58
- id: 'iFrameResizer',
59
- interval: 32,
60
- license: '1jqr0si6pnt',
61
- log: false,
62
- maxHeight: Infinity,
63
- maxWidth: Infinity,
64
- minHeight: 0,
65
- minWidth: 0,
66
- mouseEvents: true,
67
- resizeFrom: 'parent',
68
- scrolling: false,
69
- sizeHeight: true,
70
- sizeWidth: false,
71
- warningTimeout: 5000,
72
- tolerance: 0,
73
- widthCalculationMethod: 'scroll',
74
- onClose: function () {
75
- return true
76
- },
77
- onClosed: function () {},
78
- onInit: function () {},
79
- onMessage: function () {
80
- warn('onMessage function not defined')
81
- },
82
- onMouseEnter: function () {},
83
- onMouseLeave: function () {},
84
- onResized: function () {},
85
- onScroll: function () {
86
- return true
87
- }
88
- })
89
-
90
- function getMutationObserver() {
91
- return (
92
- window.MutationObserver ||
93
- window.WebKitMutationObserver ||
94
- window.MozMutationObserver
95
- )
96
- }
33
+ `;
97
34
 
98
- function addEventListener(el, evt, func) {
99
- el.addEventListener(evt, func, false)
100
- }
35
+ console.warn(msg);
101
36
 
102
- function removeEventListener(el, evt, func) {
103
- el.removeEventListener(evt, func, false)
104
- }
37
+ const encode = (s) =>
38
+ s
39
+ .replaceAll('<br>', '\n')
40
+ .replaceAll('<rb>', '\u001B[31;1m')
41
+ .replaceAll('</>', '\u001B[m')
42
+ .replaceAll('<b>', '\u001B[1m')
43
+ .replaceAll('<i>', '\u001B[3m')
44
+ .replaceAll('<u>', '\u001B[4m');
105
45
 
106
- function setupRequestAnimationFrame() {
107
- var vendors = ['moz', 'webkit', 'o', 'ms']
108
- var x
46
+ const remove = (s) => s.replaceAll('<br>', '\n').replaceAll(/<[/a-z]+>/gi, '');
109
47
 
110
- // Remove vendor prefixing if prefixed and break early if not
111
- for (x = 0; x < vendors.length && !requestAnimationFrame; x += 1) {
112
- requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
113
- }
48
+ const formatAdvise = (formatLogMsg) => (msg) =>
49
+ window.chrome // Only show formatting in Chrome as not supported in other browsers
50
+ ? formatLogMsg(encode(msg))
51
+ : formatLogMsg(remove(msg));
114
52
 
115
- if (requestAnimationFrame) {
116
- // Firefox extension content-scripts have a globalThis object that is not the same as window.
117
- // Binding `requestAnimationFrame` to window allows the function to work and prevents errors
118
- // being thrown when run in that context, and should be a no-op in every other context.
119
- requestAnimationFrame = requestAnimationFrame.bind(window)
120
- } else {
121
- log('setup', 'RequestAnimationFrame not supported')
122
- }
53
+ const msgId$1 = '[iframe-resizer]';
54
+
55
+ function setLogEnabled(enabled) {
123
56
  }
124
57
 
125
58
  function getMyID(iframeId) {
126
- var retStr = 'Host page: ' + iframeId
127
-
128
- if (window.top !== window.self) {
129
- retStr =
130
- window.parentIFrame && window.parentIFrame.getId
131
- ? window.parentIFrame.getId() + ': ' + iframeId
132
- : 'Nested host page: ' + iframeId
59
+ if (window.top === window.self) {
60
+ return `Parent page: ${iframeId}`
133
61
  }
134
62
 
135
- return retStr
63
+ return window?.parentIFrame?.getId
64
+ ? `${window.parentIFrame.getId()}: ${iframeId}`
65
+ : `Nested parent page: ${iframeId}`
136
66
  }
137
67
 
138
- function formatLogHeader(iframeId) {
139
- return msgId + '[' + getMyID(iframeId) + ']'
140
- }
68
+ const formatLogHeader = (iframeId) => `${msgId$1}[${getMyID(iframeId)}]`;
141
69
 
142
- function isLogEnabled(iframeId) {
143
- return settings[iframeId] ? settings[iframeId].log : logEnabled
144
- }
70
+ const formatLogMsg =
71
+ (iframeId) =>
72
+ (...msg) =>
73
+ [`${msgId$1}[${iframeId}]`, ...msg].join(' ');
145
74
 
146
- function log(iframeId, msg) {
147
- output('log', iframeId, msg, isLogEnabled(iframeId))
148
- }
75
+ const output = (type, iframeId, ...msg) =>
76
+ // eslint-disable-next-line no-console
77
+ window?.console[type](formatLogHeader(iframeId), ...msg);
149
78
 
150
- function info(iframeId, msg) {
151
- output('info', iframeId, msg, isLogEnabled(iframeId))
152
- }
79
+ const info = (iframeId, ...msg) => output('info', iframeId, ...msg);
153
80
 
154
- function warn(iframeId, msg) {
155
- output('warn', iframeId, msg, true)
156
- }
81
+ const warn = (iframeId, ...msg) => output('warn', iframeId, ...msg);
157
82
 
158
- function output(type, iframeId, msg, enabled) {
159
- if (true === enabled && 'object' === typeof window.console) {
160
- // eslint-disable-next-line no-console
161
- console[type](formatLogHeader(iframeId), msg)
162
- }
163
- }
83
+ const advise = (iframeId, msg) =>
84
+ // eslint-disable-next-line no-console
85
+ console?.warn(formatAdvise(formatLogMsg(iframeId))(msg));
164
86
 
165
- function iFrameListener(event) {
166
- function resizeIFrame() {
167
- function resize() {
168
- setSize(messageData)
169
- setPagePosition(iframeId)
170
- on('onResized', messageData)
171
- }
87
+ const VERSION = '5.1.5-beta.1';
172
88
 
173
- ensureInRange('Height')
174
- ensureInRange('Width')
89
+ const msgHeader = 'message';
90
+ const msgHeaderLen = msgHeader.length;
91
+ const msgId = '[iFrameSizer]'; // Must match iframe msg ID
92
+ const msgIdLen = msgId.length;
93
+ const resetRequiredMethods = Object.freeze({
94
+ max: 1,
95
+ scroll: 1,
96
+ bodyScroll: 1,
97
+ documentElementScroll: 1,
98
+ });
175
99
 
176
- syncResize(resize, messageData, 'init')
177
- }
100
+ const addEventListener = (el, evt, func, options) =>
101
+ el.addEventListener(evt, func, options || false);
178
102
 
179
- function processMsg() {
180
- var data = msg.slice(msgIdLen).split(':')
181
- var height = data[1] ? parseInt(data[1], 10) : 0
182
- var iframe = settings[data[0]] && settings[data[0]].iframe
183
- var compStyle = getComputedStyle(iframe)
103
+ const removeEventListener = (el, evt, func) =>
104
+ el.removeEventListener(evt, func, false);
184
105
 
185
- return {
186
- iframe: iframe,
187
- id: data[0],
188
- height: height + getPaddingEnds(compStyle) + getBorderEnds(compStyle),
189
- width: data[2],
190
- type: data[3]
191
- }
106
+ const l = (l) => {
107
+ if (!l) return ''
108
+ let p = -559038744,
109
+ y = 1103547984;
110
+ for (let z, t = 0; t < l.length; t++)
111
+ (z = l.codePointAt(t)),
112
+ (p = Math.imul(p ^ z, 2246822519)),
113
+ (y = Math.imul(y ^ z, 3266489917));
114
+ return (
115
+ (p ^= Math.imul(p ^ (y >>> 15), 1935289751)),
116
+ (y ^= Math.imul(y ^ (p >>> 15), 3405138345)),
117
+ (p ^= y >>> 16),
118
+ (y ^= p >>> 16),
119
+ (2097152 * (y >>> 0) + (p >>> 11)).toString(36)
120
+ )
121
+ },
122
+ p = (l) =>
123
+ l.replaceAll(/[A-Za-z]/g, (l) =>
124
+ String.fromCodePoint(
125
+ (l <= 'Z' ? 90 : 122) >= (l = l.codePointAt(0) + 19) ? l : l - 26,
126
+ ),
127
+ ),
128
+ y = [
129
+ '<iy><yi>Puchspk Spjluzl Rlf</><iy><iy>',
130
+ '<iy><yi>Tpzzpun Spjluzl Rlf</><iy><iy>',
131
+ 'Aopz spiyhyf pz hchpshisl dpao ivao Jvttlyjphs huk Vwlu-Zvbyjl spjluzlz.<iy><iy><i>Jvttlyjphs Spjluzl</><iy>Mvy jvttlyjphs bzl, <p>pmyhtl-ylzpgly</> ylxbpylz h svd jvza vul aptl spjluzl mll. Mvy tvyl pumvythapvu cpzpa <b>oaawz://pmyhtl-ylzpgly.jvt/wypjpun</>.<iy><iy><i>Vwlu Zvbyjl Spjluzl</><iy>Pm fvb hyl bzpun aopz spiyhyf pu h uvu-jvttlyjphs vwlu zvbyjl wyvqlja aolu fvb jhu bzl pa mvy myll bukly aol alytz vm aol NWS C3 Spjluzl. Av jvumpyt fvb hjjlwa aolzl alytz, wslhzl zla aol <i>spjluzl</> rlf pu <p>pmyhtl-ylzpgly</> vwapvuz av <i>NWSc3</>.<iy><iy>Mvy tvyl pumvythapvu wslhzl zll: <b>oaawz://pmyhtl-ylzpgly.jvt/nws</>',
132
+ '<i>NWSc3 Spjluzl Clyzpvu</><iy><iy>Aopz clyzpvu vm <p>pmyhtl-ylzpgly</> pz ilpun bzlk bukly aol alytz vm aol <i>NWS C3</> spjluzl. Aopz spjluzl hssvdz fvb av bzl <p>pmyhtl-ylzpgly</> pu Vwlu Zvbyjl wyvqljaz, iba pa ylxbpylz fvby wyvqlja av il wbispj, wyvcpkl haaypibapvu huk il spjluzlk bukly clyzpvu 3 vy shaly vm aol NUB Nlulyhs Wbispj Spjluzl.<iy><iy>Pm fvb hyl bzpun aopz spiyhyf pu h uvu-vwlu zvbyjl wyvqlja vy dlizpal, fvb dpss ullk av wbyjohzl h svd jvza vul aptl jvttlyjphs spjluzl.<iy><iy>Mvy tvyl pumvythapvu cpzpa <b>oaawz://pmyhtl-ylzpgly.jvt/wypjpun</>.',
133
+ ],
134
+ z = ['NWSc3', 'zvsv', 'wyv', 'ibzpulzz', 'vlt'],
135
+ t = Object.fromEntries(
136
+ [
137
+ '2cgs7fdf4xb',
138
+ '1c9ctcccr4z',
139
+ '1q2pc4eebgb',
140
+ 'ueokt0969w',
141
+ 'w2zxchhgqz',
142
+ '1umuxblj2e5',
143
+ ].map((l, p) => [l, Math.max(0, p - 1)]),
144
+ );
145
+ const getModeData = (l) => p(y[l]);
146
+ const getModeLabel = (l) => p(z[l]);
147
+ const setMode = (y) => {
148
+ const z = y[p('spjluzl')];
149
+ if (!z) return -1
150
+ const u = z.split('-');
151
+ let v = (function (y = '') {
152
+ let z = -2;
153
+ const u = l(p(y));
154
+ return u in t && (z = t[u]), z
155
+ })(u[0]);
156
+ return 0 === v || ((p) => p[2] === l(p[0] + p[1]))(u) || (v = -2), v
157
+ };
158
+
159
+ const once = (fn) => {
160
+ let done = false;
161
+
162
+ return function () {
163
+ return done
164
+ ? undefined
165
+ : ((done = true), Reflect.apply(fn, this, arguments))
166
+ }
167
+ };
168
+
169
+ const settings = {};
170
+
171
+ const onReadyDeprecated = (messageData) => {
172
+ if (typeof settings[messageData.id].onInit === 'function') {
173
+ advise(
174
+ messageData.id,
175
+ `
176
+ \u001B[31;1mDeprecated Option\u001B[m
177
+
178
+ The \u001B[1monInit()\u001B[m function is deprecated and has been replaced with \u001B[1monReady()\u001B[m. It will be removed in a future version of iFrame Resizer.
179
+ `,
180
+ );
181
+ settings[messageData.id].onInit(messageData);
182
+ }
183
+ };
184
+
185
+ const defaults = Object.freeze({
186
+ autoResize: true,
187
+ bodyBackground: null,
188
+ bodyMargin: null,
189
+ bodyPadding: null,
190
+ checkOrigin: true,
191
+ direction: 'vertical',
192
+ inPageLinks: false,
193
+ heightCalculationMethod: 'auto',
194
+ id: 'iFrameResizer',
195
+ log: false,
196
+ license: undefined,
197
+ mouseEvents: true,
198
+ offsetHeight: null,
199
+ offsetWidth: null,
200
+ postMessageTarget: null,
201
+ sameDomain: false,
202
+ scrolling: false,
203
+ sizeHeight: true,
204
+ // sizeSelector: '',
205
+ sizeWidth: false,
206
+ warningTimeout: 5000,
207
+ tolerance: 0,
208
+ waitForLoad: false,
209
+ widthCalculationMethod: 'auto',
210
+ onClose: () => true,
211
+ onClosed() {},
212
+ onInit: false,
213
+ onMessage: null,
214
+ onMouseEnter() {},
215
+ onMouseLeave() {},
216
+ onReady: onReadyDeprecated,
217
+ onResized() {},
218
+ onScroll: () => true,
219
+ });
220
+
221
+ const page = {
222
+ position: null,
223
+ version: VERSION,
224
+ };
225
+
226
+ function iframeListener(event) {
227
+ function resizeIFrame() {
228
+ setSize(messageData);
229
+ setPagePosition();
230
+
231
+ on('onResized', messageData);
192
232
  }
193
233
 
194
234
  function getPaddingEnds(compStyle) {
195
235
  if (compStyle.boxSizing !== 'border-box') {
196
236
  return 0
197
237
  }
198
- var top = compStyle.paddingTop ? parseInt(compStyle.paddingTop, 10) : 0
199
- var bot = compStyle.paddingBottom
238
+
239
+ const top = compStyle.paddingTop ? parseInt(compStyle.paddingTop, 10) : 0;
240
+ const bot = compStyle.paddingBottom
200
241
  ? parseInt(compStyle.paddingBottom, 10)
201
- : 0
242
+ : 0;
243
+
202
244
  return top + bot
203
245
  }
204
246
 
@@ -206,78 +248,68 @@ Please see https://iframe-resizer.com/upgrade for more details.
206
248
  if (compStyle.boxSizing !== 'border-box') {
207
249
  return 0
208
250
  }
209
- var top = compStyle.borderTopWidth
251
+
252
+ const top = compStyle.borderTopWidth
210
253
  ? parseInt(compStyle.borderTopWidth, 10)
211
- : 0
212
- var bot = compStyle.borderBottomWidth
254
+ : 0;
255
+ const bot = compStyle.borderBottomWidth
213
256
  ? parseInt(compStyle.borderBottomWidth, 10)
214
- : 0
257
+ : 0;
258
+
215
259
  return top + bot
216
260
  }
217
261
 
218
- function ensureInRange(Dimension) {
219
- var max = Number(settings[iframeId]['max' + Dimension]),
220
- min = Number(settings[iframeId]['min' + Dimension]),
221
- dimension = Dimension.toLowerCase(),
222
- size = Number(messageData[dimension])
223
-
224
- log(iframeId, 'Checking ' + dimension + ' is in range ' + min + '-' + max)
225
-
226
- if (size < min) {
227
- size = min
228
- log(iframeId, 'Set ' + dimension + ' to min value')
229
- }
262
+ function processMsg() {
263
+ const data = msg.slice(msgIdLen).split(':');
264
+ const height = data[1] ? Number(data[1]) : 0;
265
+ const iframe = settings[data[0]]?.iframe;
266
+ const compStyle = getComputedStyle(iframe);
230
267
 
231
- if (size > max) {
232
- size = max
233
- log(iframeId, 'Set ' + dimension + ' to max value')
268
+ return {
269
+ iframe,
270
+ id: data[0],
271
+ height: height + getPaddingEnds(compStyle) + getBorderEnds(compStyle),
272
+ width: Number(data[2]),
273
+ type: data[3],
274
+ msg: data[4],
234
275
  }
235
-
236
- messageData[dimension] = '' + size
237
276
  }
238
277
 
239
278
  function isMessageFromIFrame() {
240
279
  function checkAllowedOrigin() {
241
280
  function checkList() {
242
- var i = 0,
243
- retCode = false
244
-
245
- log(
246
- iframeId,
247
- 'Checking connection is from allowed list of origins: ' +
248
- checkOrigin
249
- )
281
+ let i = 0;
282
+ let retCode = false;
250
283
 
251
284
  for (; i < checkOrigin.length; i++) {
252
285
  if (checkOrigin[i] === origin) {
253
- retCode = true
286
+ retCode = true;
254
287
  break
255
288
  }
256
289
  }
290
+
257
291
  return retCode
258
292
  }
259
293
 
260
294
  function checkSingle() {
261
- var remoteHost = settings[iframeId] && settings[iframeId].remoteHost
262
- log(iframeId, 'Checking connection is from: ' + remoteHost)
295
+ const remoteHost = settings[iframeId]?.remoteHost;
263
296
  return origin === remoteHost
264
297
  }
265
298
 
266
299
  return checkOrigin.constructor === Array ? checkList() : checkSingle()
267
300
  }
268
301
 
269
- var origin = event.origin,
270
- checkOrigin = settings[iframeId] && settings[iframeId].checkOrigin
302
+ const { origin, sameDomain } = event;
271
303
 
272
- if (checkOrigin && '' + origin !== 'null' && !checkAllowedOrigin()) {
304
+ if (sameDomain) {
305
+ return true
306
+ }
307
+
308
+ let checkOrigin = settings[iframeId]?.checkOrigin;
309
+
310
+ if (checkOrigin && `${origin}` !== 'null' && !checkAllowedOrigin()) {
273
311
  throw new Error(
274
- 'Unexpected message received from: ' +
275
- origin +
276
- ' for ' +
277
- messageData.iframe.id +
278
- '. Message was: ' +
279
- event.data +
280
- '. This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains.'
312
+ `Unexpected message received from: ${origin} for ${messageData.iframe.id}. Message was: ${event.data}. This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains.`,
281
313
  )
282
314
  }
283
315
 
@@ -286,7 +318,7 @@ Please see https://iframe-resizer.com/upgrade for more details.
286
318
 
287
319
  function isMessageForUs() {
288
320
  return (
289
- msgId === ('' + msg).slice(0, msgIdLen) &&
321
+ msgId === `${msg}`.slice(0, msgIdLen) &&
290
322
  msg.slice(msgIdLen).split(':')[0] in settings
291
323
  ) // ''+Protects against non-string msg
292
324
  }
@@ -294,11 +326,7 @@ Please see https://iframe-resizer.com/upgrade for more details.
294
326
  function isMessageFromMetaParent() {
295
327
  // Test if this message is from a parent above us. This is an ugly test, however, updating
296
328
  // the message format would break backwards compatibility.
297
- var retCode = messageData.type in { true: 1, false: 1, undefined: 1 }
298
-
299
- if (retCode) {
300
- log(iframeId, 'Ignoring init message from meta parent page')
301
- }
329
+ const retCode = messageData.type in { true: 1, false: 1, undefined: 1 };
302
330
 
303
331
  return retCode
304
332
  }
@@ -308,412 +336,490 @@ Please see https://iframe-resizer.com/upgrade for more details.
308
336
  }
309
337
 
310
338
  function forwardMsgFromIFrame(msgBody) {
311
- log(
312
- iframeId,
313
- 'onMessage passed: {iframe: ' +
314
- messageData.iframe.id +
315
- ', message: ' +
316
- msgBody +
317
- '}'
318
- )
319
339
 
320
340
  on('onMessage', {
321
341
  iframe: messageData.iframe,
322
- message: JSON.parse(msgBody)
323
- })
324
-
325
- log(iframeId, '--')
342
+ message: JSON.parse(msgBody),
343
+ });
326
344
  }
327
345
 
328
346
  function getPageInfo() {
329
- var bodyPosition = document.body.getBoundingClientRect(),
330
- iFramePosition = messageData.iframe.getBoundingClientRect()
347
+ const bodyPosition = document.body.getBoundingClientRect();
348
+ const iFramePosition = messageData.iframe.getBoundingClientRect();
349
+ const { scrollY, scrollX, innerHeight, innerWidth } = window;
350
+ const { clientHeight, clientWidth } = document.documentElement;
331
351
 
332
352
  return JSON.stringify({
333
353
  iframeHeight: iFramePosition.height,
334
354
  iframeWidth: iFramePosition.width,
335
- clientHeight: Math.max(
336
- document.documentElement.clientHeight,
337
- window.innerHeight || 0
338
- ),
339
- clientWidth: Math.max(
340
- document.documentElement.clientWidth,
341
- window.innerWidth || 0
342
- ),
355
+ clientHeight: Math.max(clientHeight, innerHeight || 0),
356
+ clientWidth: Math.max(clientWidth, innerWidth || 0),
343
357
  offsetTop: parseInt(iFramePosition.top - bodyPosition.top, 10),
344
358
  offsetLeft: parseInt(iFramePosition.left - bodyPosition.left, 10),
345
- scrollTop: window.pageYOffset,
346
- scrollLeft: window.pageXOffset,
347
- documentHeight: document.documentElement.clientHeight,
348
- documentWidth: document.documentElement.clientWidth,
349
- windowHeight: window.innerHeight,
350
- windowWidth: window.innerWidth
359
+ scrollTop: scrollY,
360
+ scrollLeft: scrollX,
361
+ documentHeight: clientHeight,
362
+ documentWidth: clientWidth,
363
+ windowHeight: innerHeight,
364
+ windowWidth: innerWidth,
351
365
  })
352
366
  }
353
367
 
354
- function sendPageInfoToIframe(iframe, iframeId) {
355
- function debouncedTrigger() {
356
- trigger('Send Page Info', 'pageInfo:' + getPageInfo(), iframe, iframeId)
357
- }
358
- debounceFrameEvents(debouncedTrigger, 32, iframeId)
368
+ function getParentProps() {
369
+ const { iframe } = messageData;
370
+ const { scrollWidth, scrollHeight } = document.documentElement;
371
+ const { width, height, offsetLeft, offsetTop, pageLeft, pageTop, scale } =
372
+ window.visualViewport;
373
+
374
+ return JSON.stringify({
375
+ iframe: iframe.getBoundingClientRect(),
376
+ document: {
377
+ scrollWidth,
378
+ scrollHeight,
379
+ },
380
+ viewport: {
381
+ width,
382
+ height,
383
+ offsetLeft,
384
+ offsetTop,
385
+ pageLeft,
386
+ pageTop,
387
+ scale,
388
+ },
389
+ })
359
390
  }
360
391
 
361
- function startPageInfoMonitor() {
362
- function setListener(type, func) {
363
- function sendPageInfo() {
364
- if (settings[id]) {
365
- sendPageInfoToIframe(settings[id].iframe, id)
366
- } else {
367
- stop()
368
- }
392
+ const sendInfoToIframe = (type, infoFunction) => (requestType, iframeId) => {
393
+ const gate = {};
394
+
395
+ function throttle(func, frameId) {
396
+ if (!gate[frameId]) {
397
+ func();
398
+ gate[frameId] = requestAnimationFrame(() => {
399
+ gate[frameId] = null;
400
+ });
369
401
  }
402
+ }
370
403
 
371
- ;['scroll', 'resize'].forEach(function (evt) {
372
- log(id, type + evt + ' listener for sendPageInfo')
373
- func(window, evt, sendPageInfo)
374
- })
404
+ function gatedTrigger() {
405
+ trigger(
406
+ `Send ${type} (${requestType})`,
407
+ `${type}:${infoFunction()}`,
408
+ iframeId,
409
+ );
410
+ }
411
+
412
+ throttle(gatedTrigger, iframeId);
413
+ };
414
+
415
+ const startInfoMonitor = (sendInfoToIframe, type) => () => {
416
+ const sendInfo = (requestType) => () => {
417
+ if (settings[id]) {
418
+ sendInfoToIframe(requestType, id);
419
+ } else {
420
+ stop();
421
+ }
422
+ };
423
+
424
+ function setListener(requestType, listener) {
425
+ listener(window, 'scroll', sendInfo('scroll'));
426
+ listener(window, 'resize', sendInfo('resize window'));
375
427
  }
376
428
 
377
429
  function stop() {
378
- setListener('Remove ', removeEventListener)
430
+ setListener('Remove ', removeEventListener);
431
+ pageObserver.disconnect();
432
+ iframeObserver.disconnect();
379
433
  }
380
434
 
381
435
  function start() {
382
- setListener('Add ', addEventListener)
436
+ setListener('Add ', addEventListener);
437
+ pageObserver.observe(document.body, {
438
+ attributes: true,
439
+ childList: true,
440
+ subtree: true,
441
+ });
442
+ iframeObserver.observe(settings[id].iframe, {
443
+ attributes: true,
444
+ childList: false,
445
+ subtree: false,
446
+ });
383
447
  }
384
448
 
385
- var id = iframeId // Create locally scoped copy of iFrame ID
449
+ const id = iframeId; // Create locally scoped copy of iFrame ID
450
+
451
+ const pageObserver = new ResizeObserver(sendInfo('page observed'));
452
+ const iframeObserver = new ResizeObserver(sendInfo('iframe observed'));
386
453
 
387
- start()
454
+ start();
388
455
 
389
456
  if (settings[id]) {
390
- settings[id].stopPageInfo = stop
457
+ settings[id][`stop${type}`] = stop;
391
458
  }
392
- }
459
+ };
393
460
 
394
- function stopPageInfoMonitor() {
395
- if (settings[iframeId] && settings[iframeId].stopPageInfo) {
396
- settings[iframeId].stopPageInfo()
397
- delete settings[iframeId].stopPageInfo
461
+ const stopInfoMonitor = (stopFunction) => () => {
462
+ if (stopFunction in settings[iframeId]) {
463
+ settings[iframeId][stopFunction]();
464
+ delete settings[iframeId][stopFunction];
398
465
  }
399
- }
466
+ };
467
+
468
+ const sendPageInfoToIframe = sendInfoToIframe('pageInfo', getPageInfo);
469
+ const sendParentInfoToIframe = sendInfoToIframe('parentInfo', getParentProps);
470
+
471
+ const startPageInfoMonitor = startInfoMonitor(
472
+ sendPageInfoToIframe,
473
+ 'PageInfo',
474
+ );
475
+ const startParentInfoMonitor = startInfoMonitor(
476
+ sendParentInfoToIframe,
477
+ 'ParentInfo',
478
+ );
479
+
480
+ const stopPageInfoMonitor = stopInfoMonitor('stopPageInfo');
481
+ const stopParentInfoMonitor = stopInfoMonitor('stopParentInfo');
400
482
 
401
483
  function checkIFrameExists() {
402
- var retBool = true
484
+ let retBool = true;
403
485
 
404
- if (null === messageData.iframe) {
405
- warn(iframeId, 'IFrame (' + messageData.id + ') not found')
406
- retBool = false
486
+ if (messageData.iframe === null) {
487
+ warn(iframeId, `The iframe (${messageData.id}) was not found.`);
488
+ retBool = false;
407
489
  }
490
+
408
491
  return retBool
409
492
  }
410
493
 
411
494
  function getElementPosition(target) {
412
- var iFramePosition = target.getBoundingClientRect()
495
+ const iFramePosition = target.getBoundingClientRect();
413
496
 
414
- getPagePosition(iframeId)
497
+ getPagePosition();
415
498
 
416
499
  return {
417
- x: Math.floor(Number(iFramePosition.left) + Number(pagePosition.x)),
418
- y: Math.floor(Number(iFramePosition.top) + Number(pagePosition.y))
500
+ x: Number(iFramePosition.left) + Number(page.position.x),
501
+ y: Number(iFramePosition.top) + Number(page.position.y),
419
502
  }
420
503
  }
421
504
 
505
+ function scrollBy() {
506
+ const x = messageData.width;
507
+ const y = messageData.height;
508
+
509
+ const target = window.parentIframe || window;
510
+
511
+ target.scrollBy(x, y);
512
+ }
513
+
422
514
  function scrollRequestFromChild(addOffset) {
423
515
  /* istanbul ignore next */ // Not testable in Karma
424
516
  function reposition() {
425
- pagePosition = newPosition
426
- scrollTo()
427
- log(iframeId, '--')
428
- }
429
-
430
- function calcOffset() {
431
- return {
432
- x: Number(messageData.width) + offset.x,
433
- y: Number(messageData.height) + offset.y
434
- }
517
+ page.position = newPosition;
518
+ scrollTo(iframeId);
435
519
  }
436
520
 
437
521
  function scrollParent() {
438
522
  if (window.parentIFrame) {
439
- window.parentIFrame['scrollTo' + (addOffset ? 'Offset' : '')](
523
+ window.parentIFrame[`scrollTo${addOffset ? 'Offset' : ''}`](
440
524
  newPosition.x,
441
- newPosition.y
442
- )
525
+ newPosition.y,
526
+ );
443
527
  } else {
444
528
  warn(
445
529
  iframeId,
446
- 'Unable to scroll to requested position, window.parentIFrame not found'
447
- )
530
+ 'Unable to scroll to requested position, window.parentIFrame not found',
531
+ );
448
532
  }
449
533
  }
450
534
 
451
- var offset = addOffset
452
- ? getElementPosition(messageData.iframe)
453
- : { x: 0, y: 0 },
454
- newPosition = calcOffset()
455
-
456
- log(
457
- iframeId,
458
- 'Reposition requested from iFrame (offset x:' +
459
- offset.x +
460
- ' y:' +
461
- offset.y +
462
- ')'
463
- )
535
+ const calcOffset = (messageData, offset) => ({
536
+ x: messageData.width + offset.x,
537
+ y: messageData.height + offset.y,
538
+ });
539
+
540
+ const offset = addOffset
541
+ ? getElementPosition(messageData.iframe)
542
+ : { x: 0, y: 0 };
543
+
544
+ let newPosition = calcOffset(messageData, offset);
464
545
 
465
546
  if (window.top === window.self) {
466
- reposition()
547
+ reposition();
467
548
  } else {
468
- scrollParent()
549
+ scrollParent();
469
550
  }
470
551
  }
471
552
 
472
- function scrollTo() {
473
- if (false === on('onScroll', pagePosition)) {
474
- unsetPagePosition()
475
- } else {
476
- setPagePosition(iframeId)
553
+ function scrollTo(iframeId) {
554
+ const { x, y } = page.position;
555
+ const iframe = settings[iframeId]?.iframe;
556
+ if (on('onScroll', { iframe, top: y, left: x, x, y }) === false) {
557
+ unsetPagePosition();
558
+ return
477
559
  }
560
+ setPagePosition();
478
561
  }
479
562
 
480
563
  function findTarget(location) {
481
564
  function jumpToTarget() {
482
- var jumpPosition = getElementPosition(target)
565
+ const jumpPosition = getElementPosition(target);
483
566
 
484
- log(
485
- iframeId,
486
- 'Moving to in page link (#' +
487
- hash +
488
- ') at x: ' +
489
- jumpPosition.x +
490
- ' y: ' +
491
- jumpPosition.y
492
- )
493
- pagePosition = {
567
+ page.position = {
494
568
  x: jumpPosition.x,
495
- y: jumpPosition.y
496
- }
569
+ y: jumpPosition.y,
570
+ };
497
571
 
498
- scrollTo()
499
- log(iframeId, '--')
572
+ scrollTo(iframeId);
500
573
  }
501
574
 
502
575
  function jumpToParent() {
503
576
  if (window.parentIFrame) {
504
- window.parentIFrame.moveToAnchor(hash)
505
- } else {
506
- log(
507
- iframeId,
508
- 'In page link #' +
509
- hash +
510
- ' not found and window.parentIFrame not found'
511
- )
577
+ window.parentIFrame.moveToAnchor(hash);
578
+ return
512
579
  }
513
580
  }
514
581
 
515
- var hash = location.split('#')[1] || '',
516
- hashData = decodeURIComponent(hash),
517
- target =
518
- document.getElementById(hashData) ||
519
- document.getElementsByName(hashData)[0]
582
+ const hash = location.split('#')[1] || '';
583
+ const hashData = decodeURIComponent(hash);
584
+
585
+ let target =
586
+ document.getElementById(hashData) ||
587
+ document.getElementsByName(hashData)[0];
520
588
 
521
589
  if (target) {
522
- jumpToTarget()
523
- } else if (window.top === window.self) {
524
- log(iframeId, 'In page link #' + hash + ' not found')
525
- } else {
526
- jumpToParent()
590
+ jumpToTarget();
591
+ return
592
+ }
593
+
594
+ if (window.top === window.self) {
595
+ return
527
596
  }
597
+
598
+ jumpToParent();
528
599
  }
529
600
 
530
601
  function onMouse(event) {
531
- var mousePos = {}
602
+ let mousePos = {};
532
603
 
533
- if (Number(messageData.width) === 0 && Number(messageData.height) === 0) {
534
- var data = getMsgBody(9).split(':')
604
+ if (messageData.width === 0 && messageData.height === 0) {
605
+ const data = getMsgBody(9).split(':');
535
606
  mousePos = {
536
607
  x: data[1],
537
- y: data[0]
538
- }
608
+ y: data[0],
609
+ };
539
610
  } else {
540
611
  mousePos = {
541
612
  x: messageData.width,
542
- y: messageData.height
543
- }
613
+ y: messageData.height,
614
+ };
544
615
  }
545
616
 
546
617
  on(event, {
547
618
  iframe: messageData.iframe,
548
619
  screenX: Number(mousePos.x),
549
620
  screenY: Number(mousePos.y),
550
- type: messageData.type
551
- })
621
+ type: messageData.type,
622
+ });
623
+ }
624
+
625
+ const on = (funcName, val) => chkEvent(iframeId, funcName, val);
626
+
627
+ function checkSameDomain(id) {
628
+ try {
629
+ settings[id].sameDomain =
630
+ !!settings[id]?.iframe?.contentWindow?.iframeChildListener;
631
+ } catch (error) {
632
+ settings[id].sameDomain = false;
633
+ }
552
634
  }
553
635
 
554
- function on(funcName, val) {
555
- return chkEvent(iframeId, funcName, val)
636
+ function checkVersion(version) {
637
+ if (version === VERSION) return
638
+ if (version === undefined) {
639
+ advise(
640
+ iframeId,
641
+ `<rb>Legacy version detected in iframe</>
642
+
643
+ Detected legacy version of child page script. It is recommended to update the page in the iframe to use <b>@iframe-resizer/child</>.
644
+
645
+ See <u>https://iframe-resizer.com/setup/#child-page-setup</> for more details.
646
+ `,
647
+ );
648
+ return
649
+ }
650
+ }
651
+
652
+ function setTitle(title, iframeId) {
653
+ if (!settings[iframeId]?.syncTitle) return
654
+ settings[iframeId].iframe.title = title;
655
+ }
656
+
657
+ function started() {
658
+ setup = true;
556
659
  }
557
660
 
558
661
  function actionMsg() {
559
- if (settings[iframeId] && settings[iframeId].firstRun) firstRun()
662
+ if (settings[iframeId]?.firstRun) firstRun();
560
663
 
561
664
  switch (messageData.type) {
562
- case 'close': {
563
- closeIFrame(messageData.iframe)
665
+ case 'close':
666
+ closeIFrame(messageData.iframe);
564
667
  break
565
- }
566
668
 
567
- case 'message': {
568
- forwardMsgFromIFrame(getMsgBody(6))
669
+ case 'message':
670
+ forwardMsgFromIFrame(getMsgBody(6));
569
671
  break
570
- }
571
672
 
572
- case 'mouseenter': {
573
- onMouse('onMouseEnter')
673
+ case 'mouseenter':
674
+ onMouse('onMouseEnter');
574
675
  break
575
- }
576
676
 
577
- case 'mouseleave': {
578
- onMouse('onMouseLeave')
677
+ case 'mouseleave':
678
+ onMouse('onMouseLeave');
579
679
  break
580
- }
581
680
 
582
- case 'autoResize': {
583
- settings[iframeId].autoResize = JSON.parse(getMsgBody(9))
681
+ case 'autoResize':
682
+ settings[iframeId].autoResize = JSON.parse(getMsgBody(9));
584
683
  break
585
- }
586
684
 
587
- case 'scrollTo': {
588
- scrollRequestFromChild(false)
685
+ case 'scrollBy':
686
+ scrollBy();
589
687
  break
590
- }
591
688
 
592
- case 'scrollToOffset': {
593
- scrollRequestFromChild(true)
689
+ case 'scrollTo':
690
+ scrollRequestFromChild(false);
594
691
  break
595
- }
596
692
 
597
- case 'pageInfo': {
598
- sendPageInfoToIframe(
599
- settings[iframeId] && settings[iframeId].iframe,
600
- iframeId
601
- )
602
- startPageInfoMonitor()
693
+ case 'scrollToOffset':
694
+ scrollRequestFromChild(true);
603
695
  break
604
- }
605
696
 
606
- case 'pageInfoStop': {
607
- stopPageInfoMonitor()
697
+ case 'pageInfo':
698
+ sendPageInfoToIframe('start', iframeId);
699
+ startPageInfoMonitor();
608
700
  break
609
- }
610
701
 
611
- case 'inPageLink': {
612
- findTarget(getMsgBody(9))
702
+ case 'parentInfo':
703
+ sendParentInfoToIframe('start', iframeId);
704
+ startParentInfoMonitor();
613
705
  break
614
- }
615
706
 
616
- case 'reset': {
617
- resetIFrame(messageData)
707
+ case 'pageInfoStop':
708
+ stopPageInfoMonitor();
618
709
  break
619
- }
620
710
 
621
- case 'init': {
622
- resizeIFrame()
623
- on('onInit', messageData.iframe)
711
+ case 'parentInfoStop':
712
+ stopParentInfoMonitor();
624
713
  break
625
- }
626
714
 
627
- default: {
628
- if (
629
- Number(messageData.width) === 0 &&
630
- Number(messageData.height) === 0
631
- ) {
715
+ case 'inPageLink':
716
+ findTarget(getMsgBody(9));
717
+ break
718
+
719
+ case 'title':
720
+ setTitle(messageData.msg, iframeId);
721
+ break
722
+
723
+ case 'reset':
724
+ resetIFrame(messageData);
725
+ break
726
+
727
+ case 'init':
728
+ resizeIFrame();
729
+ checkSameDomain(iframeId);
730
+ checkVersion(messageData.msg);
731
+ started();
732
+ on('onReady', messageData.iframe);
733
+ break
734
+
735
+ default:
736
+ if (messageData.width === 0 && messageData.height === 0) {
632
737
  warn(
633
- 'Unsupported message received (' +
634
- messageData.type +
635
- '), this is likely due to the iframe containing a later ' +
636
- 'version of iframe-resizer than the parent page'
637
- )
638
- } else {
639
- resizeIFrame()
738
+ `Unsupported message received (${messageData.type}), this is likely due to the iframe containing a later ` +
739
+ `version of iframe-resizer than the parent page`,
740
+ );
741
+ return
640
742
  }
641
- }
743
+
744
+ if (messageData.width === 0 || messageData.height === 0) {
745
+ return
746
+ }
747
+
748
+ // Recheck document.hidden here, as only Firefox
749
+ // correctly supports this in the iframe
750
+ if (document.hidden) {
751
+ return
752
+ }
753
+
754
+ resizeIFrame();
642
755
  }
643
756
  }
644
757
 
645
- function hasSettings(iframeId) {
646
- var retBool = true
647
-
758
+ function checkSettings(iframeId) {
648
759
  if (!settings[iframeId]) {
649
- retBool = false
650
- warn(
651
- messageData.type +
652
- ' No settings for ' +
653
- iframeId +
654
- '. Message was: ' +
655
- msg
760
+ throw new Error(
761
+ `${messageData.type} No settings for ${iframeId}. Message was: ${msg}`,
656
762
  )
657
763
  }
658
-
659
- return retBool
660
764
  }
661
765
 
662
766
  function iFrameReadyMsgReceived() {
663
- // eslint-disable-next-line no-restricted-syntax, guard-for-in
664
- for (var iframeId in settings) {
665
- trigger(
666
- 'iFrame requested init',
667
- createOutgoingMsg(iframeId),
668
- settings[iframeId].iframe,
669
- iframeId
670
- )
671
- }
767
+ Object.keys(settings).forEach((iframeId) => {
768
+ if (settings[iframeId].mode >= 0)
769
+ trigger('iFrame requested init', createOutgoingMsg(iframeId), iframeId);
770
+ });
672
771
  }
673
772
 
674
773
  function firstRun() {
675
774
  if (settings[iframeId]) {
676
- settings[iframeId].firstRun = false
775
+ settings[iframeId].firstRun = false;
677
776
  }
678
777
  }
679
778
 
680
- var msg = event.data,
681
- messageData = {},
682
- iframeId = null
779
+ let msg = event.data;
780
+ let messageData = {};
781
+ let iframeId = null;
683
782
 
684
- if ('[iFrameResizerChild]Ready' === msg) {
685
- iFrameReadyMsgReceived()
686
- } else if (isMessageForUs()) {
687
- messageData = processMsg()
688
- iframeId = messageData.id
689
- if (settings[iframeId]) {
690
- settings[iframeId].loaded = true
691
- }
783
+ if (msg === '[iFrameResizerChild]Ready') {
784
+ iFrameReadyMsgReceived();
785
+ return
786
+ }
692
787
 
693
- if (!isMessageFromMetaParent() && hasSettings(iframeId)) {
694
- log(iframeId, 'Received: ' + msg)
788
+ if (!isMessageForUs()) {
789
+ return
790
+ }
695
791
 
696
- if (checkIFrameExists() && isMessageFromIFrame()) {
697
- actionMsg()
698
- }
792
+ messageData = processMsg();
793
+ iframeId = messageData.id;
794
+
795
+ if (!iframeId) {
796
+ warn('iframeResizer received messageData without id, message was: ', msg);
797
+ return
798
+ }
799
+
800
+ checkSettings(iframeId);
801
+
802
+ if (!isMessageFromMetaParent()) {
803
+ settings[iframeId].loaded = true;
804
+
805
+ if (checkIFrameExists() && isMessageFromIFrame()) {
806
+ actionMsg();
699
807
  }
700
- } else {
701
- info(iframeId, 'Ignored: ' + msg)
702
808
  }
703
809
  }
704
810
 
705
811
  function chkEvent(iframeId, funcName, val) {
706
- var func = null,
707
- retVal = null
812
+ let func = null;
813
+ let retVal = null;
708
814
 
709
815
  if (settings[iframeId]) {
710
- func = settings[iframeId][funcName]
816
+ func = settings[iframeId][funcName];
711
817
 
712
- if ('function' === typeof func) {
713
- retVal = func(val)
818
+ if (typeof func === 'function') {
819
+ retVal = func(val);
714
820
  } else {
715
821
  throw new TypeError(
716
- funcName + ' on iFrame[' + iframeId + '] is not a function'
822
+ `${funcName} on iFrame[${iframeId}] is not a function`,
717
823
  )
718
824
  }
719
825
  }
@@ -722,421 +828,262 @@ Please see https://iframe-resizer.com/upgrade for more details.
722
828
  }
723
829
 
724
830
  function removeIframeListeners(iframe) {
725
- var iframeId = iframe.id
726
- delete settings[iframeId]
831
+ const iframeId = iframe.id;
832
+ delete settings[iframeId];
727
833
  }
728
834
 
729
835
  function closeIFrame(iframe) {
730
- var iframeId = iframe.id
836
+ const iframeId = iframe.id;
731
837
  if (chkEvent(iframeId, 'onClose', iframeId) === false) {
732
- log(iframeId, 'Close iframe cancelled by onClose event')
733
838
  return
734
839
  }
735
- log(iframeId, 'Removing iFrame: ' + iframeId)
736
840
 
737
841
  try {
738
842
  // Catch race condition error with React
739
843
  if (iframe.parentNode) {
740
- iframe.parentNode.removeChild(iframe)
844
+ iframe.remove();
741
845
  }
742
846
  } catch (error) {
743
- warn(error)
847
+ warn(error);
744
848
  }
745
849
 
746
- chkEvent(iframeId, 'onClosed', iframeId)
747
- log(iframeId, '--')
748
- removeIframeListeners(iframe)
749
- if (destroyObserver) {
750
- destroyObserver.disconnect()
751
- destroyObserver = null
752
- }
850
+ chkEvent(iframeId, 'onClosed', iframeId);
851
+ removeIframeListeners(iframe);
753
852
  }
754
853
 
755
854
  function getPagePosition(iframeId) {
756
- if (null === pagePosition) {
757
- pagePosition = {
758
- x:
759
- window.pageXOffset === undefined
760
- ? document.documentElement.scrollLeft
761
- : window.pageXOffset,
762
- y:
763
- window.pageYOffset === undefined
764
- ? document.documentElement.scrollTop
765
- : window.pageYOffset
766
- }
767
- log(
768
- iframeId,
769
- 'Get page position: ' + pagePosition.x + ',' + pagePosition.y
770
- )
855
+ if (page.position === null) {
856
+ page.position = {
857
+ x: window.scrollX,
858
+ y: window.scrollY,
859
+ };
771
860
  }
772
861
  }
773
862
 
774
- function setPagePosition(iframeId) {
775
- if (null !== pagePosition) {
776
- window.scrollTo(pagePosition.x, pagePosition.y)
777
- log(
778
- iframeId,
779
- 'Set page position: ' + pagePosition.x + ',' + pagePosition.y
780
- )
781
- unsetPagePosition()
782
- }
863
+ function unsetPagePosition() {
864
+ page.position = null;
783
865
  }
784
866
 
785
- function unsetPagePosition() {
786
- pagePosition = null
867
+ function setPagePosition(iframeId) {
868
+ if (page.position !== null) {
869
+ window.scrollTo(page.position.x, page.position.y);
870
+ unsetPagePosition();
871
+ }
787
872
  }
788
873
 
789
874
  function resetIFrame(messageData) {
790
- function reset() {
791
- setSize(messageData)
792
- trigger('reset', 'reset', messageData.iframe, messageData.id)
793
- }
794
-
795
- log(
796
- messageData.id,
797
- 'Size reset requested by ' +
798
- ('init' === messageData.type ? 'host page' : 'iFrame')
799
- )
800
- getPagePosition(messageData.id)
801
- syncResize(reset, messageData, 'reset')
875
+
876
+ getPagePosition(messageData.id);
877
+ setSize(messageData);
878
+ trigger('reset', 'reset', messageData.id);
802
879
  }
803
880
 
804
881
  function setSize(messageData) {
805
- function setDimension(dimension) {
806
- if (!messageData.id) {
807
- log('undefined', 'messageData id not set')
808
- return
809
- }
810
- messageData.iframe.style[dimension] = messageData[dimension] + 'px'
811
- log(
812
- messageData.id,
813
- 'IFrame (' +
814
- iframeId +
815
- ') ' +
816
- dimension +
817
- ' set to ' +
818
- messageData[dimension] +
819
- 'px'
820
- )
821
- }
822
-
823
- function chkZero(dimension) {
824
- // FireFox sets dimension of hidden iFrames to zero.
825
- // So if we detect that set up an event to check for
826
- // when iFrame becomes visible.
827
-
828
- /* istanbul ignore next */ // Not testable in PhantomJS
829
- if (!hiddenCheckEnabled && '0' === messageData[dimension]) {
830
- hiddenCheckEnabled = true
831
- log(iframeId, 'Hidden iFrame detected, creating visibility listener')
832
- fixHiddenIFrames()
833
- }
834
- }
882
+ const iframeId = messageData.id;
835
883
 
836
- function processDimension(dimension) {
837
- setDimension(dimension)
838
- chkZero(dimension)
884
+ function setDimension(dimension) {
885
+ const size = `${messageData[dimension]}px`;
886
+ messageData.iframe.style[dimension] = size;
839
887
  }
840
888
 
841
- var iframeId = messageData.iframe.id
842
-
843
- if (settings[iframeId]) {
844
- if (settings[iframeId].sizeHeight) {
845
- processDimension('height')
846
- }
847
- if (settings[iframeId].sizeWidth) {
848
- processDimension('width')
849
- }
889
+ if (settings[iframeId].sizeHeight) {
890
+ setDimension('height');
850
891
  }
851
- }
852
-
853
- function syncResize(func, messageData, doNotSync) {
854
- /* istanbul ignore if */ // Not testable in PhantomJS
855
- if (
856
- doNotSync !== messageData.type &&
857
- requestAnimationFrame &&
858
- // including check for jasmine because had trouble getting spy to work in unit test using requestAnimationFrame
859
- !window.jasmine
860
- ) {
861
- log(messageData.id, 'Requesting animation frame')
862
- requestAnimationFrame(func)
863
- } else {
864
- func()
892
+ if (settings[iframeId].sizeWidth) {
893
+ setDimension('width');
865
894
  }
866
895
  }
867
896
 
868
- function trigger(calleeMsg, msg, iframe, id, noResponseWarning) {
897
+ function trigger(calleeMsg, msg, id, noResponseWarning) {
869
898
  function postMessageToIFrame() {
870
- var target = settings[id] && settings[id].targetOrigin
871
- log(
872
- id,
873
- '[' +
874
- calleeMsg +
875
- '] Sending msg to iframe[' +
876
- id +
877
- '] (' +
878
- msg +
879
- ') targetOrigin: ' +
880
- target
881
- )
882
- iframe.contentWindow.postMessage(msgId + msg, target)
899
+ const { postMessageTarget, targetOrigin } = settings[id];
900
+
901
+ if (settings[id].sameDomain) {
902
+ try {
903
+ settings[id].iframe.contentWindow.iframeChildListener(msgId + msg);
904
+ return
905
+ } catch (error) {
906
+ }
907
+ }
908
+ postMessageTarget.postMessage(msgId + msg, targetOrigin);
883
909
  }
884
910
 
885
911
  function iFrameNotFound() {
886
- warn(id, '[' + calleeMsg + '] IFrame(' + id + ') not found')
912
+ warn(id, `[${calleeMsg}] IFrame(${id}) not found`);
887
913
  }
888
914
 
889
915
  function chkAndSend() {
890
- if (
891
- iframe &&
892
- 'contentWindow' in iframe &&
893
- null !== iframe.contentWindow
894
- ) {
895
- // Null test for PhantomJS
896
- postMessageToIFrame()
897
- } else {
898
- iFrameNotFound()
916
+ if (!settings[id]?.postMessageTarget) {
917
+ iFrameNotFound();
918
+ return
899
919
  }
920
+ postMessageToIFrame();
900
921
  }
901
922
 
902
923
  function warnOnNoResponse() {
903
924
  function warning() {
904
- if (settings[id] && !settings[id].loaded && !errorShown) {
905
- errorShown = true
906
- warn(
925
+ if (settings[id] === undefined) return // iframe has been closed while we where waiting
926
+
927
+ if (!settings[id].loaded && !settings[id].loadErrorShown) {
928
+ settings[id].loadErrorShown = true;
929
+ advise(
907
930
  id,
908
- 'IFrame has not responded within ' +
909
- settings[id].warningTimeout / 1000 +
910
- ' 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.'
911
- )
931
+ `
932
+ <rb>No response from iFrame</>
933
+
934
+ The iframe (<i>${id}</>) has not responded within ${settings[id].warningTimeout / 1000} seconds. Check <b>@iframe-resizer/child</> package has been loaded in the iframe.
935
+
936
+ This message can be ignored if everything is working, or you can set the <b>warningTimeout</> option to a higher value or zero to suppress this warning.
937
+ `,
938
+ );
912
939
  }
913
940
  }
914
941
 
915
- if (
916
- !!noResponseWarning &&
917
- settings[id] &&
918
- !!settings[id].warningTimeout
919
- ) {
920
- settings[id].msgTimeout = setTimeout(
921
- warning,
922
- settings[id].warningTimeout
923
- )
942
+ if (!!noResponseWarning && !!settings[id]?.warningTimeout) {
943
+ settings[id].msgTimeout = setTimeout(warning, settings[id].warningTimeout);
924
944
  }
925
945
  }
926
946
 
927
- var errorShown = false
928
-
929
- id = id || iframe.id
930
-
931
947
  if (settings[id]) {
932
- chkAndSend()
933
- warnOnNoResponse()
948
+ chkAndSend();
949
+ warnOnNoResponse();
934
950
  }
935
951
  }
936
952
 
937
953
  function createOutgoingMsg(iframeId) {
938
- return (
939
- iframeId +
940
- ':' +
941
- settings[iframeId].bodyMarginV1 +
942
- ':' +
943
- settings[iframeId].sizeWidth +
944
- ':' +
945
- settings[iframeId].log +
946
- ':' +
947
- settings[iframeId].interval +
948
- ':' +
949
- settings[iframeId].enablePublicMethods +
950
- ':' +
951
- settings[iframeId].autoResize +
952
- ':' +
953
- settings[iframeId].bodyMargin +
954
- ':' +
955
- settings[iframeId].heightCalculationMethod +
956
- ':' +
957
- settings[iframeId].bodyBackground +
958
- ':' +
959
- settings[iframeId].bodyPadding +
960
- ':' +
961
- settings[iframeId].tolerance +
962
- ':' +
963
- settings[iframeId].inPageLinks +
964
- ':' +
965
- settings[iframeId].resizeFrom +
966
- ':' +
967
- settings[iframeId].widthCalculationMethod +
968
- ':' +
969
- settings[iframeId].mouseEvents
970
- )
954
+ const iframeSettings = settings[iframeId];
955
+
956
+ return [
957
+ iframeId,
958
+ '8', // Backwards compatibility (PaddingV1)
959
+ iframeSettings.sizeWidth,
960
+ iframeSettings.log,
961
+ '32', // Backwards compatibility (Interval)
962
+ true, // Backwards compatibility (EnablePublicMethods)
963
+ iframeSettings.autoResize,
964
+ iframeSettings.bodyMargin,
965
+ iframeSettings.heightCalculationMethod,
966
+ iframeSettings.bodyBackground,
967
+ iframeSettings.bodyPadding,
968
+ iframeSettings.tolerance,
969
+ iframeSettings.inPageLinks,
970
+ 'child', // Backwards compatibility (resizeFrom)
971
+ iframeSettings.widthCalculationMethod,
972
+ iframeSettings.mouseEvents,
973
+ iframeSettings.offsetHeight,
974
+ iframeSettings.offsetWidth,
975
+ iframeSettings.sizeHeight,
976
+ iframeSettings.license,
977
+ page.version,
978
+ iframeSettings.mode,
979
+ // iframeSettings.sizeSelector,
980
+ ].join(':')
971
981
  }
972
982
 
973
- function isNumber(value) {
974
- return typeof value === 'number'
975
- }
983
+ let count = 0;
984
+ let setup = false;
985
+ let vAdvised = false;
976
986
 
977
- function setupIFrame(iframe, options) {
978
- function setLimits() {
979
- function addStyle(style) {
980
- var styleValue = settings[iframeId][style]
981
- if (Infinity !== styleValue && 0 !== styleValue) {
982
- iframe.style[style] = isNumber(styleValue)
983
- ? styleValue + 'px'
984
- : styleValue
985
- log(iframeId, 'Set ' + style + ' = ' + iframe.style[style])
986
- }
987
- }
987
+ const connectResizer = (options) => (iframe) => {
988
+ function newId() {
989
+ let id = options?.id || defaults.id + count++;
988
990
 
989
- function chkMinMax(dimension) {
990
- if (
991
- settings[iframeId]['min' + dimension] >
992
- settings[iframeId]['max' + dimension]
993
- ) {
994
- throw new Error(
995
- 'Value for min' +
996
- dimension +
997
- ' can not be greater than max' +
998
- dimension
999
- )
1000
- }
991
+ if (document.getElementById(id) !== null) {
992
+ id += count++;
1001
993
  }
1002
994
 
1003
- chkMinMax('Height')
1004
- chkMinMax('Width')
1005
-
1006
- addStyle('maxHeight')
1007
- addStyle('minHeight')
1008
- addStyle('maxWidth')
1009
- addStyle('minWidth')
1010
- }
1011
-
1012
- function newId() {
1013
- var id = (options && options.id) || defaults.id + count++
1014
- if (null !== document.getElementById(id)) {
1015
- id += count++
1016
- }
1017
995
  return id
1018
996
  }
1019
997
 
1020
998
  function ensureHasId(iframeId) {
1021
- if (typeof iframeId !== 'string') {
1022
- throw new TypeError('Invaild id for iFrame. Expected String')
999
+ if (iframeId && typeof iframeId !== 'string') {
1000
+ throw new TypeError('Invalid id for iFrame. Expected String')
1023
1001
  }
1024
1002
 
1025
- if ('' === iframeId) {
1003
+ if (iframeId === '' || !iframeId) {
1026
1004
  // eslint-disable-next-line no-multi-assign
1027
- iframe.id = iframeId = newId()
1028
- logEnabled = (options || {}).log
1029
- log(
1030
- iframeId,
1031
- 'Added missing iframe ID: ' + iframeId + ' (' + iframe.src + ')'
1032
- )
1005
+ iframe.id = iframeId = newId();
1006
+ setLogEnabled((options || {}).log);
1033
1007
  }
1034
1008
 
1035
1009
  return iframeId
1036
1010
  }
1037
1011
 
1038
1012
  function setScrolling() {
1039
- log(
1040
- iframeId,
1041
- 'IFrame scrolling ' +
1042
- (settings[iframeId] && settings[iframeId].scrolling
1043
- ? 'enabled'
1044
- : 'disabled') +
1045
- ' for ' +
1046
- iframeId
1047
- )
1013
+
1048
1014
  iframe.style.overflow =
1049
- false === (settings[iframeId] && settings[iframeId].scrolling)
1050
- ? 'hidden'
1051
- : 'auto'
1052
- switch (settings[iframeId] && settings[iframeId].scrolling) {
1053
- case 'omit': {
1015
+ settings[iframeId]?.scrolling === false ? 'hidden' : 'auto';
1016
+
1017
+ switch (settings[iframeId]?.scrolling) {
1018
+ case 'omit':
1054
1019
  break
1055
- }
1056
1020
 
1057
- case true: {
1058
- iframe.scrolling = 'yes'
1021
+ case true:
1022
+ iframe.scrolling = 'yes';
1059
1023
  break
1060
- }
1061
1024
 
1062
- case false: {
1063
- iframe.scrolling = 'no'
1025
+ case false:
1026
+ iframe.scrolling = 'no';
1064
1027
  break
1065
- }
1066
1028
 
1067
- default: {
1029
+ default:
1068
1030
  iframe.scrolling = settings[iframeId]
1069
1031
  ? settings[iframeId].scrolling
1070
- : 'no'
1071
- }
1032
+ : 'no';
1072
1033
  }
1073
1034
  }
1074
1035
 
1075
- // The V1 iFrame script expects an int, where as in V2 expects a CSS
1076
- // string value such as '1px 3em', so if we have an int for V2, set V1=V2
1077
- // and then convert V2 to a string PX value.
1078
1036
  function setupBodyMarginValues() {
1079
- if (
1080
- 'number' ===
1081
- typeof (settings[iframeId] && settings[iframeId].bodyMargin) ||
1082
- '0' === (settings[iframeId] && settings[iframeId].bodyMargin)
1083
- ) {
1084
- settings[iframeId].bodyMarginV1 = settings[iframeId].bodyMargin
1085
- settings[iframeId].bodyMargin =
1086
- '' + settings[iframeId].bodyMargin + 'px'
1037
+ const { bodyMargin } = settings[iframeId];
1038
+
1039
+ if (typeof bodyMargin === 'number' || bodyMargin === '0') {
1040
+ settings[iframeId].bodyMargin = `${bodyMargin}px`;
1087
1041
  }
1088
1042
  }
1089
1043
 
1090
1044
  function checkReset() {
1091
- // Reduce scope of firstRun to function, because IE8's JS execution
1092
- // context stack is borked and this value gets externally
1093
- // changed midway through running this function!!!
1094
- var firstRun = settings[iframeId] && settings[iframeId].firstRun,
1095
- resetRequertMethod =
1096
- settings[iframeId] &&
1097
- settings[iframeId].heightCalculationMethod in resetRequiredMethods
1098
-
1099
- if (!firstRun && resetRequertMethod) {
1100
- resetIFrame({ iframe: iframe, height: 0, width: 0, type: 'init' })
1045
+ const firstRun = settings[iframeId]?.firstRun;
1046
+ const resetRequestMethod =
1047
+ settings[iframeId]?.heightCalculationMethod in resetRequiredMethods;
1048
+
1049
+ if (!firstRun && resetRequestMethod) {
1050
+ resetIFrame({ iframe, height: 0, width: 0, type: 'init' });
1101
1051
  }
1102
1052
  }
1103
1053
 
1104
1054
  function setupIFrameObject() {
1105
1055
  if (settings[iframeId]) {
1106
- settings[iframeId].iframe.iFrameResizer = {
1056
+ const resizer = {
1107
1057
  close: closeIFrame.bind(null, settings[iframeId].iframe),
1108
1058
 
1109
- removeListeners: removeIframeListeners.bind(
1110
- null,
1111
- settings[iframeId].iframe
1112
- ),
1113
-
1114
- resize: trigger.bind(
1115
- null,
1116
- 'Window resize',
1117
- 'resize',
1118
- settings[iframeId].iframe
1119
- ),
1120
-
1121
- moveToAnchor: function (anchor) {
1122
- trigger(
1123
- 'Move to anchor',
1124
- 'moveToAnchor:' + anchor,
1125
- settings[iframeId].iframe,
1126
- iframeId
1127
- )
1059
+ disconnect: removeIframeListeners.bind(null, settings[iframeId].iframe),
1060
+
1061
+ removeListeners() {
1062
+ advise(
1063
+ iframeId,
1064
+ `
1065
+ <rb>Deprecated Method Name</>
1066
+
1067
+ The \u001B[removeListeners()</> method has been renamed to \u001B[disconnect()</>.
1068
+ `,
1069
+ );
1070
+ this.disconnect();
1128
1071
  },
1129
1072
 
1130
- sendMessage: function (message) {
1131
- message = JSON.stringify(message)
1132
- trigger(
1133
- 'Send Message',
1134
- 'message:' + message,
1135
- settings[iframeId].iframe,
1136
- iframeId
1137
- )
1138
- }
1139
- }
1073
+ resize: trigger.bind(null, 'Window resize', 'resize', iframeId),
1074
+
1075
+ moveToAnchor(anchor) {
1076
+ trigger('Move to anchor', `moveToAnchor:${anchor}`, iframeId);
1077
+ },
1078
+
1079
+ sendMessage(message) {
1080
+ message = JSON.stringify(message);
1081
+ trigger('Send Message', `message:${message}`, iframeId);
1082
+ },
1083
+ };
1084
+
1085
+ settings[iframeId].iframe.iframeResizer = resizer;
1086
+ settings[iframeId].iframe.iFrameResizer = resizer;
1140
1087
  }
1141
1088
  }
1142
1089
 
@@ -1145,344 +1092,229 @@ Please see https://iframe-resizer.com/upgrade for more details.
1145
1092
  // event listener also catches the page changing in the iFrame.
1146
1093
  function init(msg) {
1147
1094
  function iFrameLoaded() {
1148
- trigger('iFrame.onload', msg, iframe, undefined, true)
1149
- checkReset()
1095
+ trigger('iFrame.onload', `${msg}:${setup}`, id, true);
1096
+ checkReset();
1150
1097
  }
1151
1098
 
1152
- function createDestroyObserver(MutationObserver) {
1153
- if (!iframe.parentNode) {
1154
- return null
1155
- }
1099
+ const { id } = iframe;
1156
1100
 
1157
- var destroyObserver = new MutationObserver(function (mutations) {
1158
- mutations.forEach(function (mutation) {
1159
- var removedNodes = Array.prototype.slice.call(mutation.removedNodes) // Transform NodeList into an Array
1160
- removedNodes.forEach(function (removedNode) {
1161
- if (removedNode === iframe) {
1162
- closeIFrame(iframe)
1163
- }
1164
- })
1165
- })
1166
- })
1167
- destroyObserver.observe(iframe.parentNode, {
1168
- childList: true
1169
- })
1170
- return destroyObserver
1171
- }
1101
+ if (settings[id].mode === -1) return // modal()
1102
+ if (settings[id].mode === -2) return
1172
1103
 
1173
- var MutationObserver = getMutationObserver()
1174
- if (MutationObserver) {
1175
- destroyObserver = createDestroyObserver(MutationObserver)
1176
- }
1177
-
1178
- addEventListener(iframe, 'load', iFrameLoaded)
1179
- trigger('init', msg, iframe, undefined, true)
1104
+ addEventListener(iframe, 'load', iFrameLoaded);
1105
+ if (settings[id].waitForLoad === false)
1106
+ trigger('init', `${msg}:${setup}`, id, true);
1180
1107
  }
1181
1108
 
1182
1109
  function checkOptions(options) {
1183
- if ('object' !== typeof options) {
1110
+ if (!options) return {}
1111
+
1112
+ if (typeof options !== 'object') {
1184
1113
  throw new TypeError('Options is not an object')
1185
1114
  }
1186
- }
1187
1115
 
1188
- function copyOptions(options) {
1189
- // eslint-disable-next-line no-restricted-syntax
1190
- for (var option in defaults) {
1191
- if (Object.prototype.hasOwnProperty.call(defaults, option)) {
1192
- settings[iframeId][option] = Object.prototype.hasOwnProperty.call(
1193
- options,
1194
- option
1195
- )
1196
- ? options[option]
1197
- : defaults[option]
1198
- }
1116
+ if (
1117
+ 'sizeWidth' in options ||
1118
+ 'sizeHeight' in options ||
1119
+ 'autoResize' in options
1120
+ ) {
1121
+ advise(
1122
+ iframeId,
1123
+ `<rb>Deprecated Option</>
1124
+
1125
+ The <b>sizeWidth</>, <b>sizeHeight</> and <b>autoResize</> options have been replaced with new <b>direction</> option which expects values of <i>"vertical"</>, <i>"horizontal"</> or <i>"horizontal"</>.
1126
+ `,
1127
+ );
1199
1128
  }
1129
+
1130
+ return options
1200
1131
  }
1201
1132
 
1202
- function getTargetOrigin(remoteHost) {
1203
- return '' === remoteHost ||
1204
- null !== remoteHost.match(/^(about:blank|javascript:|file:\/\/)/)
1205
- ? '*'
1206
- : remoteHost
1133
+ function checkMode() {
1134
+ const { mode } = settings[iframeId];
1135
+ if (mode < 0) advise('Parent', `${getModeData(mode + 2)}${getModeData(2)}`);
1136
+ if (vAdvised || mode < 0) return
1137
+ vAdvised = true;
1138
+ info(`v${VERSION} (${getModeLabel(mode)})`);
1139
+ if (mode < 1) advise('Parent', getModeData(3));
1207
1140
  }
1208
1141
 
1209
- function depricate(key) {
1210
- var splitName = key.split('Callback')
1142
+ function setDirection() {
1143
+ if (settings[iframeId].direction === 'horizontal') {
1144
+ settings[iframeId].sizeWidth = true;
1145
+ settings[iframeId].sizeHeight = false;
1146
+ return
1147
+ }
1148
+
1149
+ if (settings[iframeId].direction === 'none') {
1150
+ settings[iframeId].sizeWidth = false;
1151
+ settings[iframeId].sizeHeight = false;
1152
+ settings[iframeId].autoResize = false;
1153
+ return
1154
+ }
1211
1155
 
1212
- if (splitName.length === 2) {
1213
- var name =
1214
- 'on' + splitName[0].charAt(0).toUpperCase() + splitName[0].slice(1)
1215
- this[name] = this[key]
1216
- delete this[key]
1217
- warn(
1156
+ if (settings[iframeId].direction !== 'vertical') {
1157
+ throw new TypeError(
1218
1158
  iframeId,
1219
- "Deprecated: '" +
1220
- key +
1221
- "' has been renamed '" +
1222
- name +
1223
- "'. The old method will be removed in the next major version."
1159
+ `Direction value of "${settings[iframeId].direction}" is not valid`,
1224
1160
  )
1225
1161
  }
1226
1162
  }
1227
1163
 
1228
- function processOptions(options) {
1229
- options = options || {}
1230
-
1231
- settings[iframeId] = Object.create(null) // Protect against prototype attacks
1232
- settings[iframeId].iframe = iframe
1233
- settings[iframeId].firstRun = true
1234
- settings[iframeId].remoteHost =
1235
- iframe.src && iframe.src.split('/').slice(0, 3).join('/')
1236
-
1237
- checkOptions(options)
1238
- Object.keys(options).forEach(depricate, options)
1239
- copyOptions(options)
1240
-
1241
- if (settings[iframeId]) {
1242
- settings[iframeId].targetOrigin =
1243
- true === settings[iframeId].checkOrigin
1244
- ? getTargetOrigin(settings[iframeId].remoteHost)
1245
- : '*'
1164
+ function setOffset(offset) {
1165
+ if (!offset) return
1166
+ if (settings[iframeId].direction === 'vertical') {
1167
+ settings[iframeId].offsetHeight = offset;
1168
+ } else {
1169
+ settings[iframeId].offsetWidth = offset;
1246
1170
  }
1247
1171
  }
1248
1172
 
1249
- function beenHere() {
1250
- return iframeId in settings && 'iFrameResizer' in iframe
1251
- }
1252
-
1253
- var iframeId = ensureHasId(iframe.id)
1254
-
1255
- if (beenHere()) {
1256
- warn(iframeId, 'Ignored iFrame, already setup.')
1257
- } else {
1258
- processOptions(options)
1259
- setScrolling()
1260
- setLimits()
1261
- setupBodyMarginValues()
1262
- init(createOutgoingMsg(iframeId))
1263
- setupIFrameObject()
1173
+ function getTargetOrigin(remoteHost) {
1174
+ return remoteHost === '' ||
1175
+ remoteHost.match(/^(about:blank|javascript:|file:\/\/)/) !== null
1176
+ ? '*'
1177
+ : remoteHost
1264
1178
  }
1265
- }
1266
1179
 
1267
- function debouce(fn, time) {
1268
- if (null === timer) {
1269
- timer = setTimeout(function () {
1270
- timer = null
1271
- fn()
1272
- }, time)
1180
+ function getPostMessageTarget() {
1181
+ if (settings[iframeId].postMessageTarget === null)
1182
+ settings[iframeId].postMessageTarget = iframe.contentWindow;
1273
1183
  }
1274
- }
1275
1184
 
1276
- var frameTimer = {}
1277
- function debounceFrameEvents(fn, time, frameId) {
1278
- if (!frameTimer[frameId]) {
1279
- frameTimer[frameId] = setTimeout(function () {
1280
- frameTimer[frameId] = null
1281
- fn()
1282
- }, time)
1185
+ function chkTitle(iframeId) {
1186
+ const title = settings[iframeId]?.iframe?.title;
1187
+ return title === '' || title === undefined
1283
1188
  }
1284
- }
1285
1189
 
1286
- // Not testable in PhantomJS
1287
- /* istanbul ignore next */
1288
-
1289
- function fixHiddenIFrames() {
1290
- function checkIFrames() {
1291
- function checkIFrame(settingId) {
1292
- function chkDimension(dimension) {
1293
- return (
1294
- '0px' ===
1295
- (settings[settingId] && settings[settingId].iframe.style[dimension])
1296
- )
1297
- }
1298
-
1299
- function isVisible(el) {
1300
- return null !== el.offsetParent
1301
- }
1302
-
1303
- if (
1304
- settings[settingId] &&
1305
- isVisible(settings[settingId].iframe) &&
1306
- (chkDimension('height') || chkDimension('width'))
1307
- ) {
1308
- trigger(
1309
- 'Visibility change',
1310
- 'resize',
1311
- settings[settingId].iframe,
1312
- settingId
1313
- )
1314
- }
1315
- }
1316
-
1317
- Object.keys(settings).forEach(function (key) {
1318
- checkIFrame(key)
1319
- })
1190
+ function processOptions(options) {
1191
+ settings[iframeId] = {
1192
+ iframe,
1193
+ firstRun: true,
1194
+ remoteHost: iframe?.src.split('/').slice(0, 3).join('/'),
1195
+ ...defaults,
1196
+ ...checkOptions(options),
1197
+ mode: setMode(options),
1198
+ syncTitle: chkTitle(iframeId),
1199
+ };
1200
+
1201
+ setDirection();
1202
+ setOffset(options?.offset);
1203
+ getPostMessageTarget();
1204
+
1205
+ settings[iframeId].targetOrigin =
1206
+ settings[iframeId].checkOrigin === true
1207
+ ? getTargetOrigin(settings[iframeId].remoteHost)
1208
+ : '*';
1320
1209
  }
1321
1210
 
1322
- function mutationObserved(mutations) {
1323
- log(
1324
- 'window',
1325
- 'Mutation observed: ' + mutations[0].target + ' ' + mutations[0].type
1326
- )
1327
- debouce(checkIFrames, 16)
1211
+ function beenHere() {
1212
+ return iframeId in settings && 'iFrameResizer' in iframe
1328
1213
  }
1329
1214
 
1330
- function createMutationObserver() {
1331
- var target = document.querySelector('body'),
1332
- config = {
1333
- attributes: true,
1334
- attributeOldValue: false,
1335
- characterData: true,
1336
- characterDataOldValue: false,
1337
- childList: true,
1338
- subtree: true
1339
- },
1340
- observer = new MutationObserver(mutationObserved)
1215
+ const iframeId = ensureHasId(iframe.id);
1341
1216
 
1342
- observer.observe(target, config)
1217
+ if (beenHere()) {
1218
+ warn(iframeId, 'Ignored iFrame, already setup.');
1219
+ } else {
1220
+ processOptions(options);
1221
+ checkMode();
1222
+ setupEventListenersOnce();
1223
+ setScrolling();
1224
+ setupBodyMarginValues();
1225
+ init(createOutgoingMsg(iframeId));
1226
+ setupIFrameObject();
1343
1227
  }
1344
1228
 
1345
- var MutationObserver = getMutationObserver()
1346
- if (MutationObserver) {
1347
- createMutationObserver()
1348
- }
1349
- }
1229
+ return iframe?.iFrameResizer
1230
+ };
1350
1231
 
1351
- function resizeIFrames(event) {
1352
- function resize() {
1353
- sendTriggerMsg('Window ' + event, 'resize')
1232
+ function sendTriggerMsg(eventName, event) {
1233
+ function triggerEnabledIframe(iframeId) {
1234
+ if (isIFrameResizeEnabled(iframeId)) {
1235
+ trigger(eventName, event, iframeId);
1236
+ }
1354
1237
  }
1355
1238
 
1356
- log('window', 'Trigger event: ' + event)
1357
- debouce(resize, 16)
1358
- }
1239
+ const isIFrameResizeEnabled = (iframeId) =>
1240
+ settings[iframeId]?.autoResize && !settings[iframeId]?.firstRun;
1359
1241
 
1360
- // Not testable in PhantomJS
1361
- /* istanbul ignore next */
1362
- function tabVisible() {
1363
- function resize() {
1364
- sendTriggerMsg('Tab Visible', 'resize')
1365
- }
1366
-
1367
- if ('hidden' !== document.visibilityState) {
1368
- log('document', 'Trigger event: Visibility change')
1369
- debouce(resize, 16)
1370
- }
1242
+ Object.keys(settings).forEach(triggerEnabledIframe);
1371
1243
  }
1372
1244
 
1373
- function sendTriggerMsg(eventName, event) {
1374
- function isIFrameResizeEnabled(iframeId) {
1375
- return (
1376
- settings[iframeId] &&
1377
- 'parent' === settings[iframeId].resizeFrom &&
1378
- settings[iframeId].autoResize &&
1379
- !settings[iframeId].firstRun
1380
- )
1245
+ function tabVisible() {
1246
+ if (document.hidden === false) {
1247
+ sendTriggerMsg('Tab Visible', 'resize');
1381
1248
  }
1382
-
1383
- Object.keys(settings).forEach(function (iframeId) {
1384
- if (isIFrameResizeEnabled(iframeId)) {
1385
- trigger(eventName, event, settings[iframeId].iframe, iframeId)
1386
- }
1387
- })
1388
1249
  }
1389
1250
 
1390
- function setupEventListeners() {
1391
- addEventListener(window, 'message', iFrameListener)
1251
+ const setupEventListenersOnce = once(() => {
1252
+ addEventListener(window, 'message', iframeListener);
1253
+ addEventListener(document, 'visibilitychange', tabVisible);
1254
+ window.iframeParentListener = (data) =>
1255
+ iframeListener({ data, sameDomain: true });
1256
+ });
1392
1257
 
1393
- addEventListener(window, 'resize', function () {
1394
- resizeIFrames('resize')
1395
- })
1258
+ const id = '[iframeResizer] ';
1396
1259
 
1397
- addEventListener(document, 'visibilitychange', tabVisible)
1260
+ function createIframeResize() {
1261
+ function setup(element) {
1262
+ switch (true) {
1263
+ case !element:
1264
+ throw new TypeError(`${id}iframe is not defined`)
1398
1265
 
1399
- addEventListener(document, '-webkit-visibilitychange', tabVisible)
1400
- }
1266
+ case !element.tagName:
1267
+ throw new TypeError(`${id}Not a valid DOM element`)
1401
1268
 
1402
- function factory() {
1403
- function init(options, element) {
1404
- function chkType() {
1405
- if (!element.tagName) {
1406
- throw new TypeError('Object is not a valid DOM element')
1407
- } else if ('IFRAME' !== element.tagName.toUpperCase()) {
1269
+ case element.tagName.toUpperCase() !== 'IFRAME':
1408
1270
  throw new TypeError(
1409
- 'Expected <IFRAME> tag, found <' + element.tagName + '>'
1271
+ `${id}Expected <IFRAME> tag, found <${element.tagName}>`,
1410
1272
  )
1411
- }
1412
- }
1413
1273
 
1414
- if (element) {
1415
- chkType()
1416
- setupIFrame(element, options)
1417
- iFrames.push(element)
1418
- }
1419
- }
1420
-
1421
- function warnDeprecatedOptions(options) {
1422
- if (options && options.enablePublicMethods) {
1423
- warn(
1424
- 'enablePublicMethods option has been removed, public methods are now always available in the iFrame'
1425
- )
1274
+ default:
1275
+ connectWithOptions(element);
1276
+ iFrames.push(element);
1426
1277
  }
1427
1278
  }
1428
1279
 
1429
- var iFrames
1280
+ let connectWithOptions;
1281
+ let iFrames;
1430
1282
 
1431
- setupRequestAnimationFrame()
1432
- setupEventListeners()
1283
+ return function (options, target) {
1284
+ if (typeof window === 'undefined') return [] // don't run for server side render
1433
1285
 
1434
- return function iFrameResizeF(options, target) {
1435
- iFrames = [] // Only return iFrames past in on this call
1436
-
1437
- warnDeprecatedOptions(options)
1286
+ connectWithOptions = connectResizer(options);
1287
+ iFrames = []; // Only return iFrames passed in on this call
1438
1288
 
1439
1289
  switch (typeof target) {
1440
1290
  case 'undefined':
1441
- case 'string': {
1442
- Array.prototype.forEach.call(
1443
- document.querySelectorAll(target || 'iframe'),
1444
- init.bind(undefined, options)
1445
- )
1291
+ case 'string':
1292
+ document.querySelectorAll(target || 'iframe').forEach(setup);
1446
1293
  break
1447
- }
1448
1294
 
1449
- case 'object': {
1450
- init(options, target)
1295
+ case 'object':
1296
+ setup(target);
1451
1297
  break
1452
- }
1453
1298
 
1454
- default: {
1455
- throw new TypeError('Unexpected data type (' + typeof target + ')')
1456
- }
1299
+ default:
1300
+ throw new TypeError(`${id}Unexpected data type (${typeof target})`)
1457
1301
  }
1458
1302
 
1459
- return iFrames
1303
+ return Object.freeze(iFrames)
1460
1304
  }
1461
1305
  }
1462
1306
 
1463
- function createJQueryPublicMethod($) {
1464
- if (!$.fn) {
1465
- info('', 'Unable to bind to jQuery, it is not fully loaded.')
1466
- } else if (!$.fn.iFrameResize) {
1467
- $.fn.iFrameResize = function $iFrameResizeF(options) {
1468
- function init(index, element) {
1469
- setupIFrame(element, options)
1470
- }
1307
+ const iframeResize = createIframeResize();
1471
1308
 
1472
- return this.filter('iframe').each(init).end()
1473
- }
1474
- }
1309
+ if (typeof window !== 'undefined') {
1310
+ window.iFrameResize =
1311
+ window.iFrameResize ||
1312
+ function (...args) {
1313
+ advise('', 'Deprecated: iFrameResize(), please use iframeResize()');
1314
+ iframeResize(...args);
1315
+ };
1475
1316
  }
1476
1317
 
1477
- if (window.jQuery !== undefined) {
1478
- createJQueryPublicMethod(window.jQuery)
1479
- }
1318
+ return iframeResize;
1480
1319
 
1481
- if (typeof define === 'function' && define.amd) {
1482
- define([], factory)
1483
- } else if (typeof module === 'object' && typeof module.exports === 'object') {
1484
- // Node for browserfy
1485
- module.exports = factory()
1486
- }
1487
- window.iFrameResize = window.iFrameResize || factory()
1488
- })()
1320
+ }));