By airportyh

Making justtodolist work for chrome and safari

Since Chrome is so great, I wanted to use it for all my browser needs. But the apps I've been working on myself have not been targeted for WebKit - the rendering engine used by chrome, and also used my Safari. This is mostly due to laziness on my part - having to handle two browsers at a time is chaos enough. But Safari compatibility is on my todo list for more than one of my projects, and chrome is a good push for this cause. And so I went in today and made just todo list. compatible with Chrome and Safari. The differences I encountered were:
  1. This is really prototype specific - prototype adds an empty underscore parameter for all Ajax request for WebKit browsers. Because apparently, Safari errors out when you try to post with an empty body on XHR calls. And, who knows, this might already be fixed in WebKit. I happened to have code that was not handling this fact on the server side. This was no biggy.
  2. This is an error on my part really, but I had a form with a text input inside. But also registered for the key events on the text input so that when enter is pressed I called form.submit(). The key event code is really unnecessary because an enter on the text input triggers the form submit on both FF and IE. So, although on the other 2 browsers this was no problem, in WebKit this triggers 2 posts. So... just DON'T do this.

Google Chrome

by airportyh posted at 09-02-2008 10:33PM - Comments (0)   browser google javascript programming tech
Google just released this awesome browser. They have a great comic strip walking you through what the big deal is about, which is a must read for web developers. I've been using the browser for half a day and it's been pretty rock solid for all the sites I normally use. Javascript is clearly MUCH faster thanks to the v8 engine, which I think Steve Yegge alluded to a while ago. I like many of it's different features, and think it's a great boost to the browser world as well as javascript, i.e. the NBL(Next Big Language).

Play Date with jQuery

by airportyh posted at 08-31-2008 11:47PM - Comments (0)   javascript jquery programming prototype
I had a new toy project and started out with my trusty sidekick: prototype.js but a bit of the way in i decide to try my hand at jQuery instead, since I've already read a lot about jQuery and really like the monad-like paradigm which allows you to write elegant "flow" code without having to worry about null values anywhere in the chain.

It was quite easy translating my existing prototype.js code to jQuery(probably just around 30 lines).
  • The end result was probably 20% more succient.
  • I love the css 3 capable selectors, it's very refreshing to be able to use attribute and partial string match selectors which normally you don't get to use for your work. 
  • I also like the way attributes are set as chained methods(again, in the monad flavor), you do something like $('#myid').attr('value') to get the value and $('#myid').attr('value', 1) to set the value to 1. This again, allows you to chain stuff together. What's the point of this? ...I guess I just like the monad thing.
  • I think the jQuery syntax for behavioral javascript is prettier than prototype.js + lowpro.js
I really have nothing bad to say about jQuery. Even the UI components seem pretty on par with prototype.js, there's jqueryui, from which I used the autocomplete plugin. It's a little bit unfortunate that I had already invested about 1800 lines of javascript code on writing javascript components based on prototype.js and scriptaculous at work, otherwise had I started over I would very probably use jQuery. I will definitely go jQuery for my other projects.

Are there anything from prototype.js that I miss? Well, yes, I miss the array extensions from prototype, which lets you use ruby/smalltalk/lisp-like internal iterator style list operations. jQuery has a $.each, but it's not quite as pretty... but it gets the job done. And I haven't looked, but I am not sure there's an equivalent to prototype's Event.KEY_RETURN, Event.KEY_BACKSPACE and such in jQuery. Also, I had gotten comfortable to the OO model from prototype, and doing without it will be different, but then again I am adaptable. Plus, there's nothing at all stopping you from using jQuery and prototype.js together.

The z-index IE bug

by airportyh posted at 08-23-2008 02:38PM - Comments (0)   css javascript programming
Yeah, the z-index IE bug, have you heard of it? I was bitten by it a couple of days ago. In my case, I had a list of text fields in a form layed out from top to bottom. The problem is, I have these interactive drop downs on that can activate just under the text fields when you focus on the field and there is a validation error, which I use relative/absolute positioning to get in the right place, and so the position: relative declaration triggers the IE bug which causes the text field beneath the one that has the focus to occlude its drop down. My solution? I now have a javascript snippet that runs as the dom is ready that sets the z-index of all the containers(the one that has position: relative) of the text fields in descending order. So for example, if you have 10 text fields, the first one would have its z-index: 10 and the last one would have z-index: 1.

