1515# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717#
18- # $Id: htmltemplate.py,v 1.64 2002-01-21 03:25:59 richard Exp $
18+ # $Id: htmltemplate.py,v 1.65 2002-01-22 00:12:06 richard Exp $
1919
2020__doc__ = """
2121Template engine.
@@ -109,62 +109,82 @@ def do_stext(self, property, escape=0):
109109 return s
110110 return StructuredText (s ,level = 1 ,header = 0 )
111111
112- def do_field (self , property , size = None , height = None , showid = 0 ):
113- ''' display a property like the plain displayer, but in a text field
114- to be edited
112+ def determine_value (self , property ):
113+ '''determine the value of a property using the node, form or
114+ filterspec
115115 '''
116- if not self .nodeid and self .form is None and self .filterspec is None :
117- return _ ('[Field: not called from item]' )
118116 propclass = self .properties [property ]
119- if (isinstance (propclass , hyperdb .Link ) or
120- isinstance (propclass , hyperdb .Multilink )):
121- linkcl = self .db .classes [propclass .classname ]
122- def sortfunc (a , b , cl = linkcl ):
123- if cl .getprops ().has_key ('order' ):
124- sort_on = 'order'
125- else :
126- sort_on = cl .labelprop ()
127- r = cmp (cl .get (a , sort_on ), cl .get (b , sort_on ))
128- return r
129117 if self .nodeid :
130118 value = self .cl .get (self .nodeid , property , None )
131- # TODO: remove this from the code ... it's only here for
132- # handling schema changes, and they should be handled outside
133- # of this code...
134119 if isinstance (propclass , hyperdb .Multilink ) and value is None :
135- value = []
120+ return []
121+ return value
136122 elif self .filterspec is not None :
137123 if isinstance (propclass , hyperdb .Multilink ):
138- value = self .filterspec .get (property , [])
124+ return self .filterspec .get (property , [])
139125 else :
140- value = self .filterspec .get (property , '' )
126+ return self .filterspec .get (property , '' )
127+ # TODO: pull the value from the form
128+ if isinstance (propclass , hyperdb .Multilink ):
129+ return []
141130 else :
142- # TODO: pull the value from the form
143- if isinstance (propclass , hyperdb .Multilink ): value = []
144- else : value = ''
131+ return ''
132+
133+ def make_sort_function (self , classname ):
134+ '''Make a sort function for a given class
135+ '''
136+ linkcl = self .db .classes [classname ]
137+ if linkcl .getprops ().has_key ('order' ):
138+ sort_on = 'order'
139+ else :
140+ sort_on = linkcl .labelprop ()
141+ def sortfunc (a , b , linkcl = linkcl , sort_on = sort_on ):
142+ return cmp (linkcl .get (a , sort_on ), linkcl .get (b , sort_on ))
143+ return sortfunc
144+
145+ def do_field (self , property , size = None , showid = 0 ):
146+ ''' display a property like the plain displayer, but in a text field
147+ to be edited
148+
149+ Note: if you would prefer an option list style display for
150+ link or multilink editing, use menu().
151+ '''
152+ if not self .nodeid and self .form is None and self .filterspec is None :
153+ return _ ('[Field: not called from item]' )
154+
155+ if size is None :
156+ size = 30
157+
158+ propclass = self .properties [property ]
159+
160+ # get the value
161+ value = self .determine_value (property )
162+
163+ # now display
145164 if (isinstance (propclass , hyperdb .String ) or
146165 isinstance (propclass , hyperdb .Date ) or
147166 isinstance (propclass , hyperdb .Interval )):
148- size = size or 30
149167 if value is None :
150168 value = ''
151169 else :
152170 value = cgi .escape (str (value ))
153171 value = '"' .join (value .split ('"' ))
154172 s = '<input name="%s" value="%s" size="%s">' % (property , value , size )
155173 elif isinstance (propclass , hyperdb .Password ):
156- size = size or 30
157174 s = '<input type="password" name="%s" size="%s">' % (property , size )
158175 elif isinstance (propclass , hyperdb .Link ):
176+ sortfunc = self .make_sort_function (propclass .classname )
177+ linkcl = self .db .classes [propclass .classname ]
178+ options = linkcl .list ()
179+ options .sort (sortfunc )
180+ # TODO: make this a field display, not a menu one!
159181 l = ['<select name="%s">' % property ]
160182 k = linkcl .labelprop ()
161183 if value is None :
162184 s = 'selected '
163185 else :
164186 s = ''
165187 l .append (_ ('<option %svalue="-1">- no selection -</option>' )% s )
166- options = linkcl .list ()
167- options .sort (sortfunc )
168188 for optionid in options :
169189 option = linkcl .get (optionid , k )
170190 s = ''
@@ -176,37 +196,46 @@ def sortfunc(a, b, cl=linkcl):
176196 lab = option
177197 if size is not None and len (lab ) > size :
178198 lab = lab [:size - 3 ] + '...'
199+ lab = cgi .escape (lab )
179200 l .append ('<option %svalue="%s">%s</option>' % (s , optionid , lab ))
180201 l .append ('</select>' )
181202 s = '\n ' .join (l )
182203 elif isinstance (propclass , hyperdb .Multilink ):
204+ sortfunc = self .make_sort_function (propclass .classname )
205+ linkcl = self .db .classes [propclass .classname ]
183206 list = linkcl .list ()
184207 list .sort (sortfunc )
185208 l = []
186209 # map the id to the label property
187- # TODO: allow reversion to the older <select> box style display
188210 if not showid :
189211 k = linkcl .labelprop ()
190212 value = [linkcl .get (v , k ) for v in value ]
191- if size is None :
192- size = '10'
193- l .insert (0 ,'<input name="%s" size="%s" value="%s">' % (property ,
194- size , ',' .join (value )))
195- s = "<br>\n " .join (l )
213+ value = cgi .escape (',' .join (value ))
214+ s = '<input name="%s" size="%s" value="%s">' % (property , size , value )
196215 else :
197216 s = _ ('Plain: bad propclass "%(propclass)s"' )% locals ()
198217 return s
199218
200219 def do_menu (self , property , size = None , height = None , showid = 0 ):
201220 ''' for a Link property, display a menu of the available choices
202221 '''
222+ if not self .nodeid and self .form is None and self .filterspec is None :
223+ return _ ('[Field: not called from item]' )
224+
203225 propclass = self .properties [property ]
204- if self .nodeid :
205- value = self .cl .get (self .nodeid , property )
206- else :
207- # TODO: pull the value from the form
208- if isinstance (propclass , hyperdb .Multilink ): value = []
209- else : value = None
226+
227+ # make sure this is a link property
228+ if not (isinstance (propclass , hyperdb .Link ) or
229+ isinstance (propclass , hyperdb .Multilink )):
230+ return _ ('[Menu: not a link]' )
231+
232+ # sort function
233+ sortfunc = self .make_sort_function (propclass .classname )
234+
235+ # get the value
236+ value = self .determine_value (property )
237+
238+ # display
210239 if isinstance (propclass , hyperdb .Link ):
211240 linkcl = self .db .classes [propclass .classname ]
212241 l = ['<select name="%s">' % property ]
@@ -215,21 +244,31 @@ def do_menu(self, property, size=None, height=None, showid=0):
215244 if value is None :
216245 s = 'selected '
217246 l .append (_ ('<option %svalue="-1">- no selection -</option>' )% s )
218- for optionid in linkcl .list ():
247+ options = linkcl .list ()
248+ options .sort (sortfunc )
249+ for optionid in options :
219250 option = linkcl .get (optionid , k )
220251 s = ''
221252 if optionid == value :
222253 s = 'selected '
223- l .append ('<option %svalue="%s">%s</option>' % (s , optionid , option ))
254+ if showid :
255+ lab = '%s%s: %s' % (propclass .classname , optionid , option )
256+ else :
257+ lab = option
258+ if size is not None and len (lab ) > size :
259+ lab = lab [:size - 3 ] + '...'
260+ lab = cgi .escape (lab )
261+ l .append ('<option %svalue="%s">%s</option>' % (s , optionid , lab ))
224262 l .append ('</select>' )
225263 return '\n ' .join (l )
226264 if isinstance (propclass , hyperdb .Multilink ):
227265 linkcl = self .db .classes [propclass .classname ]
228- list = linkcl .list ()
229- height = height or min (len (list ), 7 )
266+ options = linkcl .list ()
267+ options .sort (sortfunc )
268+ height = height or min (len (options ), 7 )
230269 l = ['<select multiple name="%s" size="%s">' % (property , height )]
231270 k = linkcl .labelprop ()
232- for optionid in list :
271+ for optionid in options :
233272 option = linkcl .get (optionid , k )
234273 s = ''
235274 if optionid in value :
@@ -240,7 +279,9 @@ def do_menu(self, property, size=None, height=None, showid=0):
240279 lab = option
241280 if size is not None and len (lab ) > size :
242281 lab = lab [:size - 3 ] + '...'
243- l .append ('<option %svalue="%s">%s</option>' % (s , optionid , option ))
282+ lab = cgi .escape (lab )
283+ l .append ('<option %svalue="%s">%s</option>' % (s , optionid ,
284+ lab ))
244285 l .append ('</select>' )
245286 return '\n ' .join (l )
246287 return _ ('[Menu: not a link]' )
@@ -1002,6 +1043,9 @@ def render(self, form):
10021043
10031044#
10041045# $Log: not supported by cvs2svn $
1046+ # Revision 1.64 2002/01/21 03:25:59 richard
1047+ # oops
1048+ #
10051049# Revision 1.63 2002/01/21 02:59:10 richard
10061050# Fixed up the HTML display of history so valid links are actually displayed.
10071051# Oh for some unit tests! :(
0 commit comments