Let’s say I have following simple plugin:
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
I don’t want to make any changes to the plugin itself, but I would like to wrap with another function and extend its namespace as follow:
(function($) {
$.fn.myFunction = function () {
(function ($) {
$.fn.greenify = function () {
this.css("color", "green");
return this;
};
}(jQuery));
};
})(jQuery);
So I can call the plugin function like this:
$(selector). myFunction().greenify();
Basically I want to disable calling ‘greenify’ function directly.
Is it possible?
It's not clear from the question, but I'm assuming the simple plugin "greenify" is a third-party or other "forced to use" plugin that you, for whatever reason, can't change. Let's also assume that it's actually quite a complicated plugin and simplified for the sake of the question.
This means
The usual method for overwriting something is to take a copy, then make the new version do what you want, possibly calling the old version, eg:
var oldfoo = foo;
foo = function() {
alert("foo called");
oldfoo(); // or oldfoo.apply(this) to be clearer
}
The same principle can be applied here, but instead make 'foo' (in the example above) null - to get rid of it, eg:
var oldfoo = foo;
newfoo = function() {
alert("foo called");
oldfoo(); // or oldfoo.apply(this) to be clearer
}
foo = null;
The complication is with jquery and wanting to keep the method chaining, which can be achieved by storing 'this' and applying it as desired.
Here's the full code with explanation comments:
// The original plugin to be wrapped
(function ( $ ) {
$.fn.greenify = function() {
// changed to background-color for more impact (demo purposes)
this.css( "background-color", "lightgreen" );
return this;
};
}( jQuery ));
(function($) {
// allow this to be referred to later
// inside another loop where 'this' is something else
var me = this;
// take a copy of the original
// this stays inside the scope of (function($)) so can't be seen outside
me.original_greeny = $.fn.greenify;
// provide a wrapper
$.fn.myFunction = function () {
// the jquery elements for applying later
var $this = $(this)
// exported function
return {
greenify: function() {
// Call the original function with the jquery elements
// and return them for chaining
return me.original_greeny.apply($this)
}
};
};
})(jQuery);
// Now remove the original completely
(function ( $ ) {
$.fn.greenify = null;
}(jQuery));
// As desired, also demonstrating chaining still works
$("#a").myFunction().greenify().css("font-style", "italic")
// Confirm that the original has been removed
// gives error $(...).greenify is not a function
try {
$("#a").greenify()
} catch(e) {
$("#a").text("error on $().greenify: " + e)
}
and a jsfiddle