Commits

Anonymous committed 32d8153

nested renderers added. Tests broken atm

  • Participants
  • Parent commits 5f6b6f5

Comments (0)

Files changed (1)

File pyramid_simpleform/renderers.py

 from webhelpers.html import tags
 from webhelpers.html.builder import HTML
 
-class FormRenderer(object):
-    """
-    A simple form helper. Uses WebHelpers to render individual
-    form widgets: see the WebHelpers library for more information
-    on individual widgets.
-    """
 
-    def __init__(self, form, csrf_field='_csrf'):
+class Renderer(object):
 
-        self.form = form
-        self.data = self.form.data
-        self.context = []
-        self.csrf_field = csrf_field
+    def __init__(self, data, errors, id_prefix=None):
+        self.data = data
+        self.errors = errors
+        self.id_prefix = id_prefix
 
-    def value(self, name, default=None):
-        try:
-            context = self.context[0]  
-            data = self.data.get(context, {})
-        except IndexError:
-            data = self.data
+    def get_sequence(self, name, min_entries=0):
 
-        return data.get(name, default)
+        data = self.value(name, [])
+        errors = self.errors.get(name, {})
 
-    def begin(self, url=None, **attrs):
-        """
-        Creates the opening <form> tags.
+        return SequenceRenderer(name, data, errors, min_entries=min_entries)
 
-        By default URL will be current path.
-        """
-        url = url or self.form.request.path
-        multipart = attrs.pop('multipart', self.form.multipart)
-        return tags.form(url, multipart=multipart, **attrs)
+    def get_mapping(self, name):
 
