@hcaptcha/react-hcaptcha 1.7.0 → 1.8.0

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/esm/index.js CHANGED
@@ -1,49 +1,54 @@
1
1
  import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
2
2
  import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
3
3
  import * as React from 'react';
4
- import { generateQuery } from "./utils.js";
4
+ import { generateQuery, getFrame, getMountElement } from "./utils.js";
5
5
  var SCRIPT_ID = 'hcaptcha-api-script-id';
6
6
  var HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; // Prevent loading API script multiple times
7
7
 
8
- var resolveFn;
9
- var rejectFn;
10
- var mountPromise = new Promise(function (resolve, reject) {
11
- resolveFn = resolve;
12
- rejectFn = reject;
13
- }); // Generate hCaptcha API script
8
+ var scripts = []; // Generate hCaptcha API script
14
9
 
15
10
  var mountCaptchaScript = function mountCaptchaScript(params) {
16
11
  if (params === void 0) {
17
12
  params = {};
18
13
  }
19
14
 
20
- var parent = params.scriptLocation || document.head;
15
+ var element = getMountElement(params.scriptLocation);
21
16
  delete params.scriptLocation;
22
- var doc = parent.ownerDocument || document;
17
+ var frame = getFrame(element);
18
+ var script = scripts.find(function (_ref) {
19
+ var scope = _ref.scope;
20
+ return scope === frame.window;
21
+ });
23
22
 
24
- if (doc.getElementById(SCRIPT_ID)) {
23
+ if (frame.document.getElementById(SCRIPT_ID) && script) {
25
24
  // API was already requested
26
- return mountPromise;
27
- } // Create global onload callback
28
-
29
-
30
- window[HCAPTCHA_LOAD_FN_NAME] = resolveFn;
31
- var domain = params.apihost || "https://js.hcaptcha.com";
32
- delete params.apihost;
33
- var script = doc.createElement("script");
34
- script.id = SCRIPT_ID;
35
- script.src = domain + "/1/api.js?render=explicit&onload=" + HCAPTCHA_LOAD_FN_NAME;
36
- script.async = params.loadAsync !== undefined ? params.loadAsync : true;
37
- delete params.loadAsync;
25
+ return script.promise;
26
+ }
38
27
 
39
- script.onerror = function (event) {
40
- return rejectFn('script-error');
41
- };
28
+ var promise = new Promise(function (resolve, reject) {
29
+ // Create global onload callback
30
+ frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;
31
+ var domain = params.apihost || "https://js.hcaptcha.com";
32
+ delete params.apihost;
33
+ var script = frame.document.createElement("script");
34
+ script.id = SCRIPT_ID;
35
+ script.src = domain + "/1/api.js?render=explicit&onload=" + HCAPTCHA_LOAD_FN_NAME;
36
+ script.async = params.loadAsync !== undefined ? params.loadAsync : true;
37
+ delete params.loadAsync;
38
+
39
+ script.onerror = function (event) {
40
+ return reject('script-error');
41
+ };
42
42
 
43
- var query = generateQuery(params);
44
- script.src += query !== "" ? "&" + query : "";
45
- parent.appendChild(script);
46
- return mountPromise;
43
+ var query = generateQuery(params);
44
+ script.src += query !== "" ? "&" + query : "";
45
+ element.appendChild(script);
46
+ });
47
+ scripts.push({
48
+ promise: promise,
49
+ scope: frame.window
50
+ });
51
+ return promise;
47
52
  };
48
53
 
