FormUtil.py :  » Web-Frameworks » Aquarium » aquarium-2.3 » aquarium » widget » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Aquarium 
Aquarium » aquarium 2.3 » aquarium » widget » FormUtil.py
"""This module contains the FormUtil class."""

__docformat__ = "restructuredtext"

# Created: Mon May  3 13:22:08 PDT 2004
# Author: Bob VanZant
# Email: bob@norcalttora.com, jjinux@users.sourceforge.net
#
# Copyright (c) Bob VanZant.  All rights reserved.

import re

from aquarium.util.AquariumClass import AquariumClass
from aquarium.util.HasFriends import HasFriends


class FormUtil(AquariumClass, HasFriends):

    """This is a utility to build consistent HTML forms.

    The purpose of this class is not to "abstract" HTML.  Its purpose is to
    provide "macros" so that you can get things done more quickly and
    consistently.  If your needs are very generic, you can use high-level
    macros like ``field``.  In your needs are less generic, you can use
    middle-level macros like ``textField`` and ``label``.  At the bottom are
    very low-level macros like ``getErrorMsg`` and ``getDefault``.  Naturally,
    you can subclass this class as needed.

    This class also mixes in the ``HasFriends`` mixin.  That means if you need
    to add a new method ``fooField``, simply create a new module called
    ``aquarium.widget.formutil.fooField`` containing a function called
    ``fooField``.  The ``fooField`` function should accept a ``FormUtil``
    instance called ``self`` as its first argument (i.e. it *acts* like a
    method in this class).  Then ``fooField`` will *just work*.

    The following attributes are used:

    defaults
      This is a list of dicts.  When looking for a default value, the list will
      be traversed, and the first dict to define the given name will be used
      for the value.

    errors
      This is a dict where each key is a field name and each value is the error
      message associated with that field.  Fields that do not have an error
      will not be present in this dict.  If left to its default value in the
      constructor, I'll look in ``actionResults.errors``.  I'll look for
      ``actionResults`` in both ``ctx`` and ``session``.

    The following class attributes are used:

    labelClass
      This is the CSS class for labels.

    errorClass
      This is the CSS class for errors.

    """

    labelClass = "label"
    errorClass = "error"

    def __init__(self, ctx, defaults=None, errors=None):
        """Accept the arguments."""
        AquariumClass.__init__(self, ctx)
        if not defaults:
            defaults = []
        if not errors:
            try:
                errors = ctx.actionResults.errors
            except:
                pass
        if not errors:
            try:
                errors = ctx.session["actionResults"].errors
            except:
                pass
        if not errors:
            errors = {}
        self.defaults = defaults
        self.errors = errors

    def field(self, label, name, type, **attributes):
        """Build a field with a label in a table row.

        type
          This can be any "blah" for which there exists a "blahField".

        """
        label = self.label(name, label)
        field = getattr(self, "%sField" % type)(name, **attributes)
        return '<tr valign="top"><td>%s</td><td>%s</td></tr>' % (label, field)

    def textField(self, name, **attributes):
        """Returns a string representing a text field."""
        return self.inputField(name, "text", **attributes)

    def passwordField(self, name, providePasswordDefault=False, **attributes):
        """Returns a string representing a password field."""
        if not providePasswordDefault:
            attributes["value"] = ""
        return self.inputField(name, "password", **attributes)

    def fileField(self, name, **attributes):
        """Returns a string representing a file upload field."""
        return self.inputField(name, "file", **attributes)

    def radioField(self, name, value, **attributes):
        """Returns a string representing a radio button.

        value
          This will be used for the value attribute of the field.  It should
          not be confused with the value coming from ``self.defaults``.

        """
        if str(value) == str(self.getDefault(name)):
            attributes["checked"] = "checked"
        return self.inputField(name, "radio", value=value, **attributes)

    def checkBoxField(self, name, value, **attributes):
        """Returns a string representing a checkbox.

        value
          This will be used for the value attribute of the field.  It should
          not be confused with the value coming from ``self.defaults``.

        """
        if name.endswith('[]'):
            default = self.getDefault(name[:-len('[]')])
        else:
            default = self.getDefault(name)
        if isinstance(default, list):
            checked = str(value) in default
        else:
            checked = str(value) == str(default)
        if checked:
            attributes["checked"] = "checked"
        return self.inputField(name, "checkbox", value=value, **attributes)

    def inputField(self, name, type, **attributes):
        """Returns a string representing an input field of type ``type``."""
        htmlent = self._ctx.htmlent
        value = attributes.get("value", self.getDefault(name))
        className = self.ifError(name, self.errorClass)
        attributes.update({
            "name": htmlent(name),
            "type": type,
            "value": htmlent(value),
            "class": className
        })
        return "<input %s />" % self.attributes(attributes)

    def selectField(self, name, options, **attributes):
        """Returns a string representing a fully fledged select box.
                                                                                
        options
          See the option argument of ``optionField``.
                                                                                
        """
        htmlent = self._ctx.htmlent
        if name.endswith('[]'):
            default = self.getDefault(name[:-len('[]')])
        else:
            default = self.getDefault(name)
        attributes["name"] = htmlent(name)
        attributes["class"] = self.ifError(name, self.errorClass)
        return "\n".join(
            ['<select %s>' % self.attributes(attributes)] +
            [self.optionField(option, default)
             for option in options] +
            ['</select>']
        )

    def optionField(self, option, selectedValue):
        """Return an option for use within a select.
                                                                                
        option
          This is either a single value to be used as both the label
          and the value or a tuple of the form ``(label, value)``.
                                                                                
        """
        htmlent = self._ctx.htmlent
        if isinstance(option, tuple):
            (label, value) = option
        else:
            (label, value) = (option, option)
        selected = ""
        if isinstance(selectedValue, list):
            if str(value) in selectedValue:
                selected = ' selected="selected"'
        else:
            if str(value) == str(selectedValue):
                selected = ' selected="selected"'
        return '<option value="%s"%s>%s</option>' % (htmlent(value), selected,
                                                     htmlent(label))

    def textAreaField(self, name, **attributes):
        """Returns a string representing a textarea."""
        htmlent = self._ctx.htmlent
        attributes["name"] = htmlent(name)
        return "<textarea %s>%s</textarea>" % (self.attributes(attributes),
                                               htmlent(self.getDefault(name)))

    def attributes(self, attributes):
        """Return a set of HTML tag attributes."""
        return " ".join(['%s="%s"' % (key, attributes[key]) 
                        for key in attributes.keys()])
            
    def getErrorMsg(self, name, brk=True, **attributes):
        """Return the error message for a field, if present.

        name
          The name of the field we're dealing with.

        brk
          If True, use a div, otherwise use a span.

        attributes
          These will be used for the div or span.

        I will wrap it with the CSS class ``self.errorClass``.

        """
        if brk:
            tag = "div"
        else:
            tag = "span"
        attributes["class"] = self.errorClass
        if self.errors.has_key(name):
            return '<%s %s>%s</%s>' % (tag, self.attributes(attributes), 
                                       self.errors[name], tag)
        return ""

    def getDefault(self, name):
        """Return the default value for the given field.

        I will *not* run htmlent on it.  If no default can be found, I'll
        return "".

        """

        reIndex = re.compile(r"\[([\w\s]+)\]*")
        reName = re.compile(r"(.*?)\[")
        # Parse out trailing dict notation
        idxs = reIndex.findall(name)
        m = reName.search(name)
        if m:
            idxs = [m.group(1)] + idxs

        for source in self.defaults:
            if idxs:
                tmp_source = source
                for idx in idxs:
                    if not tmp_source.has_key(idx):
                        break
                    else:
                        tmp_source = tmp_source[idx]
                else:
                    return tmp_source
            else:
                if source.has_key(name):
                    if source[name] is not None:
                        return source[name]
                    else:
                        return ""
        return ""
            
    def label(self, name=None, label=None, brk=True, **attributes):
        """Return a label and the error message defined by the validator.
        
        Wrap it with the CSS class ``self.labelClass``.

        name
          If None do not attempt to display an error message.

        label
          If None do not show a label but only show the error message.

        brk
          If True, use a div, otherwise use a span.

        attributes
          These will be used for the div or span of the label, but they won't
          be passed onto ``self.getErrorMsg``.

        """
        ret = ""
        # Using name == "null" is a common no-error-msgs-please trick
        if name and name != "null":
            tag = "label"
            attributes["for"] = name
        else: 
            tag = "span"

        if brk:
            brkTag = "<br />"
        else:
            brkTag = ""

        attributes["class"] = self.labelClass
        if label:
            ret += '<%s %s>%s</%s>%s' % (tag, self.attributes(attributes),
                    label, tag, brkTag)
        if name:
            ret += self.getErrorMsg(name, brk)
        return ret

    def ifError(self, name, if_, else_=""):
        """Return ``if_`` if there was an error, ``else_`` otherwise."""
        if self.errors.has_key(name):
            return if_
        else:
            return else_

    def focusField(self, form, field):
        """Output the JavaScript to focus a field.

        Use this to set the default focus of a form.  Call this *after* you
        have output the given field.

        form
          This is the name attribute of the ``<form>`` tag.

        field
          This is the name or ``id`` attribute of the field.

        """
        htmlent = self._ctx.htmlent
        return """\
<script type="text/javascript"><!--
    document.%s.%s.focus();
// --></script>""" % (htmlent(form), htmlent(field))
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.