Code

. All forms now have "double-submit" protection when Javascript is enabled
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 14 Feb 2002 23:39:18 +0000 (23:39 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 14 Feb 2002 23:39:18 +0000 (23:39 +0000)
  on the client-side.

git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@626 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
roundup/cgi_client.py
roundup/htmltemplate.py

index 9a2ee92886229a7287eb9df351d256f25b1d605f..a14d0e562dfa82c6849e017cf8f92bb47ba378a5 100644 (file)
@@ -11,6 +11,8 @@ Fixed:
  . mailgw checks encoding on first part too.
  . #511586 ] unittest FAIL: testReldate_date
  . Added a uniquely Roundup header to email, "X-Roundup-Name"
+ . All forms now have "double-submit" protection when Javascript is enabled
+   on the client-side.
 
 
 2002-01-24 - 0.4.0
index aea9d1d13ee74a57e5b5290944dae517a3190e54..ad521c428626e575b77acde5d8622aae8853fac9 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: cgi_client.py,v 1.100 2002-01-16 07:02:57 richard Exp $
+# $Id: cgi_client.py,v 1.101 2002-02-14 23:39:18 richard Exp $
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
@@ -80,6 +80,20 @@ class Client:
         if self.debug:
             self.headers_sent = headers
 
+    single_submit_script = '''
+<script language="javascript">
+submitted = false;
+function submit_once() {
+    if (submitted) {
+        alert("Your request is being processed.\\nPlease be patient.");
+        return 0;
+    }
+    submitted = true;
+    return 1;
+}
+</script>
+'''
+
     def pagehead(self, title, message=None):
         url = self.env['SCRIPT_NAME'] + '/'
         machine = self.env['SERVER_NAME']
@@ -113,10 +127,12 @@ class Client:
 ''')
         else:
             add_links = ''
+        single_submit_script = self.single_submit_script
         self.write(_('''<html><head>
 <title>%(title)s</title>
 <style type="text/css">%(style)s</style>
 </head>
+%(single_submit_script)s
 <body bgcolor=#ffffff>
 %(message)s
 <table width=100%% border=0 cellspacing=0 cellpadding=2>
@@ -348,9 +364,9 @@ class Client:
             if self.nodeid:
                 cl = self.db.classes[self.classname]
                 l = cl.get(self.nodeid, 'nosy')
-               if assignedto_id in l:
-                   return
-               props['nosy'] = l
+                if assignedto_id in l:
+                    return
+                props['nosy'] = l
             else:
                 props['nosy'] = []
         if assignedto_id not in props['nosy']:
@@ -746,7 +762,7 @@ class Client:
         self.write(_('''
 <table>
 <tr><td colspan=2 class="strong-header">Existing User Login</td></tr>
-<form action="login_action" method=POST>
+<form onSubmit="return submit_once()" action="login_action" method=POST>
 <input type="hidden" name="__destination_url" value="%(action)s">
 <tr><td align=right>Login name: </td>
     <td><input name="__login_name"></td></tr>
@@ -770,7 +786,7 @@ class Client:
 <p>
 <tr><td colspan=2 class="strong-header">New User Registration</td></tr>
 <tr><td colspan=2><em>marked items</em> are optional...</td></tr>
-<form action="newuser_action" method=POST>
+<form onSubmit="return submit_once()" action="newuser_action" method=POST>
 <input type="hidden" name="__destination_url" value="%(action)s">
 <tr><td align=right><em>Name: </em></td>
     <td><input name="realname" value="%(realname)s"></td></tr>
@@ -1079,10 +1095,12 @@ class ExtendedClient(Client):
 ''')
         else:
             add_links = ''
+        single_submit_script = self.single_submit_script
         self.write(_('''<html><head>
 <title>%(title)s</title>
 <style type="text/css">%(style)s</style>
 </head>
+%(single_submit_script)s
 <body bgcolor=#ffffff>
 %(message)s
 <table width=100%% border=0 cellspacing=0 cellpadding=2>
@@ -1182,6 +1200,10 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.100  2002/01/16 07:02:57  richard
+#  . lots of date/interval related changes:
+#    - more relaxed date format for input
+#
 # Revision 1.99  2002/01/16 03:02:42  richard
 # #503793 ] changing assignedto resets nosy list
 #
index c4f8866fc05239d29ad26c4ebcd3e1c896072386..e913dc2968968b72f59d1d32bed61fcb204a5929 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: htmltemplate.py,v 1.71 2002-01-23 06:15:24 richard Exp $
+# $Id: htmltemplate.py,v 1.72 2002-02-14 23:39:18 richard Exp $
 
 __doc__ = """
 Template engine.
@@ -708,7 +708,7 @@ class IndexTemplate(TemplateFunctions):
         # display the filter section
         if (show_display_form and 
                 self.instance.FILTER_POSITION in ('top and bottom', 'top')):
-            w('<form action="%s">\n'%self.classname)
+            w('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
             self.filter_section(filter_template, filter, columns, group,
                 all_filters, all_columns, show_customization)
             # make sure that the sorting doesn't get lost either
@@ -790,7 +790,7 @@ class IndexTemplate(TemplateFunctions):
         # display the filter section
         if (show_display_form and hasattr(self.instance, 'FILTER_POSITION') and
                 self.instance.FILTER_POSITION in ('top and bottom', 'bottom')):
-            w('<form action="%s">\n'%self.classname)
+            w('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
             self.filter_section(filter_template, filter, columns, group,
                 all_filters, all_columns, show_customization)
             # make sure that the sorting doesn't get lost either
@@ -1000,7 +1000,7 @@ class ItemTemplate(TemplateFunctions):
             #  designators...
 
         w = self.client.write
-        w('<form action="%s%s" method="POST" enctype="multipart/form-data">'%(
+        w('<form onSubmit="return submit_once()" action="%s%s" method="POST" enctype="multipart/form-data">'%(
             self.classname, nodeid))
         s = open(os.path.join(self.templates, self.classname+'.item')).read()
         replace = ItemTemplateReplace(self.globals, locals(), self.cl, nodeid)
@@ -1030,7 +1030,7 @@ class NewItemTemplate(TemplateFunctions):
             s = open(os.path.join(self.templates, c+'.newitem')).read()
         except IOError:
             s = open(os.path.join(self.templates, c+'.item')).read()
-        w('<form action="new%s" method="POST" enctype="multipart/form-data">'%c)
+        w('<form onSubmit="return submit_once()" action="new%s" method="POST" enctype="multipart/form-data">'%c)
         for key in form.keys():
             if key[0] == ':':
                 value = form[key].value
@@ -1043,6 +1043,9 @@ class NewItemTemplate(TemplateFunctions):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.71  2002/01/23 06:15:24  richard
+# real (non-string, duh) sorting of lists by node id
+#
 # Revision 1.70  2002/01/23 05:47:57  richard
 # more HTML template cleanup and unit tests
 #