In a related note, if you use the relative/absolute positioning technique, the child element that has position: absolute is considered the child of the parent element that has position: relative in terms of z-index, which if you then have overflow: hidden on the parent element or its ancestors, the child element would get cut out if it's position is out of bounds, vs if you didn't have position: relative set on the parent element then the child would not get cut out because it's considered to be the child of the root element in terms of z-index.

The Hidden Singleton with Javascript

by airportyh posted at 08-23-2008 01:04PM - Comments (0)   javascript programming
This pattern is well documented else where, I think I first saw it in the Definitive Javascript book. Let's say you want to provide a function that does stuff with a static variable, but don't want that static variable to be global(visible to the outside)? You would do this:

myfunction = function(){
    var mysingleton = new Singleton();
    return function(x, y){
        return mysingleton.doit(x,y);
    };
}();


so now you can do myfunction(1,2) which in reality calls the doit method of the same instance of Singleton everytime. As a more concrete example, you can create a counter function like this:

counter = function(){
    var i = 0;
    return function(){
        return i++;
    };
}();


Each time you call counter() the result increases by 1.

A variation of this pattern is to extend an existing function/method by replacement. This is similar to the ruby practice of aliasing a method to a different name and then sticking a new method in it's place that at some point calls the original version. Anyway, for example, let's say you have an existing function from an existing library... say scriptaculous effects' Effect.Shake. You want to change the default options without having to rename the function(so that all your existing code that depends on it doesn't not need to change), you would do:

    Effect.Shake = function(){
        var original = Effect.Shake;
        return function(element, options){
           
original(element, Object.extend({
                distance: 5,
                duration: 0.5
              }, options || {}));
        };
    }();


So I've changed the default distance to 5 and duration to 0.5 throughout my app for any calls to shake() by adding this in one place only.

Relativize that thing: todays CSS war story

by airportyh posted at 08-22-2008 12:43AM - Comments (0)   css html javascript programming
Today, I had a seemingly simple problem: position a floating label element inside of a text input field, inside a elastic layout. To achieve an effect like:

Moreover, I wanted to implement this as a generic javascript widget that I can reuse throughout the application. This was hard, real hard.

At first, I just used position: absolute and set the position of the label relative the the root document, getting the coordinates required from the position and dimension of the companion text field. Well, this didn't work so well when the window is resized. Too bad we got an elastic layout, if we had a fixed width one I would have been done. My quick and dirty solution was to register the window.onresize callback and reset the positions of the labels whenever the window is resized. This actually worked well in IE, but not so in FF. The problem with FF is that the callback is invoked too sparsely, it's just not responsive enough when you are just dragging the corner of the window around, but you see these labels in all the wrong places while you are dragging around the corner of the browser until you leave your mouse still for a second, at which point the labels receive the event and jump to where they should be. This just plain looks bad, and although your users probably won't resize the window too much, I think it will definitely give the impression of a cheesy app.

So, my first attempt at a work around is a brute force one. I wrote my onresize callback functionality for FF that is more responsive. Here was the code.
 /* this is a funny hack in FF to get window resize events more often */
var ffonresize = function(){
    var listeners = [];
    var dim = document.viewport.getDimensions();
    var pe = null;
    pe = new PeriodicalExecuter(function(pe) {
        var nd = document.viewport.getDimensions();
        if (!(nd.width == dim.width && nd.height == dim.height)){
            dim = nd;
            listeners.each(function(l){l(nd)});
        }
    }, 0.2);
    return function(listener){
        listeners.push(listener);
    }
}();

/*
...
*/
if (Prototype.Browser.Gecko)
    ffonresize(this.__onResize);
else
    Event.observe(window, 'resize', this.__onResize);


This improved the situation, but... not good enough. Then I thought, there must be a way with position: relative to do it. After all, isn't that what it's for?

I tried making the label element position: relative, but this didn't work: you could shift the position of the element relative to where it would have been, but the space for where it would have been is still taken up, and now it's an empty space...
I did some research. One of the best resources is quirksmode again, this is also a helpful article. It turns out the common practice to use is to have a container that is relative and then a child under it that is absolute, which will cause the child to use the parent's position as the reference point. But trying the things out didn't work at first. After some trial and error, I figured out that, not only does the parent have to be position: relative, it also had to be display: block. My parent container happened to be table cells, so I either had to set their display to block or add a div under them. Setting their display to block didn't work for me because it completely messed up the layout of the table, so I had to go with the second method.

