what do we do about html5 types?

227 views
Skip to first unread message

Massimo DiPierro

unread,
Jan 9, 2013, 11:32:41 AM1/9/13
to web2py-d...@googlegroups.com

Mariano Reingart

unread,
Jan 9, 2013, 1:18:23 PM1/9/13
to web2py-d...@googlegroups.com
+1 to use "date", "time", etc INPUT types
does it interfere with old browsers?

Mariano Reingart
http://www.sistemasagiles.com.ar
http://reingart.blogspot.com


On Wed, Jan 9, 2013 at 1:32 PM, Massimo DiPierro
<massimo....@gmail.com> wrote:
> https://groups.google.com/forum/?fromgroups=#!topic/web2py/EaN_I2c96dI
>
> --
> -- mail from:GoogleGroups "web2py-developers" mailing list
> make speech: web2py-d...@googlegroups.com
> unsubscribe: web2py-develop...@googlegroups.com
> details : http://groups.google.com/group/web2py-developers
> the project: http://code.google.com/p/web2py/
> official : http://www.web2py.com/
>
>

Alan Etkin

unread,
Jan 9, 2013, 2:48:10 PM1/9/13
to web2py-d...@googlegroups.com

When a browser does not recognize a particular type value for an <input>, it reverts to it's default value, which is text. So, all of the following are equivalent on browsers that do not support type="number"

 
http://stackoverflow.com/questions/10521445/html5-input-number-and-incompatible-browsers

is that a fact?

For me, old helpers should be HTML4.01 and HTML5 optional

What about a global or request variable to activate HTML5 helpers? Would it be too complicated?

Jan-Karel Visser

unread,
Jan 9, 2013, 3:09:18 PM1/9/13
to web2py-d...@googlegroups.com
HTML5 form inputs are compatible with HTML4, HTML4 just defaults them to input type text,

Here's something i'm working on, works with web2py and web3py, it's quite basic at the moment...
It generates HTML5 forms, based on the models in Dal

Usage:

form = Vorm(db[my_table], id=request.arg[2])
form.show()

our like sql form widget thingy.

form =  Vorm(db[my_table])

{{=form.widget['date']}}


