def widget(field, value, download_url=None, **attributes): """ generates a INPUT file tag. Optionally provides an A link to the file, including a checkbox so the file can be deleted. All is wrapped in a DIV. see also: :meth:`FormWidget.widget` :param download_url: Optional URL to link to the file (default = None) """ default = dict(_type='file', ) attr = UploadWidget._attributes(field, default, **attributes) inp = INPUT(**attr) if download_url and value: url = download_url + '/' + value (br, image) = ('', '') if UploadWidget.is_image(value): br = BR() image = IMG(_src=url, _width=UploadWidget.DEFAULT_WIDTH) inp = DIV( inp, '[', A(UploadWidget.GENERIC_DESCRIPTION, _href=url), '|', INPUT(_type='checkbox', _name=field.name + UploadWidget.ID_DELETE_SUFFIX), 'delete]', br, image) return inp
def __call__(self, field, value, **attributes): default = dict( _type='text', value=(value != None and str(value)) or '', ) attr = StringWidget._attributes(field, default, **attributes) div_id = self.keyword + '_div' attr['_autocomplete'] = 'off' if self.is_reference: key2 = self.keyword + '_aux' key3 = self.keyword + '_auto' attr['_class'] = 'string' name = attr['_name'] if 'requires' in attr: del attr['requires'] attr['_name'] = key2 value = attr['value'] record = self.db(self.fields[1] == value).select( self.fields[0]).first() attr['value'] = record and record[self.fields[0].name] attr['_onblur']="jQuery('#%(div_id)s').delay(3000).fadeOut('slow');" % \ dict(div_id=div_id,u='F'+self.keyword) attr['_onkeyup'] = "jQuery('#%(key3)s').val('');var e=event.which?event.which:event.keyCode; function %(u)s(){jQuery('#%(id)s').val(jQuery('#%(key)s :selected').text());jQuery('#%(key3)s').val(jQuery('#%(key)s').val())}; if(e==39) %(u)s(); else if(e==40) {if(jQuery('#%(key)s option:selected').next().length)jQuery('#%(key)s option:selected').attr('selected',null).next().attr('selected','selected'); %(u)s();} else if(e==38) {if(jQuery('#%(key)s option:selected').prev().length)jQuery('#%(key)s option:selected').attr('selected',null).prev().attr('selected','selected'); %(u)s();} else if(jQuery('#%(id)s').val().length>=%(min_length)s) jQuery.get('%(url)s?%(key)s='+escape(jQuery('#%(id)s').val()),function(data){if(data=='')jQuery('#%(key3)s').val('');else{jQuery('#%(id)s').next('.error').hide();jQuery('#%(div_id)s').html(data).show().focus();jQuery('#%(div_id)s select').css('width',jQuery('#%(id)s').css('width'));jQuery('#%(key3)s').val(jQuery('#%(key)s').val());jQuery('#%(key)s').change(%(u)s);jQuery('#%(key)s').click(%(u)s);};}); else jQuery('#%(div_id)s').fadeOut('slow');" % \ dict(url=self.url,min_length=self.min_length, key=self.keyword,id=attr['_id'],key2=key2,key3=key3, name=name,div_id=div_id,u='F'+self.keyword) return TAG[''](INPUT(**attr), INPUT(_type='hidden', _id=key3, _value=value, _name=name, requires=field.requires), DIV(_id=div_id, _style='position:absolute;')) else: attr['_name'] = field.name attr['_onblur']="jQuery('#%(div_id)s').delay(3000).fadeOut('slow');" % \ dict(div_id=div_id,u='F'+self.keyword) attr['_onkeyup'] = "var e=event.which?event.which:event.keyCode; function %(u)s(){jQuery('#%(id)s').val(jQuery('#%(key)s').val())}; if(e==39) %(u)s(); else if(e==40) {if(jQuery('#%(key)s option:selected').next().length)jQuery('#%(key)s option:selected').attr('selected',null).next().attr('selected','selected'); %(u)s();} else if(e==38) {if(jQuery('#%(key)s option:selected').prev().length)jQuery('#%(key)s option:selected').attr('selected',null).prev().attr('selected','selected'); %(u)s();} else if(jQuery('#%(id)s').val().length>=%(min_length)s) jQuery.get('%(url)s?%(key)s='+escape(jQuery('#%(id)s').val()),function(data){jQuery('#%(id)s').next('.error').hide();jQuery('#%(div_id)s').html(data).show().focus();jQuery('#%(div_id)s select').css('width',jQuery('#%(id)s').css('width'));jQuery('#%(key)s').change(%(u)s);jQuery('#%(key)s').click(%(u)s);}); else jQuery('#%(div_id)s').fadeOut('slow');" % \ dict(url=self.url,min_length=self.min_length, key=self.keyword,id=attr['_id'],div_id=div_id,u='F'+self.keyword) return TAG[''](INPUT(**attr), DIV(_id=div_id, _style='position:absolute;'))
def widget(field, value, **attributes): """ generates an INPUT text tag. see also: :meth:`FormWidget.widget` """ default = dict( _type='text', value=(value != None and str(value)) or '', ) attr = StringWidget._attributes(field, default, **attributes) return INPUT(**attr)
def widget(field, value, **attributes): """ generates an INPUT checkbox tag. see also: :meth:`FormWidget.widget` """ default = dict( _type='checkbox', value=value, ) attr = BooleanWidget._attributes(field, default, **attributes) return INPUT(**attr)
def widget(field, value, **attributes): """ generates a INPUT password tag. If a value is present it will be shown as a number of '*', not related to the length of the actual value. see also: :meth:`FormWidget.widget` """ default = dict( _type='password', _value=(value and PasswordWidget.DEFAULT_PASSWORD_DISPLAY) or '', ) attr = PasswordWidget._attributes(field, default, **attributes) return INPUT(**attr)
def widget(field, value, **attributes): """ generates an INPUT text tag. see also: :meth:`FormWidget.widget` """ if value: if isinstance(value, unicode): value = value.encode("utf-8") default = dict( _type='hidden', value=(value != None and str(value)) or '', ) attr = StringWidget._attributes(field, default, **attributes) return INPUT(**attr)
def widget(field, value, **attributes): """ generates a TABLE tag, including INPUT checkboxes (multiple allowed) see also: :meth:`FormWidget.widget` """ # was values = re.compile('[\w\-:]+').findall(str(value)) values = not isinstance(value, (list, tuple)) and [value] or value attr = OptionsWidget._attributes(field, {}, **attributes) requires = field.requires if not isinstance(requires, (list, tuple)): requires = [requires] if requires: if hasattr(requires[0], 'options'): options = requires[0].options() else: raise SyntaxError, 'widget cannot determine options of %s' \ % field options = [(k, v) for k, v in options if k != ''] opts = [] cols = attributes.get('cols', 1) totals = len(options) mods = totals % cols rows = totals / cols if mods: rows += 1 for r_index in range(rows): tds = [] for k, v in options[r_index * cols:(r_index + 1) * cols]: tds.append( TD( INPUT(_type='checkbox', _name=field.name, requires=attr.get('requires', None), hideerror=True, _value=k, value=(k in values)), v)) opts.append(TR(tds)) if opts: opts[-1][0][0]['hideerror'] = False return TABLE(*opts, **attr)
def widget(field, value, **attributes): _id = '%s_%s' % (field._tablename, field.name) _name = field.name if field.type == 'list:integer': _class = 'integer' else: _class = 'string' items=[LI(INPUT(_id=_id,_class=_class,_name=_name,value=v,hideerror=True)) \ for v in value or ['']] script = SCRIPT(""" // from http://refactormycode.com/codes/694-expanding-input-list-using-jquery (function(){ jQuery.fn.grow_input = function() { return this.each(function() { var ul = this; jQuery(ul).find(":text").keypress(function (e) { return (e.which == 13) ? pe(ul) : true; }); }); }; function pe(ul) { var new_line = ml(ul); rel(ul); new_line.appendTo(ul); new_line.find(":text").focus(); return false; } function ml(ul) { var line = jQuery(ul).find("li:first").clone(true); line.find(':text').val(''); return line; } function rel(ul) { jQuery(ul).find("li").each(function() { var trimmed = jQuery.trim(jQuery(this.firstChild).val()); if (trimmed=='') jQuery(this).remove(); else jQuery(this.firstChild).val(trimmed); }); } })(); jQuery(document).ready(function(){jQuery('#%s_grow_input').grow_input();}); """ % _id) attributes['_id'] = _id + '_grow_input' return TAG[''](UL(*items, **attributes), script)
def __init__(self, table, record=None, deletable=False, linkto=None, upload=None, fields=None, labels=None, col3={}, submit_button='Submit', delete_label='Check to delete:', showid=True, readonly=False, comments=True, keepopts=[], ignore_rw=False, record_id=None, formstyle='table3cols', **attributes): """ SQLFORM(db.table, record=None, fields=['name'], labels={'name': 'Your name'}, linkto=URL(r=request, f='table/db/') """ self.ignore_rw = ignore_rw self.formstyle = formstyle nbsp = XML(' ') # Firefox2 does not display fields with blanks FORM.__init__(self, *[], **attributes) ofields = fields keyed = hasattr(table, '_primarykey') # if no fields are provided, build it from the provided table # will only use writable or readable fields, unless forced to ignore if fields == None: fields = [ f.name for f in table if (ignore_rw or f.writable or f.readable) and not f.compute ] self.fields = fields # make sure we have an id if self.fields[0] != table.fields[0] and \ isinstance(table,Table) and not keyed: self.fields.insert(0, table.fields[0]) self.table = table # try to retrieve the indicated record using its id # otherwise ignore it if record and isinstance(record, (int, long, str, unicode)): if not str(record).isdigit(): raise HTTP(404, "Object not found") record = table._db(table.id == record).select().first() if not record: raise HTTP(404, "Object not found") self.record = record self.record_id = record_id if keyed: if record: self.record_id = dict([(k, record[k]) for k in table._primarykey]) else: self.record_id = dict([(k, None) for k in table._primarykey]) self.field_parent = {} xfields = [] self.fields = fields self.custom = Storage() self.custom.dspval = Storage() self.custom.inpval = Storage() self.custom.label = Storage() self.custom.comment = Storage() self.custom.widget = Storage() self.custom.linkto = Storage() for fieldname in self.fields: if fieldname.find('.') >= 0: continue field = self.table[fieldname] comment = None if comments: comment = col3.get(fieldname, field.comment) if comment == None: comment = '' self.custom.comment[fieldname] = comment if labels != None and fieldname in labels: label = labels[fieldname] colon = '' else: label = field.label colon = ': ' self.custom.label[fieldname] = label field_id = '%s_%s' % (table._tablename, fieldname) label = LABEL(label, colon, _for=field_id, _id=field_id + SQLFORM.ID_LABEL_SUFFIX) row_id = field_id + SQLFORM.ID_ROW_SUFFIX if field.type == 'id': self.custom.dspval.id = nbsp self.custom.inpval.id = '' widget = '' if record: if showid and 'id' in fields and field.readable: v = record['id'] widget = SPAN(v, _id=field_id) self.custom.dspval.id = str(v) xfields.append((row_id, label, widget, comment)) self.record_id = str(record['id']) self.custom.widget.id = widget continue if readonly and not ignore_rw and not field.readable: continue if record: default = record[fieldname] else: default = field.default cond = readonly or \ (not ignore_rw and not field.writable and field.readable) if default and not cond: default = field.formatter(default) dspval = default inpval = default if cond: # ## if field.represent is available else # ## ignore blob and preview uploaded images # ## format everything else if field.represent: inp = field.represent(default) elif field.type in ['blob']: continue elif field.type == 'upload': inp = UploadWidget.represent(field, default, upload) else: inp = field.formatter(default) elif hasattr(field, 'widget') and field.widget: inp = field.widget(field, default) elif field.type == 'upload': inp = self.widgets.upload.widget(field, default, upload) elif field.type == 'boolean': inp = self.widgets.boolean.widget(field, default) if default: inpval = 'checked' else: inpval = '' elif OptionsWidget.has_options(field): if not field.requires.multiple: inp = self.widgets.options.widget(field, default) else: inp = self.widgets.multiple.widget(field, default) if fieldname in keepopts: inpval = TAG[''](*inp.components) elif str(field.type).startswith('list'): inp = self.widgets.list.widget(field, default) elif field.type == 'text': inp = self.widgets.text.widget(field, default) elif field.type == 'password': inp = self.widgets.password.widget(field, default) if self.record: dspval = PasswordWidget.DEFAULT_PASSWORD_DISPLAY else: dspval = '' elif field.type == 'blob': continue else: inp = self.widgets.string.widget(field, default) xfields.append((row_id, label, inp, comment)) self.custom.dspval[fieldname] = dspval or nbsp self.custom.inpval[fieldname] = inpval or '' self.custom.widget[fieldname] = inp # if a record is provided and found, as is linkto # build a link if record and linkto: for (rtable, rfield) in table._referenced_by: if keyed: rfld = table._db[rtable][rfield] query = urllib.quote( str(rfld == record[rfld.type[10:].split('.')[1]])) else: # <block> query = urllib.quote( str(table._db[rtable][rfield] == record.id)) lname = olname = '%s.%s' % (rtable, rfield) if ofields and not olname in ofields: continue if labels and lname in labels: lname = labels[lname] widget = A(lname, _class='reference', _href='%s/%s?query=%s' % (linkto, rtable, query)) xfields.append( (olname.replace('.', '__') + SQLFORM.ID_ROW_SUFFIX, '', widget, col3.get(olname, ''))) self.custom.linkto[olname.replace('.', '__')] = widget # </block> # when deletable, add delete? checkbox self.custom.deletable = '' if record and deletable: widget = INPUT( _type='checkbox', _class='delete', _id=self.FIELDKEY_DELETE_RECORD, _name=self.FIELDNAME_REQUEST_DELETE, ) xfields.append( (self.FIELDKEY_DELETE_RECORD + SQLFORM.ID_ROW_SUFFIX, LABEL(delete_label, _for=self.FIELDKEY_DELETE_RECORD, _id=self.FIELDKEY_DELETE_RECORD + SQLFORM.ID_LABEL_SUFFIX), widget, col3.get(self.FIELDKEY_DELETE_RECORD, ''))) self.custom.deletable = widget # when writable, add submit button self.custom.submit = '' if not readonly: widget = INPUT(_type='submit', _value=submit_button) xfields.append( ('submit_record' + SQLFORM.ID_ROW_SUFFIX, '', widget, col3.get('submit_button', ''))) self.custom.submit = widget # if a record is provided and found # make sure it's id is stored in the form if record: if not self['hidden']: self['hidden'] = {} if not keyed: self['hidden']['id'] = record['id'] (begin, end) = self._xml() self.custom.begin = XML("<%s %s>" % (self.tag, begin)) self.custom.end = XML("%s</%s>" % (end, self.tag)) if formstyle == 'table3cols': table = TABLE() for id, a, b, c in xfields: td_b = self.field_parent[id] = TD(b, _class='w2p_fw') table.append( TR(TD(a, _class='w2p_fl'), td_b, TD(c, _class='w2p_fc'), _id=id)) elif formstyle == 'table2cols': table = TABLE() for id, a, b, c in xfields: td_b = self.field_parent[id] = TD(b, _class='w2p_fw', _colspan="2") table.append( TR(TD(a, _class='w2p_fl'), TD(c, _class='w2p_fc'), _id=id + '1', _class='even')) table.append(TR(td_b, _id=id + '2', _class='odd')) elif formstyle == 'divs': table = TAG['']() for id, a, b, c in xfields: div_b = self.field_parent[id] = DIV(b, _class='w2p_fw') table.append( DIV(DIV(a, _class='w2p_fl'), div_b, DIV(c, _class='w2p_fc'), _id=id)) elif formstyle == 'ul': table = UL() for id, a, b, c in xfields: div_b = self.field_parent[id] = DIV(b, _class='w2p_fw') table.append( LI(DIV(a, _class='w2p_fl'), div_b, DIV(c, _class='w2p_fc'), _id=id)) elif type(formstyle) == type(lambda: None): table = TABLE() for id, a, b, c in xfields: td_b = self.field_parent[id] = TD(b, _class='w2p_fw') newrows = formstyle(id, a, td_b, c) if type(newrows).__name__ != "tuple": newrows = [newrows] for newrow in newrows: table.append(newrow) else: raise RuntimeError, 'formsyle not supported' self.components = [table]
def __init__(self, table, record=None, deletable=False, download="", upload=None, fields=None, labels=None, col3={}, submit_button='Submit', delete_label='Check to delete:', showid=True, readonly=False, comments=True, keepopts=[], ignore_rw=False, formstyle='divs', record_pk_name='_id', tabs=[], **attributes): """ FORMBUILDER(db.table, record=None, fields=['name'], labels={'name': 'Your name'}, """ self.table = table if record: for itm in record: if isinstance(record[itm], (list, tuple)): if not (itm in self.table.fields and self.table[itm].type.startswith("list::")): record[itm] = record[itm][-1] self.custom_file = upload self.ignore_rw = ignore_rw self.formstyle = formstyle self.record_pk_name = record_pk_name nbsp = XML(' ') # Firefox2 does not display fields with blanks attributes.update({"_id": "hyform_%s" % self.table._tablename}) FORM.__init__(self, *[], **attributes) ofields = fields # if no fields are provided, build it from the provided table # will only use writable or readable fields, unless forced to ignore if fields == None: fields = [ f.name for f in table if (ignore_rw or f.writable or f.readable) ] self.record = record self.field_parent = {} xfields = {} xfields_keys = [] self.fields = fields self.custom = Storage() self.custom.dspval = Storage() self.custom.inpval = Storage() self.custom.label = Storage() self.custom.comment = Storage() self.custom.widget = Storage() for fieldname in self.fields: if fieldname.find('.') >= 0: continue field = self.table[fieldname] comment = None if comments: comment = col3.get(fieldname, field.comment) if comment == None: comment = '' self.custom.comment[fieldname] = comment if labels != None and fieldname in labels: label = labels[fieldname] colon = '' else: label = field.label colon = ': ' self.custom.label[fieldname] = label field_id = '%s_%s' % (table._tablename, fieldname) label = LABEL(label, colon, _for=field_id, _id=field_id + FORMBUILDER.ID_LABEL_SUFFIX) row_id = field_id + FORMBUILDER.ID_ROW_SUFFIX if readonly and not ignore_rw and not field.readable: continue if record: default = record.get(fieldname, field.default) else: default = field.default cond = readonly or \ (not ignore_rw and not field.writable and field.readable) if default and not cond: default = field.formatter(default) dspval = default inpval = default if cond: # ## if field.represent is available else # ## ignore blob and preview uploaded images # ## format everything else if field.represent: inp = field.represent(default) elif field.type in ['blob']: continue elif field.type == 'upload': inp = UploadWidget.represent(field, default, download) elif field.type == 'boolean': inp = self.widgets.boolean.widget(field, default, _disabled=True) else: inp = field.formatter(default) elif field.type == 'upload': if hasattr(field, 'widget') and field.widget: inp = field.widget(field, default, download) else: inp = self.widgets.upload.widget(field, default, download) elif hasattr(field, 'widget') and field.widget: inp = field.widget(field, default) elif field.type == 'boolean': inp = self.widgets.boolean.widget(field, default) if default: inpval = 'checked' else: inpval = '' elif OptionsWidget.has_options(field): if not field.requires.multiple: inp = self.widgets.options.widget(field, default) else: inp = self.widgets.multiple.widget(field, default) if fieldname in keepopts: inpval = TAG[''](*inp.components) elif field.type.startswith('list:'): inp = self.widgets.list.widget(field, default) elif field.type == 'text': inp = self.widgets.text.widget(field, default) elif field.type == 'hidden': inp = self.widgets.hidden.widget(field, default) elif field.type == 'password': inp = self.widgets.password.widget(field, default) if self.record: dspval = PasswordWidget.DEFAULT_PASSWORD_DISPLAY else: dspval = '' elif field.type == 'blob': continue else: inp = self.widgets.string.widget(field, default) xfields_keys.append(fieldname) xfields[fieldname] = (row_id, label, inp, comment) self.custom.dspval[fieldname] = dspval or nbsp self.custom.inpval[fieldname] = inpval or '' self.custom.widget[fieldname] = inp # when writable, add submit button self.custom.submit = '' if not readonly: widget = INPUT(_type='submit', _class="submit", _value=submit_button, _id="submit_%s" % self.table._tablename) self.custom.submit = widget # if a record is provided and found # make sure it's id is stored in the form if record: if not self['hidden']: self['hidden'] = {} (begin, end) = self._xml() self.custom.begin = XML("<%s %s>" % (self.tag, begin)) self.custom.end = XML("%s</%s>" % (end, self.tag)) table = TAG['']() if formstyle == 'divs': # tabs = [ # {"tabname":"personal","caption":"个人信息","fields":["login","age"]}, # {"tabname":"comp","caption":"公司信息","fields":["login","age"]}, # {"tabname":"gf","caption":"朋友信息","fields":["login","age"]}, # ] if tabs: tab_headers = UL() tab_bodys = [] for i, tab in enumerate(tabs): tbody = DIV(_id="body_%s" % (tab.get("tabname", ""))) if i == 0: li = LI(tab.get("caption", ""), _class="active", _id="tab_%s" % (tab.get("tabname", ""))) tbody['_class'] = "active" else: li = LI(tab.get("caption", ""), _style="display:none;", _id="tab_%s" % (tab.get("tabname", ""))) tbody['_style'] = "display:none;" tab_headers.append(li) for f in tab.get("fields", []): if f in xfields_keys: id, a, b, c = xfields[f] div_b = self.field_parent[id] = DIV( b, _class='w2p_fw') tbody.append( DIV(DIV(a, _class='w2p_fl'), div_b, DIV(c, _class='w2p_fc'), _id=id, _class="fb_row")) tab_bodys.append(tbody) tab_headers = DIV(tab_headers, _id="tab_headers_%s" % self.table._tablename) tab_bodys = DIV(tab_bodys, _id="tab_bodys_%s" % self.table._tablename) table.append(DIV(tab_headers, tab_bodys)) else: for d in xfields_keys: id, a, b, c = xfields[d] div_b = self.field_parent[id] = DIV(b, _class='w2p_fw') table.append( DIV(DIV(a, _class='w2p_fl'), div_b, DIV(c, _class='w2p_fc'), _id=id, _class="fb_row")) self.components = [table, self.custom.submit]