Hi all, I''m curious what you think is the best way to prevent double form submission when a user double clicks the submit button? (Also handling multiple clicks due to slow response time and impatient users.) I''m curious about how you folks are achieving this and if there may be a nice railsy solution. Basically any html-driven web app will have to contend with this problem, if we can agree on the best solution then perhaps it could end up as a rails feature. Thoughts? Thanks -Josh Whiting
Michael Schuerig
2005-Jul-10 17:09 UTC
Re: preventing double form submission (double clicking)
On Sunday 10 July 2005 18:43, Josh Whiting wrote:> I''m curious what you think is the best way to prevent double form > submission when a user double clicks the submit button?if (!window.Form) { var Form = new Object(); } Form.blockMultipleSubmits = function(form) { form = $(form); form.__hasBeenSubmitted = false; Event.observe(form, ''submit'', Form.multipleSubmitBlocker); }; Form.blockMultipleSubmitsForAllForms = function() { var forms = document.forms; for (var i = 0; i < forms.length; i++) { Form.blockMultipleSubmits(forms[i]); } }; Form.multipleSubmitBlocker = function(event) { var form = Event.element(event); if (form.__hasBeenSubmitted) { Event.stop(event); } var submitButtons = Form.Element.findElements(form, ''submit''); for (var i = 0; i < submitButtons.length; i++) { submitButtons[i].disabled = true; } form.__hasBeenSubmitted = true; }; Michael -- Michael Schuerig Thinking is trying to make up mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org for a gap in one''s education. http://www.schuerig.de/michael/ --Gilbert Ryle
David Corbin
2005-Jul-10 17:10 UTC
Re: preventing double form submission (double clicking)
On Sunday 10 July 2005 12:43 pm, Josh Whiting wrote:> Hi all, > > I''m curious what you think is the best way to prevent double form > submission when a user double clicks the submit button? (Also > handling multiple clicks due to slow response time and impatient > users.) I''m curious about how you folks are achieving this and if > there may be a nice railsy solution. Basically any html-driven web app > will have to contend with this problem, if we can agree on the best > solution then perhaps it could end up as a rails feature. Thoughts? >Every form gets a token. That token goes into the session when the form is generated.. Form processing verifies the token and removes it from the session. Another option would be to use JS on the client side to ignore subsequent clicks. David
Steve Willer
2005-Jul-11 03:39 UTC
Re: Re: preventing double form submission (double clicking)
The drawback with your approach is that, at least in MSIE, a "disabled" form element won''t submit anything. So you can''t have any code that detects form submission via the submit button; you have to use a hidden field or something. Also, does Form.Element.findElements(form, ''submit'') do what you are expecting? Submit isn''t a tag ... it''s a type of input tag. I haven''t used that function, so maybe it''s correct and I''m wrong. Steve On 7/10/05, Michael Schuerig <michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org> wrote:> On Sunday 10 July 2005 18:43, Josh Whiting wrote: > > > I''m curious what you think is the best way to prevent double form > > submission when a user double clicks the submit button? > > if (!window.Form) { > var Form = new Object(); > } > > Form.blockMultipleSubmits = function(form) { > form = $(form); > form.__hasBeenSubmitted = false; > Event.observe(form, ''submit'', Form.multipleSubmitBlocker); > }; > > Form.blockMultipleSubmitsForAllForms = function() { > var forms = document.forms; > for (var i = 0; i < forms.length; i++) { > Form.blockMultipleSubmits(forms[i]); > } > }; > > Form.multipleSubmitBlocker = function(event) { > var form = Event.element(event); > if (form.__hasBeenSubmitted) { > Event.stop(event); > } > var submitButtons = Form.Element.findElements(form, ''submit''); > for (var i = 0; i < submitButtons.length; i++) { > submitButtons[i].disabled = true; > } > form.__hasBeenSubmitted = true; > }; > > > Michael > > -- > Michael Schuerig Thinking is trying to make up > mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org for a gap in one''s education. > http://www.schuerig.de/michael/ --Gilbert Ryle > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Michael Schuerig
2005-Jul-11 08:11 UTC
Re: preventing double form submission (double clicking)
On Monday 11 July 2005 05:39, Steve Willer wrote:> The drawback with your approach is that, at least in MSIE, a > "disabled" form element won''t submit anything. So you can''t have any > code that detects form submission via the submit button; you have to > use a hidden field or something.Sorry, I don''t understand what you''re saying. I only disable the submit elements after the first submit. After that I don''t want to submit anything as another page will be loaded. Well, at least in the pre-ajax days. Maybe I need to add a reset method that allows forms to be submitted again.> Also, does Form.Element.findElements(form, ''submit'') do what you are > expecting? Submit isn''t a tag ... it''s a type of input tag. I haven''t > used that function, so maybe it''s correct and I''m wrong.You could not have used that function as it''s one of my own making and I forgot to include it the first time around. See below. Michael Form.Element.findElements = function(form, typeName, name) { form = $(form); return [].concat( Form.Element.selectByTypeAndName( form.getElementsByTagName(''input''), typeName, name), Form.Element.selectByTypeAndName( form.getElementsByTagName(''select''), typeName, name), Form.Element.selectByTypeAndName( form.getElementsByTagName(''button''), typeName, name) ); } Form.Element.selectByTypeAndName = function(elements, typeName, name) { if (!typeName && !name) { return elements; } var matches = []; for (var i = 0; i < elements.length; i++) { var element = elements[i]; if (typeName && element.type != typeName) { continue; } if (name && element.name != name) { continue; } matches.push(element); } return matches; }; -- Michael Schuerig Failures to use one''s frontal lobes mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org can result in the loss of them. http://www.schuerig.de/michael/ --William H. Calvin
Julian ''Julik'' Tarkhanov
2005-Jul-11 11:10 UTC
Re: Re: preventing double form submission (double clicking)
On 11-jul-2005, at 10:11, Michael Schuerig wrote:> On Monday 11 July 2005 05:39, Steve Willer wrote: > >Maybe just a <%= single_submit ''Send'' %> that will disable the submit as soon as it is clicked? <input type=''submit'' onclick=''this.disabled = true''>Boo!</input> Is this session/etc. handling really needed for this? -- Julian "Julik" Tarkhanov
Josh Whiting
2005-Jul-11 13:36 UTC
Re: Re: preventing double form submission (double clicking)
On 7/11/05, Michael Schuerig <michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org> wrote:> elements after the first submit. After that I don''t want to submit > anything as another page will be loaded. Well, at least in the pre-ajax > days. Maybe I need to add a reset method that allows forms to be > submitted again.Yeah, my concern with a js solution is re-submitting the form. Say they submit it, get an error on the next page, and hit back. Will, in all browsers, the button be enabled again? (Even if the page is cached, e.g. not reloaded?) I don''t have the resources to test that sort of thing, so I''m skeptical. I''d use it if I knew that user''s weren''t going to be locked out by disabled buttons when they legimately want to re-submit. Perhaps a timeout that enables the button after a couple seconds? -josh w
Josh Whiting
2005-Jul-11 13:40 UTC
Re: preventing double form submission (double clicking)
On 7/10/05, David Corbin <dcorbin-wmGZ+vDKSyrZJqsBc5GL+g@public.gmane.org> wrote:> Every form gets a token. That token goes into the session when the form is > generated.. Form processing verifies the token and removes it from the > session.Okay, but on the second click, when the controller sees that the form has already been processed, what does it do? The browser will show the results of the second request, not the first one, to the user. So, the user double clicks the button and then sees "sorry you already submitted this form"? I''d like them to see the results as if that second click never happened... -josh w
Sean T Allen
2005-Jul-11 13:45 UTC
Re: Re: preventing double form submission (double clicking)
Josh Whiting wrote:>On 7/11/05, Michael Schuerig <michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org> wrote: > > >>elements after the first submit. After that I don''t want to submit >>anything as another page will be loaded. Well, at least in the pre-ajax >>days. Maybe I need to add a reset method that allows forms to be >>submitted again. >> >> > >Yeah, my concern with a js solution is re-submitting the form. Say >they submit it, get an error on the next page, and hit back. Will, in >all browsers, the button be enabled again? (Even if the page is >cached, e.g. not reloaded?) I don''t have the resources to test that >sort of thing, so I''m skeptical. I''d use it if I knew that user''s >weren''t going to be locked out by disabled buttons when they >legimately want to re-submit. Perhaps a timeout that enables the >button after a couple seconds? > >-josh w > >they would be locked out until the page is reloaded. which is the entire point, no? _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Josh Whiting
2005-Jul-11 13:47 UTC
Re: Re: preventing double form submission (double clicking)
On 7/11/05, Sean T Allen <sean-5W9FBhQXBOtBDgjK7y7TUQ@public.gmane.org> wrote:> they would be locked out until the page is reloaded. > which is the entire point, no?Not exactly, the point is really to prevent multiple submissions from double clicks, not to prevent all submissions after the first one. Submit form, get new page, hit back button (to cached page), and resubmit, is a normal flow that should be accomodated. Maybe this will work, maybe it won''t, I''m not versed enough in Javascript across browsers to know...
Sean T Allen
2005-Jul-11 14:01 UTC
Re: Re: preventing double form submission (double clicking)
Josh Whiting wrote:>On 7/11/05, Sean T Allen <sean-5W9FBhQXBOtBDgjK7y7TUQ@public.gmane.org> wrote: > > >>they would be locked out until the page is reloaded. >>which is the entire point, no? >> >> > >Not exactly, the point is really to prevent multiple submissions from >double clicks, not to prevent all submissions after the first one. >Submit form, get new page, hit back button (to cached page), and >resubmit, is a normal flow that should be accomodated. Maybe this will >work, maybe it won''t, I''m not versed enough in Javascript across >browsers to know.. > >It wont. What can work... disabled submit button... on error submission page with info prepopulated.. user fixes problem.. resubmits client side checking can help as well as if there is an obvious error you can alert the user and renable the submit button. _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Josh Whiting
2005-Jul-12 21:00 UTC
Re: preventing double form submission (double clicking)
On 7/10/05, David Corbin <dcorbin-wmGZ+vDKSyrZJqsBc5GL+g@public.gmane.org> wrote:> Every form gets a token. That token goes into the session when the form is > generated.. Form processing verifies the token and removes it from the > session. >Wouldn''t this fail in a multi-process (fastcgi) environment due to a race condition? - Request A comes in, loads the session - Request B comes in (a second button click), loads the session (same state as A) - A does the work and removes the token - B, unaware of A, does the same work and removes the token - A saves the session - B saves the session on top of A''s save, blindly clobbering it In order for it to work, the sessions have to be serialized, e.g. locked on read until the end of the request, preventing other concurrent requests from read access until the first one is finished. Is this possible with the current session implementation? I''ve personally verified in my fastcgi environment that, indeed, sessions clobber each other on current requests. Try accessing this controller action from two separate browser windows/tabs within a second or two of each other: def clobber @session[''counter''] ||= 0 @session[''counter''] = @session[''counter''] + 1 sleep(5) render_text "that was a nice little nap, my counter says: #{@session[''counter'']}" end With session locking, each page request would get the right (unique) count, but in concurrent requests multiple requests will end up with the same count. (Note: don''t use separate browsers, just multiple window/tabs of the same browser, so the same cookie is sent.) -josh w.
Josh Whiting
2005-Jul-12 21:07 UTC
Re: preventing double form submission (double clicking)
> [...] Try accessing this > controller action from two separate browser windows/tabs within > a second or two of each other:Just a follow up on this: I''ve noticed that Firefox, bless it''s heart, does not send multiple concurrent requests to the same URL. To test it in firefox, give one tab the URL for the action and another tab the same URL with an arbitrary query string: http://localhost/myController/clobber and http://localhost/myController/clobber?foo=bar each tab will show the same end result on the counter. otherwise, FF waits until one is finished before sending the other and it falsely appears that the race condition isn''t an issue. -jw
David Corbin
2005-Jul-13 00:28 UTC
Re: preventing double form submission (double clicking)
On Tuesday 12 July 2005 05:00 pm, Josh Whiting wrote:> On 7/10/05, David Corbin <dcorbin-wmGZ+vDKSyrZJqsBc5GL+g@public.gmane.org> wrote: > > Every form gets a token. That token goes into the session when the form > > is generated.. Form processing verifies the token and removes it from the > > session. > > Wouldn''t this fail in a multi-process (fastcgi) environment due to a > race condition? >Sounds like you''re right, but that would seem to be general problem with fastcgi anyway, if sessions are cookie based.