Adding the div was annoying because not only did I have to go to a few different places in the app to add the markup, it also made my widget depend on more. Of course, I guess I could inject the div dynamically, but I haven't tried that yet. So, this worked, I no longer had to use the onresize callback and reset the position of the labels, I just set:

position: absolute;
top: 2px;
right: 5%;


Top of 2px to give the top some space, right of 5% to give enough space for the label. Both are relative to the divs I newly added. Well, this kinda worked... except for my short textfields. See, I had long text fields that take up almost 100% of the width of the parent, but also shorter ones that take up about 60%, so while it worked well for the long textfield, sitting right inside it on the right edge, it was well outside of the short textfields. I wanted to use javascript to figure out what's the % of the width of the text field, which I could use to calculate where the label should be, but that number is in my css, and using javascript you can only get dimensions in terms of pixels, i.e., all the percentage info is lost.

What to do? Well, I calculated the percentage by doing a division between the text field and its parent's width in pixels, this is my code(using prototype.js):
right: (1 + 100 * (1 - this.field.getWidth() / this.field.up().getWidth())) + "%"

Yeah, it's pretty crazy, but it worked, beautifully. It works in IE7, FF3, and Safari, didn't work in Opera, but that could have been because other javascript bugs I had wrt Opera.

Maintaining Order in GAE

by airportyh posted at 08-15-2008 12:01AM - Comments (0)   appengine googleappengine programming
In a previous post I alluded to problems I encountered with using GAE's object model. This is the follow up to that.

In my todo list app, a main feature was to make reordering your todo list a breeze. When I wrote it with mysql, I used the standard relational database pattern to store an ordered list: create a field SEQ in the items table which holds the a sequence number(integer) that represents the order of the item in the list. But this means for every reordering I do, I have to update all active items in the list. I figured since I am only going to have small lists, it shouldn't matter, and it worked fine with mysql. When I did a port of this to GAE, reordering became terribly slow. A friend of mind told me that this is just a characteristic of object databases. My solution was to create a list field in the parent object(list), which remaps the sequence numbers into the correct order for the items. This way, updating the order only took saving the list object. Of course, this approach is more complicated. There are a couple of other possible approaches:
  1. As my friend mentioned: do a link list in the database. Instead of a SEQ field you would have a NEXT field which points to the item that's next to this one. This would make small reorderings(of the type: you take one object and move it to a different place in the list), a constant time operation, in terms of number of updates(3 updates total).
  2. Make the SEQ field a float, which would allow you to insert a item in between 2 other items with only one update. But because of numerical precision issues, sooner or later you would have to relabel the whole list for the SEQ numbers to be not too close together, which would be triggered like a garbage collection operation would be.
My current approach I think is about on par with these 2 in terms of complexity. I like the linked list solution because it's more scalable, you can really reorder/maintain arbitrarily large lists without missing a beat. For my app though, I only need to handle small lists, so I have no reason to switch for now

The Best Way to Watch the Olympics

by airportyh posted at 08-12-2008 07:44PM - Comments (1)   family olympics sports tv
Okay, here's the best way to watch the Beijing Olympics(in the US):
  1. On a Mac-mini that's hooked up to a 50" DLP Samsung TV or larger...
  2. Go to nbcolympics.com and click on "TV & Online Listings".
  3. Fill out some forms to go through which asks what's your TV provider... it's really BS. Don't choose Cablevision or From the Air and you'll be okay.
  4. When you are through, choose the Online Listings tab, this will list by sport. Live events will show with the listing, so if there are live events you want to watch, just click on that. Otherwise, click on the sport that you are interested in watching and you will get a listing of the prerecorded events that you can watch, click on one and video will start.
  5. The Video player requires Microsoft Silverlight, just follow the steps to install it. It works with Mac too.
  6. Once the video player is working, and the main content (after the ads) is going, you can click the "Enlarge Video" button on the bottom right.
  7. There is no fullscreen mode, but that's where the Mac's zoom function comes in. Do Cmd-Option-8 to enable zooming if it isn't already, and then Cmd-Option-=(or plus) to zoom in to the desired size, (Cmd-Option-(minus) to zoom out).
  8. One last step to hide the mouse cursor by pressing shift-Cmd-4 and the moving the cursor away from the center. Curtesy of this article.
  9. That's it! Perfect! Resolution is pretty good, I'd say on par with analog TV. The selection is MUCH MUCH better than on NBC's TV line up. There's no commentary, which could be good and bad, I personally like it. AND, MOST importantly, No Ads! 'nuff said.

