Overriding jQuery functions - best practice - javascript

My web application is using a number of JQuery plugins such as the Datatables, and it's corresponding Row Reordering and Sorting plugins.
The problem is that we need to add some fixes to account for annoying IE8 inconsistencies.
So, for example, in one of the plugins _mouseDrag() method we need to add some extra logic at the start. Is there a way to override this function without modifying the plugin's source code?
In an OO language you would typically override a class method, add some logic and then call the super() method to avoid modifying an API's source code.
Therefore, I am wondering how we can best support this in JavaScript without modifying the library itself.
Thanks
Updated Question
Based on the example below, how do I override my _mouseDrag function which exists as the following in the 3rd party library:
(function( $, undefined ) {
$.widget("ui.sortable", $.ui.mouse, {
_mouseDrag: function (event){
...
}
How do I override this exactly?

Try this (see Demo: http://jsfiddle.net/2rZN7/):
(function ($) {
var oldPluginFunction = $.fn.pluginFunction;
$.fn.pluginFunction = function () {
// your code
return oldPluginFunction.call(this);
};
})(jQuery);
From Demo:
HTML:
<span id="text1">text1</span>
<span id="text2">text2</span>
JavaScript:
// define and use plugin
$.fn.pluginFunction = function (color) {
return this.each(function () {
$(this).css('color', color);
});
};
$('#text1').pluginFunction('red');
// redefine and use plugin
(function ($) {
var oldPluginFunction = $.fn.pluginFunction;
$.fn.pluginFunction = function () {
$(this).css('font-size', 24)
return oldPluginFunction.apply(this, arguments);
};
})(jQuery);
$('#text2').pluginFunction('red');

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

Method overloading in jQuery plugin

I came across this problem while I was trying to customize one of the 3rd party plugins we use in our web application.
We tend to not update the core plugin file just to make sure we don't run into issues when we upgrade 3rd party plugins. Best way to avoid this is either extend existing functionality with new set of methods or to override existing plugin methods outside the main plugin file.
One of the plugin I tried to apply this approach was written in an unusual way where it defined all methods in an object outside main plugin function.
So my question is how do we Extend or more likely Overload one of the methods (validateFields, showErrorMsg) of valEngine plugin without updating plugin code.
Here is a JS Fiddle with a rough prototype.
http://jsfiddle.net/g9Ng9/
// Can't update any of this.
(function($) {
"use strict";
var methods = {
validateFields: function() {
console.log('I perform validation of fields!');
},
showErrorMsg: function() {
console.log('I log error messages');
}
};
$.fn.valEngine = function() {
console.log('I access methods within method object!');
methods.validateFields();
methods.showErrorMsg();
};
})(jQuery);
// Can't update any of this.
// Your code goes here
Thanks in advance.
There is no direct way to get this done as the whole point of keeping those methods outside plugin definition is to keep them private.
So in order to overload the methods object method like 'validateFields' we need to amend the core plugin file in some form.
Something similar to what Abraham Uribe mentioned here in his JS Fiddle: http://jsfiddle.net/g9Ng9/1/
// Can't update any of this.
(function($) {
"use strict";
var methods = {
validateFields: function() {
console.log('I perform validation of fields!');
},
showErrorMsg: function() {
console.log('I log error messages');
}
};
$.fn.valEngine = function() {
console.log('I access methods within method object!');
methods.validateFields();
methods.showErrorMsg();
};
$.fn.valEngine.methods=methods;
});
$().valEngine();
$.fn.valEngine.methods.validateFields=function(){
console.log("validateFields");
};
$().valEngine();
You can extend or overload jQuery methods by using extend() method.
A simple example would be
jQuery.fn.extend({
validateFields: function() {
// your custom code here
}
});
I am not sure but, the namespace in your case would be jQuery.fn.ValEngine.

jQuery plugin with multiple methods

I am going to wrap some of my functions in a nice manner and for this I want to go with jQuery approach. Like jQuery having a lots of methods
$.parseJson()
$.ajax()
$("div").text("hey my testing");
and both methods are present in a same jQuery file. But while reading about how to make a jquery plugin, its specified that you don't need to create multiple functions inside a same plugin. Instead pass an argument which contains the method name as string.
So, Is that the below snippet is correct or do i need to make some corrections in it.
<script type="text/javascript">
(function ($) {
$.fn.testMethod1 = function () {
return $(this).each(function () { });
};
$.fn.testMethod2 = function () {
return $(this).each(function () { });
};
$.test = function () {
return "testresult"
};
})(jQuery);
$("div1").testMethod1();
$("div2").testMethod2();
$.test();
//Is that needed to be replace in a different way like
$("div1").myPlugin("testMethod1");
$("div1").myPlugin("testMethod2");
$("div1").myPlugin("test");
</script>
The second way is preferred because it conserves namespace in the jQuery object.
Read the official jQuery doc for this: Plugins/Authoring
Have you try using jquery boilerplate. It is a good point to start study jQuery plugin development. It's provide a safe and(seem to be) a good solution to create a plugin. They use your second way to call a method.

How to create a jQuery function (a new jQuery method or plugin)?

I know that in JavaScript the syntax is as follows:
function myfunction(param){
//some code
}
Is there a way to declare a function in jQuery that can be added to an element? For example:
$('#my_div').myfunction()
From the Docs:
(function( $ ){
$.fn.myfunction = function() {
alert('hello world');
return this;
};
})( jQuery );
Then you do
$('#my_div').myfunction();
In spite of all the answers you already received, it is worth noting that you do not need to write a plugin to use jQuery in a function. Certainly if it's a simple, one-time function, I believe writing a plugin is overkill. It could be done much more easily by just passing the selector to the function as a parameter. Your code would look something like this:
function myFunction($param) {
$param.hide(); // or whatever you want to do
...
}
myFunction($('#my_div'));
Note that the $ in the variable name $param is not required. It is just a habit of mine to make it easy to remember that that variable contains a jQuery selector. You could just use param as well.
While there is a plethora of documentation / tutorials out there, the simple answer for your question is this:
// to create a jQuery function, you basically just extend the jQuery prototype
// (using the fn alias)
$.fn.myfunction = function () {
// blah
};
Inside that function, the this variable corresponds to the jQuery wrapped set you called your function on. So something like:
$.fn.myfunction = function () {
console.log(this.length);
};
$('.foo').myfunction();
... will flush to the console the number of elements with the class foo.
Of course, there is a bit more to semantics than that (as well as best practices, and all that jazz), so make sure you read up on it.
To make a function available on jQuery objects you add it to the jQuery prototype (fn is a shortcut for prototype in jQuery) like this:
jQuery.fn.myFunction = function() {
// Usually iterate over the items and return for chainability
// 'this' is the elements returns by the selector
return this.each(function() {
// do something to each item matching the selector
}
}
This is usually called a jQuery plugin.
Example - http://jsfiddle.net/VwPrm/
Yup — what you’re describing is a jQuery plugin.
To write a jQuery plugin, you create a function in JavaScript, and assign it to a property on the object jQuery.fn.
E.g.
jQuery.fn.myfunction = function(param) {
// Some code
}
Within your plugin function, the this keyword is set to the jQuery object on which your plugin was invoked. So, when you do:
$('#my_div').myfunction()
Then this inside myfunction will be set to the jQuery object returned by $('#my_div').
See http://docs.jquery.com/Plugins/Authoring for the full story.
$(function () {
//declare function
$.fn.myfunction = function () {
return true;
};
});
$(document).ready(function () {
//call function
$("#my_div").myfunction();
});
You can also use extend (the way you create jQuery plugins):
$.fn.extend(
{
myfunction: function ()
{
},
myfunction2: function ()
{
}
});
Usage:
$('#my_div').myfunction();
You can write your own jQuery plugins(function which can be called on selected elements) like below:
(function( $ ){
$.fn.myFunc = function(param1, param2){
//this - jquery object holds your selected elements
}
})( jQuery );
Call it later like:
$('div').myFunc(1, null);
Yes, methods you apply to elements selected using jquery, are called jquery plugins and there is a good amount of info on authoring within the jquery docs.
Its worth noting that jquery is just javascript, so there is nothing special about a "jquery method".
Create a "colorize" method:
$.fn.colorize = function custom_colorize(some_color) {
this.css('color', some_color);
return this;
}
Use it:
$('#my_div').colorize('green');
This simple-ish example combines the best of How to Create a Basic Plugin in the jQuery docs, and answers from #Candide, #Michael.
A named function expression may improve stack traces, etc.
A custom method that returns this may be chained. (Thanks #Potheek.)
You can always do this:
jQuery.fn.extend({
myfunction: function(param){
// code here
},
});
OR
jQuery.extend({
myfunction: function(param){
// code here
},
});
$(element).myfunction(param);
It sounds like you want to extend the jQuery object via it's prototype (aka write a jQuery plugin). This would mean that every new object created through calling the jQuery function ($(selector/DOM element)) would have this method.
Here is a very simple example:
$.fn.myFunction = function () {
alert('it works');
};
Demo
Simplest example to making any function in jQuery is
jQuery.fn.extend({
exists: function() { return this.length }
});
if($(selector).exists()){/*do something here*/}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Define a function in jQuery</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(document).ready(function() {
$.fn.myFunction = function() {
alert('You have successfully defined your function!');
}
$(".call-btn").click(function(){
$.fn.myFunction();
});
});
</script>
</head>
<body>
<button type="button" class="call-btn">Click Here</button>
</body>
</html>

jQuery plugin namespace for specific objects

I'm am trying to create a jQuery plugin that will add new namespace functions to the context object(s), while maintaining full chain-ability. I'm not sure if it's possible, but here's an example of what I have so far:
(function ($) {
var loadScreen = $('<div />').text('sup lol');
$.fn.someplugin = function (args) {
var args = args || {},
$this = this;
$this.append(loadScreen);
return {
'caption' : function (text) {
loadScreen.text(text);
return $this;
}
};
}
})(jQuery);
This works fine if I do $(document.body).someplugin().caption('hey how\'s it going?').css('background-color', '#000');
However I also need the ability to do $(document.body).someplugin().css('background-color', '#000').caption('hey how\'s it going?');
Since .someplugin() returns it's own object, rather than a jQuery object, it does not work as expected. I also need to be able to later on access .caption() by $(document.body). So for example if a variable is not set for the initial $(document.body).someplugin(). This means that somehow how .caption() is going to be set through $.fn.caption = function () ... just for the document.body object. This is the part which I'm not quite sure is possible. If not, then I guess I'll have to settle for requiring that a variable to be set, to maintain plugin functions chain-ability.
Here's an example code of what I expect:
$(document.body).someplugin().css('background-color', '#000');
$('.non-initialized').caption(); // Error, jQuery doesn't know what caption is
$(document.body).caption('done loading...');
Here's what I'm willing to settle for if that is not possible, or just very inefficient:
var $body = $(document.body).someplugin().css('background-color', '#000');
$('.non-initialized').caption(); // Error, jQuery doesn't know what caption is
$body.caption('done loading...');
The be jquery-chainable, a jQuery method MUST return a jQuery object or an object that supports all jQuery methods. You simply have to decide whether you want your plugin to be chainable for other jQuery methods or whether you want it to return your own data. You can't have both. Pick one.
In your code examples, you could just define more than one plugin method, .someplugin() and .caption(). jQuery does not have a means of implementing a jQuery plugin method that applies to one specific DOM object only. But, there is no harm in making the method available on all jQuery objects and you can only use it for the ones that it makes sense for.
I think you could use this:
(function ($) {
var loadScreen = $('<div />').text('sup lol');
$.fn.someplugin = function (args) {
var args = args || {},
$this = this;
$this.append(loadScreen);
return(this);
}
$.fn.caption = function (text) {
loadScreen.text(text);
return this;
}
})(jQuery);
$(document.body).someplugin().css('background-color', '#000');
$('.non-initialized').caption('whatever');
$(document.body).caption('done loading...');
If there's supposed to be some connection between the two .caption() calls, please explain that further because I don't follow that from your question.

Calling function from within jquery plugin

I'm writing my first jquery plugin and wondered what the correct/best practice way of referencing another function from within a plugin was? Is there a better way to define bar in my plugin script. Should it be within function($) ? I'd also like it to be available to other plugins within the script.
function bar() {
return 'is this best paractice?';
}
(function($) {
$.fn.foo = function() {
alert(bar());
};
}(jQuery));
Why doesn't something like this work:
(function($) {
$.fn.bar = function() {
return 'is this best paractice?';
};
}(jQuery));
(function($) {
$.fn.foo = function() {
alert(bar());
};
}(jQuery));
Thanks
Functions added to $.fn will be used as jQuery plugins. If you just want to provide a global function from your plugin you add it to $ directly (e.g. $.bar = function() ...).
If you just want use the function internally for your plugin put it within function($). That way you make it available only in that scope (the anonymous function) and not everywhere.

Categories

Resources