I need a way to overwrite the jQuery $.post method, parameters url.
I need to append a string to every script I have without editing them one by one. The string value may change because it's created by the system.
I know there's a way to overwrite at 100% the value of the parameter but not just appending.
Thanks you.
Depending on the modifications you want to do, you may use one off .ajaxStart or .ajaxSend methods to override the url parameter.
In a general way, you can modify an existing JavaScript function using the "Duck Punching pattern". You can read this article by Paul Irish to know how it works http://paulirish.com/2010/duck-punching-with-jquery/
Here's is the final pattern he recommends for using with jQuery
(function($){
// store original reference to the method
var _old = $.fn.method;
$.fn.method = function(arg1,arg2){
if ( ... condition ... ) {
return ....
} else { // do the default
return _old.apply(this,arguments);
}
};
})(jQuery);
Consider using a custom function:
var updateUrl = function(url){
return url + someStuff
}
$.post(
updateUrl( yourUrl ),
data,
successCallback
);
So you wrap the overriding logic once in updateUrl, and that's it.
Related
I am writing a jQuery plugin which, ideally I would like in it's own namespace.
So far, this seems to work (in terms of namespace nesting)
(function($) {
$.fn.nspace = {
foo: function() {
// Does not work becuase $(this) is not the correct selector.
$(this).show();
}
}
})(jQuery);
So given then example above, I might call my function like so:
$("html, body").nspace.foo();
but $(this) is not [html, body]...How can I solve this?
EDIT: To clarify (based on user comments)...
$("html, body").nspace.foo(); should call foo for [html, body] but, $(this) inside nspace resolves to nspace...so it's trying to call nspace.foo();
You shouldn't do this, but just because I dislike when someone says "You can't" in programming (often untrue, especially in Javascript) - here's how you could do this:
The jQuery object is constructed each time using its prototype.init function, which is aliased to fn.init, so you could overwrite it with a wrapped function that adds your namespace object in a way that doesn't harm any existing usage or libraries, like so:
(function($) {
var baseInit = $.fn.init;
$.fn.init = function(selector, context, rootjQuery) {
// Instantiate jQuery the way it expects
var j = new baseInit(selector, context, rootjQuery);
// Add our extra object/namespace
// Use j inside to refer to the current jQuery object
j.nspace = {
foo: function() {
j.show();
}
};
// Return it all and other libraries are none the wiser
return j;
}
})(jQuery);
http://jsfiddle.net/b9chris/7TPZY/
You should consider using the classic pattern for a jQuery plugin: define only one method: in your case, nspace. Inside this method, you'll take every case into account. Sounds hard, but it's pretty easy once you've looked into that.
(By the way you definitely have to look at that when writing a jQuery plugin)
You can't add an object as a plugin and still get the jQuery object that was used to get the object. You simply have no reference to that jQuery object when you call a method in your object.
Put the function directly as the plugin:
(function($) {
$.fn.nspace = function() {
this.show();
};
})(jQuery);
Usage:
$("html, body").nspace();
(Note that the object is the jQuery instance, not a selector or an element, so you don't need to use $(this)).
Let's say I have a jquery plugin that has an onSelect attribute. The user sets it to a function, and when that function is called, this refers to the object the plugin is applied to. All is good.
If I want to write a plugin that wraps this plugin, in order to inject some code into the onSelect, I do something like this:
// Get whatever the user put in
var extOnSelect = options['onSelect'];
// delete the onSelect attribute
delete options['onSelect'];
// re-add onSelect as an anonymous function that calls my method and the user's
var options = $.extend({
'onSelect': function() { onSelect(); extOnSelect(); }
}, options);
// call the plugin that I am wrapping / injecting extra onSelect code into
$(this).externalPlugin(options);
Then it will pass in my own onSelect code, while preserving what the user entered.
The only problem is, within each of those two functions this no longer refers to the object, it now refers to I think the generic inline function.
What's the best solution to fix this?
Use apply and the arguments object:
extOnSelect.apply(this, arguments);
to call extOnSelect exactly like the current function.
You could use call, but then you would need to pass the event object (and other possibe arguments) explicitly.
I think you need to use call method of javascript functions.
var options = $.extend({
'onSelect': function() { onSelect.call(this); extOnSelect.call(this); }
}, options);
I have been creating my own library for a custom layout script. For ease of use, I am trying to emulate how jQuery exposes its library through the jQuery() which makes the code very easy to read and straightforward. I have come up with something that works but I am not sure if this is the correct way to do this. Rather than keep the functions internal all the functions are "appended" to the library. Anyways, the code which works for me so far is as follows:
slateUI = (function(slateID){
slateUI.ID = slateID;
return slateUI;
});
and a related function looks something like this:
slateUI.doSomething = function(content)
{
//DID SOMETHING USING slateUI.ID
}
I am fairly new to OOP like features of the language. I am sure there is a better way to approach this. The issue that I have is handing down the Element to an appened function call so for instance:
slateUI("#someSlate").doSomething(...)
Obtains its element from the slateUI.ID
Is this the correct way to approach this? Or is this a hacked way that I came up with and there is some straight forward way to do this?
// function which returns a new SlateUI object (so we dont have to use the "new" keyword)
slateUI = function ( slateID ) {
return new SlateUI( slateID );
};
// class definition
function SlateUI ( slateId ) {
this.id = slateId;
}
// methods added to the class prototype (allows for prototypical inheritance)
SlateUI.prototype.someFunction = function() {
alert( this.id );
return this; // adding this line to the end of each method allows for method chaining
};
// usage
slateUI( 'someid' ).someFunction();
The short version of your question is that you're looking for the ability to chain your functions.
This is achieved simply by returning the relevant object from each function. If the function has no other return value, then just return the this variable, to pass control back to the caller.
I'm trying to relay dynamic parameters from a web page into a function, which then passes them to a call inside the function. For example, take the simplified snippet below, as it is now, passing in the parameters directly is not problem. But how do I pass in a parameter which colorbox accepts without making a parameter for showColorbox() for every possible colorbox parameter?
function showColorbox(title, url, width, height, modal, params) {
$.colorbox({title:title, href:url, width:width, height:height, opacity:0.7});
}
For instance, colorbox accepts passing in an event function, such as below if I called colorbox directly:
$.colorbox({title:title, href:url, width:width, height:height, opacity:0.7,
onComplete: function() {
$.colorbox.resize();
}
});
So, without adding some code or making another parameter and parsing it out somehow inside showColorbox(), is there a way for me to pass the onComplete param/code [via showColorbox(....{onComplete:yada yada}) or something] and have them relayed to the $.colorbox() function?
UPDATE:
Ended up using the following successfully, added an extra objParams parameter to the showColorbox() function.
//m_title, m_url, m_width, m_height are from fixed parameters for showColorbox()
var objBase = {title:m_title,href:m_url,width:m_width,height:m_height} ;
var objFinal = {};
//add base parameters passed in directly, fixed params
for(var item in objBase) {
objFinal[item] = objBase[item];
}
//add the parameters from objParams passed in (variable params/values)
for(var item in objParams) {
objFinal[item] = objParams[item]
}
//call function with combined parameters in object
$.colorbox(objFinal)
None of the callers needed to be updated, but now passing in a new object using parameters which $.colorbox understands works fine! Thanks again!
It sounds like the solution you're looking for is wanting there to be a simple way to pass individual parameters of variable arguments as a named property value in an object literal. If so no there is no way to achieve this. Primarily because in this case there are no names for the arguments so there would be nothing for them to map to.
The best way to approach this problem altogether is to require an object at every stage and omit the extra parameters altogether.
function showColorbox(obj) {
...
$.colorbox(obj);
}
showColorbox({title:title, href:url, width:width, height:height, opacity:0.7});
Why not just accept one parameter which is the object you pass to colorbox?
function showColorbox(params) {
$.colorbox(params);
}
Then you can call it like this:
showColorbox({title:title, href:url, width:width, height:height, opacity:0.7});
Almost all of the examples in the jQuery tutorials that I've read, usually use one major public function for their selecting plugin. When I say 'selecting' plugin, I mean one that is not simply a static function extended onto jQuery.
For example:
(function($) {
jQuery.fn.actionList = function(options) {
var opts = $.extend({}, $.fn.actionList.defaults, options);
return this.each(function(){
alert(this);
});
};
$.fn.actionList.defaults = {
listHtml: '<div>Set the list html</div>'
};
})(jQuery);
but not:
jQuery.log = function(message) {
if(window.console) {
console.debug(message);
} else {
alert(message);
}
};
This works fine for most things, but what I would like to do is be able to call a second function on the object returned from the first call.
var actionBox = $('actionBox').actionList(options);
//Many light-cycles later
actionBox.refreshData(data);
or maybe even:
$('actionBox').actionList(options);
// laaateerr
$('actionBox').actionList.refreshData(data);
I'm guessing one or both of these is not possible or, at least not advisable, but I'm only now getting into the deepest aspects of jQuery and javascript.
Could someone explain how to do this, or if it's not possible or advisable, why? and what they would do instead?
Thanks for reading!
I'm not quite sure what you're getting at, but you can call a second function on the object returned from the first function - in fact, it is very much encouraged to return a jQuery object from your plugins, and the reason why you can chain commands in jQuery.
Using your examples
var actionBox = $('actionBox').actionList(options);
//Many light-cycles later
actionBox.refreshData(data);
would work fine, so long as both .actionList() and .refreshData(data) commands both return a jQuery object.
And
$('actionBox').actionList.refreshData(data);
would need to be
$('actionBox').actionList().refreshData(data);
EDIT:
Looking at the jQuery source code,
jQuery.fn = jQuery.prototype = {
/*
Load of 'property' functions of jQuery object...
*/
}
so, adding properties (a.k.a plugins) to jQuery.fn extends the prototype of the jQuery object. When you call
$(selector, context);
a new jQuery object is returned, using the init property function of the jQuery object
jQuery = window.jQuery = window.$ = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context );
},
I think I've got a plugin that might be very useful for you. It allows you to apply any constructor/object to jQuery as it's own namespace AND you can use 'this' as you would normally with jQuery to refer to the object set. Using this[methodName] will call a method on your object, etc.
http://code.google.com/p/jquery-plugin-dev/source/browse/trunk/jquery.plugin.js
Some code samples are here:
http://groups.google.com/group/jquery-dev/browse_thread/thread/664cb89b43ccb92c/34f74665423f73c9?lnk=gst&q=structure+plugin+authoring#34f74665423f73c9
It's about halfway down the page.
I hope you find it useful!