From ade7bd4b74d9ae42c54648cc7390d8c067b5c5e3 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 18 Oct 2012 17:49:57 +0200 Subject: Djangoization - Major refactoring (step 1) --- ishtar_common/widgets.py | 368 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 ishtar_common/widgets.py (limited to 'ishtar_common/widgets.py') diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py new file mode 100644 index 000000000..ecc48a1e8 --- /dev/null +++ b/ishtar_common/widgets.py @@ -0,0 +1,368 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2010-2011 Étienne Loks +# Copyright (C) 2007 skam +# (http://djangosnippets.org/snippets/233/) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# 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. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# See the file COPYING for details. + +from django import forms +from django.conf import settings +from django.core.urlresolvers import resolve, reverse +from django.db.models import fields +from django.forms.widgets import flatatt +from django.template import Context, loader +from django.utils.encoding import smart_unicode +from django.utils.html import escape +from django.utils.safestring import mark_safe +from django.utils.simplejson import JSONEncoder +from django.utils.translation import ugettext_lazy as _ + +import models + +class DeleteWidget(forms.CheckboxInput): + def render(self, name, value, attrs=None): + final_attrs = flatatt(self.build_attrs(attrs, name=name, + value='1')) + output = [''] + output.append(u"%s" % (final_attrs, _("Delete"))) + output.append('') + return mark_safe('\n'.join(output)) + +class SquareMeterWidget(forms.TextInput): + def render(self, name, value, attrs=None): + if not value: + value = u"" + final_attrs = flatatt(self.build_attrs(attrs, name=name, value=value)) + output = u' %s '\ + u'(0 ha)' % (final_attrs, + settings.SURFACE_UNIT_LABEL, attrs['id']) + output += """ + +""" % {"id":attrs['id'], "safe_id":attrs['id'].replace('-', '_')} + return mark_safe(output) + +AreaWidget = forms.TextInput +if settings.SURFACE_UNIT == 'square-metre': + global AreaWidget + AreaWidget = SquareMeterWidget + +class JQueryDate(forms.TextInput): + def __init__(self, *args, **kwargs): + super(JQueryDate, self).__init__(*args, **kwargs) + if 'class' not in self.attrs: + self.attrs['class'] = '' + self.attrs['class'] = 'date-pickup' + + def render(self, name, value=None, attrs=None): + rendered = super(JQueryDate, self).render(name, value, attrs) + # use window.onload to be sure that datepicker don't interfere + # with autocomplete fields + rendered += """ + +""" % {"name":name, "country":settings.COUNTRY} + return rendered + +class JQueryAutoComplete(forms.TextInput): + def __init__(self, source, associated_model=None, options={}, attrs={}, + new=False): + """ + Source can be a list containing the autocomplete values or a + string containing the url used for the request. + """ + self.options = None + self.attrs = {} + self.source = source + self.associated_model = associated_model + if len(options) > 0: + self.options = JSONEncoder().encode(options) + self.attrs.update(attrs) + self.new = new + + def render_js(self, field_id): + if isinstance(self.source, list): + source = JSONEncoder().encode(self.source) + elif isinstance(self.source, str) or isinstance(self.source, unicode): + source = "'%s'" % escape(self.source) + else: + try: + source = "'" + unicode(self.source) + "'" + except: + raise ValueError('source type is not valid') + options = 'source : ' + source + options += ''', select: function( event, ui ) { + if(ui.item){ + $('#id_%s').val(ui.item.id); + } else { + $('#id_%s').val(null); + } + }, minLength: 2 + ''' % (field_id, field_id) + if self.options: + options += ',%s' % self.options + + js = u'$(\'#id_select_%s\').autocomplete({%s});\n' % (field_id, options) + js += u'''$(\'#id_select_%s\').live('click', function(){ + $('#id_%s').val(null); + $('#id_select_%s').val(null); +});''' % (field_id, field_id, field_id) + return js + + def render(self, name, value=None, attrs=None): + attrs_hidden = self.build_attrs(attrs, name=name) + attrs_select = self.build_attrs(attrs) + + if value: + val = escape(smart_unicode(value)) + attrs_hidden['value'] = val + attrs_select['value'] = val + if self.associated_model: + try: + attrs_select['value'] = unicode(self.associated_model.\ +objects.get(pk=value)) + except: + attrs_select['value'] = "" + if not self.attrs.has_key('id'): + attrs_hidden['id'] = 'id_%s' % name + attrs_select['id'] = 'id_select_%s' % name + if 'class' not in attrs_select: + attrs_select['class'] = 'autocomplete' + new = '' + if self.new: + model_name = self.associated_model._meta.object_name.lower() + url_new = reverse('new-' + model_name, args=[attrs_select['id']]) + new = u' +' % url_new + html = u'''%(new)s\ +\ + + ''' % { + 'attrs_select' : flatatt(attrs_select), + 'attrs_hidden' : flatatt(attrs_hidden), + 'js' : self.render_js(name), + 'new':new + } + return html + +class JQueryJqGrid(forms.RadioSelect): + COL_TPL = "{name:'%(idx)s', index:'%(idx)s', sortable:true}" + class Media: + js = ['%s/js/i18n/grid.locale-%s.js' % (settings.MEDIA_URL, + settings.COUNTRY), + '%s/js/jquery.jqGrid.min.js' % settings.MEDIA_URL, + ] + css = {'all':['%s/media/ui.jqgrid.css' % settings.MEDIA_URL, + ]} + + def __init__(self, source, form, associated_model, attrs={}, + table_cols='TABLE_COLS', multiple=False, multiple_cols=[2], new=False, + new_message="", source_full=None): + self.source = source + self.form = form + self.attrs = attrs + self.associated_model = associated_model + self.table_cols = table_cols + self.multiple = multiple + self.multiple_cols = multiple_cols + self.new, self.new_message = new, new_message + self.source_full = source_full + + def render(self, name, value=None, attrs=None): + t = loader.get_template('form_snippet.html') + rendered = t.render(Context({'form':self.form})) + rendered += u"\n\n"\ + u"" % ( + name, unicode(_("Search"))) + if self.new: + model_name = self.associated_model._meta.object_name.lower() + url_new = reverse('new-' + model_name) + rendered += u'

