Reputation: 146390
I have this little jQuery plugin:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript"><!--
(function($){
$.fn.foo = function(options){
var options = $.extend({
text: "Foo!",
}, options
);
this.prepend(
$("<span></span>").text(options.text)
).css({color: "white", backgroundColor: "black"});
return this;
};
})(jQuery);
$(function(){
$("div").foo().foo({text: "Bar!"}).css({border: "1px solid red"});
});
//--></script>
</head>
<body>
<div>One</div>
<div>Two</div>
<div>Three</div>
</body>
</html>
Now I want to improve it so you are able to control where the text gets inserted by means of providing a callback function:
$(function(){
var optionsFoo = {
text: "Foo!",
insertionCallback: $.append
}
var optionsBar = {
text: "Bar!",
insertionCallback: $.prepend
}
$("div").foo(optionsFoo).foo(optionsBar).css({border: "1px solid red"});
});
(Please remember this is just sample code. I want to learn a technique rather than fix an issue.)
Can I pass a jQuery method as an argument and use it inside the plugin in the middle of a chain? If so, what's the syntax? If not, what's the recommended alternative?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript"><!--
(function($){
$.fn.foo = function(options){
var options = $.extend({
text: "Foo!",
insertionCallback: $.append
}, options
);
options.insertionCallback.call(this, // options.insertionCallback is undefined
$("<span></span>").text(options.text)
).css({color: "white", backgroundColor: "black"});
return this;
};
})(jQuery);
$(function(){
var optionsFoo = {
text: "Foo!",
insertionCallback: $.append
}
var optionsBar = {
text: "Bar!",
insertionCallback: $.prepend
}
$("div").foo(optionsFoo).foo(optionsBar).css({border: "1px solid red"});
});
//--></script>
</head>
<body>
<div>One</div>
<div>Two</div>
<div>Three</div>
</body>
</html>
Upvotes: 2
Views: 384
Reputation: 65435
Not an answer to your question, but the recommended style is:
<script type="text/javascript">
//this
jQuery(function($) {
//... stuff using the jQuery lib, using the $
});
//not this
$(function() {
//...
});
//or this
(function($) {
//...
})(jQuery);
</script>
Upvotes: 0
Reputation: 630379
You can also do this string based to keep it simple, like this:
(function($){
$.fn.foo = function(options){
var options = $.extend({
text: "Foo!",
insertionCallback: "append"
}, options
);
return this[options.insertionCallback]($("<span></span>").text(options.text))
.css({color: "white", backgroundColor: "black"});
};
})(jQuery);
Then your call looks like this:
$(function(){
var optionsFoo = {
text: "Foo!",
insertionCallback: "append"
}
var optionsBar = {
text: "Bar!",
insertionCallback: "prepend"
}
$("div").foo(optionsFoo).foo(optionsBar).css({border: "1px solid red"});
});
You can test it here, this would allow you to use append
, prepend
, html
and text
, giving you a few options to set the content. In this case we're just taking advantage of JavaScript being a dynamic language, where this.prepend(something)
is equal to this["prepend"](something)
.
Upvotes: 1
Reputation: 29267
Sure you can, JavaScript is really dynamic:
this.prepend(
$("<span></span>").text(options.text)
).css({color: "white", backgroundColor: "black"});
You can replace the native call to this.prepend()
with the jQuery function you pass in the options object as a parameter.
Since most jQuery methods behave on a current set of elements (the this
object in your plugin) you need to use apply
or call
to make it work. This way you can call the options.insertionCallback
function with the current this
object as its context.
Something like:
options.insertionCallback.call(this, // pass the current context to the jQuery function
$("<span></span>").text(options.text)
).css({color: "white", backgroundColor: "black"});
Edit
However you can't access jQuery methods directly from the $
namespace, you need a constructed jQuery object to access its methods, or simply use $.fn.functionName
as Nick Craver pointed out.
alert($.prepend); // won't alert the function
alert($.fn.prepend); // will alert the function
Upvotes: 1
Reputation: 235972
extend it like so:
(function($){
$.fn.foo = function(options){
var options = $.extend({
text: "Foo!",
cb: null
}, options
);
if($.isFunction(options.cb)){
// optimal also pass parameters for that callback
options.cb.apply(this, []);
}
this.prepend(
$("<span></span>").text(options.text)
).css({color: "white", backgroundColor: "black"});
return this;
};
})(jQuery);
I don't really understand what you mean with
Can I pass a jQuery method as an argument and use it inside the plugin in the middle of a chain?
Why would you want to pass a jQuery method
? it's already in there so you can just call it on any jQuery object
.
Upvotes: 1