I want to take an existing DOM object and extend it with some functionality. I know there''s a way to do this with prototype. Unfortunately, I''m not entirely sure how to do this. Basically, I want to take an existing DOM object and turn it into a ''widget'' by adding some functionality. say we have a span: <span id="blah">some text here</span> I want to be able to, in javascript, do something like this: var whatever = new ActiveSpan("blah"); and have the ActiveSpan class extend it with some functionality (like onclick events, attributes, etc) here''s what I have in mind, but I''m not sure this is exactly correct: var ActiveSpan = Class.create(); ActiveSpan.prototype = { initalize: function(span) { Object.extend(span, this); this.registerCallbacks(); }, registerCallbackss: function() { Event.observe(this, ''click'', clickHandler.bindAsEventListener(this); }, clickHandler: function(e) { this.style.background = "red"; } } does this look right? Also, I''ll eventually want to go through the child elements in the initalize method to set those children up as well. The overall goal of this is to create an enhanced table class where you just call a function and it does all sorts of things like handling mouseovers, mouseouts, zebra striping, etc. If I''m completely wrong, and someone has an example they can point me at, that would be great! If this looks ok, though, I''ll continue on with it :) If this is not possible, or if I have to attach my code to the object like: span.BLAH = new ActiveSpan .. let me know :) I just want to do this in an as prototype-like way as possible. -Jeremy _______________________________________________ Rails-spinoffs mailing list Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs
Jeremy Kitchen
2006-Mar-09 21:22 UTC
Re: extending an existing DOM object in a prototype way
On Thursday 09 March 2006 13:12, Jeremy Kitchen wrote:> var ActiveSpan = Class.create(); > ActiveSpan.prototype = { > initalize: function(span) { > Object.extend(span, this);actually, that would be $(span), but you get the idea ;) (I hope!) -Jeremy -- Jeremy Kitchen ++ kitchen-RA8HwDor7flnDGu+y90WmgC/G2K4zDHf@public.gmane.org In the beginning was The Word and The Word was Content-type: text/plain -- The Word of Bob. _______________________________________________ Rails-spinoffs mailing list Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs
This is a good (and common) practice. A good rule I try to stick to is, if more than 1 element needs some specific behaviors/functionality, make a separate class for that, and extend the element with it when needed. There are a couple things to keep in mind. One is, you almost always will need to have a setup() method in your behavior class which you can call after extending the element, which will actually handle wiring up event handlers/activating the "widget". Two, keep handles to all your event handlers (unlike what you did in your example), which leads to.. Three, define a dispose() method to clean up resources when the widget (or behavior) is no longer needed... Finally, I don''t do the extending from within the controller class, like in your example. I reserve the contructor arguments for other things, like behavior options, etc.. (or sometimes for passing a reference to the parent object), then I use an instance of the controller to do the extension from the application (or outer object) scope. Like so... var ActiveSpan = Class.create(); ActiveSpan.prototype = { initalize: function(options) { // setup the widget options... this.options = Object.extend({...default options...}, options || {}); }, setup: function() { //making this an instance method ensures you are wiring up events to a DOM element (i.e. the element has already been extended with this class -- "this" will now be the DOM element extended with the ActiveSpan methods, and not just an "ActiveSpan") this.registerCallbacks(); } registerCallbackss: function() { //ALWAYS store DOM handlers in variables so you can dispose of them (prevent memory leaks) this.clickHandlerPointer this.clickHandler.bindAsEventListener(this); Event.observe(this, ''click'', this.clickHandlerPointer); }, clickHandler: function(e) { this.style.background = this.options.color || "red"; }, dispose: function() { //get rid of the DOM event handlers... Event.stopObserving(this, ''click'', this.clickHandlerPointer); this.clickHandlerPointer = null; //...other disposal code... } }; ...Then in your calling code (I''m assuming it''s another object)... var myActiveSpanBase = new ActiveSpan({"red"}); Object.extend($(''someSpan''), myActiveSpanBase); $(''someSpan'').setup(); Or, more concisely... Object.extend($(''someSpan''), new ActiveSpan({"blue"}); $(''someSpan'').setup(); I think you can see how this allows you some flexibility. You can either use the same base instance to extend like elements, or you can use different instances for each element when you need some custom setup. -----Original Message----- From: rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Jeremy Kitchen Sent: Thursday, March 09, 2006 3:12 PM To: rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: [Rails-spinoffs] extending an existing DOM object in a prototype way I want to take an existing DOM object and extend it with some functionality. I know there''s a way to do this with prototype. Unfortunately, I''m not entirely sure how to do this. Basically, I want to take an existing DOM object and turn it into a ''widget'' by adding some functionality. say we have a span: <span id="blah">some text here</span> I want to be able to, in javascript, do something like this: var whatever = new ActiveSpan("blah"); and have the ActiveSpan class extend it with some functionality (like onclick events, attributes, etc) here''s what I have in mind, but I''m not sure this is exactly correct: var ActiveSpan = Class.create(); ActiveSpan.prototype = { initalize: function(span) { Object.extend(span, this); this.registerCallbacks(); }, registerCallbackss: function() { Event.observe(this, ''click'', clickHandler.bindAsEventListener(this); }, clickHandler: function(e) { this.style.background = "red"; } } does this look right? Also, I''ll eventually want to go through the child elements in the initalize method to set those children up as well. The overall goal of this is to create an enhanced table class where you just call a function and it does all sorts of things like handling mouseovers, mouseouts, zebra striping, etc. If I''m completely wrong, and someone has an example they can point me at, that would be great! If this looks ok, though, I''ll continue on with it :) If this is not possible, or if I have to attach my code to the object like: span.BLAH = new ActiveSpan .. let me know :) I just want to do this in an as prototype-like way as possible. -Jeremy The information transmitted in this electronic mail is intended only for the person or entity to which it is addressed and may contain confidential, proprietary, and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from all computers.