Reputation: 404
I'd like to override a function which is being made by a javascript plugin. I know how to override regular window functions, but this is different. I'm not sure how to name it, but the structure of that function is like:
window.something.function
I have no idea how to override that. I have tried the following:
var originalFunction = window.something.function;
window.something.function = function(parameter) {
alert('called');
return originalFunction(parameter);
}
But it's not working.
Does someone know a solution?
Edit: As I have been told my question is unclear, I have edited it again using the actual names of the plug-in.
The plugin is meant to be used as:
var myColor = new jscolor(target, options)
When this is being used, there is a function "inside" the object "jscolor" which is being called when setting the value of target element. I want to override that function to add an extra functionality without changing the original js file.
Code:
if (!window.jscolor) { window.jscolor = (function () {
var jsc = {
.....
jscolor : function (targetElement, options) {
....
//Function I want to change:
this.exportColor = function (flags) {
if (!(flags & jsc.leaveValue) && this.valueElement) {
var value = this.toString();
if (this.uppercase) { value = value.toUpperCase(); }
if (this.hash) { value = '#' + value; }
if (jsc.isElementType(this.valueElement, 'input')) {
this.valueElement.value = value;
} else {
this.valueElement.innerHTML = value;
}
}
}
}
};
My attempts so far:
var origJsColor = jscolor.exportColor;
jscolor.exportColor = function(flags) {
console.log('called');
return origJsColor(flags);
}
and the window attempt above.
Upvotes: 1
Views: 3353
Reputation: 1074138
The jscolor
code you've shown creates an object with its own copy of exportColor
(one is created for each object). So to replace it, you have to replace it on each instance as the instance is created.
You can do that as a one-off in much the way you showed, just working with the instance rather than the plugin function, and using Function#call
to call it with the right this
:
// Get the instance
var c = new jscolor(target, options)
// Update it
var origExportColor = c.exportColor;
c.exportColor = function(flags) {
console.log('called');
return origExportColor.call(c, flags); // Note the changes on this line
};
Or instead of
return origExportColor.call(c, flags);
you might use
return origExportColor.apply(c, arguments);
...if there's any chance of the function being called with anything other than exactly one argument. (arguments
is a magic pseudo-array containing the arguments used to call the function.)
If you want to do that for all instance you might create, you can put a facade in front of jscolor
to do that to each instance:
var realJscolor = jscolor;
jscolor = function() {
// Call the real function, passing along all the arguments we
// get automatically (`arguments` is a magic pseudo-array)
var retVal = realJscolor.apply(this, arguments);
// If it returned a non-`null` object, we want to use that instead
// of `this`; if not, we keep using `this`
if (!retVal || typeof retVal !== "object") {
retVal = this;
}
// Slip in our version of exportColor
var origExportColor = retVal.exportColor;
retVal.exportColor = function(flags) {
console.log('called');
// (Maybe use `apply` here instead)
return origExportColor.call(retVal, flags);
};
// Return the result, in case the real function overrode `this`
return retVal;
};
jscolor.prototype = realJscolor.prototype;
Then just use jscolor
normally:
var c = new jscolor(target, options);
The reason for the retVal
thing is that although normally a new
expression's result is a refernece to the new object created by new
, a constructor function can return a non-null
object reference and, if it does, the new
expression's result is that object reference instead. That's why we check the return value of realJscolor
.
Of course, that means that all uses of jscolor
on the page that use the global will now use your updated function instead. If you don't want that, just use your own name and don't override jscolor
:
var myColor = function() {
var retVal = jscolor.apply(this, arguments);
// ...and so on...
return retVal;
};
myColor.prototype = jscolor.prototype;
Usage:
var c = new myColor(target, options);
Upvotes: 2
Reputation: 1
Function
function a() {alert(this)} // will print `window` obejct
is defined in the window scope. That is, it is a method of the window. Your more difficult
situation comes from the fact that this
is different from window if you define function as a method in another object.
var a = {method: function() {alert(this)}}
you call a.method() but see that the same window again. You need to bind your function to the parent object to make it compete method.
Upvotes: 0