In these recent weeks, i'm writing a javascript UI component that can shrink/expand and hide/show. I call it "browser" in later paragraphs.
It's a pretty easy-to-write component where it only has 3 different states as shown below.
The first state is a hidden state which the "browser" hides itself somewhere in the page.
When clicking on those boxes shown, the "browser" shows itself and presents an abstract view of data.
When selecting a little box of the list on the right, the "browser" enters a state that displays detail view of data.
Whenever in either the abstract or detail state, once the grey-out area or the little close button [x] got a click on it, the browser goes back to hidden state. And, the browser can switch between the abstract state and the detail state by clicking on some buttons.
So, it sounds strict forward and thus my very first naive attempt was to implement it by just using the event-driven approach which i explicitly controlled the hide/show and shrink/expand line-by-line with the help of some if-else statements.
But after doing that for 2-3 days... the mess becomes not-that-easy to manage and little UI bugs come out from those event handler blocks. I had to trace those handler blocks and to find out where the UI effect went wrong. So, i decided to rewrite the entire mess with the GoF State Pattern (spending half an hour or so in implementing that) and post it here :P
As i wrote, the "browser" has some states {hidden, abstract, detail} and each state will transit to each another triggered by some events. It is pretty nice that the situation aligns to the state pattern perfectly. So, what i need to do with javascript is to implement a browser object that holds a state object where the state object references to either a hidden or abstract or detail state object.
The above class diagram shows some of the details of my implementation. The enter() function of HiddenState is to hide the browser while the paint() function of it is to show the browser and transits the browser state from hidden to abstract. When AbstractState is set, it's enter() function displays the abstract content. Upon some events like button click, browser's roll() function is called and delegated to AbstractState roll() function where DetailState is going to be entered.
The full implementation of this "browser" is available at github (line 323-559). Although it's pretty long (i already skipped implementing the inheritance :P), the "browser" now is simply mixing the State pattern and UI event handlers for ui transition, effects, and content displaying. If you trace further down the source, you will find my naive strict forward implementation of the "browser" where i believe it's pretty a mess to manage :P
Tuesday, August 24, 2010
hacker...
in these few days, i was packing my desktop in school as i'm leaving it very soon. From the desktop, i found something which is GREAT and got my focus.
flying back to 2009 autumn, there was a zeuux summit held in CityU. It was my pleasure to see Richard Stallman and Akira Urushibata there.
And, what i found in my desktop is Akira's excellent presentation "slide". Enjoy it :D
flying back to 2009 autumn, there was a zeuux summit held in CityU. It was my pleasure to see Richard Stallman and Akira Urushibata there.
And, what i found in my desktop is Akira's excellent presentation "slide". Enjoy it :D
Labels:
foss
Tuesday, August 03, 2010
python decorator for input validation
I was reading how decorator in python can be used to state machine... And, wonder, can this also apply to input validation for web framework like web.py.
I tried the following:
I tried the following:
def getInput(): ''' simulate web.input() for web.py framework ''' return { 'x': 'banananaa', 'y': None, 'z': 'zz', } def validate_required(rules): ''' validation decorator ''' def wrapper(method): ''' wrapping the actual handler ''' def validate(*args, **kwargs): ''' validation take places according to rules ''' inputs = getInput() for k in inputs.keys(): if k in rules: f = rules[k] else: continue input = inputs[k] if not f(input): out = 'Invalid input %s - %s' % (k, input) print out # or raise Exception here to stop execution return method(*args, **kwargs) return validate return wrapper class Handler: rules = { 'x': lambda(x): len(x) > 0, 'y': lambda(y): y is not None, 'z': lambda(z): z is not None and len(z) > 3, } @validate_required(rules) def POST(self): print 'do something' # simulate request handling h = Handler() h.POST()
Labels:
foss