source: cows_wps/trunk/cows_wps/renderer/form_renderer.py @ 7535

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows_wps/trunk/cows_wps/renderer/form_renderer.py@7535
Revision 7535, 6.6 KB checked in by astephen, 11 years ago (diff)

Fixed to async argument handler working.

Line 
1import os
2
3from genshi.template import TemplateLoader
4from genshi.builder import * 
5from genshi import HTML
6
7
8class FormRenderer(object):
9    """
10    A set of rendering methods for HTML forms.
11    """
12
13    def __init__(self):
14        # Instantiate Genshi template loader
15        self.templateLoader = TemplateLoader(
16           os.path.join(os.getcwd(), 'cows_wps/templates'),
17           auto_reload=True)
18
19    def htmlify(self, html): return HTML(html)
20
21    def renderRadioButton(self, name, is_boolean = True, values = None):
22        """
23        Returns HTML of radio button.
24        """
25        if is_boolean == True:
26            values = ("true", "false")
27
28        html = ""
29        for value in values:
30            html += """         <input type="radio" id="%s" name="%s" value="%s" />
31                <label for="%s">%s</label><br />\n"""   
32
33        return html
34
35    def renderTextInput(self, name, dtype, optional = False, default = None, multiple = False):
36        """
37        Returns HTML for text input including onChange validator.
38        optional is a boolean.
39
40        Populates with default value if not None.
41        If multiple is true then makes box bigger.
42        """
43        if default == None: default = ""
44
45        allowed_dtypes = ("any", "float", "int", "string", "datetime")
46        js_opt = str(optional).lower()
47
48        if dtype not in allowed_dtypes:
49            raise Exception("Invalid type sent to FormRenderer.renderTextInput(): %s" % dtype)
50
51        validators = {"int": ("/^[0-9]+$/", "The %s input must be an integer." % name), 
52                      "float": ("/^[-+]?([0-9]*\.[0-9]+|[0-9]+)$/", "The %s input must be a decimal number." % name),
53                      "string": ("/[0-9a-zA-Z]+/", "The %s input must include text characters." % name),
54                      "any": ("/.*/", "No message."),
55                      "datetime": ("/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}/", "The %s input must be a date/time entry as follows YYYY-MM-DDThh:mm:ss (e.g. 2009-01-01T12:00:00)." % name)}
56
57        (regex, msg) = validators[dtype]
58
59        if multiple == True:
60            on_change = "validateTextAreaInput"; 
61        else:
62            on_change = "validateTextInput";
63
64        tag_contents = """name="%s" id="%s" value="%s" onChange="%s(this.value, %s, '%s', %s);" """ % (name, name, default, on_change, regex, msg, js_opt)
65
66        if multiple == True:
67            # Use textarea
68            html = """<textarea cols="50" rows="3" %s ></textarea>""" % tag_contents
69            html += """\n<script type="text/javascript">registerTextArea('%s');</script>""" % name
70
71            validator_type = "textarea"
72        else:
73            # Use text input
74            html = '<input type="text" %s />' % tag_contents
75            validator_type = "text"
76
77        html += """<br />\n<script type="text/javascript">addValidator('%s', '%s', %s, '%s', %s);</script>\n""" % (name, validator_type, regex, msg, js_opt)
78        return html
79
80    def renderSelectList(self, name, values, optional = False, multiple = False, 
81                         option_names = None, selected = None, size = 1):
82        """
83        Returns HTML for select list.
84
85        If optional is True then add an extra option called "-- Please select --".
86        """
87        # Do some checks
88        if option_names == None:
89            option_names = values[:]
90       
91        if optional == True:
92            values.insert(0, "")
93            option_names.insert(0, "-- Please select --")
94
95        if len(values) != len(option_names):
96            raise Exception("Length of 'values' and 'option_names' sent to renderSelectList() must be the same and are not.")
97
98        multiple_string = ""
99        multiple_msg = "one"
100
101        if multiple == True:
102            multiple_string = 'multiple="multiple"'
103            multiple_msg = "at least one"
104
105        html = """<select %s name="%s" id="%s">\n""" % (multiple_string, name, name)
106       
107        for (i, value) in enumerate(values):
108            option_name = option_names[i]
109
110#            html += "%s--%s++%s.." % (i, value, selected)
111            # FIXME: Does not pick up submitted value here from 'selected' arg.
112            selected_flag = ""
113            if selected == value:
114                selected_flag = 'selected="selected"' 
115
116            html += """ <option %s value="%s">%s</option>\n""" % (selected_flag, value, option_name)
117
118        html += "</select>\n"
119
120        msg = "Please ensure you have selected %s entry for the %s input." % (multiple_msg, name)
121        js_opt = str(optional).lower()
122        html += """\n<script type="text/javascript">addValidator('%s', '%s', %s, '%s', %s);</script>\n""" % (name, "select", "null", msg, js_opt)
123        return html
124
125    def renderBBox(self, name, extent):
126        """
127        Renders a bounding box and (west, south, east, north) selectors.
128        ``extent`` is received as a string of "west|south|east|north".
129        """
130        if extent == False: extent = "-180|-90|180|90"
131        (w, s, e, n) = extent.split("|")
132
133        html = """    <div id="bounding_container">
134        <div> BBox = <span id="bbox_show_val"></span></div>
135        <div id="bounds_control_container"></div>
136        <div id="map_container">
137            <div id='map'></div>
138        </div>
139            <input type="hidden" name="%s" id="bbox_hidden_input" />
140            <script type="text/javascript">
141                var initial_extent = [%s, %s, %s, %s];
142                addValidator('bbox_hidden_input', 'bounding_box', '%s', 'Your selected spatial bounding box must overlap with the available extent of: (%s) as ("west|south|east|north").', false);
143            </script>
144        </div>
145        """ % (name, w, s, e, n, extent, extent)
146        return html     
147
148    def renderTypeAheadDirList(self, name, base_dir):
149        """
150        Renders type-ahead widget for directory listing.
151        """
152        html = """      <script type="text/javascript" src="/js/ext/jquery-1.3.2/jquery-1.3.2.js"></script>
153        <script type="text/javascript" src="/js/ui/type_ahead_dirs.js"></script>
154        <script type="text/javascript">
155                var current_list = false;
156                var abs_pos_%s = null;
157
158                $(document).ready(function(){
159                        initTypeAhead("%s", "type_ahead_for_%s", "%s");
160                        abs_pos_%s = type_ahead_div.offset();   
161                        positionRespDiv(abs_pos_%s);
162                });
163        </script>
164
165        <p>Press down button to fill with text...</p>
166        <div style="z-index: 1;">
167                <input type="text" id="%s" name="%s" value="" style="width: 505px; height: 25px;" onBlur="hideSuggestions();" onFocus="showSuggestions();" />
168        </div>
169        <div id="type_ahead_for_%s" style="width: 500px; background-color: yellow; border-style: solid; border-width: 1px; position: static;"></div>
170""" % (name, name, name, base_dir, name, name, name, name, name)
171        return html 
Note: See TracBrowser for help on using the repository browser.