Is There Any Unobtrusive Way To Hook Into JQuery Methods For Triggers?
Solution 1:
It's pretty easy to write a "hook" function:
function hook(original, wrapper) {
return function() {
wrapper.apply(this, arguments);
return original.apply(this, arguments);
}
}
The wrapper
function you provide will be called with the same arguments as the original
function, before the original function itself is called.
An example of use:
$.fn.attr = hook($.fn.attr, function(attribute, value) {
alert('attribute: '+attribute+', value: '+value);
});
$('a.pie').attr('href', 'http://blueberry.pie');
// An alert says "attribute: href, value: http://blueberry.pie"
(Sidenote: It'd be an easy extension to let your wrapper
cancel the call to the original
function, as well, but that's getting more featureful than you wanted.)
You could either use this directly to do what you want, or you could make the wrapper
function just fire custom jquery events which you listen for in the standard jquery ways.
Solution 2:
Turns out this hack will work; I use data's built-in setData triggers (and the aforementioned 'hook' to add functionality atop jQuery's attr and removeAttr) to duplicate attrs within the data object on the jQuery object. Although it's somewhat dirty, I get the functionality to hook into data-change triggers for data, attr, and, if written, any other jQuery methods that track key/value pairs.
(function($) {
var binder = function(e, dataKey, dataValue) {
return (function(dataKey, dataValue, self) {
var $this = $(self),
oldValue = $this.data(dataKey),
newValue = dataValue,
passed = {
attr: dataKey,
from: oldValue,
to: newValue
};
var isAttribute = !!($this.data(dataKey + "-attribute"));
if(oldValue !== newValue) {
var attrPrefix = isAttribute ? "attr-" : "";
$this.trigger(attrPrefix + dataKey + "-changed", passed);
$this.trigger(attrPrefix + "data-changed", passed);
}
})(dataKey, dataValue, this);
};
var hook = function(original, wrapper) {
return function() {
wrapper.apply(this, arguments);
return original.apply(this, arguments);
};
};
$.fn.attr = hook($.fn.attr, function(attr, val) {
if(val) {
$(this).data(attr + "-attribute", true);
$(this).data(attr, val);
}
});
$.fn.removeAttr = hook($.fn.removeAttr, function(attr) {
$(this).removeData(attr + "-attribute");
$(this).removeData(attr);
});
$.fn.observeData = function() {
$(this).bind("setData", binder);
};
})(jQuery);
Solution 3:
There is no event for this currently existing within jQuery.
The livequery plugin may provide something of what you need, such as changing classes. Basically the selector is saved and then any changes in the DOM that change what the selector affects then calls the passed functions, etc.
Solution 4:
And why don't you use the simplest approach:
jQuery.fn.changeAttr = function(attrName,attrValue) {
return this.each(function(){
this.attr(attrName,attrValue);
alert('The att: '+attrName+ ' is now '+attrValue);
});
};
And then just:
$('.friends a').changeAttr('rel','friend')
Sorry if it doesn't work, I don't remember exactly the syntax for extending jQuery.
Solution 5:
Here's a modification to attr()
along the lines of what you're talking about.
(function(attr) {
jQuery.attr = function(elem, name, value) {
var current = attr(elem, name, undefined); // read current value
var retval = current;
if (value !== undefined) { // writing
retval = attr(elem, name, value); // call original
jQuery.event.trigger('attr.changed', {
attribute: name,
from: current,
to: value
}, elem)
}
return retval; // return original
}
})(jQuery.attr);
Usage should be:
$(".friend a").bind("attr.changed", function(e, changed) {
alert("The " + changed.attribute + " attribute changed from " + changed.from + " to " + changed.to + "!");
});
$(".friends a").attr("class", "foo"); // triggers alert
I don't believe css()
is possible as the .style
property can't trigger events. data()
I don't know.
Note I don't condone its usage, this was just an academic effort. What you want incurs a performance penalty on attr()
in order to populate the from
property of the event argument. We have to read the old value before we write the new one.
Post a Comment for "Is There Any Unobtrusive Way To Hook Into JQuery Methods For Triggers?"