diff --git a/recaptcha.js b/recaptcha.js
new file mode 100644
index 0000000..220966f
--- /dev/null
+++ b/recaptcha.js
@@ -0,0 +1,18 @@
+(function ($, window, document) {
+
+ Drupal.behaviors.recaptcha = {
+ widgets: {},
+ attach: function (context, settings) {
+ // Check if the reCAPTCHA script is loaded yet. If not, don't worry: the
+ // onload callback recaptchaOnLoad() will make sure that this function is
+ // called again once grecaptcha is defined.
+ if (typeof(grecaptcha) === 'undefined' || typeof(grecaptcha.render) === 'undefined' ) {
+ return;
+ }
+ $('.g-recaptcha', context).once('drupal-recaptcha').each(function () {
+ Drupal.behaviors.recaptcha.widgets[this.id] = grecaptcha.render(this, $(this).data());
+ });
+ }
+ };
+
+})(jQuery, window, document);
diff --git a/recaptcha.module b/recaptcha.module
index 1e65aab..0af8234 100644
--- a/recaptcha.module
+++ b/recaptcha.module
@@ -68,7 +68,7 @@ function recaptcha_permission() {
/**
* Implements hook_captcha().
*/
-function recaptcha_captcha($op, $captcha_type = '') {
+function recaptcha_captcha($op, $captcha_type = '', $captcha_sid = '') {
global $language;
switch ($op) {
@@ -101,6 +101,7 @@ function recaptcha_captcha($op, $captcha_type = '') {
}
$attributes = array(
+ 'id'=>'g-recaptcha'.$captcha_sid,
'class' => 'g-recaptcha',
'data-sitekey' => $recaptcha_site_key,
'data-theme' => variable_get('recaptcha_theme', 'light'),
@@ -114,15 +115,49 @@ function recaptcha_captcha($op, $captcha_type = '') {
$captcha['form']['recaptcha_widget'] = array(
'#markup' => '
',
'#suffix' => $noscript,
+ '#attached' => array(
+ 'js' => array(
+ drupal_get_path('module', 'recaptcha') . '/recaptcha.js',
+ ),
+ ),
+ );
+
+ // The reCAPTHCHA onload callback must be defined before the
+ // reCAPTHCHA script itself is loaded. Since the reCAPTHCHA script is
+ // currently added with drupal_add_html_head(), we must do the same
+ // here so we can control the ordering of the script tags in .
+ // The recaptchaOnLoad() function tries to initialize the recaptcha's
+ // on the page. If the Drupal behavior is not available yet, don't
+ // worry: Drupal's attachBehaviors() will take care of it later.
+ $onload_js = << 'script',
+ '#value' => $onload_js,
+ '#weight' => -1,
);
+ drupal_add_html_head($data, 'recaptcha_onload');
// @todo: #1664602: D7 does not yet support "async" in drupal_add_js().
// drupal_add_js(url('https://www.google.com/recaptcha/api.js', array('query' => array('hl' => $language->language), 'absolute' => TRUE)), array('defer' => TRUE, 'async' => TRUE, 'type' => 'external'));
$data = array(
'#tag' => 'script',
'#value' => '',
+ '#weight' => 0,
'#attributes' => array(
- 'src' => url('https://www.google.com/recaptcha/api.js', array('query' => array('hl' => $language->language), 'absolute' => TRUE)),
+ 'src' => url('https://www.google.com/recaptcha/api.js', array(
+ 'absolute' => TRUE,
+ 'query' => array(
+ 'hl' => $language->language,
+ 'onload' => 'recaptchaOnLoad',
+ 'render' => 'explicit',
+ ),
+ )),
'async' => 'async',
'defer' => 'defer',
),
diff --git a/recaptcha.test b/recaptcha.test
index 4afedf7..0d35de6 100644
--- a/recaptcha.test
+++ b/recaptcha.test
@@ -127,13 +127,17 @@ class ReCaptchaBasicTest extends DrupalWebTestCase {
// Check if there is a reCAPTCHA on the login form.
$this->drupalGet('user');
- $this->assertRaw($grecaptcha, '[testReCaptchaOnLoginForm]: reCAPTCHA is shown on form.');
- $this->assertRaw('', '[testReCaptchaOnLoginForm]: reCAPTCHA is shown on form.');
+ $captcha_sid = $this->getCaptchaSid();
+ $grecaptcha = '';
+ $this->assertRaw($grecaptcha, '[testReCaptchaOnLoginForm]: reCAPTCHA is shown on form.' . $grecaptcha);
+ $this->assertRaw('', '[testReCaptchaOnLoginForm]: reCAPTCHA API script is present.');
$this->assertNoRaw($grecaptcha . '