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 -~----------~----~----~----~------~----~------~--~---