Komodo Edit vs E texteditor

by airportyh posted at 08-05-2008 02:21PM - Comments (0)   programming texteditor
I tried out Komodo Edit - IDE for scripting languages like python and ruby. For work now, I am doing python/turbogears/javascript development, and I have been using E texteditor - a textmate clone for windows, which I have been happy with, but also have a few problems with.

Komodo Edit is a polished IDE. It has auto-code-complete for python, ruby and javascript libraries out of the box, which E texteditor does not(E texteditor does not support code complete at all). It's code highlighting and code assist support is much more polish than E texteditor's, which I must say, is pretty buggy. It also has one feature that's close to my heart - split view on the same file - which I have enjoyed in my emacs days but have yet to find one editor I liked since which has it. It has a good mako template plugin, which is very important to me since that's what I am using for work, and E texteditor does not yet have. It is not sluggish like Eclipse but actually quite snappy. It is written on Mozilla's XUL framework, and uses the same extension framework that Firefox uses. There's an open source version of Komodo Edit, which you can't say the same about E texteditor.

So, Komodo Edit is pretty good, but there are some disadvantages wrt E texteditor. The most annoying one, is the crashiness. Sometimes Komodo Edit just crashes without any warning. This can quickly dissuade its users...me...from using it. E texteditor is not free of crashing, but I feel it's more stable. There are also some E texteditor features(mostly from textmate) that I have grown to love and are helpful but are missing from Komodo Edit. One is multiple selection and multiple line selection, these features are huge once you learn to use them. The search and replace feature in E texteditor is much handier and less cluggy, Komodo Edit is this area of UI design is a bit behind. Also, although Komodo Edit's project panel on the left hand side is nice, the search/filter feature is way too slow and so the lack of a "jump to file..." shortcut is inexcusable(plus, E texteditor's jump to file dialog is really nice, it has as-you-type style filtering that permits spelling errors, like Firefox' awesome bar and Launchy).

So, which one will I use? I am really torn. The two editors are so different in style and philosophy, and each have very compelling advantages over the other. I will probably switch back and forth between the two for a short time before settling on one.

Web Dev with Google App Engine

by airportyh posted at 07-29-2008 10:32PM - Comments (0)   appengine google programming python
I wrote my first Google App Engine app! It's located at justtodolist.appspot.com. It's yet another todo list - I have been a tadalist user for a while and thought I could make it slightly better, and so I did. Here is to jot down some thoughts on GAE.

First up, the things I like.
  1. The number one benefit of GAE for me is definitely one step deployment. No that you couldn't step up one step deployment for rails apps, but it just takes a lot of work to set this stuff up the first time. With GAE, it's one step deploy the first time. I would say it's easier even than php. A large part because of benefit number two
  2. there is no database to set up. As most people know by now, you use GQL/Big Table on GAE, and it is very different from relational databases. Setting up is really minimal. You specify your model in a DSL similar to what you'd write with SQLObject or Elixir, or Data Mapper for Ruby folks. And then boom! you are running.
  3. There's no user authentication to setup either, it's basically Gmail authentication, if you are willing to go along, that is. The User API is very simple, and you can start using it right away
  4. Development server is nice, it picks up changes immediately when you save any project file
  5. The number of projects files you have is very minimal, it's very non-cluttery.
