Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

HTML5 Forms #98

Open
wants to merge 2 commits into from

3 participants

@faruken

Some HTML5 forms such as email, url, number, range, color, search, telephone and datalist.

@aaronsw

Shouldn't these be indented like the others?

@aaronsw

URLs should be surrounded by angle brackets, not backticks:

@aaronsw

Hmm, missing indent here too.

@aaronsw
Owner

This looks great -- can you fix the two issues I mention above?

@aaronsw
Owner

Looks good -- I just have a couple tweaks in the comments. Can you make and update?

@pjz

s/caucious/caution/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 14, 2011
  1. @faruken
Commits on Sep 15, 2011
  1. @faruken

    Fixed indentation.

    faruken authored
This page is out of date. Refresh to see the latest.
Showing with 143 additions and 14 deletions.
  1. +143 −14 web/form.py
View
157 web/form.py
@@ -18,7 +18,7 @@ class Form(object):
>>> f = Form(Textbox("x"))
>>> f.render()
- '<table>\n <tr><th><label for="x">x</label></th><td><input type="text" id="x" name="x"/></td></tr>\n</table>'
+ u'<table>\n <tr><th><label for="x">x</label></th><td><input type="text" id="x" name="x"/></td></tr>\n</table>'
"""
def __init__(self, *inputs, **kw):
self.inputs = inputs
@@ -187,18 +187,110 @@ class Textbox(Input):
"""Textbox input.
>>> Textbox(name='foo', value='bar').render()
- '<input type="text" id="foo" value="bar" name="foo"/>'
+ u'<input type="text" id="foo" value="bar" name="foo"/>'
>>> Textbox(name='foo', value=0).render()
- '<input type="text" id="foo" value="0" name="foo"/>'
+ u'<input type="text" id="foo" value="0" name="foo"/>'
"""
def get_type(self):
return 'text'
+
+class Telephone(Input):
+ """Telephone input.
+
+ See: <http://dev.w3.org/html5/spec/Overview.html#the-input-element>
+
+ >>> Telephone(name='tel', value='55512345').render()
+ u'<input type="tel" id="tel" value="55512345" name="tel"/>'
+ """
+ def get_type(self):
+ return 'tel'
+
+
+class Email(Input):
+ """Email input.
+
+ See: <http://dev.w3.org/html5/spec/Overview.html#the-input-element>
+
+ >>> Email(name='email', value='me@example.org').render()
+ u'<input type="email" id="email" value="me@example.org" name="email"/>'
+
+ """
+ def get_type(self):
+ return 'email'
+
+
+class Search(Input):
+ """Search input.
+
+ See: <http://dev.w3.org/html5/spec/Overview.html#text-state-and-search-state>
+
+ >> Search(name='search', value='Search').render()
+ u'<input type="search" id="search" value="Search" name="search"/>'
+
+ >>> Search(name='search', value='Search', required='required', pattern='[a-z0-9]{2,30}', placeholder='Search...').render()
+ u'<input name="search" pattern="[a-z0-9]{2,30}" required="required" value="Search" type="search" placeholder="Search..." id="search"/>'
+
+ """
+ def get_type(self):
+ return 'search'
+
+
+class Url(Input):
+ """URL input.
+
+ See: <http://dev.w3.org/html5/spec/Overview.html#url-state>
+
+ >>> Url(name='url', value='url').render()
+ u'<input type="url" id="url" value="url" name="url"/>'
+ """
+ def get_type(self):
+ return 'url'
+
+
+class Number(Input):
+ """Number input.
+
+ See: <http://dev.w3.org/html5/spec/Overview.html#number-state>
+
+ >>> Number(name='num', min='0', max='10', step='2', value='5').render()
+ u'<input name="num" min="0" max="10" value="5" step="2" type="number" id="num"/>'
+ """
+ def get_type(self):
+ return 'number'
+
+
+class Range(Input):
+ """Range input.
+
+ See: <http://dev.w3.org/html5/spec/Overview.html#range-state>
+
+ >>> Range(name='range', min='0', max='10', step='2', value='5').render()
+ u'<input name="range" min="0" max="10" value="5" step="2" type="range" id="range"/>'
+ """
+ def get_type(self):
+ return 'range'
+
+
+class Color(Input):
+ """Color input.
+
+ Warning: Only Opera 11 supports.
+
+ See: <http://dev.w3.org/html5/spec/Overview.html#color-state>
+
+ >>> Color(name='color').render()
+ u'<input type="color" id="color" name="color"/>'
+ """
+ def get_type(self):
+ return 'color'
+
+
class Password(Input):
"""Password input.
>>> Password(name='password', value='secret').render()
- '<input type="password" id="password" value="secret" name="password"/>'
+ u'<input type="password" id="password" value="secret" name="password"/>'
"""
def get_type(self):
@@ -208,7 +300,7 @@ class Textarea(Input):
"""Textarea input.
>>> Textarea(name='foo', value='bar').render()
- '<textarea id="foo" name="foo">bar</textarea>'
+ u'<textarea id="foo" name="foo">bar</textarea>'
"""
def render(self):
attrs = self.attrs.copy()
@@ -216,13 +308,50 @@ def render(self):
value = net.websafe(self.value or '')
return '<textarea %s>%s</textarea>' % (attrs, value)
+
+class Datalist(Input):
+ """Datalist input.
+
+ This is currently supported by only Firefox and Opera. Use it with caucious.
+ Datalist cannot be used separately. It must be bound to an input.
+
+ An example can be viewed on
+ <http://dev.w3.org/html5/spec/Overview.html#url-state>
+
+ >>> Datalist(name='list', args=[('a', 'b'), ('c', 'd')]).render()
+ u'<datalist id="list" name="list"><option label="a" value="b"><option label="c" value="d"></datalist>'
+ >>> Datalist(name='list', args=[['a', 'b'], ['c', 'd']]).render()
+ u'<datalist id="list" name="list"><option label="a" value="b"><option label="c" value="d"></datalist>'
+ >>> Datalist(name='list', args=['a', 'b', 'c', 'd']).render()
+ u'<datalist id="list" name="list"><option value="a"><option value="b"><option value="c"><option value="d"></datalist>'
+ """
+ def __init__(self, name, args, *validators, **kwargs):
+ self.args = args
+ super(Datalist, self).__init__(name, *validators, **kwargs)
+
+ def render(self):
+ attrs = self.attrs.copy()
+ attrs['name'] = self.name
+ label_p = ''
+ x = '<datalist %s>' % attrs
+ for arg in self.args:
+ if isinstance(arg, (tuple, list)):
+ label_p = ' label="%s"' % net.websafe(arg[0])
+ label = net.websafe(arg[1])
+ else:
+ label = net.websafe(arg)
+ x += '<option%s value="%s">' % (label_p, label)
+ x += '</datalist>'
+ return x
+
+
class Dropdown(Input):
r"""Dropdown/select input.
>>> Dropdown(name='foo', args=['a', 'b', 'c'], value='b').render()
- '<select id="foo" name="foo">\n <option value="a">a</option>\n <option selected="selected" value="b">b</option>\n <option value="c">c</option>\n</select>\n'
+ u'<select id="foo" name="foo">\n <option value="a">a</option>\n <option selected="selected" value="b">b</option>\n <option value="c">c</option>\n</select>\n'
>>> Dropdown(name='foo', args=[('a', 'aa'), ('b', 'bb'), ('c', 'cc')], value='b').render()
- '<select id="foo" name="foo">\n <option value="a">aa</option>\n <option selected="selected" value="b">bb</option>\n <option value="c">cc</option>\n</select>\n'
+ u'<select id="foo" name="foo">\n <option value="a">aa</option>\n <option selected="selected" value="b">bb</option>\n <option value="c">cc</option>\n</select>\n'
"""
def __init__(self, name, args, *validators, **attrs):
self.args = args
@@ -274,14 +403,14 @@ class Checkbox(Input):
"""Checkbox input.
>>> Checkbox('foo', value='bar', checked=True).render()
- '<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
+ u'<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
>>> Checkbox('foo', value='bar').render()
- '<input type="checkbox" id="foo_bar" value="bar" name="foo"/>'
+ u'<input type="checkbox" id="foo_bar" value="bar" name="foo"/>'
>>> c = Checkbox('foo', value='bar')
>>> c.validate('on')
True
>>> c.render()
- '<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
+ u'<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
"""
def __init__(self, name, *validators, **attrs):
self.checked = attrs.pop('checked', False)
@@ -311,9 +440,9 @@ class Button(Input):
"""HTML Button.
>>> Button("save").render()
- '<button id="save" name="save">save</button>'
+ u'<button id="save" name="save">save</button>'
>>> Button("action", value="save", html="<b>Save Changes</b>").render()
- '<button id="action" value="save" name="action"><b>Save Changes</b></button>'
+ u'<button id="action" value="save" name="action"><b>Save Changes</b></button>'
"""
def __init__(self, name, *validators, **attrs):
super(Button, self).__init__(name, *validators, **attrs)
@@ -331,7 +460,7 @@ class Hidden(Input):
"""Hidden Input.
>>> Hidden(name='foo', value='bar').render()
- '<input type="hidden" id="foo" value="bar" name="foo"/>'
+ u'<input type="hidden" id="foo" value="bar" name="foo"/>'
"""
def is_hidden(self):
return True
@@ -343,7 +472,7 @@ class File(Input):
"""File input.
>>> File(name='f').render()
- '<input type="file" id="f" name="f"/>'
+ u'<input type="file" id="f" name="f"/>'
"""
def get_type(self):
return 'file'
Something went wrong with that request. Please try again.