This project is archived and is in readonly mode.

#738 ✓invalid
josh vermette

"domchanged" event?

Reported by josh vermette | August 26th, 2009 @ 01:34 AM | in 2.0 (closed)

My apologies if such a thing exists, I have searched around in the boards and the code and don't find any evidence of it. I do some custom classes where at the bottom I use domready to get elements with a certain class tag, and then initialize them for do certain things... standard practice I think.

I ran into a problem today where I was loading some html using Request, and while the mootools-based class was already loaded I noticed that the elements with the class tags I mentioned above weren't loading. Turned out of course to be because they're initialized on domready, which had already come and gone since this was an ajax request that updated the dom.

So I hacked request.HTML to do:
$(window).fireEvent("domchanged", container) where in this case container is this.options.update, the container that was updated in the Request. Generally though, container would be the container that had its contents replaced. This let me addEvent in my classes so they monitored not only domready but domchanged, and in the domchanged handler they got the affected container so that they didn't have to screw things up that had already been handled.

The hack is as simple as the code below... it's hacky because I had to have the original Request.HTML.success function called while replacing it with another, thus the use of prototype... but getting it into the base code the real way would be trivial.

//--------------------------------- var tmp_html_prototype_success = Request.HTML.prototype.success;
Request.HTML.implement({ success: function(text) {

        boundTmp = tmp_html_prototype_success.bind(this);
        boundTmp(text);                                   
        if (this.options.update) {
            //Fire our custom event to let things know the dom has changed. 
            $(window).fireEvent("domchanged", this.options.update);
        }   
    }

});
//---------------------------------

Comments and changes to this ticket

  • Jan Kassens

    Jan Kassens August 26th, 2009 @ 09:51 AM

    • State changed from “new” to “invalid”
    • Assigned user set to “Jan Kassens”

    A domchanged event is unfortunately not possible, since there can always be third-party javascript, or just some javascript written by the user, which simply uses plain dom methods or innerHTML to change the dom. We can't track those.

    In your case you should probably just add a 'success' event to your requests in order to retrigger any plugin instantiations for that part.

  • frangossauro

    frangossauro August 26th, 2009 @ 01:22 PM

    This is a more general approach os settings events on DOM manipulation:

    http://www.bennadel.com/blog/1623-Ask-Ben-Detecting-When-DOM-Elemen...

  • josh vermette

    josh vermette August 26th, 2009 @ 05:15 PM

    I can respect that, though one more note in case it helps -- adding a "success" event is not possible here, since the Request object and the classes/objects which would need to know about this have no idea each other exists. Adding a "domchanged" event might not be perfect since as you say there will always be client packages which might not implement it, but it definitely fills a functional gap in the mootools package and any who wish to comply with the practice can easily add it to their code.

    Thanks for the link, though it's only for node removal and it requires situation-specific hacking to get IE to comply... this domchanged event really is an elegant and easy solution compared to that!

    Just my extra $0.02, thanks for your time.

    j.

  • Jan Kassens

    Jan Kassens August 26th, 2009 @ 05:53 PM

    One solution for your problem might be "Class events", so you could do Request.addEvent('success', fn); which would be fired when the event is fired on any instance. Unfortunately this doesnt really fit in how Events are implemented atm. I might try to implement them for MooTools 2 though.

  • Jan Kassens

    Jan Kassens August 26th, 2009 @ 05:59 PM

    Note to the link: It only works if you only use jQuery to modify the dom, it doesnt detect modifications by vanilla js or innerHTML. I don't think implementing such functionality would not be worth the performance hit. (Since each and every single .inject, .dispose, .set('html',html), and friends would need to trigger an event)

  • Sebastian Markbåge

    Sebastian Markbåge August 26th, 2009 @ 09:16 PM

    I've given this pattern a lot of thought actually as it opens up for a lot of new interesting patterns. Namely events during adding, moving and removing elements from the DOM.

    Let's say you want to wire up some of your existing elements to various classes or listeners etc. A typical pattern would be to use a domready listener, then use a selector to find the elements and iterate through those to attach events etc.

    window.addEvent('domready', function(){
      $$('#box ul li').each(function(element){
        ...
      });
    }
    

    Imagine that you use Event delegation to subscribe to new elements instead.

    window.addListener('#box ul li', function(element){
      ...
    });
    

    This would attach behavior continuously as new elements are added to the document. You can now wire up logic to your elements the same way as with CSS.

    In MooTools 2.0 this kind of thing will be much easier to do and with much better performance. So the benefits may out way the other issues for some users. (I smell a plugin coming.)

    However, I've since reached the conclusion that there's a lot more to be gained by doing things the other way around using a presenter model pattern. Instead of wiring up to your DOM you'd generate your DOM from presenter objects using a data binding template.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Shared Ticket Bins

Pages