Code

Applied Stefan Seefeld's html4/xhtml patch with some changes.
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Sat, 6 Dec 2003 00:00:54 +0000 (00:00 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Sat, 6 Dec 2003 00:00:54 +0000 (00:00 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2019 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
doc/customizing.txt
doc/index.txt
roundup/cgi/templating.py
templates/classic/config.py
templates/minimal/config.py

index fd2a449d930ca88d833dfb7a1c95a2a01a3358dc..685ab7058171f5f12d0cf819c4e86dd818fcf815 100644 (file)
@@ -21,6 +21,8 @@ Feature:
   828963)
 - ignore incoming email with "Precedence: bulk" (sf patch 843489)
 - use HTTP 'Content-Length' header (modified sf patch 844577)
+- HTML generated is now HTML4 (or optionally XHTML) compliant (sf feature
+  814314 and sf patch 834620)
 
 Fixed:
 - mysql documentation fixed to note requirement of 4.0+ and InnoDB
index 0136601910ec8a56f34d249378bd9c36dd0a9db6..137ca79761d0ba10a48398f62121b1522103746b 100644 (file)
@@ -2,7 +2,7 @@
 Customising Roundup
 ===================
 
-:Version: $Revision: 1.105 $
+:Version: $Revision: 1.106 $
 
 .. This document borrows from the ZopeBook section on ZPT. The original is at:
    http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -180,6 +180,11 @@ The configuration variables available are:
  Default class to use in the mailgw if one isn't supplied in email
  subjects. To disable, comment out the variable below or leave it blank.
 
+**HTML_VERSION** -  ``'html4'`` or ``'xhtml'``
+ HTML version to generate. The templates are html4 by default. If you
+ wish to make them xhtml, then you'll need to change this var to 'xhtml'
+ too so all auto-generated HTML is compliant.
+
 The default config.py is given below - as you
 can see, the MAIL_DOMAIN must be edited before any interaction with the
 tracker is attempted.::
@@ -255,6 +260,11 @@ tracker is attempted.::
     MAIL_DEFAULT_CLASS = 'issue'   # use "issue" class by default
     #MAIL_DEFAULT_CLASS = ''        # disable (or just comment the var out)
 
+    # HTML version to generate. The templates are html4 by default. If you
+    # wish to make them xhtml, then you'll need to change this var to 'xhtml'
+    # too so all auto-generated HTML is compliant.
+    HTML_VERSION = 'html4'         # either 'html4' or 'xhtml'
+
     # 
     # SECURITY DEFINITIONS
     #
@@ -1054,6 +1064,10 @@ returning.
 Default templates
 -----------------
 
+The default templates are html4 compliant. If you wish to change them to be
+xhtml compliant, you'll need to change the ``HTML_VERSION`` configuration
+variable in ``config.py`` to ``'xhtml'`` instead of ``'html4'``.
+
 Most customisation of the web view can be done by modifying the
 templates in the tracker ``'html'`` directory. There are several types
 of files in there. The *minimal* template includes:
index fac1c91c84424afecac01d4ede346178116d5506..953ecf65af8a5986d65de9eaa92d71d9d3eadca1 100644 (file)
@@ -49,6 +49,7 @@ implement this system on their time.
 
 Thanks also to the many people on the mailing list, in the sourceforge
 project and those who just report bugs:
+Thomas Arendsen Hein,
 Anthony Baxter,
 Cameron Blackwood,
 Jeff Blaine,
@@ -66,7 +67,6 @@ Johannes Gijsbers,
 Gus Gollings,
 Dan Grassi,
 Engelbert Gruber,
-Thomas Arendsen Hein,
 Juergen Hermann,
 Tobias Hunger,
 James Kew,
index 537a1cbf1e3aa251ac7db48ad8102df63beda2df..6fa573e9d26483c066c576942a7a6f0788913b8b 100644 (file)
@@ -24,6 +24,14 @@ from roundup.cgi.PageTemplates.Expressions import getEngine
 from roundup.cgi.TAL.TALInterpreter import TALInterpreter
 from roundup.cgi import ZTUtils
 
+def input_html4(**attrs):
+    """Generate an 'input' (html4) element with given attributes"""
+    return '<input %s>'%' '.join(['%s="%s"'%item for item in attrs.items()])
+
+def input_xhtml(**attrs):
+    """Generate an 'input' (xhtml) element with given attributes"""
+    return '<input %s/>'%' '.join(['%s="%s"'%item for item in attrs.items()])
+
 class NoTemplate(Exception):
     pass
 
@@ -295,6 +303,14 @@ class HTMLClass(HTMLPermissions):
         self._klass = self._db.getclass(self.classname)
         self._props = self._klass.getprops()
 
+        html_version = 'html4'
+        if hasattr(self._client.instance.config, 'HTML_VERSION'):
+            html_version = self._client.instance.config.HTML_VERSION
+        if html_version == 'xhtml':
+            self.input = input_xhtml
+        else:
+            self.input = input_html4
+
     def __repr__(self):
         return '<HTMLClass(0x%x) %s>'%(id(self), self.classname)
 
@@ -478,8 +494,8 @@ class HTMLClass(HTMLPermissions):
     def submit(self, label="Submit New Entry"):
         ''' Generate a submit button (and action hidden element)
         '''
-        return '  <input type="hidden" name="@action" value="new">\n'\
-        '  <input type="submit" name="submit" value="%s">'%label
+        return self.input(type="hidden",name="@action",value="new") + '\n' + \
+               self.input(type="submit",name="submit",value=label)
 
     def history(self):
         return 'New node - no history'
@@ -556,8 +572,8 @@ class HTMLItem(HTMLPermissions):
     def submit(self, label="Submit Changes"):
         ''' Generate a submit button (and action hidden element)
         '''
-        return '  <input type="hidden" name="@action" value="edit">\n'\
-        '  <input type="submit" name="submit" value="%s">'%label
+        return self.input(type="hidden",name="@action",value="edit") + '\n' + \
+               self.input(type="submit",name="submit",value=label)
 
     def journal(self, direction='descending'):
         ''' Return a list of HTMLJournalEntry instances.
@@ -844,6 +860,15 @@ class HTMLProperty:
             self._formname = '%s%s@%s'%(classname, nodeid, name)
         else:
             self._formname = name
+
+        html_version = 'html4'
+        if hasattr(self._client.instance.config, 'HTML_VERSION'):
+            html_version = self._client.instance.config.HTML_VERSION
+        if html_version == 'xhtml':
+            self.input = input_xhtml
+        else:
+            self.input = input_html4
+        
     def __repr__(self):
         return '<HTMLProperty(0x%x) %s %r %r>'%(id(self), self._formname,
             self._prop, self._value)
@@ -918,7 +943,7 @@ class StringHTMLProperty(HTMLProperty):
         else:
             value = cgi.escape(str(self._value))
             value = '&quot;'.join(value.split('"'))
-        return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size)
+        return self.input(name=self._formname,value=value,size=size)
 
     def multiline(self, escape=0, rows=5, cols=40):
         ''' Render a multiline form edit field for the property
@@ -958,15 +983,15 @@ class PasswordHTMLProperty(HTMLProperty):
     def field(self, size = 30):
         ''' Render a form edit field for the property.
         '''
-        return '<input type="password" name="%s" size="%s">'%(self._formname, size)
+        return self.input(type="password", name=self._formname, size=size)
 
     def confirm(self, size = 30):
         ''' Render a second form edit field for the property, used for 
             confirmation that the user typed the password correctly. Generates
             a field with name "@confirm@name".
         '''
-        return '<input type="password" name="@confirm@%s" size="%s">'%(
-            self._formname, size)
+        return self.input(type="password", name="@confirm@%s"%self._formname,
+            size=size)
 
 class NumberHTMLProperty(HTMLProperty):
     def plain(self):
@@ -982,7 +1007,7 @@ class NumberHTMLProperty(HTMLProperty):
         else:
             value = cgi.escape(str(self._value))
             value = '&quot;'.join(value.split('"'))
-        return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size)
+        return self.input(name=self._formname,value=value,size=size)
 
     def __int__(self):
         ''' Return an int of me
@@ -1007,14 +1032,16 @@ class BooleanHTMLProperty(HTMLProperty):
         ''' Render a form edit field for the property
         '''
         checked = self._value and "checked" or ""
-        s = '<input type="radio" name="%s" value="yes" %s>Yes'%(self._formname,
-            checked)
-        if checked:
-            checked = ""
+        if self._value:
+            s = self.input(type="radio",name=self._formname,value="yes",checked="checked")
+            s += 'Yes'
+            s +=self.input(type="radio",name=self._formname,value="no")
+            s += 'No'
         else:
-            checked = "checked"
-        s += '<input type="radio" name="%s" value="no" %s>No'%(self._formname,
-            checked)
+            s = self.input(type="radio",name=self._formname,value="yes")
+            s += 'Yes'
+            s +=self.input(type="radio",name=self._formname,value="no",checked="checked")
+            s += 'No'
         return s
 
 class DateHTMLProperty(HTMLProperty):
@@ -1042,7 +1069,7 @@ class DateHTMLProperty(HTMLProperty):
         else:
             value = cgi.escape(str(self._value.local(self._db.getUserTimezone())))
             value = '&quot;'.join(value.split('"'))
-        return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size)
+        return self.input(name=self._formname,value=value,size=size)
 
     def reldate(self, pretty=1):
         ''' Render the interval between the date and now.