'\ + u'%s

' % (url_new, unicode(self.new_message)) + rendered += "\n

%s

\n" % unicode(_("Search and select an item")) + extra_cols = [] + col_names, col_idx = [], [] + for k in self.form.fields: + field = self.form.fields[k] + col_idx.append(u'"%s"' % k) + for field_name in getattr(self.associated_model, self.table_cols): + field = self.associated_model + keys = field_name.split('.') + field_verbose_name = "" + for key in keys: + if hasattr(field, 'rel'): + field = field.rel.to + try: + field = field._meta.get_field(key) + field_verbose_name = field.verbose_name + field_name = field.name + except fields.FieldDoesNotExist: + if hasattr(field, key + '_lbl'): + field_name = key + field_verbose_name = getattr(field, key + '_lbl') + else: + continue + col_names.append(u'"%s"' % field_verbose_name) + extra_cols.append(self.COL_TPL % {'idx':field_name}) + col_names = col_names and ",\n".join(col_names) or "" + col_idx = col_idx and ",\n".join(col_idx) or "" + extra_cols = extra_cols and ",\n".join(extra_cols) or "" + rendered += u"
\n"\ + u"
\n"% (name, name) + encoding = settings.ENCODING or 'utf-8' + rendered += u"
\n" % name + if unicode(self.source_full): + rendered += u"%s (%s) %s - "\ + u"%s\n" % ( + unicode(_("Export as CSV")), encoding, unicode(self.source), + unicode(_(u"simple")), unicode(self.source_full), + unicode(_(u"full")),) + else: + rendered += u'%s (%s)\n' % ( + unicode(self.source), unicode(_("Export as CSV")), encoding) + rendered += "
\n" + if self.multiple: + rendered += u''\ + u'
    \n
\n' % ( + name, unicode(_("Add")), name) + rendered += '\n' % (name, + name) + dct = {'name':name, + 'col_names':col_names, + 'extra_cols':extra_cols, + 'source':unicode(self.source), + 'col_idx':col_idx, + 'no_result':unicode(_("No results")), + 'loading':unicode(_("Loading...")), + 'remove':unicode(_(u"Remove")), + 'sname':name.replace('-', ''), + 'multi_cols': ",".join((u'"%d"' % col \ + for col in self.multiple_cols)) + } + rendered += """\n" + return mark_safe(rendered) + -- cgit v1.2.3