Yes, renaming the package in widgets is the right thing IMO since
widget will be (are) first class component for TG.
>
> I know that there are times when you need complete 100% control over
> how things look on the web. Even though you can extensively customize
> widgets, there will be circumstances where you need to go even
> further. For this reason, widgets also support output of Kid for the
> purposes of customization. You'll be able to take that output and drop
> it directly into your template so that you can modify however you need
> to.
>
Great!
> ...
>
> Customizing Widgets
> -------------------
>
> The easiest customization you can do is to include a stylesheet that
> implements the classes used by the widgets. All of the standard
> widgets should use CSS classes extensively and consistently to make
> them easy to customize.
Is there an easy way to customize classes names used by widgets without
specifying a different template? maybe a dictionary? I'm sure I'm
missing something here (excuse me in this case)
>
> That's not hard. How do you know what to put in that template? The
> TurboGears Toolbox will help with that, but this message isn't about
> the Toolbox :)
The Toolbox looks cool indeed! Can't wait to see it in action.
>
> Sometimes just changing the generated markup isn't enough and you need
> to change the behavior of the widget. Widgets are standard Python, so
> subclassing will let you customize further.
Brilliant!
>
> Writing Widgets
> ---------------
> I'll go for what is currently the most complex widget to show the
> parts of writing a widget:
>
> class CalendarDatePicker(Widget):
> css=[CSSLink(static, "calendar-system.css")]
> javascript=[JSLink(static, "calendar.js"),
> JSLink(static, "lang/calendar-en.js"),
> JSLink(static, "calendar-setup.js")]
Regarding the calendar widget, I've seen you have put all its
javascripts under the static directory, maybe (since there are many
things there and it will probably grow) it's better to put them on
static/calendar/ (easier to maintain/update), the same goes for others
widgets.
>
> But, I wanted to get a first look out there. I think this is ready for
> people to start playing with and trying out (and certainly commenting
> on!).
Great work IMHO, it's clear that you have put much thought (and time)
on this problem.
0.9 will simply rock!
Ciao
Michele
This might seem strange, but first thing that jumps out about this
example is the "style" doesn't feel right. Or at least it doesn't feel
consistent with sqlobject. Maybe something more like this:
class MyForm (widgets.Form):
age = widgets.TextField(
default=0,
validators=(
validators.Int(min=4, max=12),
validators.Required())
I still need to read about formencode, so I'm not sure if my list of
validators even makes sense. Now that I think of it, composition (ala
composite pattern) would probably beat lists for testability anyway.
> Widgets have two similar methods for using them: insert and render. In
> practice, insert is the one that is used most often. The difference
> between them is that render returns HTML (or whatever text form you're
> expecting) and insert returns a Element generator, which is convenient
> for inclusion in a surrounding Kid template.
Smart! I like it.
> The validator is important because you can have something like a
> select widget that needs to translate between IDs and names. Or, you
> could have a repeating form element widget that takes in a collection
> of data as its value.
Hmm. I really need to go read about formencode.... (going now :)
I totally agree (also on the FormEncode way of doing this).
I don't see any need to put the form you are constructing into another
class definition that needs to be instanced later, there is already the
FormTable widgets class that act as a constructor of the instance you
are building and want to use.
But my vision can clearly be wrong, as you said is just like vim vs
emacs.
Ciao
Michele
>From a modeling perspective, I believe it's valid (but pedantic) to say
"a login form is a type of form". In fact, I think tg could pretty
safely provide a LoginForm (extends TableForm) widget. A default
template would be vanilla w/ lots-o css hooks, be bound to tg_user and
tg_role tables, etc. The template could handle ordering, etc. etc..
(heck, @expose could even pick up 'required_role' and 'login_url' key
words).
>From an implementation perspective we (the oopers of the world) have
learned that composition/instance based design is waaaay more powerful
(less rigid really) than inheritance. For that reason alone, I'm
completely on board with your implementation. Beyond that, I'm into
your implementation because it's intelligent, working code :)
If determining the type -v- instance mattered, I would have to note
that forms don't appear to be stateful. And (I can't believe I'm saying
this, dimiss it immediately!) that it could be implemented as a
singleton. Of course, all of my comments are makeing me feel like I'm
becoming an "architect astronaut"
(http://www.joelonsoftware.com/articles/fog0000000018.html).
Actually, I was a little dismissive of this thread when I sat down to
write. In truth, I'm glad it's not being trivialized. Style and design
are ___realllllly___ important. TG's base products (SQLObject,
MochiKet, et al.) are perfect examples of thoughful design. So, thanks
for thinking out loud.
-- Levi