One of the problems that some developers have is trying to load reCaptcha on multiple forms on the same page. This is specifically useful when you have multiple user registration forms. I had this problem and had to solve it. I found that I really like this reCaptcha module, but it didn't allow for what I am trying to do.
So after a few days of work I have come up with an integrated solution. It can probably be modified to be specific to the forms in question, but I didn't have a need for that at this point. So I didn't go that far. But this should integrate well into the module with a little bit of dev work. I have included the patch file set against dev and some sample files to help show exactly what you need to do.
To the maintainers, please include this or something similar into the codebase so that others can use it and so that it can stay with the module through updates. If you would like any help with this please let me know. Thanks!
Sample code has been included to demonstrate this in action. Notice that in order for this to work you need a button or JS event that switches between the forms and, using that same action, allows a fresh reCaptcha instance to be loaded into the desired form.
To know more about how to do this, please refer to the sample files:
sample_multiform_loading.php
sample_multiform_loading.js
Comment | File | Size | Author |
---|---|---|---|
#156 | 1833822-155-allow-multiple-per-page-D8.patch | 1.86 KB | Dan.Ashdown |
| |||
#151 | 1833822-latest-dev.patch | 6.13 KB | firestonej |
#149 | 1833822-147-allow-multiple-per-page-D7-reroll.patch | 5.79 KB | 5n00py |
#147 | 1833822-147-allow-multiple-per-page-D7.patch | 5.89 KB | sokru |
#145 | error_recaptcha.png | 162.56 KB | lomasr |
Comments
Comment #1
patrick.thurmond@gmail.comForgot to change a function name in a function call in the sample php file. Here is the correct one.
Comment #2
Liam MorlandIs this intended to solve #1283004: Support multiple reCAPTCHA widgets on the page?
Comment #3
patrick.thurmond@gmail.comThis would help with that. But due to the multiple instance restrictions from Google this would require some kind of JS event on the page in order to load each instance one at a time. So it is not the most perfect solution. But unless there is a way to use namespaces in JS or something like that then I don't think there is any other solution for using multiple instances of reCaptcha on a page (darn you Google).
Comment #4
Liam MorlandThanks. The sample files need more documentation including an overall description of how this system works.
Since this requires custom code anyway, the recaptcha_custom_load variable should be set by that custom code, not in the reCAPTCHA UI.
Please provide your changes in a single patch file.
Comment #5
Liam MorlandComment #6
patrick.thurmond@gmail.comYeah, that makes sense. I will work on those things over the Thanksgiving break and post my update. Thanks!
Comment #7
Liam MorlandPlease try the latest development version of reCAPTCHA to see if this patch is still required. If so, please re-roll.
Comment #8
BTMash CreditAttribution: BTMash commentedI just tried the dev version of the module and the issue of only showing the captcha on the first form still persists. I haven't yet tried the patch but is there anything else that needs to be done otherwise to get multiple forms showing up?
Comment #9
Liam MorlandI don't know. I haven't run into this problem. We need someone to figure out why it doesn't work and to write a patch to fix it.
Comment #10
BTMash CreditAttribution: BTMash commentedOk, I think I figured something out. What we need is (a) testing and (b) optimization (I am sure the javascript is somewhat horrid). But it seems to reasonably well. What I am doing is creating containers with different ids ('recaptcha_ajax_api_container_N'), the javascript goes through all such containers, marks the first one to show recaptcha and when a form element from another form is selected (or focused on), it will destroy the first recaptcha and create a new recaptcha within the new form.
Comment #11
BTMash CreditAttribution: BTMash commentedTo note: this only works with the ajax api so far. I have no clue how the non-ajax api works.
Comment #12
Liam MorlandThat sounds like a good approach. The reading I have done says that it is not possible to have more than one reCAPTCHA per page, so your approach of creating them as needed would work around this restriction.
If it only works in the Ajax API, that is better than it not working at all.
Comment #13
Liam MorlandComment #14
Liam MorlandPlease re-roll your patch from a checkout of just reCAPTCHA so that the resulting patch will apply. The patch file should not include paths outside of the reCATPCHA module directory.
Comment #15
BTMash CreditAttribution: BTMash commentedThere seem to have been a few changes since when the patch was first created (a few things around
$recaptcha_custom_html
. This should apply cleanly against commit a137f09a696e599e3650b6736504055ba34ff629Comment #16
BTMash CreditAttribution: BTMash commentedAlso, unassigned.
Comment #17
Liam MorlandI'll look at this shortly. Thanks.
Comment #18
Liam MorlandThanks for the patch.
Settings, such as the following, need to be put under Drupal.settings.recaptcha to ensure they don't conflict with anything else.
Attached is a re-roll after I fixed the indentation in the dev. version.
I would appreciate it if others would test the patch and let us know if it is working for them.
Comment #19
RobLoachLooks like it's coming along!
Doesn't need $(document).ready() since behaviors are run automatically on that.
Could we use ['recaptcha'][$js_key] instead? Wouldn't want to overwrite any other settings.
Might be able to just use:
Might be a bit simpler.
If we did the above, we wouldn't need the $containers[] array.
Comment #20
BTMash CreditAttribution: BTMash commentedMakes sense.
This is in
hook_js_alter
. Unfortunately, this is pretty much the only way to get to the recaptcha data that we are setting up.We need the
$containers
array due to hook_js_alter needing to know how many containers are being dealt with. We could create a function that holds the static value or simply use drupal_static (hence I opted for the latter).Comment #21
llillf CreditAttribution: llillf commentedhi all,
i notice that there is no recaptcha.js file for drupal 6 module. is there a solution or patch for drupal 6?
Thanks a lot
Comment #22
Liam MorlandNew features are not being added to the D6 version.
Comment #23
BTMash CreditAttribution: BTMash commentedHere is a revision based on suggestions in #18 and #19 (minus my feedback from #20)
Comment #24
Liam MorlandThanks.
Has anyone else tried this? What is an easy way to get a page with multiple CAPTCHAs for testing?
Comment #25
morgothz CreditAttribution: morgothz commentedPatch on #23 don't apply correctly.
It needs a little change. I'll try to attach that patch fixed.
With these changes it works well to me.
Comment #26
morgothz CreditAttribution: morgothz commentedComment #27
BTMash CreditAttribution: BTMash commentedRerolling the patch by @morgothz due to changes in recaptcha.js
Comment #28
pengie CreditAttribution: pengie commentedI applied the Patch from 27.
I have Drupal 7.25 with the latest version of Captcha/recaptcha
The patch works great... for about an hour, then it stops. Then I clear caches through performance and it works again. Then an hour or so later it stops...
When it stops, I get this JS error: "Uncaught TypeError: Cannot read property '0' of undefined" on line 4 in reference to : Drupal.settings.recaptcha.containers[0]
under performance I turned off the options and have tried none, 1 min, 3 minute and a few others for min cache life and nothing has changed. The recaptcha still disappears leaving only the reCaptcha description. Then I hit "clear all caches" and it magically works again. I tried installing Cache Exclude and set it for the page, but it doesn't seem to do anything.
The page in question is here: http://fivecitiesvet.com/book-appointment
Anyhelp would be appreciated.
Comment #29
BTMash CreditAttribution: BTMash commentedThe way the array was figured out was incorrect in the patch. Try the new one.
Comment #31
Jim.M CreditAttribution: Jim.M commentedIf someone faces the issue and isn't able to apply the patch from comment #29 - here's a patch that is rebuilt for current 1.x-dev version of the module.
Comment #32
Liam MorlandComment #40
Liam MorlandPlease try out the patch in #31 and let us know if it is working for you.
Can anyone suggest an easy way to get multiple reCAPTCHAs on a single page?
Comment #41
hass CreditAttribution: hass commentedWe should move this case to 8.x-2-x first and backport later. Otherwise we end up in regressions.
Comment #42
Liam MorlandAgreed.
Comment #43
hass CreditAttribution: hass commentedComment #44
ak55 CreditAttribution: ak55 commentedI needed to implement this and added some code.
The attachment is the patch but I don't think it is following Drupal Standard, so if someone absorbs this functionality to the next version, it would be great.
This is working only for the 7.x-2.0 branch which utilizes recaptcha2.0.
Comment #45
stuhannaford CreditAttribution: stuhannaford commentedDoes anyone know if patch #44 is possible on a Drupal 6 install with ReCaptcha 2.0? Changes seem fairly straight forward when comparing with 6 module file until you get to drupal_add_html_head section. Anyone know how that would be re-worked for D6 version?
Comment #46
hass CreditAttribution: hass commentedComment #47
fox mulder CreditAttribution: fox mulder commented#44 causes a notice:
Notice: Undefined index: recaptcha_render_callback_script in recaptcha_captcha() function...
changing
$callback_script = $current_head['recaptcha_render_callback_script'];
to this:$callback_script = (isset($current_head['recaptcha_render_callback_script'])) ? $current_head['recaptcha_render_callback_script'] : NULL;
solves the problemComment #48
Lanny Heidbreder CreditAttribution: Lanny Heidbreder at Stone Ward commentedHere's a reroll of #44 incorporating #47 that seems to work (and apply cleanly).
Comment #50
fox mulder CreditAttribution: fox mulder commented#44 causes another warning on admin/config/people/captcha page:
Warning: Missing argument 3 for recaptcha_captcha() recaptcha_captcha() function (.../recaptcha/recaptcha.module line 77).
It comes from call_user_func_array() in _captcha_available_challenge_types():
Comment #56
VVVi CreditAttribution: VVVi commentedHere is improved #48.
Comment #57
hass CreditAttribution: hass commentedComment #58
hass CreditAttribution: hass commentedCode style issues, core apis not used, not d8 code.
Comment #59
hamrant CreditAttribution: hamrant at DEWEB Studio for Drupal Ukraine Community commented#56 - git warning
The patch solved the problem and looks good after a few minor fixes of coding standards.
Tested on recaptcha 7.x-2.0
Suggest moving 8.x-2.x-dev in a separate issue.
Comment #60
hamrant CreditAttribution: hamrant at DEWEB Studio for Drupal Ukraine Community commentedComment #68
hass CreditAttribution: hass commentedComment #69
3blake7 CreditAttribution: 3blake7 commentedFor 7.x-2.x-dev to work with:
https://www.drupal.org/project/bootstrap_login_modal
I applied number #56
However, if you click login or register with an empty field or wrong credentials, it refreshes and the recaptcha doesn't display.
I fixed that with:
https://www.drupal.org/node/1463768 #21
However that fails because of the first patch. So I manually added */ at the end of the correct line and did:
Not sure how to make patches, sorry.
Comment #70
3blake7 CreditAttribution: 3blake7 commentedattached it a combined patch, it combines 1833822 #56 and 1463768 #21
It's for 7.x-2.x-dev
Comment #71
nikathoneChanged version in order to upload a patch against 7.x-2.x-dev. Patch coming...
Comment #72
nikathoneRemoved reference to recaptcha.js from #70 which seems to do not be needed anymore. Tested #70 with latest recaptcha and it's working. Patch applied against 7.x-2.x-dev
Comment #73
nikathoneComment #74
VVVi CreditAttribution: VVVi commentedAs described here #69, after submitting with an wrong credentials the recapcha disappear. It is connected to ajax submit. The patch from #72 doesn't work for me. So here is new one, that is integration of my previous patch from #56 and #12 from issues #2493183.
Comment #80
VVVi CreditAttribution: VVVi commentedHere is updated #74, for fixing tests.
Comment #81
VVVi CreditAttribution: VVVi commentedResubmitting the patch from #80, because tests weren't run.
Comment #82
hass CreditAttribution: hass commentedSee #58
Comment #83
VVVi CreditAttribution: VVVi commented@hass Yes, you are right, this code for D7, because exist the same trouble for D7 version of the module. Should I open new issue instead? Thank you.
Comment #84
VVVi CreditAttribution: VVVi commentedComment #95
VVVi CreditAttribution: VVVi commentedComment #96
hass CreditAttribution: hass commentedNothing get's committed if code quality and security bugs are not fixed and D8 will always committed very first.
Do not change the version again.
Comment #97
marcvangendSome remarks on the patch in #81 regarding coding standards:
Add a newline to the end of the file.
Why not use the url() options to add the parameters? Ie.
Should be a complete sentence, with a space after the //, starting with a captital letter, and ending with a dot.
The closing bracket and the else statement should be on separate lines.
Comment #98
marcvangendHere's a re-roll of the patch in #81, addressing the remarks in #97.
@hass I understand and respect that you want to fix this in the D8 branch first. I hope that sharing my comments and code helps to achieve that. In any case, for me (and the project I'm working on) it was very helpful to find D7 patches here as well.
Comment #99
AsadKamil CreditAttribution: AsadKamil at Valuebound commentedPatch failed,
Comment #100
marcvangend@AsadKamil The patch applies perfectly on my own machine and on simplytest.me. Against which branch did you try to apply the patch? The patch is meant for 7.x-2.x, as you can see in the file name
1833822-98-allow-multiple-per-page-D7-do-not-test.patch
.Comment #101
AsadKamil CreditAttribution: AsadKamil at Valuebound commented@marcvangend I tried applying that patch to D8 version,may be that is why It got failed.
Comment #102
marcvangendManual testing showed that a JS error "ReCAPTCHA placeholder element must be empty" occurred often, but not always. The cause was that the grecaptcha.render() method was triggered in two different places (inline JS and recaptcha.js).
The patch attached is a major cleanup of the previous patch, introducing (compared to #98) the following changes:
To be completely clear: this is a patch against 7.x-2.x. I hope it will help move the 8.x version forward as well, but do not try to apply it to 8.x branches.
Comment #108
AsadKamil CreditAttribution: AsadKamil at Valuebound commented@marcvangend ,here in the issue you have mentioned 8.x-2.x-dev branch so I have applied the patch to the same and now I have applied it to 7.x-2.x-dev branch it is successfully applied.Thanks for the patch
Please change the version in the issue and update.
Comment #109
marcvangend@AsadKamil, please read #57, #68, #82, #96... It is the explicit (and entirely understandable) wish of the project maintainer that the version of the issue is not changed until this problem is solved on the 8.x branch. Reading an issue's comment history before you get involved, helps understand what is happening in the last couple of comments.
Comment #110
marcvangendYet another patch. I had to bring back a dedicated onload callback because it can happen that the recaptcha script is loaded before the Drupal behaviors are. We cannot place this onload callback in the regular .js file because it needs to be defined before the recaptcha script itself (which is currently added with drupal_add_html_head as a workaround for missing async/defer support) is loaded. That is why the onload callback is also placed using drupal_add_html_head.
Hopefully this will fix the test failures.
Comment #116
DarkteK CreditAttribution: DarkteK commentedFinally the patch #98 worked for me :) +1 !!
Comment #117
kiwimind CreditAttribution: kiwimind commentedConfirming that the patch in #110 works as expected when applied to 7.x-2.2.
Thanks.
Comment #118
arulan_pari CreditAttribution: arulan_pari as a volunteer and commentedComment #119
hass CreditAttribution: hass commentedComment #120
lomasr CreditAttribution: lomasr at gai Technologies Pvt Ltd for gai Technologies Pvt Ltd commentedSorry I am little confused with the version . Is it 7.x-2.x-dev or 8.x-2.x-dev ?
Comment #121
Liam MorlandIssues are fixed in 8.x-2.x-dev then backported to 7.x-2.x-dev.
Comment #122
Agiss CreditAttribution: Agiss as a volunteer and commentedI can confirm that patch #110 worked with 7.x-2.2
Thanks
Comment #123
poniesConfirming patch #110 works with 7.x-2.2.
Comment #124
gcalex5 CreditAttribution: gcalex5 as a volunteer commentedConfirming patch #110 works for 7.x-2.2 had 2 forms loading recaptchas via modal windows. Only oddity was that the recaptcha.js file needed manually moved to where it was expected to be.
Comment #125
drupalmonkey CreditAttribution: drupalmonkey as a volunteer commentedConfirming #110 worked for me in 7.x-2.2.
Comment #126
Homotechsual CreditAttribution: Homotechsual commentedWell a bit of fun there :-)
If you run into an issue where PHP errors out on the raw JS in the middle (as I did) try replacing that section (line 133 - 138) with:
Comment #127
thedotwriter CreditAttribution: thedotwriter commented#110 works good for me but it's not enough to work with Invisible reCAPTCHA .
When using the invisible widget, we need to use a function called
grecaptcha.execute()
and pass it the widget ID as argument. If not, execute() tries to validate the first widget created, which means that submitting the second form will triggered the CAPTCHA of the first form.The recaptcha.js file created by the patch on #110 must be modified to store widget IDs returned by
grecaptcha.render()
when called (API documentation). To do that, the following modification should do the job:Modify the line 13:
grecaptcha.render(this, $(this).data());
By the following:
Drupal.behaviors.recaptcha.widgets[this.id] = grecaptcha.render(this, $(this).data());
Add this line:
widgets: {},
Before:
attach: function (context, settings) {
A working implementation of Invisible reCAPTCHA is already available as a patch but it needs to be modified to take into account the changes I'm suggesting here.
Since it's another subject, I'm gonna post the small changes needed over there and link to this answer for the first part of the solution : https://www.drupal.org/node/2852269
Comment #128
hass CreditAttribution: hass commentedComment #129
ashwinparmarCan someone please post Drupal 8 Version Patch for Allow multiple recaptcha on Same Page. withing Form Page or Form Block(s).
I have uploaded my patch file, Please check it.
Comment #130
ashwinparmarComment #131
jedihe CreditAttribution: jedihe as a volunteer commentedI'm attaching an updated patch for D7, based upon #110. The changes can be seen in the interdiff:
Let's see if the test bot likes this one.
EDIT: running the tests with simplytest.me result in a pass :)
Comment #132
jedihe CreditAttribution: jedihe as a volunteer commentedSwitching to 7.x-2.x temporarily in order to trigger full testing now that I got the tests passing again for PHP 5.6 + MySQL 5.5.
Comment #133
jedihe CreditAttribution: jedihe as a volunteer commentedD7 is a pass :), back to 8.x-2.x.
Comment #134
janehollander CreditAttribution: janehollander commentedPatch in #130 refused to apply, re-submitting this patch in correct format.
It may need some more work, but seems to be functioning correctly so far - submitting it to get this issue moving for Drupal 8.
Comment #135
ashwinparmarRe upload with remove trailing space as checked in failed test cases.
Comment #136
andrea.cavattoni CreditAttribution: andrea.cavattoni commented#131 looks good
Comment #137
ashwinparmarUpdated patch again:
Comment #138
hass CreditAttribution: hass commentedAre you planing to share a patch that is not failing?`
Comments on the code:
Code style bug
No need to make an extra line. Combine both together, please.
Debugging code exists and XSS CODE INJECTION is possible via site_key setting.
Move together into one array.
Comment #139
ZalemCitizen CreditAttribution: ZalemCitizen commentedHad a "fatal: corrupt patch at line 134" when applying #131
Don't know why. I applied manually last part of patch (in recaptcha.test) and it's working fine. Thanks jedihe
Comment #140
acrosmanThe patch in #131 applied and worked fine for me against the current D7 release (7.x-2.2).
Comment #141
batkorPatch #137 working Drupal 8.4.4. ty
Error using patch
Error message:
patching file recaptcha.module
Hunk # 4 FAILED at 99.
Hunk # 5 succeeded at 100 (offset -9 lines).
Hunk # 6 succeeded at 176 with fuzz 2 (offset -9 lines).
1 out of 6 hunks FAILED - saving rejects to file recaptcha.module.rej
Comment #142
hass CreditAttribution: hass commentedThere are bugs in the patch shared in #131, see #2969211: Uncaught TypeError: grecaptcha.render is not a function.
Comment #143
veronicaSeveryn CreditAttribution: veronicaSeveryn at Inclind Inc commentedBased on https://www.drupal.org/project/recaptcha/issues/2969211 patch from #131 was adjusted a little.
I just fixed the recaptcha.js one single line:
instead of
if (typeof grecaptcha == 'undefined') {
I put
if (typeof(grecaptcha) === 'undefined' || typeof(grecaptcha.render) === 'undefined' ) {
Based on users' feedback, looks like D8 is also having similar issue - I didn't test it.
Comment #144
firestonej CreditAttribution: firestonej commentedConfirmed – #143 works to solve the race condition as well as the original problem of multiple forms per page.
Comment #145
lomasr CreditAttribution: lomasr at gai Technologies Pvt Ltd for gai Technologies Pvt Ltd commentedApplied #143 but I am getting error. Please see the error screenshot.
Comment #146
sja1 CreditAttribution: sja1 as a volunteer and commented+1 for #143. I had been using #131, and it stopped working (was throwing a javascript error: "grecaptcha.render is not a function"). I applied #143 which fixed the javascript error, and recaptcha started working correctly again.
Comment #147
sokru CreditAttribution: sokru as a volunteer commentedRe-roll & minor coding standards fix of #143, so the patch can be applied against latest 2.x-dev branch. Also this was conflicting against issue #2852269: Integrate Invisible reCAPTCHA option from Google so I renamed the recaptcha.js to recaptcha-multiple.js.
Comment #148
mattwmc CreditAttribution: mattwmc commentedWhere is recaptcha-multiple.js?? I can't find it in the latest dev for D7.
Update: I see its a new file you create.
#147 gives me error and doesn't work:
Undefined variable: captcha_sid in recaptcha_captcha() (line 108 of /sites/all/modules/recaptcha/recaptcha.module).
this is line 108:
'id' => 'g-recaptcha' . $captcha_sid,
Comment #149
5n00py CreditAttribution: 5n00py commentedRe-roll patch for D7
Comment #150
FiNeX CreditAttribution: FiNeX as a volunteer commentedHi, I've tried the patch #137 but it simply makes disappear any recapcha after the first one, so it is not working for me (manually applied against latest webform/recapcha modules).
Comment #151
firestonej CreditAttribution: firestonej as a volunteer commentedFresh patch. Applies cleanly to 7.x-2.x, includes all the work from #143 (some was lost in #149) and fixes some typos in documentation.
Comment #152
FiNeX CreditAttribution: FiNeX as a volunteer commentedHi, the bug is still reproducible on D8. Until Captca/reCaptcha are not reliable shouldn't a warning be added on the module pages to inform that the module is not ready for production environment? Thanks.
Comment #153
AnybodyI can confirm that this heavy problem still exists with 8.x-2.x-dev and recaptcha is not usable with two forms on the same page (for example CTA in the footer and another form on the page). So I suggest to increase the priority and change this to a bug, reason: As FiNeX wrote in #152 I agree that this will be unexpected for most developers and breaks functionality for this not unrealistic use case.
This issue should also be fixed at the same time to ensure the module works correctly and tests don't fail due to the other patch: #2493183: Ajax support / Use behaviors
Comment #154
Dan.Ashdown CreditAttribution: Dan.Ashdown at Full Fat Things commentedPatch no longer applied to D8, I've reworked it to use a Drupal behaviour so that this also works on forms that are loaded in after page load.
Comment #156
Dan.Ashdown CreditAttribution: Dan.Ashdown at Full Fat Things commentedAccidentally created patch against D9, rerolled.
Comment #157
Liam Morland8.x-2.x is no longer supported. If this applies to 8.x-3.x, please re-open.