So as you can see GAE is great for rapid prototyping. Now for things I am not that crazy about. Actually, most of the benefits I spoke of has some caveats:
  1. Although deployment is easy. Sometimes issues arise from the fact that things work slightly differently in production vs development. Such as, you need indices to build fully in production for the app to be ready to run, or for some reason, transaction rules work differently in production vs development(I haven't dug down to this fully, but it might be a bug)
  2. Big Table is cool, it's supposed to be super scalable, but there are a couple of things that are annoying about it. I can get over the fact that it's fundamentally different from relational databases: things like you can't do aggregate queries, joins and so forth. For performance too, some things you will just have to do differently than you would normally with relation databases. I am okay with that. What pains me is that there is no proper data migration path. When you change your models(add or remove fields, and so forth), the old stuff just stick around. To migrate the old data, you basically have to manually write a script that loops over the existing data structures and modify them, but the script has to be triggered from an http request just like everything else because that's the only way to run your code on GAE on the production server... getto! Also, I am extremely annoyed that while in development you can just clear your datastore. There is no analog in production. I realize though that this is a work in progress and that things will get better in the future.
  3. Well, the caveat for using Gmail authentication is that... your users must have a Gmail account, duh... I am sure you can use other authentication schemes if you want, I don't see anything preventing that
  4. Yes the development server is nice, but for some reason it was progressively running slower on my company Dell D820 laptop. This is so especially if you perform extensive modification of the data models.
Here are some other thoughs:
  1. The development console is not good, man! It's no where near the usability of the python interactive shell. I've heard of an alternative but haven't seen it yet.
  2. I haven't dug into how to do TDD with it yet, but I've read it's possible.
  3. Again, Big Table is VERY different from relational databases. I originally ported my todo list app from a SQLObject -> MySQL backend, with only 2 data models: TodoList and TodoItem. In Big Table we still have the 2, but they look kinda different. I had to change it because of performance reasons. I'll put the discussion of that on a separate post.
  4. I haven't got a great handle of how transaction/entity groups work. I thought I did, until my transaction code didn't work, will have to look closer into it. Documentation on this is kinda sparse. Right now my code is non-transactional.
Open Source GAE Apps?

Here's another thought. Will it be possible to popularize open source GAE apps? I think the most important reason for the popularity of open source php apps is the ease of deployment. With the ease of deployment of GAE, I think conditions might be ripe for there to emerge a movement of good open source GAE apps. Then again though, people might resist the vendor specific/non-open source nature of GAE. We will see.

Impressions of Turbogears 4 months in

by airportyh posted at 07-17-2008 10:53PM - Comments (0)   programming python ruby turbogears
I've been a user of Turbogears for 4 months now, working on a client facing app. The app has not gone production yet, so I don't have much insight on deployment, but I have a lot of experience on the development side - I started from scratch - and here is what I learned so far.

Freedom of Choice
Turbogears as a framework is pretty agnostic of different components such as ORM, or template engine. Although there is a default choice, I found it wasn't hard to stray away from it.

Mako
I ended up choosing Mako as the template engine because, coming from rails, I felt kid and genshi were too heavyweight for my taste since they are based on XSLT and requires your markup to be valid XML before it can do anything, which obviously means there's an XML parsing step it has to do. Mako is more like erb in that it's "text-based", e.i. it's perfectly fine to render non-valid XML code. But Mako turned out to be much more than another erb. With Mako you can easily write helper template functions and reuse them everywhere. You can also write inversion-of-control template style functions which take in a partial template and calls it inside its body. It always puzzled me why you couldn't do that with erb or haml or most of the ruby template engines easily. With erb, you have to write a partial view as a separate file, but calling a partial with local parameters is inconvient, you have to write something like:

render :partial => 'my_control', :locals => {:control_id => 'con', :height=> '50px'}

and since this is so inconvient, i usually end up wrapping it with a helper method like:

def my_control(control_id, height)
    render :partial => 'my_control', :locals => {:control_id => control_id, :height=> height}
end


Of course this is partially due to the culture in rails that you normally write helpers in ruby rather than in a template language. In Mako you don't have to do this extra step, which makes me happy. Now if you want to do the inversion of control thing, in erb it's even worse! In mako you would just do this. So, in general, I am able to refactor my views a lot easier with mako and therefore I find myself doing it a lot more often.

SQLAlchemy
SQLAlchemy is a main stream ORM in the python community. It's direction is different from that of ActiveRecord and is a lot more similar to Hibernate of Java but also has similarities to Ambition of Ruby and Linq of .NET. It is similar to Hibernate in that it is very fully featured, has sessional transaction management, and can coupe with a large variety of schemas. It is similar to ambition and linq in that you can contruct queries in your host language in a very succint and elegant way(I know you can build queries in Hibernate's criteria API too, but it's not quite elegant). I like SQLAlchemy a lot! Here's a couple of sqlalchemy tricks I like. First one:

    fields = [
        User.user_name,
        User.display_name,
        User.email_address
    ]
    results = User.query.filter(or_(*[f.ilike('%' + q + '%') for f in fields]))


The above code does a wildcard partial string match of the string q against any of the three fields listed in the fields list. Second example:

    page = User.query[10:20]
           
This looks like array slicing, but no, it's slicing against the query results! It's smart enough to build the query using OFFSET and LIMIT or equivalent. You can easily do pagination with this technique.

Python's Named Parameters
Another thing I like when working with turbogears is python's named parameters. Whereas rubists use the hash as the poor man's name parameters, python has real named parameters, which is not only safer, but more elegant.

Python's Polluted Name Space
I run into this problem once in a while, but I hit on it 2 or 3 times in the last week! In python, list, dict, str, int, etc. are the names of fundamental types in the language, therefore you can't(actually you can, but don't want to) use them as variable names. More than once I've tried to use list as a variable name, which python doesn't complain about immediately but causes a cryptic error down the road.
I've also tried use from as a variable name, which turns out to be a keyword in the language, this causes a syntax error, which you don't see until you realize it's a keyword. Now, of course, more languages suffer from this problem, ruby isn't any different, but I think ruby has better error messages for these syntax errors: it will tell you the symbol that is unexpected and what symbols it was expecting.