#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
 Vorm
 A lightweight (html5) form generator
 Copyright Jan-Karel Visser - all rights are reserved
 Licensed under the LGPLv3 (http://www.gnu.org/licenses/lgpl.html)

 This program is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

"""

import re

vorm_divstart = ''
vorm_divend = ''
vorm_label = '<label for="{id}">{label}</label>'
vorm_input = '<input type="{type}" id="{id}" name="{name}"{value}{opt}/>'
vorm_comment = '<small>{comment}</small>'
vorm_textarea = '<textarea name="{name}" id="{id}"{opt}>{value}</textarea>'
vorm_html5 = ['email', 'range', 'password', 'datetime', 'date', 'url',
              'number']
#sets the input fields
vorm_valid = {'username': 'text', 'telephone': 'tel'}


def vorm_validate(soort, invoer, options=False):
    if not invoer:
        return False
    vorm_types = {
        "email": \
        "^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$",
        "telephone": \
        "^([\+][0-9]{1,3}([ \.\-])?)?([\(]{1}[0-9]{3}[\)])?([0-9A-Z \.\-]\
        {1,32})((x|ext|extension)?[0-9]{1,4}?)$",
        "username": \
        "^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|\
        ^[a-zA-Z]*[\S]$",
        "imageurl": \
        "^(http\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(?:\/\S*)?(?:[a-zA-Z0-9_])\
        +\.(?:jpg|jpeg|gif|png))$",
        "domainname": \
        "(?:[^0-9][a-zA-Z0-9]+(?:(?:\-|\.)[a-zA-Z0-9]+)*)",
        "number": \
        "^(?:\d+,\s*)*\d+\s*$",
        "password": \
        "^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,8}$",
        "name": \
        "^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,8}$",
        "url": \
        "^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,8}$",
        "date": \
        "([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})",
        "datetime": \
        "([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})",
        "time": \
        "([0-1][0-9]|2[0-3]):[0-5][0-9]",
        "alphanumeric": \
        "^[a-zA-Z0-9\s]+$",
        "null": \
        "^.{0,0}",
        "comma_integer": \
        "^((\d{1,3}(,\d{3})*)|(\d{1,3}))$",
        "postcode": \
        "^[0-9]{4}\s{0,2}[a-zA-z]{2}$",
        "age": \
        "^(1[89]|[2-9]\d)$",
        "number": \
        "^[-+]?([0-9]{1,3}[,]?)?([0-9]{3}[,]?)*[.]?[0-9]*$"
        }
    if soort == 'x': #working onit
        return False
    elif soort == 's': #working onit
        return False
    elif soort == 'f': #working onit
        return False
    elif re.match(vorm_types[soort], invoer) != None:
        return True
    else:
        return False


class Vorm:

    def __init__(self, table, id=0):
        self.table = table
        self.veld = ''
        self.waarden = dict()
        self.form = ''
        self.postkey = []
        self.opslaan = {}
        self.valideer = {}
        self.widget = {}
        self.id = id
        self.create_form()

    def fields(self, item):
        #set the id
        #set the label

        if item.writable and not item.compute:
            tid = str(item)
            tid = tid.split('.')[1]
            self.postkey.append(tid)
            if item.widget:
                self.valideer[tid] = item.widget
            label = vorm_label.replace('{id}', str(tid))
            label = label.replace('{label}', str(item.label))
            if item.type == 'text':
                invoer = vorm_textarea.replace('{id}', str(tid))
                if self.waarden:
                    invoer = invoer.replace('{value}', str(self.waarden[tid]))
            else:
                invoer = vorm_input.replace('{id}', str(tid))
            if item.widget in vorm_html5:
                invoer = invoer.replace('{type}', str(item.widget))
            if item.widget in vorm_valid:
                invoer = invoer.replace('{type}', vorm_valid[item.widget])
            if item.comment:
                invoer = invoer.replace('{opt}', ' placeholder="' \
                                                + str(item.comment) + '"{opt}')
            if item.required:
                invoer = invoer.replace('{opt}', ' required')
            #hide the id
            if item.label == 'Id':
                if self.waarden:
                    label = ''
                    invoer = invoer.replace('{type}', 'hidden')
                else:
                    if self.id == 0:
                        self.widget[tid] = ''
                        return
            else:
                invoer = invoer.replace('{type}', 'text')

            invoer = invoer.replace('{name}', str(tid))
            invoer = invoer.replace('{opt}', '')
            if self.waarden:
                if self.waarden[tid] == None:
                    self.waarden[tid] = ''
                invoer = invoer.replace('{value}',\
                                    ' value="' + str(self.waarden[tid]) + '" ')
            if item.default:
                invoer = invoer.replace('{value}',\
                                    ' value="' + str(item.default) + '" ')
            invoer = invoer.replace('{value}', '')
            self.widget[tid] = vorm_divstart + label + invoer + vorm_divend
            self.form += self.widget[tid]

    def show(self):
        return self.form

    def form_id(self):
        if self.id > 0:
            return '<input type="hidden" name="id" value="'\
                                                        + str(self.id) + '" />'
        else:
            return ''

    def delete(self):
        if self.id > 0:
            try:
                del self.table[self.id]
            except:
                pass

    def save(self, post=False, save=True):
        if post:
            for k in self.postkey:
                if not k == 'id':
                    if k in post:
                        if k in self.valideer:
                            if vorm_validate(self.valideer[k], post[k]):
                                self.opslaan[k] = post[k]
                            else:
                                return False
                        self.opslaan[k] = post[k]
                else:
                    if k == 'id' and post['id']:
                        self.id = post[k]
            if save:
                self.table[self.id] = self.opslaan
                self.form = ''
                self.postkey = []
                self.opslaan = {}
                self.widget = {}
                self.valideer = {}
                self.create_form()
            return True
        return False
    
    def row(self):
        return self.waarden

    def get(self, id):
        return self.table[id]

    def create_form(self):
        if self.id > 0:
            try:
                self.waarden = self.table[self.id]
            except:
                pass
        for items in self.table:
            self.fields(items)


2013/1/9 Alan Etkin <spam...@gmail.com>

Massimo DiPierro

unread,
Jan 27, 2013, 11:29:21 AM1/27/13
to web2py-d...@googlegroups.com
So, what do we do about this?

Alan Etkin

unread,
Jan 27, 2013, 12:48:09 PM1/27/13
to web2py-d...@googlegroups.com
I think that the new widget types might break app code that query widget elements by attribute.

How about a request/response .html5 attribute so widgets know which type the must define?

Bruno Rocha

unread,
Jan 27, 2013, 1:31:50 PM1/27/13
to web2py-d...@googlegroups.com
Also there is the useful "required" argument, so when a field has required=True or IS_NOT_EMPTY validator it can defaults to "required" for client side validation.

Also, for the "number" type it has max and min so when using a datatype "integer" with IS_IN_RANGE or IS_LENGHT we can default to thos properties.

response.html5_form = True or SQLFORM(..., html5=True)

Alan Etkin

unread,
Jan 27, 2013, 1:56:41 PM1/27/13
to web2py-d...@googlegroups.com
Also there is the useful "required" argument, so when a field has required=True or IS_NOT_EMPTY validator it can defaults to

Just in case w3c launches another html with a like_this or tweet attribute:

response.html_version = "5" # defaults to "4.01"
 

Massimo DiPierro

unread,
Jan 27, 2013, 1:34:45 PM1/27/13
to web2py-d...@googlegroups.com
How about we drop it and we only use them for the new web3py helpers (https://github.com/mdipierro/web3py/blob/master/web3py/helpers.py) and forms (https://github.com/mdipierro/web3py/blob/master/web3py/forms.py) and we backport them to web2py as an option?

Massimo

Bruno Rocha

unread,
Jan 27, 2013, 8:50:49 PM1/27/13
to web2py-d...@googlegroups.com
On Sun, Jan 27, 2013 at 4:34 PM, Massimo DiPierro <massimo....@gmail.com> wrote:
How about we drop it and we only use them for the new web3py helpers (https://github.com/mdipierro/web3py/blob/master/web3py/helpers.py) and forms (https://github.com/mdipierro/web3py/blob/master/web3py/forms.py) and we backport them to web2py as an option?

Massimo

 For me it is no problem, because I am working mostly with custom forms where I can easily change attributes to html5. But I think web2py projects will be alive for a long time until web3py gets done.

Is there a roadmap? IF I go there and Fork web3py, what I can start looking for contribute? I hope to start new projects on web2py3 soon.

Marin Pranjić

unread,
Jan 28, 2013, 7:13:42 AM1/28/13
to web2py-d...@googlegroups.com
+1

Massimo DiPierro

unread,
Jan 27, 2013, 9:45:38 PM1/27/13
to web2py-d...@googlegroups.com
We can backport some of the modules to web2py today.

I think it is too soon to start contributing to web3py because I am not sure where it is going.

I think it will contain:

dal.py (the same of web2py)
template.py (the same of web2py)
helpers.py (better/faster implementation of web2py helpers but not 100% compatible because of names)
forms.py (Better implementation of SQLFORM).

One thing that would help is make sure dal.py and template.py work with both python 2.7 and 3.3.


Massimo DiPierro

unread,
Jan 28, 2013, 10:09:23 AM1/28/13
to web2py-d...@googlegroups.com
There is no roadmap but...

I would say the priorities are 
1) make sure what is there works with python 2 and python 3
2) make sure the Form class has widgets similar to web2py's but HTML5 compliant

Everything else needs to be brainstormed.

--
-- mail from:GoogleGroups "web2py-developers" mailing list
make speech: web2py-d...@googlegroups.com
unsubscribe: web2py-develop...@googlegroups.com
details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Richard Vézina

unread,
Mar 22, 2013, 2:21:09 PM3/22/13
to web2py-d...@googlegroups.com

Hello,

I was facing issue with multiple widget definitions and override for the same field... I need html placeholder in my project for reducing the contextual help to the user, every where I can put simple descriptive placeholder I do... I use for that widget since it the only way I found that prevent parsing the a generated form...

But, now I start to fell the pain of that approach... I can no longer rely on DAL model definition because I get my placeholder from a database query (like the labels and help comment)... So having to use widget just to inject a html attribute start to be complicated because I get the placeholder dynamically and the placeholders are set just when the rigth controller is called to avoid overhead... So, for example :

I have this model :

db.define_table('ref_color_code',
    Field('id','id'),
    Field('color_code','string', widget=lambda field, value: SQLFORM.widgets.string.widget(field, value, _placeholder=T(dbplaceholders['ref_color_code.color_code']), _autocomplete='off')),
    migrate=False,
    sequence_name='ref_color_code_id_seq',
    format='%(color_code)s')

No problem there...


But because I have this function from a module (see below) that I call in controller :

def set_labels_comments_placeholders_tooltips(db, dblabels, dbhelp_comments,
    table, field, T, dbplaceholders, dbtooltips, dbunit, request, app_unit_widget):
    concat = '%s.%s' %(table, field)
    if db[table][field].type == 'text':
        if dbplaceholders[concat]!='' and dbplaceholders[concat]!=None:
            db[table][field].widget = lambda field, value: \
                SQLFORM.widgets.text.widget(field, value,
                _placeholder=T(dbplaceholders[concat]))
    if db[table][field].type == 'string':
        if dbplaceholders[concat]!='' and dbplaceholders[concat]!=None:
            db[table][field].widget = lambda field, value: \
                SQLFORM.widgets.string.widget(field, value,
                _placeholder=T(dbplaceholders[concat]))

# The call from controller...
    [ common_functions.set_labels_comments_placeholders_tooltips(db,
        dblabels_en, dbhelp_comments, request.args(0), field, T, dbplaceholders,
        dbtooltips, dbunit, request, app_unit_widget=app_unit_widget) for field in db[request.args(0)].fields ]


So, I have to put more condition in my set labels function, or pass it exception field (the one that get their widget ok)...

Not really convenient...

I don't have read the web2py code and don't know the constrains that could prevent what I will suggest...

But could we have new argument for field that could serve to pass any html argument we want to change or add?? Something like that :

html_args = dict(_placeholder='my_placeholder', _size=10, ...)

If the html arguments passed apply it makes it way to the form input html argument if not web2py just omit it...

Thanks

Richard






To unsubscribe from this group, send email to web2py-develop...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages