Skip to content

Commit

Permalink
Merge pull request #112 from hCaptcha/missing-callbacks
Browse files Browse the repository at this point in the history
Add the onOpen, onClose and onChalExpired callbacks
  • Loading branch information
zoryana94 authored Jan 26, 2022
2 parents 24f8e6d + 1ed0cd2 commit 5baebb0
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 26 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} /
|`onVerify`|`token, eKey`|When challenge is completed. The response `token` and an `eKey` (session id) are passed along.|
|`onExpire`|-|When the current token expires.|
|`onLoad`|-|When the hCaptcha API loads.|
|`onOpen`|-|When the user display of a challenge starts.|
|`onClose`|-|When the user dismisses a challenge.|
|`onChalExpired`|-|When the user display of a challenge times out with no answer.|

### Methods

Expand Down
75 changes: 62 additions & 13 deletions examples/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,30 @@ const AsyncDemo = () => {
} catch (error) {
console.log(error);
}
}
};

const handleOpen = () => {
console.log("HCaptcha [onOpen]: The user display of a challenge starts.");
};

const handleClose = () => {
console.log("HCaptcha [onClose]: The user dismisses a challenge.");
};

const handleChallengeExpired = () => {
console.log("HCaptcha [onChalExpired]: The user display of a challenge times out with no answer.");
};