@@ -1099,7 +1126,7 @@ class IntervalHTMLProperty(HTMLProperty):
         else:
             value = cgi.escape(str(self._value))
             value = '&quot;'.join(value.split('"'))
-        return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size)
+        return self.input(name=self._formname,value=value,size=size)
 
 class LinkHTMLProperty(HTMLProperty):
     ''' Link HTMLProperty
@@ -1155,7 +1182,7 @@ class LinkHTMLProperty(HTMLProperty):
         l = ['<select name="%s">'%self._formname]
         k = linkcl.labelprop(1)
         if self._value is None:
-            s = 'selected '
+            s = 'selected="selected" '
         else:
             s = ''
         l.append(_('<option %svalue="-1">- no selection -</option>')%s)
@@ -1171,7 +1198,7 @@ class LinkHTMLProperty(HTMLProperty):
             # figure if this option is selected
             s = ''
             if optionid == self._value:
-                s = 'selected '
+                s = 'selected="selected" '
 
             # figure the label
             if showid:
@@ -1200,7 +1227,7 @@ class LinkHTMLProperty(HTMLProperty):
         k = linkcl.labelprop(1)
         s = ''
         if value is None:
-            s = 'selected '
+            s = 'selected="selected" '
         l.append(_('<option %svalue="-1">- no selection -</option>')%s)
         if linkcl.getprops().has_key('order'):  
             sort_on = ('+', 'order')
@@ -1219,7 +1246,7 @@ class LinkHTMLProperty(HTMLProperty):
             # figure if this option is selected
             s = ''
             if value in [optionid, option]:
-                s = 'selected '
+                s = 'selected="selected" '
 
             # figure the label
             if showid:
@@ -1315,7 +1342,7 @@ class MultilinkHTMLProperty(HTMLProperty):
             k = linkcl.labelprop(1)
             value = [linkcl.get(v, k) for v in value]
         value = cgi.escape(','.join(value))
-        return '<input name="%s" size="%s" value="%s">'%(self._formname, size, value)
+        return self.input(name=self._formname,size=size,value=value)
 
     def menu(self, size=None, height=None, showid=0, additional=[],
             **conditions):
@@ -1342,7 +1369,7 @@ class MultilinkHTMLProperty(HTMLProperty):
             # figure if this option is selected
             s = ''
             if optionid in value or option in value:
-                s = 'selected '
+                s = 'selected="selected" '
 
             # figure the label
             if showid:
@@ -1451,6 +1478,14 @@ class HTMLRequest:
         # the special char to use for special vars
         self.special_char = '@'
 
+        html_version = 'html4'
+        if hasattr(self.client.instance.config, 'HTML_VERSION'):
+            html_version = self.client.instance.config.HTML_VERSION
+        if html_version == 'xhtml':
+            self.input = input_xhtml
+        else:
+            self.input = input_html4
+
         self._post_init()
 
     def _post_init(self):
@@ -1603,7 +1638,7 @@ env: %(env)s
         ''' return the current index args as form elements '''
         l = []
         sc = self.special_char
-        s = '<input type="hidden" name="%s" value="%s">'
+        s = self.input(type="hidden",name="%s",value="%s")
         if columns and self.columns:
             l.append(s%(sc+'columns', ','.join(self.columns)))
         if sort and self.sort[1] is not None:
index 8f9057d340cbd076e813bcf2f0aa8d2b0cf09f4e..e6f61334bcdbf579d020f4646c9734946b935791 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: config.py,v 1.3 2003-04-24 07:19:59 richard Exp $
+# $Id: config.py,v 1.4 2003-12-06 00:00:54 richard Exp $
 
 import os
 
@@ -106,6 +106,11 @@ EMAIL_LEAVE_BODY_UNCHANGED = 'no'   # either 'yes' or 'no'
 MAIL_DEFAULT_CLASS = 'issue'   # use "issue" class by default
 #MAIL_DEFAULT_CLASS = ''        # disable (or just comment the var out)
 
+# HTML version to generate. The templates are html4 by default. If you
+# wish to make them xhtml, then you'll need to change this var to 'xhtml'
+# too so all auto-generated HTML is compliant.
+HTML_VERSION = 'html4'         # either 'html4' or 'xhtml'
+
 # 
 # SECURITY DEFINITIONS
 #
index f2d3f677dad655dcb3448054553a98d7c7302a79..a3ceeb601a1d1359f6610b82ebc116b8c16b297c 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: config.py,v 1.2 2003-04-24 07:20:00 richard Exp $
+# $Id: config.py,v 1.3 2003-12-06 00:00:54 richard Exp $
 
 import os
 
@@ -110,4 +110,9 @@ EMAIL_LEAVE_BODY_UNCHANGED = 'no'   # either 'yes' or 'no'
 MAIL_DEFAULT_CLASS = 'issue'   # use "issue" class by default
 #MAIL_DEFAULT_CLASS = ''        # disable (or just comment the var out)
 
+# HTML version to generate. The templates are html4 by default. If you
+# wish to make them xhtml, then you'll need to change this var to 'xhtml'
+# too so all auto-generated HTML is compliant.
+HTML_VERSION = 'html4'         # either 'html4' or 'xhtml'
+
 # vim: set filetype=python ts=4 sw=4 et si