Ajax request may well replace parts of a page to which observers had been attached previously. The original observers may have been attached completely explicitly or more implicitly through behavio(u)r-like constructs. It is rather unlikely that knowledge about all such observers is localized in one place in the application code. Given these constraints, has someone devised an elegant way to re-attach equivalent observers after an update? Michael -- Michael Schuerig mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org http://www.schuerig.de/michael/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Create widget classes that encapsulate their own Ajax needs (i.e. autonomous
controls that handle their own html refreshing), and when one redraws
itself, re-attaches its own behaviors as needed. Each widget can be viewed
as its own mini-page.
The pattern on a high level is as follows:
Page level (can be thought of as the main application level in a standard
desktop MVC app)
---contains N controls (or widgets as we like to call them nowadays)
Widget level
---each has it''s own Ajax functionality, usually derived from a base
class
---can contain N children widgets (i.e. refreshing the outermost widget
causes its children to be redrawn via recursive piggybacking - piggybacking
can be implemented so only 1 request is required for N children rather than
N requests being queued up)
---Widget life-cycle:
1. Initial request - server renders html out to client, widget''s
container element inserts html
- Any children included in the widget''s definition are also
rendered recursively
- After html is rendered on client, a custom event is fired
(onInit for example), recursively for each widget and its children
- Each widget class has an internal init event handler which
applies behaviors to its DOM elements as required (sets up
draggables, click
handlers, etc..)
2. Subsequent requests
- a user interaction or other event triggers a widget to need to
make a server request to update its HTML
- A dispose method handles removing all behaviors,
unregistering draggables (etc..), and cleaning up it''s
resources before the
server request is made. This method is also responsible for
recursively
calling dispose on all the children widgets, as nested
children will also be
redrawn via piggybacking.
- If the widget in question is a child widget, it makes
its own request and updates its own html, re-attaches
behaviors after render
just as in step one, with no need for its parent or siblings to redraw
themselves (autonomous controls)
- Once the cleanup is done, a new request is made and the
steps in #1 above are repeated
3. Garbage collection
- it is very helpful in larger scale applications to have a
global garbage collector queue up requests for resource
de-allocation in an
asynchronous manner to aid overall application performance
Event Bus
---An application wide event (pub/sub model) mechanism is usually a
requirement to allow widget-to-widget communication and for the app-level to
dispatch global events which the widgets can respond to
---For a very easy to use custom event publisher, see my EventPublisher
class as posted earlier in the year (file attached as .txt, and link to post
on this list explaining usage:
http://threebit.net/mail-archive/rails-spinoffs/msg00538.html) -- the code
in this attached file is slightly updated from that post, use the file, not
the code at that link.
On 12/16/06, Michael Schuerig
<michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org>
wrote:>
>
>
> Ajax request may well replace parts of a page to which observers had
> been attached previously. The original observers may have been attached
> completely explicitly or more implicitly through behavio(u)r-like
> constructs. It is rather unlikely that knowledge about all such
> observers is localized in one place in the application code.
>
> Given these constraints, has someone devised an elegant way to re-attach
> equivalent observers after an update?
>
> Michael
>
> --
> Michael Schuerig
> mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org
> http://www.schuerig.de/michael/
>
> >
>
--
Ryan Gahl
Application Development Consultant
Athena Group, Inc.
Inquire: 1-920-955-1457
Blog: http://www.someElement.com
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Spinoffs" group.
To post to this group, send email to
rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---
On Saturday 16 December 2006 18:27, Ryan Gahl wrote:> Create widget classes that encapsulate their own Ajax needs (i.e. > autonomous controls that handle their own html refreshing), and when > one redraws itself, re-attaches its own behaviors as needed. Each > widget can be viewed as its own mini-page.I''m not convinced that approach will work in general. A concrete case I have in mind is this: I have a form where some input elements (kind as well as content) depend on the choices in other elements. Depending on what the user enters into the form, the dependent elements are updated by means of ajax requests. Also, the elements are continuously monitored by a purely client-side validator and immediately notify the user of invalid input. Unfortunately, these two concerns, dynamic form update and continuous validation, cut across each other. At the moment, they are blissfully ignorant of each other and that''s how it ideally should be. The drawback is that dynamically (ex)changed input elements are not hooked into the validator. The solution you suggest would, in my understanding, engender that I replace the simplicity of <%= f.text_field :last_name %> with a client-side framework managing components -- "widgets". Widgets would be anything but simple, instead they would have to fulfill several contractual obligations for playing nicely with their encompassing framework, such as sending and receiving life-cycle events. In such an environment it would certainly be possible to keep the concerns I mention above separated, but at a huge cost of developing the infrastructure first. I certainly agree that it would be great to have a (standard) client-side component framework integrated with Rails. However, this is not the case, yet, and I''m very reluctant to stumble in that direction on my own. For what it''s worth, there is a project aiming at integrating Dojo with Rails: http://rubyforge.org/projects/rojo/ I asked Alex Garrett about it at the beginning of August. He was then targetting end of August for a first release and mid October for "very railsy dojo widget integration". I take it as indicative of the effort involved that there has not been any release yet. Michael -- Michael Schuerig mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org http://www.schuerig.de/michael/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
OK, just a suggestion. Sounds like you''re not really working with a long lived single page app anyway. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Sunday 17 December 2006 00:01, Ryan Gahl wrote:> OK, just a suggestion. Sounds like you''re not really working with a > long lived single page app anyway.Indeed, sorry I didn''t explain better what I''m doing from the start. I''m not meaning to dismiss your suggestion either. It''s just that, in my opinion, it appears overly complicated for applications essentially composed of multiple pages. Here''s an idea I haven''t tried and I''m not sure if it is workable. Methods in the Event namespace already keep track of objects and their attached observers. Here''s a (faulty!) method that demonstrates what I have in mind update: function() { for (var i = 0, length = Event.observers.length; i < length; i++) { var observer = Event.observers[i]; var element = observer[0]; if (!Element.isInDOM(element)) { Event.stopObserving.apply(this, observer); if (element.id != '''') { var replacement = $(element.id); if (replacement) { observer[0] = replacement; Event._observeAndCache(this, observer); } } } } } (As is, this method messes up Event.observers array.) A method that (correctly) implements this idea could be hooked into ajax requests that change the DOM. Obviously, the above method depends on some way of finding elements in the updated DOM that correspond to removed elements. The best I''ve come up with is using an explicit id. This won''t work in the important case, where observers are attached to elements not based on their id, but based on more circumstantial conditions such as CSS selectors. Michael -- Michael Schuerig mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org http://www.schuerig.de/michael/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Michael Schuerig wrote:> On Sunday 17 December 2006 00:01, Ryan Gahl wrote: > > OK, just a suggestion. Sounds like you''re not really working with a > > long lived single page app anyway. > > Indeed, sorry I didn''t explain better what I''m doing from the start. I''m > not meaning to dismiss your suggestion either. It''s just that, in my > opinion, it appears overly complicated for applications essentially > composed of multiple pages. > > Here''s an idea I haven''t tried and I''m not sure if it is workable. > Methods in the Event namespace already keep track of objects and their > attached observers. Here''s a (faulty!) method that demonstrates what I > have in mind > > update: function() { > for (var i = 0, length = Event.observers.length; i < length; i++) { > var observer = Event.observers[i]; > var element = observer[0]; > if (!Element.isInDOM(element)) { > Event.stopObserving.apply(this, observer); > if (element.id != '''') { > var replacement = $(element.id); > if (replacement) { > observer[0] = replacement; > Event._observeAndCache(this, observer); > } > } > } > } > } > > (As is, this method messes up Event.observers array.) > A method that (correctly) implements this idea could be hooked into ajax > requests that change the DOM. > > Obviously, the above method depends on some way of finding elements in > the updated DOM that correspond to removed elements. The best I''ve come > up with is using an explicit id. This won''t work in the important case, > where observers are attached to elements not based on their id, but > based on more circumstantial conditions such as CSS selectors. > > Michael > > -- > Michael Schuerig > mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org > http://www.schuerig.de/michael/The easiest solution I''ve seen for this is to 1. destroy all the observers 2. recreate them after the page is modified _Kevin --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Hi, You might also want to have a look at event delegation: http://icant.co.uk/sandbox/eventdelegation/ cheers, Tobie --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Sunday 17 December 2006 03:27, _Kevin wrote:> The easiest solution I''ve seen for this is to > 1. destroy all the observers > 2. recreate them after the page is modifiedThereby killing any pretense of modularity. For this to work, you''d essentially have to create all your observers from one place. Michael -- Michael Schuerig mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org http://www.schuerig.de/michael/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Sunday 17 December 2006 08:34, tobie wrote:> You might also want to have a look at event delegation: > > http://icant.co.uk/sandbox/eventdelegation/Yes, that''s the right approach when the same (kind of) observer is attached to a number of similar elements. In general, you can''t assume that. Also, I think "event delegation" is not a good name for the approach. It''s just a case where event bubbling is used to implement a Chain of Responsibility. Michael -- Michael Schuerig mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org http://www.schuerig.de/michael/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Michael Schuerig wrote:> On Sunday 17 December 2006 03:27, _Kevin wrote: > > The easiest solution I''ve seen for this is to > > 1. destroy all the observers > > 2. recreate them after the page is modified > > Thereby killing any pretense of modularity. > > For this to work, you''d essentially have to create all your observers > from one place. > > Michael > > -- > Michael Schuerig > mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org > http://www.schuerig.de/michael/It''s easy, not necessarily good. _Kevin --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---