-    def end(self):
-        """
-        Closes the form, i.e. outputs </form>.
-        """
-        return tags.end_form()
-    
-    def csrf(self, name=None):
-        """
-        Returns the CSRF hidden input. Creates new CSRF token
-        if none has been assigned yet.
+        data = self.value(name, {})
+        errors = self.errors(name, [])
 
-        The name of the hidden field is **_csrf** by default.
-        """
-        name = name or self.csrf_field
-
-        token = self.form.request.session.get_csrf_token()
-        if token is None:
-            token = self.form.request.session.new_csrf_token()
-
-        return self.hidden(name, value=token)
-
-    def csrf_token(self, name=None):
-        """
-        Convenience function. Returns CSRF hidden tag inside hidden DIV.
-        """
-        return HTML.tag("div", self.csrf(name), style="display:none;")
-
-    def start_hidden_tag(self, type, name=None, id=''):
-        """
-        Renders peppercorn __start__ hidden tags with given values.
-
-        For example::
-
-            renderer.start_hidden_tag('mapping', 'series')
-            >>> <input type="hidden" name="__start__" value="series:mapping" />
-
-        :versionadded: 0.7
-        """
-
-        value = type
-        if name:
-            value = name + ":" + value
-
-        # push data stack
-        self.context.insert(0, name)
-
-        return HTML.tag(
-            "div", 
-            self.hidden('__start__', value, id=id), 
-            style="display:none;"
-        )
-
-    def start_mapping_tag(self, name=None, id=''):
-        return self.start_hidden_tag('mapping', name, id)
-
-    def start_sequence_tag(self, name=None, id=''):
-        return self.start_hidden_tag('sequence', name, id)
-
-    def end_hidden_tag(self, value=None, id=''):
-        """
-        Renders peppercorn __end__ hidden tag
-
-        For example::
-
-            renderer.end_hidden_tag()
-            >>> <input type="hidden" name="__end__" />
-
-        :versionadded: 0.7
-        """
-        self.context.pop()
-
-        return HTML.tag(
-            "div",
-            self.hidden('__end__', value, id=id),
-            style="display:none;"
-        )
-
-    def end_hidden_tags(self, num_tags):
-        """
-        Prints a number of peppercorn hidden __end__ tags
-
-        :versionadded: 0.7
-        """
-
-        rv = []
-
-        for i in xrange(num_tags):
-            rv.append(self.hidden('__end__', id=''))
-            self.context.pop()
-
-        return HTML.tag(
-            "div",
-            tags.literal("".join(rv)),
-            style="display:none;"
-        )
-
-    def hidden_tag(self, *names):
-        """
-        Convenience for printing all hidden fields in a form inside a 
-        hidden DIV. Will also render the CSRF hidden field.
-
-        :versionadded: 0.4
-        """
-        inputs = [self.hidden(name) for name in names]
-        inputs.append(self.csrf())
-        return HTML.tag("div", 
-                        tags.literal("".join(inputs)), 
-                        style="display:none;")
+        return MappingRenderer(name, data, errors)
 
     def text(self, name, value=None, id=None, **attrs):
         """
         """
         Outputs hidden input.
         """
+        if value is None:
+            value = self.value(name)
+
         return tags.hidden(
             name, 
-            self.value(name, value), 
+            value, 
             self._get_id(id, name), 
             **attrs
         )
         """
         Shortcut for **self.form.is_error(name)**
         """
-        return self.form.is_error(name)
+        return name in self.errors
 
     def errors_for(self, name):
         """
         Shortcut for **self.form.errors_for(name)**
         """
-        return self.form.errors_for(name)
+        return self.errors 
 
     def all_errors(self):
         """
         Shortcut for **self.form.all_errors()**
         """
-        return self.form.all_errors()
+        return self.errors.values()
 
     def errorlist(self, name=None, **attrs):
         """
         `label` : if **None**, uses the capitalized field name.
         """
         if 'for_' not in attrs:
-            attrs['for_'] = name
+            for_ = name.lower()
+            if self.id_prefix:
+                for_ = self.id_prefix + for_
+            attrs['for_'] = for_
+            
         label = label or name.capitalize()
         return HTML.tag("label", label, **attrs)
 
+    def value(self, name, default=None):
+        return self.data.get(name, default)
+
     def _get_id(self, id, name):
         if id is None:
             id = name
+            if self.id_prefix:
+                id = self.id_prefix + id
         return id
 
+
+class FormRenderer(Renderer):
+    """
+    A simple form helper. Uses WebHelpers to render individual
+    form widgets: see the WebHelpers library for more information
+    on individual widgets.
+    """
+
+    def __init__(self, form, csrf_field='_csrf', id_prefix=None):
+
+        self.form = form
+        self.csrf_field = csrf_field
+
+        super(FormRenderer, self).__init__(
+            self.form.data, 
+            self.form.errors, 
+            id_prefix,
+        )
+
+
+    def begin(self, url=None, **attrs):
+        """
+        Creates the opening <form> tags.
+
+        By default URL will be current path.
+        """
+        url = url or self.form.request.path
+        multipart = attrs.pop('multipart', self.form.multipart)
+        return tags.form(url, multipart=multipart, **attrs)
+
+    def end(self):
+        """
+        Closes the form, i.e. outputs </form>.
+        """
+        return tags.end_form()
+    
+    def csrf(self, name=None):
+        """
+        Returns the CSRF hidden input. Creates new CSRF token
+        if none has been assigned yet.
+
+        The name of the hidden field is **_csrf** by default.
+        """
+        name = name or self.csrf_field
+
+        token = self.form.request.session.get_csrf_token()
+        if token is None:
+            token = self.form.request.session.new_csrf_token()
+
+        return self.hidden(name, value=token)
+
+    def csrf_token(self, name=None):
+        """
+        Convenience function. Returns CSRF hidden tag inside hidden DIV.
+        """
+        return HTML.tag("div", self.csrf(name), style="display:none;")
+
+    def hidden_tag(self, *names):
+        """
+        Convenience for printing all hidden fields in a form inside a 
+        hidden DIV. Will also render the CSRF hidden field.
+
+        :versionadded: 0.4
+        """
+        inputs = [self.hidden(name) for name in names]
+        inputs.append(self.csrf())
+        return HTML.tag("div", 
+                        tags.literal("".join(inputs)), 
+                        style="display:none;")
+
+
+class SequenceRenderer(Renderer):
+
+    def __init__(self, name, data, errors, id_prefix=None, min_entries=0):
+
+        self.name = name
+        
+        num_entries = min_entries - len(data)
+        if num_entries > 0:
+            for i in xrange(num_entries):
+                data.append({})
+
+        super(SequenceRenderer, self).__init__(
+            data,
+            errors,
+            id_prefix,
+        )
+
+    def begin(self):
+        return self.hidden('__start__', value='%s:sequence' % self.name, id='')
+
+    def end(self):
+        return self.hidden('__end__', value='%s:sequence' % self.name, id='')
+
+    def __iter__(self):
+        
+        # what kind of data we dealing with ?
+    
+        for i, d in enumerate(self.data):
+
+            if not isinstance(d, dict):
+                d = {self.name : d}
+
+            errors = [] # to be determined
+            id_prefix = "%d-" % i
+
+            yield MappingRenderer(self.name, d, errors, id_prefix=id_prefix) 
+
+
+class MappingRenderer(Renderer):
+
+    def __init__(self, name, data, errors, id_prefix=None):
+
+        self.name = name
+
+        super(MappingRenderer, self).__init__(
+            data,
+            errors,
+            id_prefix,
+        )
+
+    def begin(self, name=None):
+
+        name = name or self.name
+
+        return self.hidden('__start__', value='%s:mapping' % name, id='')
+
+    def end(self, name=None):
+
+        name = name or self.name
+
+        return self.hidden('__end__', value='%s:mapping' % name, id='')
+
+