Issue with Function.bindAsEventListener When used with Event.observe like Event.observe(document,"mousedown", myobj.fnc.bindAsEventListener(myobj)) how do I do a stopObserve on this? doing something like this works correctly Event.observe(document, "mousedown", this.onMousedown) Event.stopObserving(document,"mousedown",this.onMousedown) The problem here is I have to set a global reference of my object (this) and use that in the onMousedown event. Any ideas as to how I can make use of bindAsEventListener here? --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
This is one of those things that gets to be very tedious when working with Event.observe. Currently, you have to store the function like so: this.onMousedownListener = this.onMousedown.bindAsEventListener(this); Event.observe(document, "mousedown", this.onMousedownListener); Event.stopObserving(document,"mousedown",this.onMousedownListener); If you are interested, I have submitted a patch that helps make stuff like this easier, here: http://dev.rubyonrails.org/ticket/7435 It allows you to use "wildcards" in your stopObserving like so: Event.stopObserving(document, "mousedown"); However, this would be bad practice since it would quite possibly stop observers that you didn''t want to stop. To handle this, and as an improvement for other reasons, I have suggested an EventCache API. With it you can do something like: this.events = new EventCache(); this.events.observe(document, "mousedown", this.onMousedown); //add any number of other observers to this instance of EventsCache... //stop all observers of "mousedown" for document that are stored *in this EventCache* //i.e. the function is still a wildcard, but if say another library was observing //document for "mousedown", this would not affect them this.events.stopObserving(document, "mousedown"); If you you had other observers on the same element and on the same event *and* in the same EventCache that you didn''t want to stop, then you''d still have to do something like before where you store a reference to the function you attached in the first place. There is no way to get around storing a reference in that case, but very rarely will that be necessary if you use a separate EventCache for every widget or class. If you just want to do mass-cleanup, you could stop all observers in a particular instance of an EventCache with: this.events.stopObserving(); Colin ar wrote:> Issue with Function.bindAsEventListener > When used with Event.observe like Event.observe(document,"mousedown", > myobj.fnc.bindAsEventListener(myobj)) > how do I do a stopObserve on this? > > doing something like this works correctly > > Event.observe(document, "mousedown", this.onMousedown) > Event.stopObserving(document,"mousedown",this.onMousedown) > > The problem here is I have to set a global reference of my object > (this) and use that in the onMousedown event. > > Any ideas as to how I can make use of bindAsEventListener here? > > > > > >--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Colin Mollenhour wrote:> This is one of those things that gets to be very tedious when working > with Event.observe. > Currently, you have to store the function like so: > > this.onMousedownListener = this.onMousedown.bindAsEventListener(this); > Event.observe(document, "mousedown", this.onMousedownListener); > Event.stopObserving(document,"mousedown",this.onMousedownListener); >I understand that cross-browser element observation is very complex when you start thinking about caching, stopping observation, and dealing with IE''s limitations--just look at the comments and links here: http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html. A different approach occurred to me. What are the thoughts on having Event.observe return something? For example, the code above could become: this.onMousedownListener = Event.observe(document, "mousedown", this.onMousedown.bindAsEventListener(this)); Event.stopObserving(document,"mousedown",this.onMousedownListener); Or what about an even simpler approach: var handle = Event.observe(document, ''mousedown'', this.onMousedown.bindAsEventListener(this)); handle.stopObserving(); ...where Event.observe returns a object "handle": Event.observe = function(element, name, observer) { element = $(element); ...IE model... element.addEventListener(name, observer, false); return { stopObserving: function() { element.removeEventListener(name, observer, false); }, element: element, event: name, function: observer }; }; The above function would lend itself nicely to the caching of handles, stopping all observation of a particular element or element+event, clearing all on IE unload, and it could be made to be 100% backwards compatible with the use of Event.stopObserving. What do you think? -- Ken Snyder --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Ken, definitely a good bit of candy. Nice thinking. I''d say get that code tested out and submit it as a patch. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
> A different approach occurred to me. What are the thoughts on having > Event.observe return something?I have thought about this before, and gave it some more thought since you mentioned it. I do agree that it would be clean in some cases, but not in others... I''d have to see the code to make a final judgment but here are my thoughts. Consider that for a class you want to be able to do very easy event cleanup on disposal of that class/widget. The way to do this using your proposal would be to store the events in an array so you can clean them all up without testing if one still exists or not. This would also let you cleanup additional events that your dispose method has no knowledge of, say if events were added in an onComplete call or something. this.events = []; this.events.push(Event.observe(element,''click'',this.onClick.bindAsEventListener(this)); this.events.push(Event.observe(element,''mouseover'',this.onMouseover.bindAsEventListener(this)); You could then stop all events in that array with: this.events.invoke(''stopObserving''); Except that wouldn''t remove those events from the array so to do proper cleanup you''d still have to: while(this.events.length){ this.events.shift().stopObserving(); } which is a little messier.. However, the problem occurs when you want to stop just the mouseover, you no longer have an easy way to do this while still doing proper cleanup. Not to mention, you are duplicating your event caching. The API I proposed in ticket #7435 let''s you group a bunch of arbitrary events to an object while still allowing you to clean them up individually if necessary. Since it adds "wildcards", returning an object of some sort wouldn''t be necessary to allow you to avoid having to store function references. *However*, if you really wanted the ability to return handle for an event, it could be added to the patch I submitted easily enough. The API would then look like: var handle = Event.observe(element,''click'',someFunction.bind(this)); Event.stopObserving(handle); and when using it alongside my EventCache API: this.events = new EventCache(); this.elementClick = this.events.observe(element,''click'',someFunction.bind(this)); The above handler could be cleaned up either way: 1) this.events.stopObserving(element,''click''); 2) this.events.stopObserving(this.elementClick); The second way being better if you had multiple functions observing the same element on the same event and didn''t want to stop them all. As far as what the return value is, I would make it an index to the event cache array. The EventCache would have to be changed to use "delete" rather than splice() so that the array indexes don''t change. This would prevent redundant storage of the [element,name,observer,useCapture] array. The stopObserving function could distinguish a handle from an element since the typeof for the handle would be "number" so there is no need to add an additional method. I did like the usage of splice though since it keeps the cache array small. Otherwise you have to loop through an ever-growing array for every call to stopObserving, unless of course you are using the handle as an index or are doing mass-cleanup. The number of events on a single page can become quite staggering so anything to increase efficiency is a good thing. For this reason I don''t think using a closure for every event is a good idea. Your suggestion could be added to my EventCache in a clean, efficient way where the only thing lost is the chaining (no biggie, chaining is overrated anyway) and the use of splice (the current Event class doesn''t take advantage of this anyway). It may be possible to use a key in a hash instead of an index in an array to avoid the long-looping issue.. Best of both worlds! What do you think? Colin --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Colin Mollenhour wrote:>> A different approach occurred to me. What are the thoughts on having >> Event.observe return something > It may be possible to use a key in a hash instead of an index in an > array to avoid the long-looping issue.. > > Best of both worlds! What do you think? >Yes. I posted my first draft to the Prototype-core list, read your response, then posted a second draft there as well. I think we are really on to something with an indexed object as an observer cache instead of an array. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---