49
54
  var HCaptcha = /*#__PURE__*/function (_React$Component) {
@@ -52,7 +57,17 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
52
57
  function HCaptcha(props) {
53
58
  var _this;
54
59
 
55
- _this = _React$Component.call(this, props) || this; // API Methods
60
+ _this = _React$Component.call(this, props) || this;
61
+ var element = getMountElement(_this.props.scriptLocation);
62
+ var frame = getFrame(element);
63
+ /**
64
+ * Internal reference to track hCaptcha API
65
+ *
66
+ * Required as window is relative to initialization in application
67
+ * not where the script and iFrames have been loaded.
68
+ */
69
+
70
+ _this._hcaptcha = frame.window.hcaptcha || undefined; // API Methods
56
71
 
57
72
  _this.renderCaptcha = _this.renderCaptcha.bind(_assertThisInitialized(_this));
58
73
  _this.resetCaptcha = _this.resetCaptcha.bind(_assertThisInitialized(_this));
@@ -67,7 +82,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
67
82
  _this.handleOpen = _this.handleOpen.bind(_assertThisInitialized(_this));
68
83
  _this.handleClose = _this.handleClose.bind(_assertThisInitialized(_this));
69
84
  _this.handleChallengeExpired = _this.handleChallengeExpired.bind(_assertThisInitialized(_this));
70
- var isApiReady = typeof hcaptcha !== 'undefined';
85
+ var isApiReady = typeof _this._hcaptcha !== 'undefined';
71
86
  _this.ref = /*#__PURE__*/React.createRef();
72
87
  _this.apiScriptRequested = false;
73
88
  _this.state = {
@@ -100,6 +115,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
100
115
 
101
116
  _proto.componentWillUnmount = function componentWillUnmount() {
102
117
  var captchaId = this.state.captchaId;
118
+ var hcaptcha = this._hcaptcha;
103
119
 
104
120
  if (!this.isReady()) {
105
121
  return;
@@ -185,7 +201,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
185
201
  }, this.props, {
186
202
  hl: this.props.hl || this.props.languageOverride,
187
203
  languageOverride: undefined
188
- }); //Render hCaptcha widget and provide necessary callbacks - hCaptcha
204
+ });
205
+ var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha
189
206
 
190
207
  var captchaId = hcaptcha.render(this.ref.current, renderParams);
191
208
  this.setState({
@@ -198,6 +215,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
198
215
 
199
216
  _proto.resetCaptcha = function resetCaptcha() {
200
217
  var captchaId = this.state.captchaId;
218
+ var hcaptcha = this._hcaptcha;
201
219
 
202
220
  if (!this.isReady()) {
203
221
  return;
@@ -209,6 +227,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
209
227
 
210
228
  _proto.removeCaptcha = function removeCaptcha(callback) {
211
229
  var captchaId = this.state.captchaId;
230
+ var hcaptcha = this._hcaptcha;
212
231
 
213
232
  if (!this.isReady()) {
214
233
  return;
@@ -228,7 +247,10 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
228
247
  this.setState({
229
248
  isApiReady: true
230
249
  }, function () {
231
- // render captcha and wait for captcha id
250
+ var element = getMountElement(_this3.props.scriptLocation);
251
+ var frame = getFrame(element);
252
+ _this3._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id
253
+
232
254
  _this3.renderCaptcha(function () {
233
255
  // trigger onLoad if it exists
234
256
  var onLoad = _this3.props.onLoad;
@@ -242,6 +264,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
242
264
  var _this$state = this.state,
243
265
  isRemoved = _this$state.isRemoved,
244
266
  captchaId = _this$state.captchaId;
267
+ var hcaptcha = this._hcaptcha;
245
268
  if (typeof hcaptcha === 'undefined' || isRemoved) return;
246
269
  var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
247
270
 
@@ -253,6 +276,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
253
276
  _proto.handleExpire = function handleExpire() {
254
277
  var onExpire = this.props.onExpire;
255
278
  var captchaId = this.state.captchaId;
279
+ var hcaptcha = this._hcaptcha;
256
280
 
257
281
  if (!this.isReady()) {
258
282
  return;
@@ -266,6 +290,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
266
290
  _proto.handleError = function handleError(event) {
267
291
  var onError = this.props.onError;
268
292
  var captchaId = this.state.captchaId;
293
+ var hcaptcha = this._hcaptcha;
269
294
 
270
295
  if (this.isReady()) {
271
296
  // If hCaptcha runs into error, reset captcha - hCaptcha
@@ -312,6 +337,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
312
337
  }
313
338
 
314
339
  var captchaId = this.state.captchaId;
340
+ var hcaptcha = this._hcaptcha;
315
341
 
316
342
  if (!this.isReady()) {
317
343
  return;
@@ -326,6 +352,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
326
352
 
327
353
  _proto.setData = function setData(data) {
328
354
  var captchaId = this.state.captchaId;
355
+ var hcaptcha = this._hcaptcha;
329
356
 
330
357
  if (!this.isReady()) {
331
358
  return;
@@ -339,10 +366,12 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
339
366
  };
340
367
 
341
368
  _proto.getResponse = function getResponse() {
369
+ var hcaptcha = this._hcaptcha;
342
370
  return hcaptcha.getResponse(this.state.captchaId);
343
371
  };
344
372
 
345
373
  _proto.getRespKey = function getRespKey() {
374
+ var hcaptcha = this._hcaptcha;
346
375
  return hcaptcha.getRespKey(this.state.captchaId);
347
376
  };
348
377
 
package/dist/esm/utils.js CHANGED
@@ -11,4 +11,18 @@ function generateQuery(params) {
11
11
  }
12
12
 
13
13
  ;
14
- export { generateQuery };
14
+
15
+ function getFrame(element) {
16
+ var doc = element && element.ownerDocument || document;
17
+ var win = doc.defaultView || doc.parentWindow;
18
+ return {
19
+ document: doc,
20
+ window: win
21
+ };
22
+ }
23
+
24
+ function getMountElement(element) {
25
+ return element || document.head;
26
+ }
27
+
28
+ export { generateQuery, getFrame, getMountElement };
package/dist/index.js CHANGED
@@ -34,42 +34,47 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
34
34
  var SCRIPT_ID = 'hcaptcha-api-script-id';
35
35
  var HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad'; // Prevent loading API script multiple times
36
36
 
37
- var resolveFn;
38
- var rejectFn;
39
- var mountPromise = new Promise(function (resolve, reject) {
40
- resolveFn = resolve;
41
- rejectFn = reject;
42
- }); // Generate hCaptcha API script
37
+ var scripts = []; // Generate hCaptcha API script
43
38
 
44
39
  var mountCaptchaScript = function mountCaptchaScript() {
45
40
  var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
46
- var parent = params.scriptLocation || document.head;
41
+ var element = (0, _utils.getMountElement)(params.scriptLocation);
47
42
  delete params.scriptLocation;
48
- var doc = parent.ownerDocument || document;
43
+ var frame = (0, _utils.getFrame)(element);
44
+ var script = scripts.find(function (_ref) {
45
+ var scope = _ref.scope;
46
+ return scope === frame.window;
47
+ });
49
48
 
50
- if (doc.getElementById(SCRIPT_ID)) {
49
+ if (frame.document.getElementById(SCRIPT_ID) && script) {
51
50
  // API was already requested
52
- return mountPromise;
53
- } // Create global onload callback
54
-
55
-
56
- window[HCAPTCHA_LOAD_FN_NAME] = resolveFn;
57
- var domain = params.apihost || "https://js.hcaptcha.com";
58
- delete params.apihost;
59
- var script = doc.createElement("script");
60
- script.id = SCRIPT_ID;
61
- script.src = "".concat(domain, "/1/api.js?render=explicit&onload=").concat(HCAPTCHA_LOAD_FN_NAME);
62
- script.async = params.loadAsync !== undefined ? params.loadAsync : true;
63
- delete params.loadAsync;
64
-
65
- script.onerror = function (event) {
66
- return rejectFn('script-error');
67
- };
68
-
69
- var query = (0, _utils.generateQuery)(params);
70
- script.src += query !== "" ? "&".concat(query) : "";
71
- parent.appendChild(script);
72
- return mountPromise;
51
+ return script.promise;
52
+ }
53
+
54
+ var promise = new Promise(function (resolve, reject) {
55
+ // Create global onload callback
56
+ frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;
57
+ var domain = params.apihost || "https://js.hcaptcha.com";
58
+ delete params.apihost;
59
+ var script = frame.document.createElement("script");
60
+ script.id = SCRIPT_ID;
61
+ script.src = "".concat(domain, "/1/api.js?render=explicit&onload=").concat(HCAPTCHA_LOAD_FN_NAME);
62
+ script.async = params.loadAsync !== undefined ? params.loadAsync : true;
63
+ delete params.loadAsync;
64
+
65
+ script.onerror = function (event) {
66
+ return reject('script-error');
67
+ };
68
+
69
+ var query = (0, _utils.generateQuery)(params);
70
+ script.src += query !== "" ? "&".concat(query) : "";
71
+ element.appendChild(script);
72
+ });
73
+ scripts.push({
74
+ promise: promise,
75
+ scope: frame.window
76
+ });
77
+ return promise;
73
78
  };
74
79
 
75
80
  var HCaptcha = /*#__PURE__*/function (_React$Component) {
@@ -81,7 +86,17 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
81
86
  var _this;
82
87
 
83
88
  (0, _classCallCheck2["default"])(this, HCaptcha);
84
- _this = _super.call(this, props); // API Methods
89
+ _this = _super.call(this, props);
90
+ var element = (0, _utils.getMountElement)(_this.props.scriptLocation);
91
+ var frame = (0, _utils.getFrame)(element);
92
+ /**
93
+ * Internal reference to track hCaptcha API
94
+ *
95
+ * Required as window is relative to initialization in application
96
+ * not where the script and iFrames have been loaded.
97
+ */
98
+
99
+ _this._hcaptcha = frame.window.hcaptcha || undefined; // API Methods
85
100
 
86
101
  _this.renderCaptcha = _this.renderCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
87
102
  _this.resetCaptcha = _this.resetCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
@@ -96,7 +111,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
96
111
  _this.handleOpen = _this.handleOpen.bind((0, _assertThisInitialized2["default"])(_this));
97
112
  _this.handleClose = _this.handleClose.bind((0, _assertThisInitialized2["default"])(_this));
98
113
  _this.handleChallengeExpired = _this.handleChallengeExpired.bind((0, _assertThisInitialized2["default"])(_this));
99
- var isApiReady = typeof hcaptcha !== 'undefined';
114
+ var isApiReady = typeof _this._hcaptcha !== 'undefined';
100
115
  _this.ref = /*#__PURE__*/React.createRef();
101
116
  _this.apiScriptRequested = false;
102
117
  _this.state = {
@@ -130,6 +145,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
130
145
  key: "componentWillUnmount",
131
146
  value: function componentWillUnmount() {
132
147
  var captchaId = this.state.captchaId;
148
+ var hcaptcha = this._hcaptcha;
133
149
 
134
150
  if (!this.isReady()) {
135
151
  return;
@@ -219,7 +235,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
219
235
  }, this.props, {
220
236
  hl: this.props.hl || this.props.languageOverride,
221
237
  languageOverride: undefined
222
- }); //Render hCaptcha widget and provide necessary callbacks - hCaptcha
238
+ });
239
+ var hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha
223
240
 
224
241
  var captchaId = hcaptcha.render(this.ref.current, renderParams);
225
242
  this.setState({
@@ -233,6 +250,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
233
250
  key: "resetCaptcha",
234
251
  value: function resetCaptcha() {
235
252
  var captchaId = this.state.captchaId;
253
+ var hcaptcha = this._hcaptcha;
236
254
 
237
255
  if (!this.isReady()) {
238
256
  return;
@@ -245,6 +263,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
245
263
  key: "removeCaptcha",
246
264
  value: function removeCaptcha(callback) {
247
265
  var captchaId = this.state.captchaId;
266
+ var hcaptcha = this._hcaptcha;
248
267
 
249
268
  if (!this.isReady()) {
250
269
  return;
@@ -265,7 +284,10 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
265
284
  this.setState({
266
285
  isApiReady: true
267
286
  }, function () {
268
- // render captcha and wait for captcha id
287
+ var element = (0, _utils.getMountElement)(_this3.props.scriptLocation);
288
+ var frame = (0, _utils.getFrame)(element);
289
+ _this3._hcaptcha = frame.window.hcaptcha; // render captcha and wait for captcha id
290
+
269
291
  _this3.renderCaptcha(function () {
270
292
  // trigger onLoad if it exists
271
293
  var onLoad = _this3.props.onLoad;
@@ -280,6 +302,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
280
302
  var _this$state = this.state,
281
303
  isRemoved = _this$state.isRemoved,
282
304
  captchaId = _this$state.captchaId;
305
+ var hcaptcha = this._hcaptcha;
283
306
  if (typeof hcaptcha === 'undefined' || isRemoved) return;
284
307
  var token = hcaptcha.getResponse(captchaId); //Get response token from hCaptcha widget
285
308
 
@@ -292,6 +315,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
292
315
  value: function handleExpire() {
293
316
  var onExpire = this.props.onExpire;
294
317
  var captchaId = this.state.captchaId;
318
+ var hcaptcha = this._hcaptcha;
295
319
 
296
320
  if (!this.isReady()) {
297
321
  return;
@@ -306,6 +330,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
306
330
  value: function handleError(event) {
307
331
  var onError = this.props.onError;
308
332
  var captchaId = this.state.captchaId;
333
+ var hcaptcha = this._hcaptcha;
309
334
 
310
335
  if (this.isReady()) {
311
336
  // If hCaptcha runs into error, reset captcha - hCaptcha
@@ -354,6 +379,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
354
379
  value: function execute() {
355
380
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
356
381
  var captchaId = this.state.captchaId;
382
+ var hcaptcha = this._hcaptcha;
357
383
 
358
384
  if (!this.isReady()) {
359
385
  return;
@@ -369,6 +395,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
369
395
  key: "setData",
370
396
  value: function setData(data) {
371
397
  var captchaId = this.state.captchaId;
398
+ var hcaptcha = this._hcaptcha;
372
399
 
373
400
  if (!this.isReady()) {
374
401
  return;
@@ -383,11 +410,13 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
383
410
  }, {
384
411
  key: "getResponse",
385
412
  value: function getResponse() {
413
+ var hcaptcha = this._hcaptcha;
386
414
  return hcaptcha.getResponse(this.state.captchaId);
387
415
  }
388
416
  }, {
389
417
  key: "getRespKey",
390
418
  value: function getRespKey() {
419
+ var hcaptcha = this._hcaptcha;
391
420
  return hcaptcha.getRespKey(this.state.captchaId);
392
421
  }
393
422
  }, {
package/dist/utils.js CHANGED
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.generateQuery = generateQuery;
9
+ exports.getFrame = getFrame;
10
+ exports.getMountElement = getMountElement;
9
11
 
10
12
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
13
 
@@ -25,4 +27,17 @@ function generateQuery(params) {
25
27
  }).join("&");
26
28
  }
27
29
 
28
- ;
30
+ ;
31
+
32
+ function getFrame(element) {
33
+ var doc = element && element.ownerDocument || document;
34
+ var win = doc.defaultView || doc.parentWindow;
35
+ return {
36
+ document: doc,
37
+ window: win
38
+ };
39
+ }
40
+
41
+ function getMountElement(element) {
42
+ return element || document.head;
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hcaptcha/react-hcaptcha",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "types": "types/index.d.ts",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "description": "A React library for hCaptcha",
13
13
  "scripts": {
14
- "start": "webpack serve",
14
+ "start": "webpack serve -c ./demo/webpack.config.mjs",
15
15
  "test": "jest",
16
16
  "watch": "babel src -d dist --copy-files --watch",
17
17
  "transpile": "babel src -d dist --copy-files",
package/src/index.js CHANGED
@@ -1,49 +1,50 @@
1
1
  import * as React from 'react';
2
- import { generateQuery } from "./utils.js";
2
+ import { generateQuery, getFrame, getMountElement } from "./utils.js";
3
3
 
4
4
  const SCRIPT_ID = 'hcaptcha-api-script-id';
5
5
  const HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad';
6
6
 
7
7
  // Prevent loading API script multiple times
8
- let resolveFn;
9
- let rejectFn;
10
- const mountPromise = new Promise((resolve, reject) => {
11
- resolveFn = resolve;
12
- rejectFn = reject;
13
- });
8
+ const scripts = [];
14
9
 
15
10
  // Generate hCaptcha API script
16
11
  const mountCaptchaScript = (params={}) => {
17
- const parent = params.scriptLocation || document.head;
12
+ const element = getMountElement(params.scriptLocation);
18
13
  delete params.scriptLocation;
19
14
 
20
- const doc = parent.ownerDocument || document;
15
+ const frame = getFrame(element);
16
+ const script = scripts.find(({ scope }) => scope === frame.window);
21
17
 
22
- if (doc.getElementById(SCRIPT_ID)) {
18
+ if (frame.document.getElementById(SCRIPT_ID) && script) {
23
19
  // API was already requested
24
- return mountPromise;
20
+ return script.promise;
25
21
  }
26
22
 
27
- // Create global onload callback
28
- window[HCAPTCHA_LOAD_FN_NAME] = resolveFn;
23
+ const promise = new Promise((resolve, reject) => {
24
+ // Create global onload callback
25
+ frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;
29
26
 
30
- const domain = params.apihost || "https://js.hcaptcha.com";
31
- delete params.apihost;
27
+ const domain = params.apihost || "https://js.hcaptcha.com";
28
+ delete params.apihost;
32
29
 
33
- const script = doc.createElement("script");
34
- script.id = SCRIPT_ID;
35
- script.src = `${domain}/1/api.js?render=explicit&onload=${HCAPTCHA_LOAD_FN_NAME}`;
30
+ const script = frame.document.createElement("script");
31
+ script.id = SCRIPT_ID;
32
+ script.src = `${domain}/1/api.js?render=explicit&onload=${HCAPTCHA_LOAD_FN_NAME}`;
36
33
 
37
- script.async = params.loadAsync !== undefined? params.loadAsync : true;
38
- delete params.loadAsync;
34
+ script.async = params.loadAsync !== undefined? params.loadAsync : true;
35
+ delete params.loadAsync;
39
36
 
40
- script.onerror = (event) => rejectFn('script-error');
37
+ script.onerror = (event) => reject('script-error');
41
38
 
42
- const query = generateQuery(params);
43
- script.src += query !== ""? `&${query}` : "";
39
+ const query = generateQuery(params);
40
+ script.src += query !== ""? `&${query}` : "";
44
41
 
45
- parent.appendChild(script);
46
- return mountPromise;
42
+ element.appendChild(script);
43
+ });
44
+
45
+ scripts.push({ promise, scope: frame.window });
46
+
47
+ return promise;
47
48
  };
48
49
 
49
50
 
@@ -51,6 +52,17 @@ class HCaptcha extends React.Component {
51
52
  constructor (props) {
52
53
  super(props);
53
54
 
55
+ const element = getMountElement(this.props.scriptLocation);
56
+ const frame = getFrame(element);
57
+
58
+ /**
59
+ * Internal reference to track hCaptcha API
60
+ *
61
+ * Required as window is relative to initialization in application
62
+ * not where the script and iFrames have been loaded.
63
+ */
64
+ this._hcaptcha = frame.window.hcaptcha || undefined;
65
+
54
66
  // API Methods
55
67
  this.renderCaptcha = this.renderCaptcha.bind(this);
56
68
  this.resetCaptcha = this.resetCaptcha.bind(this);
@@ -67,7 +79,8 @@ class HCaptcha extends React.Component {
67
79
  this.handleClose = this.handleClose.bind(this);
68
80
  this.handleChallengeExpired = this.handleChallengeExpired.bind(this);
69
81
 
70
- const isApiReady = typeof hcaptcha !== 'undefined';
82
+
83
+ const isApiReady = typeof this._hcaptcha !== 'undefined';
71
84
 
72
85
  this.ref = React.createRef();
73
86
  this.apiScriptRequested = false;
@@ -99,6 +112,7 @@ class HCaptcha extends React.Component {
99
112
 
100
113
  componentWillUnmount() {
101
114
  const { captchaId } = this.state;
115
+ const hcaptcha = this._hcaptcha;
102
116
 
103
117
  if (!this.isReady()) {
104
118
  return;
@@ -188,6 +202,7 @@ class HCaptcha extends React.Component {
188
202
  languageOverride: undefined
189
203
  });
190
204
 
205
+ const hcaptcha = this._hcaptcha;
191
206
  //Render hCaptcha widget and provide necessary callbacks - hCaptcha
192
207
  const captchaId = hcaptcha.render(this.ref.current, renderParams);
193
208
 
@@ -198,6 +213,7 @@ class HCaptcha extends React.Component {
198
213
 
199
214
  resetCaptcha() {
200
215
  const { captchaId } = this.state;
216
+ const hcaptcha = this._hcaptcha;
201
217
 
202
218
  if (!this.isReady()) {
203
219
  return;
@@ -208,6 +224,7 @@ class HCaptcha extends React.Component {
208
224
 
209
225
  removeCaptcha(callback) {
210
226
  const { captchaId } = this.state;
227
+ const hcaptcha = this._hcaptcha;
211
228
 
212
229
  if (!this.isReady()) {
213
230
  return;
@@ -221,6 +238,10 @@ class HCaptcha extends React.Component {
221
238
 
222
239
  handleOnLoad () {
223
240
  this.setState({ isApiReady: true }, () => {
241
+ const element = getMountElement(this.props.scriptLocation);
242
+ const frame = getFrame(element);
243
+
244
+ this._hcaptcha = frame.window.hcaptcha;
224
245
 
225
246
  // render captcha and wait for captcha id
226
247
  this.renderCaptcha(() => {
@@ -234,6 +255,7 @@ class HCaptcha extends React.Component {
234
255
  handleSubmit (event) {
235
256
  const { onVerify } = this.props;
236
257
  const { isRemoved, captchaId } = this.state;
258
+ const hcaptcha = this._hcaptcha;
237
259
 
238
260
  if (typeof hcaptcha === 'undefined' || isRemoved) return
239
261
 
@@ -245,6 +267,7 @@ class HCaptcha extends React.Component {
245
267
  handleExpire () {
246
268
  const { onExpire } = this.props;
247
269
  const { captchaId } = this.state;
270
+ const hcaptcha = this._hcaptcha;
248
271
 
249
272
  if (!this.isReady()) {
250
273
  return;
@@ -258,6 +281,7 @@ class HCaptcha extends React.Component {
258
281
  handleError (event) {
259
282
  const { onError } = this.props;
260
283
  const { captchaId } = this.state;
284
+ const hcaptcha = this._hcaptcha;
261
285
 
262
286
  if (this.isReady()) {
263
287
  // If hCaptcha runs into error, reset captcha - hCaptcha
@@ -299,6 +323,7 @@ class HCaptcha extends React.Component {
299
323
 
300
324
  execute (opts = null) {
301
325
  const { captchaId } = this.state;
326
+ const hcaptcha = this._hcaptcha;
302
327
 
303
328
  if (!this.isReady()) {
304
329
  return;
@@ -313,6 +338,7 @@ class HCaptcha extends React.Component {
313
338
 
314
339
  setData (data) {
315
340
  const { captchaId } = this.state;
341
+ const hcaptcha = this._hcaptcha;
316
342
 
317
343
  if (!this.isReady()) {
318
344
  return;
@@ -326,10 +352,12 @@ class HCaptcha extends React.Component {
326
352
  }
327
353
 
328
354
  getResponse() {
355
+ const hcaptcha = this._hcaptcha;
329
356
  return hcaptcha.getResponse(this.state.captchaId);
330
357
  }
331
358
 
332
359
  getRespKey() {
360
+ const hcaptcha = this._hcaptcha;
333
361
  return hcaptcha.getRespKey(this.state.captchaId)
334
362
  }
335
363
 
package/src/utils.js CHANGED
@@ -6,4 +6,18 @@ function generateQuery(params) {
6
6
  }).join("&");
7
7
  };
8
8
 
9
- export { generateQuery };
9
+ function getFrame(element) {
10
+ const doc = (element && element.ownerDocument) || document;
11
+ const win = doc.defaultView || doc.parentWindow;
12
+ return { document: doc, window: win };
13
+ }
14
+
15
+ function getMountElement(element) {
16
+ return element || document.head;
17
+ }
18
+
19
+ export {
20
+ generateQuery,
21
+ getFrame,
22
+ getMountElement
23
+ };