You Still Can’t Create a jQuery Plugin?
Feb 19th in Screencasts by Jeffrey Way
It's tough. You read tutorial after tutorial, but they all assume that you know more than you actually do. By the time you're finished, you're left feeling more confused than you initially were. Why did he create an empty object? What does it mean when you pass "options" as a parameter? What do "defaultsettings" actually do?
Never fear; I'm going to show you exactly how to build your own "tooltip" plugin, at the request of one of our loyal readers.
Hi, I'm Jeff. I'm the editor of Nettuts+, and the Site Manager of Theme Forest. I spend too much time in front of the computer and find myself telling my fiance', "We'll go in 5 minutes!" far too often. I just can't go out to dinner while I'm still producing FireBug errors...drives me crazy. During my free time, I sporadically write articles for my own personal blog. If it will keep you in the good graces of the church, follow us on Twitter.
Why Would I Create a Plugin in the First Place?
It might help to think of plugins in the same way as you would functions. Have you ever found yourself repeating the same procedures
for site after site? Perhaps you've created your own tabbing system that you like to use. Rather than writing the same code time and
time again, wouldn't it be easier if we could turn your long code block into one line? That's essentially what a plugin does for us.
It allows for reusability, which is paramount - if you want to keep your hourly wage high!
Step 1: The Markup
Create a new project in your favorite code editor, and paste in the following html.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="css/default.css" />
<title>You Still Can't Create a jQuery Plugin?</title>
</head>
<body>
<div id="container">
<p>
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable <a href="#" class="tooltip" title="This is my title">English</a>. Many desktop publishing packages and web
page <a href="#">editors</a> now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. <a href="#">Various</a> versions have evolved <a href="#" class="tooltip" title="The other day, I bla bla with WordPress.">over the years</a>, sometimes by accident, sometimes on purpose (injected humour and the like).
</p>
</div><!--end container-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"></script>
<script type="text/javascript" src="js/jQuery.tooltip.js"></script>
<script type="text/javascript">
$('a.tooltip').tooltip({
rounded: true
});
</script>
</body>
</html>
Explanation
This code is fairly simple; so it doesn't require too much of an overview.
- Reference a CSS file which we'll create shortly. This will allow us to style our tooltip.
- Add some generic text that contains a few anchor tags. Notice that some of them contain a class of "tooltip".
This is important!
- Import jQuery from Google's CDN.
- Call our tooltip with jQuery. Don't worry about this yet. I'll explain it shortly.
Step 2: Calling the Plugin
I typically find that it's easier to build my plugin if I first determine how I'm going to call it. Consider the following code.
<script type="text/javascript">
$('a.tooltip').tooltip({
rounded: true
});
</script>
I've decided that I want the name of my plugin to simply be called "tooltip". I've also determined that I want to be able to pass in a few
parameters in order to customize my tooltip slightly. This will purely be optional for the user though. If preferred, he or she could just type:
<script type="text/javascript">
$('a.tooltip').tooltip();
</script>
In this instance, the default options will be used.
Step 3: Building the Plugin
So now that we know how the plugin will be called, let's go ahead and build it! Create a new file in your project, and name it "jQuery.tooltip.js". There are certain naming conventions when creating a plugin that will potentially be used by others. We begin by writing 'jQuery', followed by the name of our plugin. However, I'm sure that you realize that thousands of people have created their own tooltip plugin. You might determine that it's necessary to preface "tooltip" with a unique string; perhaps your initials. In any event, it doesn't matter too much. You're free to name your plugin however you wish.
Passing jQuery as a Parameter
(function($){
...code
})(jQuery);
We must first ensure that the "$" symbol doesn't get us into any trouble. What if we were also using other Javascript libraries in our application? Have you ever thought about that? In such cases, we would need to change every "$" in our document to "jQuery". The only problem is that this is a rather sloppy solution. Instead, let's create a self invoking anonymous function, and pass "$" as an alias. That way, we're free to use "$" as much as we like without having to worry about any conflicts.
Naming the Plugin
$.fn.tooltip = function(options) {
Within our wrap, we need to declare our new plugin and make it equal to the following function. We can accomplish this task by typing jQuery.fn (short for prototype).the name of our plugin.
Remember when I specified that the user should be able to make small modifications to the tooltip? Those modifications will be stored within the "options" parameter.
Setting the Defaults
var
defaults = {
background : '#e3e3e3',
color : 'black',
rounded: false
},
It's probable that the user might not specify any options. So, we'll set our own "default" options. Because this is a tutorial for beginners, we won't do too much here. Mostly, this is demonstrating what's possible. We're allowing the user to select a background color, color, and whether or not the tooltip is rounded.
Later in our code, when we wish to access these values, we can simply type: defaults.rounded.
Merging the Defaults With the Options
So how can we determine if the user adds his or her own options? The answer is that we must merge 'defaults' with 'options'.
settings = $.extend({}, defaults, options);
We've created a new variable called "settings", and have told jQuery to merge 'defaults', and 'options', and place the results into a new object. When merging, the user selected 'options' will take precedence over the defaults.
You might be wondering why I haven't added "var" before settings. Technically, it's not required, though it's considered best practice. If you'll scroll up a bit, you'll see that after our defaults object, I added a comma. When doing so, we can continue creating more variables without the need for 'var' each time. For example...
var joe = {};
var is = {};
var good = {};
can become....
var joe = {},
is = {},
good = {};
For Each...
this.each(function() {
var $this = $(this);
var title = this.title;
It's important to keep in mind that the wrapped set that the user passes to this plugin may contain many elements - not just one. We should make sure that we use a for each statement - or jQuery's "each" method - to cycle through the code.
We begin our new function by caching $(this). Not only will it save us a few characters, but it will also speed things up, ever so slightly. It's not required, but is considered to be good practice. Many people ask, "Why do you add the dollar sign in front of your variable?". We do this to remind ourselves that we're working with the jQuery object. By doing so, I remember that I can call things like: $this.click();. Next, I'm storing the value of the title attribute into a variable called "title". You'll see why we must do this in a moment.
Error Checking
if ($this.is('a') && $this.attr('title') != '') {
this.title = '';
$this.hover(function(e){
It's easy to forget what $this is referring to. When you do forget, just go back to the way you're calling the "tooltip" method.
$('a.tooltip').tooltip();
We can see here that $this is referring to each anchor tag that has a class of "tooltip".
Back to the code; if the element in the wrapped set is, in fact, an anchor tag, AND its 'title' attribute is not empty, then run some code. This is rather self explanatory. I don't want to run a bunch of code if the user accidentally passes in an image. Additionally, I don't want to create my tooltip box if there isn't anything to show!
Within my "if" statement, I'm setting the "title" attribute of the anchor tag equal to nothing. This will stop the browser's default tooltip from loading. Next, I'm adding an event listener for when $this, or the anchor tag, is hovered over. When it is, we create a new function and pass the event object as a parameter. Don't worry about this for now, I'll explain later.
Creating Our Tooltip
var title = $this.attr('title');
$('<div id="tooltip" />')
.appendTo('body')
.hide()
.text(title)
.css({
backgroundColor: settings.background,
color: settings.color,
top: e.pageY + 10,
left: e.pageX + 20
})
.fadeIn(350);
I've created a variable called 'title' and made it equal to whatever value is contained within the anchor tag's 'title' attribute. This isn't necessary really - but it helps me.
When we add html tags to our jQuery statement, we can actually create a new element, rather than retrieve one. We're creating a new div tag with an id of 'tooltip'. Next, we'll use jQuery's wonderful chaning abilities to perform a bunch of procedures with ease.
- .appendTo('body') : Take the element that we just created and append it to the body element, just before the closing 'body' tag.
- .hide() : I want our tooltip to fade in. To achieve this effect, it must first have its display set to none.
- .text(title) : We've created our div tag; but it's still empty. Let's add some text. We specify that whatever was contained in the title attribute should be placed into this div.
- .css({..}) : We're setting the background-color, color, top, and left positions of our tooltip with CSS. Remember earlier when we merged the default settings with the user's selected options into a new 'settings' object? That will come into play now. The background-color is equal to 'settings.background'; color is 'settings.color'. Finally, we need to declare where on the page the tooltip should pop up. We can use the event object. It contains two properties called 'pageY', and 'pageX'. These contain the values of the exact coordinates of where the anchor was hovered. To add a bit of padding, we'll add 10px and 20px, respectively.
- .fadeIn(350) : Over the course of about a third of a second, our tooltip will fade in.
if (defaults.rounded) {
$('#tooltip').addClass('rounded');
}
By default, our 'rounded' option is set to 'false'. However, if 'defaults.rounded' returns true (meaning that the user added this parameter), we need to add a class of 'rounded' to our CSS file. We'll create that file soon.
Mouse Out
, function(){
// mouse out
$('#tooltip').hide();
});
"Hover" accepts two functions: mouse over, and mouse out. We've added the appropriate code for when the user mouses over our selected anchor tag. But, we also need to write some code that removes the tooltip once the mouse has left the anchor tag.
Mouse Move
It would be nice to force the tooltip box to shift when our mouse moves. Let's implement that quickly.
$this.mousemove(function(e) {
$('#tooltip').css({
top: e.pageY + 10,
left: e.pageX + 20
});
});
When the mouse moves over the anchor tag, create a function and, once again, pass the event object as a parameter. Find the 'tooltip' element, and adjust its CSS. You should realize that it's the exact code as we previously wrote. We're simply resetting these values to the new ones. Nifty, eh?
Allow for Chaning
We must allow the user to continue chaining after he's called "tooltip". For example:
$('a.tooltip').tooltip().css(..).remove();
In order to allow for this chaining, we need to return 'this'. Just before your closing curly brace, add "return this;".
Plugin Complete!
You've just successfully created a fully working plugin. It's not too advanced, but it allowed us to review some key features. Here is the final code.
Final jQuery
(function($){
$.fn.tooltip = function(options) {
var
defaults = {
background: '#e3e3e3',
color: 'black',
rounded: false
},
settings = $.extend({}, defaults, options);
this.each(function() {
var $this = $(this);
var title = this.title;
if($this.is('a') && $this.attr('title') != '') {
this.title = '';
$this.hover(function(e) {
// mouse over
$('<div id="tooltip" />')
.appendTo('body')
.text(title)
.hide()
.css({
backgroundColor: settings.background,
color: settings.color,
top: e.pageY + 10,
left: e.pageX + 20
})
.fadeIn(350);
if(settings.rounded) {
$('#tooltip').addClass('rounded');
}
}, function() {
// mouse out
$('#tooltip').remove();
});
}
$this.mousemove(function(e) {
$('#tooltip').css({
top: e.pageY + 10,
left: e.pageX + 20
});
});
});
// returns the jQuery object to allow for chainability.
return this;
}
})(jQuery);
Step 4: CSS
The last step is to add just a bit of CSS to prettify our tooltip. Create a new CSS file called 'default.css', and paste the following in.
#tooltip {
background: #e3e3e3 url(../images/search.png) no-repeat 5px 50%;
border: 1px solid #BFBFBF;
float: left;
font-size: 12px;
max-width: 160px;
padding: 1em 1em 1em 3em;
position: absolute;
}
.rounded {
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
Nothing too complicated here. I'm referencing a background image that contains the standard 'search' magnifying glass. You're welcome to download the source code to use it. Additionally, I've added a bit of padding, a maximum width, and a font-size. Most of this comes down to preference. You're free to edit it however you wish.
The only vital property is "position: absolute;". Earlier, we set the "top" and "left" values with jQuery. In order for that positioning to take effect, we must set the position to absolute! This is important. If you don't do so, it won't work.
Thanks for Reading
To all those who have emailed me asking for this tutorial, I hope it's helped in some way. If I didn't explain myself well enough, be sure to view the associated screencast, and/or ask a comment. I'll try to help you to the best of my ability. Until next time...
Ready For Level 2?
If you have a solid grasp of the techniques presented in this tutorial, you're ready to move on! Consider signing up for a Net Plus membership to view an advanced tutorial, by Dan Wellman, that will teach you how to build a more complicated jQuery plugin. It also comes with an associated screencast. Be sure to sign up now!
- Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.
User Comments
( ADD YOURS )insic February 19th
now i can create a jQuery Plugin Thanks for this tutorial. really helpful
( )Jeffrey Way February 19th
I can always rely on insic.
( )Patrick February 19th
Really, you can insic? For me – i can’t. But this tutorial helps a lot to understand and learn how jquery works
thx, Jeffrey!
( )Jeffrey Way February 19th
@Patrick – Was just a joke.
( )Patrick February 19th
I know
( )Brad February 19th
Jeffery Way is my hero.
( )visual February 19th
Nice tutorial. Now a days I really feel sorry for the Prototype+Scriptaculous frameworks. So many articles are coming out about jQuery, too few for the other frameworks. Of course jQuery rocks, but I still like prototype
.
And regarding the on going joke everybody can rely on a chick (sic)… Don’t mind people, again a joke only.
( )Meshach February 19th
Hey, thanks very much Jeffrey!
( )DKumar M. February 19th
Same and Same thing again again!!
( )Jonathan February 19th
Rock on, Jeffrey! Very interesting tutorial.
( )William Monk February 19th
Great tutorial, easy to understand with a good outcome. Thanks a lot!
( )Phillip Raffnsøe February 19th
Thanks for yet another brilliant screencast Jeff! After about a year of leeching these free tuts, I’ve decided to subscribe to plus. I know it’s worth it, especially now when all tuts+ are included.
So you should see another subscriber in the following days! Thanks for convincing me! An thanks for learning me jQuery, I use it pretty much every day.
( )Eduplessis February 19th
nice tut….. gonna make a lot of plugin now…
( )Jeffrey Way February 19th
@Phillip – Very happy to hear that. It’s 100% worth the investment. Just go out to lunch one less time every month.
( )Brenelz February 19th
Great screencast Jeffery… between the imgPreview, jPoll, and tooltip plugins I should know how to make one of my own.
One question I have is could not do this:
var title = $this.attr(’title’);
( )if($this.is(’a') && title != ”) { }
Jeffrey Way February 19th
@Brenelz – What is your question again?
( )iPad February 19th
Thanks Jeffrey, I decided to subscribe to Plus too, this is quality partners…! Your tutorials are my favorites for sure.
( )Brenelz February 19th
Oops… What I meant to say was could you not do this:
var title = $this.attr(’title’);
if($this.is(’a’) && title != ”) { }
instead of:
var title = this.title;
( )if($this.is(’a') && $this.attr(’title’) != ”) {}
Doug February 19th
Thanks for the tutorial!
This should help me create stuff for my projects.
( )Vasili February 19th
This is very helpful. Do you mind telling me the difference between this and $this (ie $(this))? That’s what always confuses me.
I loved the pizza reference.
( )Yosy February 19th
Thank you Jeffrey,
There is one problem on creating jQuery Plugin,I don’t have idea for which plugin to create.
By The Way,How You changed the theme of the aptana?and what is the name of this theme?
And how you’re deleting the tab?for example-
from this-
Yosy
To This-
Yosy
And I think I will register to the plus membership for more awesome tutorials
( )Patternhead February 19th
I guess this helps clear a few things up for some folks.
Nice job.
( )shin February 19th
Here is another tut from IBM. “Working with jQuery, Part 1: Plug-ins to create/extend jQuery functions” Michael Abernethy. http://bit.ly/mEU82
( )Jay February 19th
Thanks for this screencast?
Can you tell a bit about that Dan Wellman will teach in the more advanced tutorial? Because I consider seriously becoming “Plus”
( )Jeffrey Way February 19th
@Yosy – Email me at nettutsblog@gmail.com and I’ll send you the Aptana theme.
( )Erik Zettersten February 19th
Price of a pizza (=
( )Vasili February 19th
Hey Jeff, I was recreated this (so see if I could do it without looking back), and realized something. In the screencast, you use .hide() instead of .remove(). When you do this, you’re adding div upon div upon div to the body and they just stay there, hidden. .remove() is the way to do.
( )Craig February 19th
Great Tutorial. If anyone is interested in a tutorial on extending already-made plugins in jQuery. Check out my tutorial: http://www.tapocol.com/2008/12/11/simple-add-on-to-the-jquery-ui-draggable-widget
( )Jeffrey Way February 19th
@Vasili – Yeah. I realized that too after recording the screencast! To all those reading this, don’t use “hide()” when mousing off the anchor tag. I should have stuck with my gut. That’s why the source code doesn’t reflect it!
Thanks for bringing this to everyone’s attention, Vasili!
( )Chris Gunther February 19th
Nice tutorials. Covers all the basics and doesn’t leave anything unexplained.
( )Sérgio Soares February 19th
thanks jeffrey
( )John February 19th
Really useful tutorial, many thanks Jeffrey !
( )Steve Jobs February 19th
That insic girl (or guy) just happened to find everything useful
( )Gabe February 19th
Man, you made it so a dummy like me could follow along. Many thanks, I can’t wait to build my own! For some reason the word “plugin” carries this mysticism that is completely irrational – like it’s magic or voodoo. If I just think of it as an “include” or an external file, I feel less intimidated. Great work, Jeff.
( )Vasily February 19th
Fantastic, I did this and it works wonderfully! Thank you.
( )Good point on the price of pizza, I’ve just ordered one and I think I am going to go ahead and sign up for the Tuts+.
Jeffrey Way February 19th
@Gabe – Exactly. It sounds much harder than it really is.
@Vasily – Really happy to hear that. You won’t regret it…and you’ll be helping us out a great deal. Thank you!
( )Braden Keith February 19th
Thank you for this. Very helpful in clearing some things up.
( )M.A.Yoosuf February 19th
thank you jeff, you continue without the Pro version, till i subscribe , because hopefully EOM i will.
( )Zair Abbas February 20th
cool! this will surely gonna help!
( )thanks
Per Ulv February 20th
This is great
( )Jack Hoge February 20th
Hey Jeffrey,
In your jQuery for Beginners tutorial on Themeforest, didn’t you say you hated Aptana’s habits?
What changed your mind?
Good tutorial, should save people a solid chunk of time.
( )chris berthe February 20th
Great, thank you!
( )clhmedia February 20th
awesome stuff, will have to review this over the weekend
( )jem February 20th
Another great tutorial!
I’m starting to wonder if Jon Resig isn’t slipping Nettuts a little money under the table! I can’t recall the last time anything got posted using another framework… or are people just not sending them in!
( )Jeffrey Way February 20th
@Jack – Good memory! A few weeks ago, I gave it another chance. I quite like it now! It’s very powerful.
( )aperta February 20th
Simple and Evective … Thanks
( )Jeffrey Way February 20th
@Jem – 95% of the framework tutorials we receive are jQuery. The other 5% are for Mootools. Nothing else.
( )arma9 February 21st
It’s so simple explained that . Thanx
( )Jason February 21st
I can’t Stand it when a tutorial assumes that you know enough already to be able to handle the tutorial. I’m still wrapping my head around a stylesheet. If anyone cares to take a look at one of my sites and give me some good advice I would appreciate it a lot.
TheRandomlist.com
my email is: aaberg@gmail.com
( )Jack F February 21st
Any chance of all the TUTS and ThemeForest screencasts appearing on iTunes so I can chuck them on my iPod Touch? Would rock
( )Rocky February 21st
You rock this is the best tutorial to date so far
( )Jeffrey Way February 22nd
@Jack – They’re already there. Open iTunes and search for “NETTUTS”.
@Rocky – Thanks so much!
( )Ashish Lohorung Rai February 22nd
multiple choices … really easy for beginners …great job !
( )Messeiry February 23rd
it’s ammazing jeff.. thanks alot
( )Bryan Kwon February 23rd
am I the only one who think this could be possibly more effective when used with livequery? instead of onmousemover event.
( )chandra sekhar veera February 24th
This tooltip has an issue in IE6, just move your mouse across — “over the years” text, the tooltip’s width keeps changing.
( )Krum February 25th
Really helpful tutorial, buddy! Thanks
( )Leeiio February 25th
Thanx very much~
( )paper February 27th
Thanks
( )Shane March 11th
Hey Jeffrey – just wanted to say thanks for the tutorial.
( )jAY March 16th
Hi Jeffrey,
Thanks for the great tutorials…. I first found about tutorials a week ago via jquery.com. Your tutorials are very very cool and wonderful….
Is there any video tutorial that tells about CSS or do you plan to create one? It would be great if you post one!!!
thanks again…
( )jAY
Andrew Gunn March 18th
This is a wicked tutorial. I used it to create a watermark effect plugin for input fields: http://andrewgunn.blogspot.com/2009/01/jquery-watermark-plugin.html.
( )webcook March 21st
superb Jeffrey .. very very thanks
( )ludjer April 10th
Thanks for this sounds good.
( )Erik Groda April 18th
Thankyou, now can I make own jQuery plugins.
( )Shahriat Hossain April 20th
Helpful post thanks! I am trying to develop my own jQuery plugin and this will help me a lot.
( )Jordan Garn May 1st
Still a little bit to hard for me to follow, jQuery is hard for me to wrap my head around!
( )jerreychen June 16th
It’s helpful, thanks!
( )jQuery is great! I like it.
Emre Erkan June 24th
At the Creating our tooltip section, the last code block is a little wrong.
[code]if (defaults.rounded) {
$('#tooltip').addClass('rounded');
}[/code]
it has to be:
[code]if (settings.rounded) {
$('#tooltip').addClass('rounded');
}[/code]
It’s right in the final code.
( )