Little Verbosity
Turbogears is more verbose than rails most prominently in 2 areas: import statements and method decorators. Rails files, usually have at most 2 requires(counterpart of import in python), most of the time none at all. My TG controller files and the model.py(the file with all the model objects) usually have about 10 to 15 lines of includes, my Mako template files usually 2 to 4 lines of includes. This has a lot to do with the design of the language. The python interpreter requires each .py file to act like a module, and as a module, it must identify all of its dependences, the ruby interpreter does not require this and so your controller code, for example, doesn't need to explicitly require anything before it has what it needs to do its work.
I think method decorators are cool, but they can also be overused and become cluttery. Some of my controller methods have more than 4 or 5 lines of decorators, consisting of the mandatory expose(), access restriction spec, and form parameter validators. That's a bit much. I also don't like the fact that you need an expose() decorator for every single controller method. Rails has no such thing and usually specifies such things at the top of the class, which has pros and cons vs TG's approach, but is at the end less cluttery.

parameter list chaining in python

by airportyh posted at 07-15-2008 03:12PM - Comments (0)   programming python
Python has great support for variable length parameter lists, you have optional parameters:

>>> def o(opt=1):
...   print opt
...
>>> o()
1
>>> o(2)
2
>>> o(opt=3)
3


then you have the one star for any number of parameters:

>>> def f(*params):
...   for p in params: # params is a list
...     print p
...
>>> f(1)
1
>>> f(1,2,3,4)
1
2
3
4


and you got two stars for keyword parameters:

>>> def g(**kws):
...   for item in kws.items(): # kws is a dict
...     print item
...
>>> g(one=1)
('one', 1)
>>> g(one=1, two=2, three=3)
('three', 3)
('two', 2)
('one', 1)


You can also use them together along with regular parameters and optional parameters as long as they follow the ordering: regular > optional > single star(varargs) > double star(keyword args):

>>> def h(req, opt=None, *params, **kws):
...   print 'req=', req
...   print 'opt=', opt
...   print 'params=', params
...   print 'kws=', kws
...
>>> h(1,2,3,4)
req= 1
opt= 2
params= (3, 4)
kws= {}
>>> h(1,two=2,three=3,four=4)
req= 1
opt= None
params= ()
kws= {'four': 4, 'two': 2, 'three': 3}

>>> h(1,two=2,three=3,opt=4)
req= 1
opt= 4
params= ()
kws= {'two': 2, 'three': 3}


If you have a handle on a list or a dict object, you can use it/them directly as the parameter list when you call a function:

>>> lst = [1,2,3]
>>> f(*lst)
1
2
3
>>> dct = dict(one=1,two=2,three=3)
>>> g(**dct)
('one', 1)
('three', 3)
('two', 2)


A techique I developed is to chain function calls lazily, sort of a poor man's partial function application. Say I have a function that takes a lot of optional parameters, let's say it generates a text field of some sort:

def textfield(label, name, size=10, classname='', id=None, onclick=None, onkeypress=None):
    # blah

Now for my specific screen I want to specify a number of these parameters by default, and only vary the label and name parameters the rest of the way, so I do something like:

def tf(*params, **kws):
    textfield(size=20, classname='cool-field', *params, **kws)


now I can call it like this:
tf('Name', 'name')
tf('Birthdate', 'birthdate', onkeypress="checkBirthdate(this)")


The cool part about this is that I can add new optional parameters to textfield without having to change tf and yet still be able to use the new parameters from tf. I could have just as well use the partial function from the functional library, but this is pretty easy too.