diff --git a/README.md b/README.md
index db6a9d9..a5aedae 100755
--- a/README.md
+++ b/README.md
@@ -48,12 +48,13 @@ using top level options
{
// ...
recaptcha: {
- hideBadge: Boolean, // Hide badge element (v3 & v2 via size=invisible)
- language: String, // Recaptcha language (v2)
- mode: String, // Mode: 'base', 'enterprise'
- siteKey: String, // Site key for requests
- version: Number, // Version
- size: String // Size: 'compact', 'normal', 'invisible' (v2)
+ hideBadge: Boolean, // Hide badge element (v3 & v2 via size=invisible)
+ language: String, // Recaptcha language (v2)
+ onloadCallback: Function, // Fonction de rappel à exécuter lorsque reCAPTCHA est complètement chargé
+ mode: String, // Mode: 'base', 'enterprise'
+ siteKey: String, // Site key for requests
+ version: Number, // Version
+ size: String // Size: 'compact', 'normal', 'invisible' (v2)
},
// ...
}
diff --git a/example/base/v2/pages/index.vue b/example/base/v2/pages/index.vue
index 1606326..7cbb3ed 100644
--- a/example/base/v2/pages/index.vue
+++ b/example/base/v2/pages/index.vue
@@ -21,6 +21,7 @@
@error="onError"
@success="onSuccess"
@expired="onExpired"
+ @load="onLoad"
/>
@@ -68,6 +69,10 @@ export default {
onExpired () {
console.log('Expired')
+ },
+
+ onLoad () {
+ console.log('Loaded')
}
},
}
diff --git a/example/base/v3/pages/index.vue b/example/base/v3/pages/index.vue
index d1f9e7e..b71ab28 100644
--- a/example/base/v3/pages/index.vue
+++ b/example/base/v3/pages/index.vue
@@ -32,6 +32,7 @@ export default {
async mounted() {
try {
await this.$recaptcha.init()
+ this.$recaptcha.on('load', () => console.log('loaded'))
} catch (e) {
console.log(e);
}
diff --git a/example/enterprise/v2/pages/index.vue b/example/enterprise/v2/pages/index.vue
index 1606326..7cbb3ed 100644
--- a/example/enterprise/v2/pages/index.vue
+++ b/example/enterprise/v2/pages/index.vue
@@ -21,6 +21,7 @@
@error="onError"
@success="onSuccess"
@expired="onExpired"
+ @load="onLoad"
/>
@@ -68,6 +69,10 @@ export default {
onExpired () {
console.log('Expired')
+ },
+
+ onLoad () {
+ console.log('Loaded')
}
},
}
diff --git a/example/enterprise/v3/pages/index.vue b/example/enterprise/v3/pages/index.vue
index d1f9e7e..b71ab28 100644
--- a/example/enterprise/v3/pages/index.vue
+++ b/example/enterprise/v3/pages/index.vue
@@ -32,6 +32,7 @@ export default {
async mounted() {
try {
await this.$recaptcha.init()
+ this.$recaptcha.on('load', () => console.log('loaded'))
} catch (e) {
console.log(e);
}
diff --git a/lib/plugin.js b/lib/plugin.js
index 5f773f4..4965ed2 100644
--- a/lib/plugin.js
+++ b/lib/plugin.js
@@ -4,7 +4,11 @@ import Vue from 'vue'
const API_URL = 'https://www.recaptcha.net/recaptcha/api.js'
class ReCaptcha {
- constructor ({ hideBadge, language, mode, siteKey, version, size }) {
+ constructor ({ hideBadge, language, onloadCallback, mode, siteKey, version, size }) {
+ if (onloadCallback && typeof onloadCallback !== 'function') {
+ throw new Error('ReCaptcha error: onloadCallback must be a function')
+ }
+
if (!siteKey) {
throw new Error('ReCaptcha error: No key provided')
}
@@ -21,6 +25,7 @@ class ReCaptcha {
this.hideBadge = hideBadge
this.language = language
+ this.onloadCallback = onloadCallback
this.siteKey = siteKey
this.version = version
@@ -122,6 +127,11 @@ class ReCaptcha {
const params = []
if (this.version === 3) { params.push('render=' + this.siteKey) }
if (this.language) { params.push('hl=' + this.language) }
+ if (this.onloadCallback && typeof this.onloadCallback === 'function') {
+ if (this.version === 2) {
+ params.push('onload=recaptchaOnloadCallbackFunction')
+ }
+ }
let scriptUrl = API_URL
@@ -135,6 +145,13 @@ class ReCaptcha {
window.recaptchaSuccessCallback = (token) => this._eventBus.emit('recaptcha-success', token)
window.recaptchaExpiredCallback = () => this._eventBus.emit('recaptcha-expired')
window.recaptchaErrorCallback = () => this._eventBus.emit('recaptcha-error', 'Failed to execute')
+ window.recaptchaOnloadCallback = () => this._eventBus.emit('recaptcha-onload')
+ window.recaptchaOnloadCallbackFunction = () => {
+ this._eventBus.emit('recaptcha-onload')
+ if (typeof this.onloadCallback === 'function') {
+ this.onloadCallback();
+ }
+ }
this._ready = new Promise((resolve, reject) => {
script.addEventListener('load', () => {
@@ -149,7 +166,10 @@ class ReCaptcha {
}
this._grecaptcha = window.grecaptcha.enterprise || window.grecaptcha
- this._grecaptcha.ready(resolve)
+ this._grecaptcha.ready(() => {
+ windows.recaptchaOnloadCallbackFunction()
+ resolve()
+ });
})
script.addEventListener('error', () => {
diff --git a/lib/recaptcha.vue b/lib/recaptcha.vue
index fc0f7f3..470de0b 100644
--- a/lib/recaptcha.vue
+++ b/lib/recaptcha.vue
@@ -9,6 +9,7 @@
data-callback="recaptchaSuccessCallback"
data-expired-callback="recaptchaExpiredCallback"
data-error-callback="recaptchaErrorCallback"
+ data-onload-callback="recaptchaOnloadCallback"
class="g-recaptcha"
/>
@@ -63,6 +64,7 @@ export default {
this.$recaptcha.on('recaptcha-error', this.onError)
this.$recaptcha.on('recaptcha-success', this.onSuccess)
this.$recaptcha.on('recaptcha-expired', this.onExpired)
+ this.$recaptcha.on('recaptcha-onload', this.onLoad)
},
computed: {
@@ -83,6 +85,10 @@ export default {
onExpired() {
return this.$emit('expired')
}
+
+ onLoad() {
+ return this.$emit('load')
+ }
}
}
diff --git a/types/index.d.ts b/types/index.d.ts
index 05459ac..df64241 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -11,6 +11,11 @@ export interface ReCaptchaOptions {
*/
language?: string
+ /**
+ * Callback executed when ReCaptcha fully loads
+ */
+ onloadCallback?: Function;
+
/**
* ReCaptcha mode.
*/