return (
<div>
<HCaptcha ref={captchaRef}
<HCaptcha
ref={captchaRef}
sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
theme="light"
onVerify={() => undefined}
onOpen={handleOpen}
onClose={handleClose}
onChalExpired={handleChallengeExpired}
/>
<button onClick={executeCaptcha}>Execute asynchronously</button>
</div>
Expand All @@ -39,6 +55,9 @@ class ReactDemo extends React.Component {
this.handleChange = this.handleChange.bind(this);
this.handleReset = this.handleReset.bind(this);
this.onVerifyCaptcha = this.onVerifyCaptcha.bind(this);
this.handleOpen = this.handleOpen.bind(this);
this.handleClose = this.handleClose.bind(this);
this.handleChallengeExpired = this.handleChallengeExpired.bind(this);
// Leave languageOverride unset or null for browser autodetection.
// To force a language, use the code: https://hcaptcha.com/docs/languages
this.languageOverride = null; // "fr";
Expand All @@ -48,7 +67,7 @@ class ReactDemo extends React.Component {
this.setState({isVerified: true});
}

onVerifyCaptcha (token) {
onVerifyCaptcha(token) {
console.log("Verified: " + token);
this.setState({isVerified: true})
}
Expand All @@ -64,6 +83,18 @@ class ReactDemo extends React.Component {
this.setState({isVerified: false})
}

handleOpen() {
console.log("HCaptcha [onOpen]: The user display of a challenge starts.");
}

handleClose() {
console.log("HCaptcha [onClose]: The user dismisses a challenge.");
}

handleChallengeExpired() {
console.log("HCaptcha [onChalExpired]: The user display of a challenge times out with no answer.");
}

render() {
const { isVerified } = this.state;

Expand All @@ -85,24 +116,42 @@ class ReactDemo extends React.Component {
{!this.state.async ? (
<>
<div>
<HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
theme="light"
<HCaptcha
ref={this.captcha}
onVerify={this.onVerifyCaptcha}
languageOverride={this.languageOverride}
sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
theme="light"
onOpen={this.handleOpen}
onClose={this.handleClose}
onChalExpired={this.handleChallengeExpired}
/>
</div>

<div>
<HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
theme="dark"
<HCaptcha
ref={this.captcha}
onVerify={this.onVerifyCaptcha}
languageOverride={this.languageOverride}
sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
theme="dark"
onOpen={this.handleOpen}
onClose={this.handleClose}
onChalExpired={this.handleChallengeExpired}
/>
</div>

<div>
<HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
size="compact"
theme="dark"
<HCaptcha
ref={this.captcha}
onVerify={this.onVerifyCaptcha}
languageOverride={this.languageOverride}
sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
size="compact"
theme="dark"
onOpen={this.handleOpen}
onClose={this.handleClose}
onChalExpired={this.handleChallengeExpired}
/>
</div>
{isVerified &&
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hcaptcha/react-hcaptcha",
"version": "1.0.0",
"version": "1.1.0",
"types": "types/index.d.ts",
"main": "dist/index.js",
"files": [
Expand Down
75 changes: 63 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ class HCaptcha extends React.Component {
this.renderCaptcha = this.renderCaptcha.bind(this);
this.resetCaptcha = this.resetCaptcha.bind(this);
this.removeCaptcha = this.removeCaptcha.bind(this);
this.isReady = this.isReady.bind(this);

// Event Handlers
this.handleOnLoad = this.handleOnLoad.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleExpire = this.handleExpire.bind(this);
this.handleError = this.handleError.bind(this);
this.handleOpen = this.handleOpen.bind(this);
this.handleClose = this.handleClose.bind(this);
this.handleChallengeExpired = this.handleChallengeExpired.bind(this);

const isApiReady = typeof hcaptcha !== 'undefined';

Expand Down Expand Up @@ -88,8 +92,11 @@ class HCaptcha extends React.Component {
}

componentWillUnmount() {
const { isApiReady, isRemoved, captchaId } = this.state;
if(!isApiReady || isRemoved) return
const { captchaId } = this.state;

if (!this.isReady()) {
return;
}

// Reset any stored variables / timers when unmounting
hcaptcha.reset(captchaId);
Expand Down Expand Up @@ -124,7 +131,10 @@ class HCaptcha extends React.Component {
if (!isApiReady) return;

const renderParams = Object.assign({
"open-callback" : this.handleOpen,
"close-callback" : this.handleClose,
"error-callback" : this.handleError,
"chalexpired-callback": this.handleChallengeExpired,
"expired-callback" : this.handleExpire,
"callback" : this.handleSubmit,
}, this.props, {
Expand All @@ -141,17 +151,21 @@ class HCaptcha extends React.Component {
}

resetCaptcha() {
const { isApiReady, isRemoved, captchaId } = this.state;
const { captchaId } = this.state;

if (!isApiReady || isRemoved) return
if (!this.isReady()) {
return;
}
// Reset captcha state, removes stored token and unticks checkbox
hcaptcha.reset(captchaId)
}

removeCaptcha(callback) {
const { isApiReady, isRemoved, captchaId } = this.state;
const { captchaId } = this.state;

if (!isApiReady || isRemoved) return
if (!this.isReady()) {
return;
}

this.setState({ isRemoved: true }, () => {
hcaptcha.remove(captchaId);
Expand Down Expand Up @@ -184,28 +198,65 @@ class HCaptcha extends React.Component {

handleExpire () {
const { onExpire } = this.props;
const { isApiReady, isRemoved, captchaId } = this.state;
const { captchaId } = this.state;

if (!this.isReady()) {
return;
}

if (!isApiReady || isRemoved) return
hcaptcha.reset(captchaId) // If hCaptcha runs into error, reset captcha - hCaptcha

if (onExpire) onExpire();
}

handleError (event) {
const { onError } = this.props;
const { isApiReady, isRemoved, captchaId } = this.state;
const { captchaId } = this.state;

if (!isApiReady || isRemoved) return
if (!this.isReady()) {
return;
}

hcaptcha.reset(captchaId) // If hCaptcha runs into error, reset captcha - hCaptcha
if (onError) onError(event);
}

isReady () {
const { isApiReady, isRemoved } = this.state;

return isApiReady && !isRemoved;
}

handleOpen () {
if (!this.isReady() || !this.props.onOpen) {
return;
}

this.props.onOpen();
}

handleClose () {
if (!this.isReady() || !this.props.onClose) {
return;
}

this.props.onClose();
}

handleChallengeExpired () {
if (!this.isReady() || !this.props.onChalExpired) {
return;
}

this.props.onChalExpired();
}

execute (opts = null) {
const { isApiReady, isRemoved, captchaId } = this.state;
const { captchaId } = this.state;

if (!isApiReady || isRemoved) return;
if (!this.isReady()) {
return;
}

if (opts && typeof opts !== "object") {
opts = null;
Expand Down
Loading

0 comments on commit 5baebb0

Please sign in to comment.