diff --git a/config/install/recaptcha.settings.yml b/config/install/recaptcha.settings.yml index 00ec248..6c7165d 100644 --- a/config/install/recaptcha.settings.yml +++ b/config/install/recaptcha.settings.yml @@ -4,5 +4,6 @@ widget: theme: 'light' type: 'image' size: '' + badge: 'bottomright' tabindex: 0 noscript: false diff --git a/config/schema/recaptcha.schema.yml b/config/schema/recaptcha.schema.yml index dd90863..866c02f 100644 --- a/config/schema/recaptcha.schema.yml +++ b/config/schema/recaptcha.schema.yml @@ -23,6 +23,9 @@ recaptcha.settings: size: type: string label: 'Size' + badge: + type: string + label: 'Badge' tabindex: type: integer label: 'Tabindex' diff --git a/js/recaptcha.invisible.js b/js/recaptcha.invisible.js new file mode 100644 index 0000000..e4158e8 --- /dev/null +++ b/js/recaptcha.invisible.js @@ -0,0 +1,63 @@ +/** + * @file + * Invisible reCaptcha behaviors. + */ + +/** + * The submit object that was clicked. + * + * @type {object} + */ +var clickedSubmit = ''; + +/** + * reCaptcha data-callback that submits the form. + * + * @param token + * The validation token. + */ +function onInvisibleSubmit(token) { + clickedSubmit.click(); + clickedSubmit = ''; +} + +(function ($, Drupal) { + + 'use strict'; + + /** + * Handles the submission of the form with the invisible reCaptcha. + * + * @type {Drupal~behavior} + * + * @prop {Drupal~behaviorAttach} attach + * Attaches the behavior for the invisible reCaptcha. + */ + Drupal.behaviors.invisibleRecaptcha = { + attach: function (context) { + $('form', context).each(function () { + var $form = $(this); + + if ($form.find('.g-recaptcha[data-size="invisible"]').length) { + $form.find(':submit').on('click', function (e) { + if (clickedSubmit.length === 0) { + e.preventDefault(); + validateInvisibleCaptcha(this); + } + }); + } + }); + + /** + * Triggers the reCaptcha to validate the form. + * + * @param {object} button + * The submit button object was clicked. + */ + function validateInvisibleCaptcha(button) { + clickedSubmit = button; + grecaptcha.execute(); + } + } + }; +})(jQuery, Drupal); diff --git a/recaptcha.libraries.yml b/recaptcha.libraries.yml new file mode 100644 index 0000000..6ecef6d --- /dev/null +++ b/recaptcha.libraries.yml @@ -0,0 +1,7 @@ +recaptcha.invisible: + version: VERSION + js: + js/recaptcha.invisible.js: {} + dependencies: + - core/jquery + - core/drupal \ No newline at end of file diff --git a/recaptcha.module b/recaptcha.module index 674fa36..9bcadf2 100644 --- a/recaptcha.module +++ b/recaptcha.module @@ -100,8 +100,16 @@ function recaptcha_captcha($op, $captcha_type = '') { 'data-theme' => $config->get('widget.theme'), 'data-type' => $config->get('widget.type'), 'data-size' => $config->get('widget.size'), + 'data-badge' => $config->get('widget.badge'), 'data-tabindex' => $config->get('widget.tabindex'), ]; + + // Set the callback for invisible captcha. + if ('invisible' === $config->get('widget.size')) { + $attributes['data-callback'] = 'onInvisibleSubmit'; + $captcha['form']['#attached']['library'][] = 'recaptcha/recaptcha.invisible'; + } + // Filter out empty tabindex/size. $attributes = array_filter($attributes); diff --git a/src/Form/ReCaptchaAdminSettingsForm.php b/src/Form/ReCaptchaAdminSettingsForm.php index fd2ca6d..8a7013d 100644 --- a/src/Form/ReCaptchaAdminSettingsForm.php +++ b/src/Form/ReCaptchaAdminSettingsForm.php @@ -87,10 +87,27 @@ class ReCaptchaAdminSettingsForm extends ConfigFormBase { '#options' => [ '' => $this->t('Normal (default)'), 'compact' => $this->t('Compact'), + 'invisible' => $this->t('Invisible'), ], '#title' => $this->t('Size'), '#type' => 'select', ]; + $form['widget']['recaptcha_badge'] = [ + '#default_value' => $config->get('widget.badge'), + '#description' => $this->t('Reposition the reCAPTCHA badge. "Inline" allows you to control the CSS.'), + '#options' => [ + 'bottomright' => $this->t('Bottom Right (default)'), + 'bottomleft' => $this->t('Bottom Left'), + 'inline' => $this->t('Inline'), + ], + '#title' => $this->t('Badge'), + '#type' => 'select', + '#states' => array( + 'visible' => array( + ':input[name="recaptcha_size"]' => array('value' => 'invisible'), + ), + ), + ]; $form['widget']['recaptcha_tabindex'] = [ '#default_value' => $config->get('widget.tabindex'), '#description' => $this->t('Set the tabindex of the widget and challenge (Default = 0). If other elements in your page use tabindex, it should be set to make user navigation easier.', [':tabindex' => Url::fromUri('http://www.w3.org/TR/html4/interact/forms.html', ['fragment' => 'adef-tabindex'])->toString()]), @@ -120,6 +137,7 @@ class ReCaptchaAdminSettingsForm extends ConfigFormBase { ->set('widget.theme', $form_state->getValue('recaptcha_theme')) ->set('widget.type', $form_state->getValue('recaptcha_type')) ->set('widget.size', $form_state->getValue('recaptcha_size')) + ->set('widget.badge', $form_state->getValue('recaptcha_badge')) ->set('widget.tabindex', $form_state->getValue('recaptcha_tabindex')) ->set('widget.noscript', $form_state->getValue('recaptcha_noscript')) ->save();