Custom event document onContentChange

Here jsFiddle to test sample

I'm currently writing a jquery snippet to handle any html content change in DOM 'triggered' by any jquery domManip function (extending some functions). Not sure it's the best way to do it, so any advices will be welcome. This snippet works as expected if binded to document. However, if i try to bind it to a specific element, i'm facing problem which some function as .remove(). Maybe it's due to custom event not using normal propagation behaviour but i'm really not sure.

This is a working sample, i bind 'contentChange' event to document, works cross-browser as i can test it: {Firefox, IE9, Chrome and Safari under Win7}

;
(function ($) {
    $.fn.contentChange = function (types, data, fn) {
        return this.on('contentChange', types, null, data, fn);
    };
    var oDomManip = $.fn.domManip,
        oHtml = $.fn.html,
        oEmpty = $.fn.empty,
        oRemove = $.fn.remove,
        extendFct = function (oFct, sender, args) {
            return oFct.apply(sender, args), $.event.trigger('contentChange');
            //=>if testing specific element (#test) use instead following line
             //return oFct.apply(sender, args), $(sender).trigger('contentChange');
        };
    $.fn.domManip = function () {
        extendFct(oDomManip, this, arguments)
    };
    $.fn.html = function () {
        extendFct(oHtml, this, arguments)
    };
    $.fn.empty = function () {
        extendFct(oEmpty, this, arguments)
    };
    $.fn.remove = function () {
        extendFct(oRemove, this, arguments)
    };

})(jQuery);

I use: $.event.trigger('contentChange') to trigger custom event.

Called like it:

$(document).contentChange(function () {
    console.log("onContentChange")
});

However, if i use:

$('#test').contentChange(function () {
    console.log("onContentChange")
});

The custom event is not triggered. So, to trigger a custom event on a specific element, i can triggered it like this:

$(sender).trigger('contentChange');

But now, call to remove() method on self or children doesn't triggered my custom event. I can understand that event callback function won't be called if i remove the element, but why isn't it called when removing children (while it's working if binded to document!)?

I was expecting this line to make custom event bubbles to '#test':

$('#test').find('div:first').remove();

Is there any way to triggered this custom event binded to a specific element when manipulating this element and/or its children?

Answers:

Answer

You need to trigger the event on the element that was modified.

http://jsfiddle.net/Gw4Lj/2/

return oFct.apply(sender, args), sender.trigger('contentChange');

however, with that change, you will no longer catch the event that was triggered on an element that isn't connected to the DOM because it isn't a descendant of that document, which is ok in my opinion because it isn't associated to that DOM, it's in a DOM Fragment.

Answer

I come with slightly modified version wich seems to work fine for the purpose i reach. Need optimization for the .on() method extend, so please feel free to share your feedbacks.

Inspired from here: https://groups.google.com/forum/?fromgroups=#!topic/jquery-dev/ZaMw2XB6wyM

Thanks to Wil Stuckey

Here jsFiddle

;(function ($) {
    var fctsToObserve = {
        append: [$.fn.append, 'self'],
        prepend: [$.fn.prepend, 'self'],
        remove: [$.fn.remove, 'parent'],
        before: [$.fn.before, 'parent'],
        after: [$.fn.after, 'parent']
    }, fctsObserveKeys = '';
    $.each(fctsToObserve, function (key, element) {
        fctsObserveKeys += "hasChanged." + key + " ";
    });
    var oOn = $.fn.on;
    $.fn.on = function () {
        if (arguments[0].indexOf('hasChanged') != -1) arguments[0] += " " + fctsObserveKeys;
        return oOn.apply(this, arguments);
    };
    $.fn.hasChanged = function (types, data, fn) {
        return this.on(fctsObserveKeys, types, null, data, fn);
    };
    $.extend($, {
        observeMethods: function (namespace) {
            var namespace = namespace ? "." + namespace : "";
            var _len = $.fn.length;
            delete $.fn.length;
            $.each(fctsToObserve, function (key) {
                var _pre = this;
                $.fn[key] = function () { 
                    var target = _pre[1] === 'self' ? this : this.parent(),
                        ret = _pre[0].apply(this, arguments);
                    target.trigger("hasChanged." + key + namespace, arguments);
                    return ret;
                };
            });
            $.fn.length = _len;
        }
    });
    $.observeMethods()
})(jQuery);

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.