I would like to alter the functionality of $.prepend() (and probably $.append()) for the purpose of having an “on DOM change event”.
Can I do something as simple as:
$.prepend = function() { alert('Hello World'); };
Or do I need to use the $.extend() function or $.prototype.prepend or $.fn.prepend?
[I realise I’ll need to include the original source for the prepend() function in my new one otherwise jQuery will break!]
EDIT :: Final Solution
For those who are interested:
$.extend($, {
domChangeStack: [],
onDomChange: function(selector, fn, unbind, removeFromStack) {
/* Needs to store: selector, function, unbind flag, removeFromStack flag */
jQuery.domChangeStack.push([selector, fn, unbind, removeFromStack]);
},
domChangeEvent: function() {
/* Ideally should only affect inserted HTML/altered DOM, but this doesn't */
var stackItem, newStack = [];
while (stackItem = jQuery.domChangeStack.pop()) {
var selector = stackItem[0],
fn = stackItem[1],
unbind = stackItem[2],
remove = stackItem[3];
if (unbind) { $(selector).unbind(); }
// Need to pass the jQuery object as fn is anonymous
fn($(selector));
if (!remove) { newStack.push(stackItem); }
}
jQuery.domChangeStack = newStack;
// Show something happened!
console.log("domChangeEvent: stack size = " + newStack.length);
}
});
$.fn.prepend = function() {
var result = this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.insertBefore( elem, this.firstChild );
}
});
// Need to actually alter DOM above before calling the DOMChange event
$.domChangeEvent();
return result;
};
And usage:
/* Run the given function on the elements found by the selector,
* don't run unbind() beforehand and don't pop this DOMChange
* event off the stack.
*/
$.onDomChange(".element_class", function(jObj) {
jObj.do_something_awesome();
}, false, false);
Which method you want to use depends on how much you need to change. Since
.prependis merely a method that resides in.fnyou don’t have to mess with the prototype.I most cases its enough to rename the original method, create your own function that does what you want and end with a call to the original function, like this:
Note:
.applyand.callare more or less identical. The only difference is that.applypasses arguments by reference while.callpasses them by value, so I prefer to use.applybefore.callwhere possible. See MDC for referenceBut if you look at the source of jQuery (see src/manipulation.js) you’ll see that this method is very small so you can just implement it directly.
In the next example I will use
.extendinstead, but it’s not a must; you could just replace it like in the first example.You can override
.domManipor any other method in the same way, like in the following example. You’ll probably see why I prefer to use.extendhere.See test case on jsFiddle