To me, and I'm sure many of you, /lift/ is more than just a web
framework; it is the blazing torch that will lead web developers out
of the darkness and into a glorious new age of innovation. Perhaps
that's a bit dramatically worded, but the opportunity is definitely
there, the stage is set. Over the past decade we've seen many good
frameworks rise and fall, each one offering something fantastic and
groundbreaking. There's an uproar of buzz and chatter, bloggers
extolling the great virtues of what looks to be 'the next best things
since sliced bread..." or, rather, the next best thing since the last
framework they raved about. A few years pass and the framework drops
off the face of the earth. But this wont happen to /lift/. Why?
Because we're going to learn from the successes and failures of the
frameworks before us and deliver something that developers will cry
for.
One important lesson I think we can learn from past frameworks is that
you need to allow third parties the ability to develop products that
expand your framework. What's more, you need to cater to them. The
resulting implicit co-branding is priceless. /lift/ is written in what
I believe to be the next "up and coming" language, and as a result
will share in some of the buzz that surrounds it. Companies will want
to take advantage of the wagon and some how hook into the success.
Remember JSF? Everyone got on board with writing widgets/components
for it and as a result several big names were advertising it. Its buzz
had buzz!
Outside of marketing and outside of usability, there is one
incontrovertible motivation; /lift/ is an awesome framework, it should
have an awesome widget system. One that overcomes the limitations of
others in the market and excels at meeting the demand of a widget
writer to deliver high quality widgets so that they may excel excel at
meeting the user's demands for delivering high quality web
applications. To kick this discussion off I'll outline the important
features of what I believe to be the perfect system.
* A single page should be able to support widgets from multiple
libraries. This seems like a no-brainer, but surprisingly isn't
possible with Ruby on Rails out of the box
* There should be a system where a widget can specify required
resources and have them injected dynamically by the renderer.
* Widgets should be able to access and inject into <head>...</head>.
* Widgets should have access to their children, parent, and other
widgets on the page (this last part by id).
* There should be a phase that each widget undergoes before /any/
rendering occurs
* Widgets should be able to attach "Ajax Listeners" to 1) the users
session, 2) the rendered page, 3) the application. Not sure how this
last part fits into the current system, but would be a huge step in
the right direction, especially if closures were supported.
attachAjaxListener(listener, scope)
* The ability to customize the rendering of a widget's children
* The ability to customize the render lifecycle of each component
The life cycle I propose (This is scratch, so bear with me and build
on my ideas)
1) XML document is parsed
2) Tags are converted to instances of the corresponding widget and
stored in some kind of ordered map
3) Objects are outfitted with a reference to a "Page" object, which is
a widget itself, that represents the page. This object may also
include links to needed resources (javascript, css, other pages) and
provides the widgets with an opportunity to inject requirements.
3) The Page's render method is called.
4) Rendering then occurs, building an xml tree. Each widget inherits a
render method that then calls
A. startTag
B. tagBody
C. renderChildren <- is passed a list of children
D. endTag
5) xml is pushed to the client and ajax listeners wait to be abused
Ideas? Suggestions? Rejection?
I have written widget/component libraries for several frameworks and
am absolutely sick of limited, unusable, and overly complex widget
systems. So I figured I'd submit to this group an outline of my dream
widget system, in hopes of using this project as a means of bringing
that dream into fruition.
To me, and I'm sure many of you, /lift/ is more than just a web
framework; it is the blazing torch that will lead web developers out
of the darkness and into a glorious new age of innovation.
Perhaps
that's a bit dramatically worded, but the opportunity is definitely
there, the stage is set. Over the past decade we've seen many good
frameworks rise and fall, each one offering something fantastic and
groundbreaking. There's an uproar of buzz and chatter, bloggers
extolling the great virtues of what looks to be 'the next best things
since sliced bread..." or, rather, the next best thing since the last
framework they raved about. A few years pass and the framework drops
off the face of the earth. But this wont happen to /lift/. Why?
Because we're going to learn from the successes and failures of the
frameworks before us and deliver something that developers will cry
for.
One important lesson I think we can learn from past frameworks is that
you need to allow third parties the ability to develop products that
expand your framework. What's more, you need to cater to them. The
resulting implicit co-branding is priceless. /lift/ is written in what
I believe to be the next "up and coming" language, and as a result
will share in some of the buzz that surrounds it. Companies will want
to take advantage of the wagon and some how hook into the success.
Remember JSF? Everyone got on board with writing widgets/components
for it and as a result several big names were advertising it. Its buzz
had buzz!
Outside of marketing and outside of usability, there is one
incontrovertible motivation; /lift/ is an awesome framework, it should
have an awesome widget system. One that overcomes the limitations of
others in the market and excels at meeting the demand of a widget
writer to deliver high quality widgets so that they may excel excel at
meeting the user's demands for delivering high quality web
applications. To kick this discussion off I'll outline the important
features of what I believe to be the perfect system.
* A single page should be able to support widgets from multiple
libraries. This seems like a no-brainer, but surprisingly isn't
possible with Ruby on Rails out of the box
* There should be a system where a widget can specify required
resources and have them injected dynamically by the renderer.
* Widgets should be able to access and inject into <head>...</head>.
* Widgets should have access to their children, parent, and other
widgets on the page (this last part by id).
* There should be a phase that each widget undergoes before /any/
rendering occurs
* Widgets should be able to attach "Ajax Listeners" to 1) the users
session, 2) the rendered page, 3) the application. Not sure how this
last part fits into the current system, but would be a huge step in
the right direction, especially if closures were supported.
attachAjaxListener(listener, scope)
* The ability to customize the rendering of a widget's children
* The ability to customize the render lifecycle of each component
The life cycle I propose (This is scratch, so bear with me and build
on my ideas)
1) XML document is parsed
2) Tags are converted to instances of the corresponding widget and
stored in some kind of ordered map
3) Objects are outfitted with a reference to a "Page" object, which is
a widget itself, that represents the page. This object may also
include links to needed resources (javascript, css, other pages) and
provides the widgets with an opportunity to inject requirements.
3) The Page's render method is called.
4) Rendering then occurs, building an xml tree. Each widget inherits a
render method that then calls
A. startTag
B. tagBody
C. renderChildren <- is passed a list of children
D. endTag
5) xml is pushed to the client and ajax listeners wait to be abused
Ideas? Suggestions? Rejection?
> > * A single page should be able to support widgets from multiple
> > libraries. This seems like a no-brainer, but surprisingly isn't
> > possible with Ruby on Rails out of the box
>
> Yes. There's one caveat with this that I've recently run into with jQuery
> vs. Scriptaculous... the namespace issue. This is more of a JavaScript
> issue, but it still exists... sigh.
>
If you're speaking about keeping variable names unique, what I've done
in the past (with java web frameworks) is write a utility for
generating unique names and have it persist itself in the user's
request.
> > * Widgets should have access to their children, parent, and other
> > widgets on the page (this last part by id).
>
> I'd like to understand some use cases for this.
>
If you want a widgit to render differently depending on its
environment, or if you want one widgit to modify itself or another
widgit. Like say you have a widgit that generates a special kind of
ajax form, why write multiple kinds of fields and confuse the
implementor when you can just write one and have it adjust to fit the
circumstance. Or say you want to add conditional rendering depending
on a widgits children. An "[ajax] validator" widget would be an
example of this. This sort of drop in extra functionality makes people
go crazy. Or if you have an ajax data grid that automatically updates
values based on xml. Now you could define all the different attributes
(location of xml, interval of refresh, which data to grab, what
formatting should be done to that data, etc etc) in one place or you
could separate the "grid" concept from the "dataset" concept and have
two, especially the second one, reusable widgets. Or to take it a bit
further, what if they don't want to use a dataset to populate the
grid? What if they want to use a different method... It's about
providing implementors/users with the freedom they deserve... and
making our job as simple as possible later down on the road.
> > * There should be a phase that each widget undergoes before /any/
> > rendering occurs
>
> Yeah... makes sense... although there's a nasty circular issue... lift
> snippets can emit XHTML that is then run through the method that looks for
> lift tags so that it's possible for a snippet to emit code that will contain
> <lift:snippet/> tags that will be properly processed. This level of
> recursion has come in quite handy ( e.g., a side bar that's a log-in panel
> if the user's not logged in or a friend list if the user is logged in.)
> Having an explicit pre-processing phase will likely rule out recursive
> snippets.
>
I think you could solve this by allowing widgets to add children to
themselves or others (which has value of its own). Allowing for this
sort of functionality would be the main point of a preprocessing
phase.
> > * Widgets should be able to attach "Ajax Listeners" to 1) the users
> > session, 2) the rendered page, 3) the application. Not sure how this
> > last part fits into the current system, but would be a huge step in
> > the right direction, especially if closures were supported.
> > attachAjaxListener(listener, scope)
>
> That's already a reality. Ajax calls are already bound to functions (I was
> demoing this to a guy on the Groovy team on Friday and he was amazed at how
> little code it took to do Ajax and how natural the code flowed.)
>
Are they scoped like I described? If they aren't it would be cool if
we could work that in... A user specific session persisted ajax
listener with a memory seems /very/ useful.
> > * The ability to customize the rendering of a widget's children
> > * The ability to customize the render lifecycle of each component
>
> Please tell me a little more about what you mean by the above.
>
Alright, so each widget has 5 rendering methods each representing a
stage in the life cycle:
preProcess, startTag, tagBody, renderChildren, endTag
and then a "render" method that invokes the 5. The renderChildren
method, when not overridden, invokes the "render" method of its
children. This gives a widgit designer absolute control and minimizes
how much code needs to be written by us and others. In case some one
in the world hasn't noticed, I'm all about allowing for customization.
The added benefit is there is no overhead from rendering code outside
of the widgit, the widgit's existence takes up exactly as much
resources as it needs to deliver its payload
> > Ideas? Suggestions? Rejection?
>
> Suggestions (in random order):
>
> Please help me understand the stuff I've flagged
If any questions remain, please go ahead and ask them, I know I can be
vague sometimes.
> Please help me understand how I can deal with reaching for the high goals
> you've set for lift (okay this is a joke that underlies my fears of
> failure.)
Well, having a plan is always good. I decided to start a new post to
answer this one
> Sign the lift IP assignment and send to to me so I can make you a committer
I have some work I need to get to, but I definitely will later. For
awhile my primary contribution might have to be in the list since I've
been mobbed lately with work and school (yes, I'm still an undergrad).
Luckily I've been finding ways to incorporate scala/lift/java into
work and school.
> Tell us a little about the projects your working on
Once I become a committer I'll do the Hello post and introduction.
> Create some use cases and scenarios to help us all understand the "why"
> behind the suggestions
If after this post there is anything still left foggy, let me know and
I'll try to clarify.
> Keep up the good workThanks,
>
> David
>
> > > >
> >
>
> > * Widgets should be able to attach "Ajax Listeners" to 1) the users
> > session, 2) the rendered page, 3) the application. Not sure how this
> > last part fits into the current system, but would be a huge step in
> > the right direction, especially if closures were supported.
> > attachAjaxListener(listener, scope)
>
> That's already a reality. Ajax calls are already bound to functions (I was
> demoing this to a guy on the Groovy team on Friday and he was amazed at how
> little code it took to do Ajax and how natural the code flowed.)
>
Are they scoped like I described? If they aren't it would be cool if
we could work that in... A user specific session persisted ajax
listener with a memory seems /very/ useful.