Is there way to override jQuery's core functions ?
Say I wanted to add an alert(this.length) in size: function()
Instead of adding it in the source
size: function() {
alert(this.length)
return this.length;
},
I was wondering if it would be possible to do something like this :
if (console)
{
console.log("Size of div = " + $("div").size());
var oSize = jQuery.fn.size;
jQuery.fn.size = function()
{
alert(this.length);
// Now go back to jQuery's original size()
return oSize(this);
}
console.log("Size of div = " + $("div").size());
}
You almost had it, you need to set the this reference inside of the old size function to be the this reference in the override function, like this:
var oSize = jQuery.fn.size;
jQuery.fn.size = function() {
alert(this.length);
// Now go back to jQuery's original size()
return oSize.apply(this, arguments);
};
The way this works is Function instances have a method called apply, whose purpose is to arbitrarily override the inner this reference inside of the function's body.
So, as an example:
var f = function() { console.log(this); }
f.apply("Hello World", null); //prints "Hello World" to the console
You can override plugins method by prototype it in a separate file without modifying original source file as below::
(function ($) {
$.ui.draggable.prototype._mouseDrag = function(event, noPropagation) {
// Your Code
},
$.ui.resizable.prototype._mouseDrag = function(event) {
// Your code
}
}(jQuery));
Now put your logic here or original code with your new idea that is needed in your project.
Related
I try to change some way to call methods into namespace.
Calling parent methods (I dont think its possible)
Creating and call inheritance function
Calling inside another method (mostly jquery onReady event function) (this.MyFunction() not working)
I split every namespace in files (want to keep it that way)
I try How to call function A from function B within the same namespace? but I didn't succed to split namespaces.
my fiddle sample got only 1 sub-namespace but could be more.
https://jsfiddle.net/forX/kv1w2rvc/
/**************************************************************************
// FILE Master.js
***************************************************************************/
if (!Master) var Master = {};
Master.Print= function(text){
console.log("master.Print :" + text);
$("body").append("<div>master.Print : " + text + "</div>");
}
/**************************************************************************
// FILE Master.Test1.js
***************************************************************************/
if (!Master) var Master = {};
if (!Master.Test1) Master.Test1 = {};
/**************************************************************************
* Descrition :
* Function for managing event load/documentReady
**************************************************************************/
Master.Test1.onReady = function () {
$(function () {
Master.Test1.Function1(); //try to replace because need all namespace.
try {
this.Function2(); //not working
}
catch(err) {
console.log("this.Function2 not working");
$("body").append("<div>this.Function2 not working</div>");
}
try {
this.Print("onReady"); //not working
}
catch(err) {
console.log("this.Print not working");
$("body").append("<div>this.Print not working</div>");
}
try {
Print("onReady"); //not working
}
catch(err) {
console.log("Print not working");
$("body").append("<div>Print not working</div>");
}
});
}
Master.Test1.Function1 = function () {
console.log("Function1");
$("body").append("<div>Function1</div>");
this.Function3(); //working because not inside another function
}
Master.Test1.Function2 = function () {
$("body").append("<div>Function2</div>");
console.log("Function2");
}
Master.Test1.Function3 = function () {
$("body").append("<div>Function3</div>");
console.log("Function3");
Master.Print("Function3"); //try to replace because need all namespace.
}
Master.Test1.onReady();
I use Master.Test1.Function1(); and I want to change that because Function1 is inside the same namespace.
I use Master.Print("Function3"); I dont think I can change that. the way I try to use it, it's more an inheritance function. but I dont know if theres a way to do that?
Maybe I should change the my namespace methode? maybe prototype will do what I want?
You can capture the this in a variable because this inside $(function() {}) will point to document object. The below will work provided you never change the calling context of onReady -- i.e. it is always called on the Test1 object and not called on other context:
Master.Test1.onReady = function () {
var self = this;
$(function () {
self.Function1();
// ..
});
}
To access Print you have to reference using the Master object like: Master.Print() as it won't be available in the Test1 object
this is document within .ready() or jQuery() alias for .ready() where function(){} is parameter $(function() {}). this at this.Function2() will reference document.
"Objects" in javascript are not built the same way as in most object-oriented languages. Essentially, what you are building is a hierarchy of static methods that have no real internal state in-and-of themselves. Therefore, when one of the defined methods is invoked, the context (or state) of that method depends on what object invoked the method.
If you want to have any internal context, you will need to create an "instance" of an "object prototype". At that point, you can use "this.otherFunction" within your other functions. Here is a small example:
var MyObject = function() {};
MyObject.functionOne = function() {
console.log("Function 1");
this.functionTwo();
};
MyObject.functionTwo = function() {
console.log("Function 2");
};
var instanceOne = new MyObject();
instanceOne.functionOne();
You might get some more information about object definition here
I can't figure out how to use a Javascript constructor method in a jQuery .click method. I'm trying to get a button's function to change dynamically based on a constructor. Here's the set up:
<button onclick="">
</button>
needs to call a method that changes depending on another button. The following is my broken code:
function GloveMode (name , array) {
this.colorArray = array;
this.displaySettings = function(){
//Title
$("#displayTitle").text(this.name);
//Display Color Set
$("#displayColors").empty();
//Totally Broken
$("#upArrow").click( function(){
addColor();
});
};
this.addColor = function(){
console.log(this.colorArray.length);
};
};
I can't figure out how to get $("#upArrow").click() to call this.colorArray properly, or how to call this.addColor() in the .click() method! Please help.
Your Problem is that "this" means something different in each function body. So save the wanted "this" to a variable e.g. "self" and use that.
function GloveMode (name , array)
{
var self = this;
this.colorArray = array;
this.displaySettings = function()
{
//Title
$("#displayTitle").text(this.name);
//Display Color Set
$("#displayColors").empty();
//Totally Broken
$("#upArrow").click( function()
{
self.addColor();
});
};
this.addColor = function()
{
console.log(self.colorArray.length);
};
};
I can't help but notice there are two seemingly useless functions in the source code of jQuery (For v1.9.1, it's line 2702 and line 2706):
function returnTrue() {
return true;
}
function returnFalse() {
return false;
}
Which both are called quite often within jQuery. Is there a reason why they don't simply substitute the function call with a boolean true or false?
If an object property, function argument, etc expects a function you should provide a function not a boolean.
For example in vanilla JavaScript:
var a = document.createElement("a");
a.href = "http://www.google.com/";
/*
* see https://developer.mozilla.org/en-US/docs/DOM/element.onclick
* element.onclick = functionRef;
* where functionRef is a function - often a name of a function declared
* elsewhere or a function expression.
*/
a.onclick = true; // wrong
a.onclick = returnTrue; // correct
a.onclick = function() { return true; }; // correct
Also, writing:
someProperty: returnTrue,
Is more convenient than writing:
someProperty: function(){
return true;
},
Especially since they are called quite often.
it was used like this:
stopImmediatePropagation: function() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
}
here isImmediatePropagationStopped is a query method. used like this event.isImmediatePropagationStopped()
of course, you can define a instance method, like:
event.prototyoe.isImmediatePropagationStopped = function() { return this._isImmediatePropagationStopped };
stopImmediatePropagation: function() {
this._isImmediatePropagationStopped = true; //or false at other place.
this.stopPropagation();
}
but you have to introduce a new instance property _isImmediatePropagationStopped to store the status.
with this trick, you can cut off bunch of instance properties for hold true/false status here, like _isImmediatePropagationStopped, _isDefaultPrevented etc.
so that, in my opinion, this is just a matter of code style, not right or wrong.
PS: the query methods on event, like isDefaultPrevented , isPropagationStopped, isImmediatePropagationStopped are defined in DOM event level 3 sepc.
spec: http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-Event-isImmediatePropagationStopped
I need to add some functionality to a core JavaScript object function, without touching the original file.
How can I extend the following object function from my object below while keeping the namespace intact?
core object
(function() {
var DOM = tinymce.DOM;
tinymce.create('tinymce.plugins.WordPress', {
// i need to extend this function
_hideButtons : function() {
// stuff here
};
});
tinymce.PluginManager.add('wordpress', tinymce.plugins.WordPress);
})();
my object
I tried this, but it doesn't work:
(function() {
tinymce.create('tinymce.plugins.Mine', {
init : function(ed, url) {
ed.plugins.wordpress._hideButtons.prototype = function() {
// new function stuff
}
},
});
tinymce.PluginManager.add('mine', tinymce.plugins.Mine);
})();
Am I on the right track?
extending was, in fact, not what i needed.
by just removing .prototype above, allowed me to completely over write the function in question. this is exactly what i wanted to do.
check it...
(function() {
tinymce.create('tinymce.plugins.Mine', {
init : function(ed, url) {
ed.plugins.wordpress._hideButtons = function() {
// new function stuff
}
},
});
tinymce.PluginManager.add('mine', tinymce.plugins.Mine);
})();
JSFiddle: http://jsfiddle.net/M2ALY/3/
My goal is to make a module that I can use and distribute. Therefore I must not pollute the global namespace. The module I'm making is also going to be used multiple times on one web page. That's why I chose to use OOP, but this introduced a problem.
I want my object to bind a function to be run when the user clicks an element in the DOM. In this simplified example I made, I want an alert box to pop up when the user clicks a paragraph. As an example, one of the things I need in the real project I'm working on is: The user clicks a canvas, the function figures out where the user clicked and saves it to this.clientX and this.clientY.
Instead of doing
this.bind = function() {
$("p1").bind('click', function() {
// code here
});
}
I figured it would work if I did:
this.bind = function() {obj.codeMovedToThisMethod()}
The problem is that this isn't a good design. Inside the "class" you shouldn't need to know the name of the object(s) that is going to be made of this "class". This doesn't get better when I'm making multiple objects of the "class"...
So I figured I could do
$("p1").bind('click', function(this) {
// code here
});
}
But it didn't work because sending this into the function didn't work as I thought.
How should I solve this problem?
Here is a simplified sample problem. (Same as JSFiddle.)
var test = function() {
this.alert = function() {
alert("Hi");
}
this.bind = function() {
$("#p1").bind('click', function() {
obj.alert();
});
}
}
window.obj = new test();
obj.bind();
// What if I want to do this:
var test2 = function() {
// Private vars
this.variable = "This secret is hidden.";
this.alert = function() {
alert(this.variable);
}
this.bind = function() {
$("#p2").bind('click', function(this) {
obj2.alert();
this.alert();
});
}
}
window.obj2 = new test2();
obj2.bind();
Thanks!
Read MDN's introduction to the this keyword. As it's a keyword, you can't use it as a parameter name.
Use either
this.bind = function() {
var that = this;
$("#p2").on('click', function(e) {
that.alert();
// "this" is the DOM element (event target)
});
}
or $.proxy, the jQuery cross-browser equivalent to the bind() function:
this.bind = function() {
$("#p2").on('click', $.proxy(function(e) {
this.alert();
}, this));
}