• Creating a jQuery Plugin: A Beginner’s Guide

  • By: Jarod Taylor | Category: jQuery
  • This is not an introduction to jQuery or a tutorial on the basic syntax rules of jQuery, but, rather how to take what little knowledge you already have of jQuery to the next level by putting it to practical use, and building a jQuery plugin.

    By taking your knowledge of CSS, and what knowledge you already have of jQuery, I'm going to walk you through the processes of creating a jQuery plugin. I feel, by using the skills you're already comfortable with, like CSS, it will be easier to wrap your head around jQuery. So instead of trying to learn a bunch of programming concepts, you may or may not understand, you're going to learn something new by using concepts that are already familiar to you. Once you're finished with this tutorial, you'll then be ready to take the necessary steps in really learning jQuery.

    Get SourceView Demo

    Introduction (Part One)

    My first jQuery plugin, Meerkat, is what we'll be creating in this tutorial. I learned a great deal while creating this plugin. It's not to say I don't have a lot more to learn, but, it did give me enough experience that I feel much more comfortable working with it now. I strongly encourage you to take what you already know, as well as what you learn from this tutorial, and build your own plugin. Even if it's something very basic, you'll really bake the syntax into your brain rather than feeling the need to always refer to the jQuery Documentation for help.

    Before we get started, you should at least have a general understanding of the basics of jQuery. When I refer to "basics", I mean, the very basics. It would help to have basic understanding of the javascript syntax. I'll be referencing sites often throughout the tutorial. Other than that, you should have a pretty good knowledge of CSS in order to really understand what we're accomplishing.

    Here are some of the jQuery API we'll be using in our plugin:

    As always, let me give you a breakdown of the steps we'll be taking in creating Meerkat. You can certainly skip any steps you may already feel comfortable with.

    Tutorial Navigation
    Part One
    1. Introduction (Part One)
    2. Create a basic layout for the demonstration
    3. Add Meerkat using HTML & CSS
    4. Add Meerkat using jQuery
    5. Move IE6 Conditions to our jQuery
    6. Add a "close" option to Meerkat
    7. Make Meerkat appear and disappear sexier
    8. Interlude (End Part One)
    Part Two
    1. Introduction (Part Two)
    2. The Anatomy of a jQuery plugin
    3. Turn our existing jQuery script into a plugin
    4. Add customizable selector to Meerkat
    5. Ode to a Cheeseburger
    6. Meerkat needs some options
    7. Meerkat's animation options
    8. Annoying page viewers is not a good idea
    9. Meerkat wants to reach higher heights
    10. IE6 body background fix
    11. Final Thoughts

    A lot of the core functionality of our plugin actually utilizes the same techniques used in my Fixed Header & Footer Layout: A Beginner’s Guide tutorial. In that tutorial we worked out a way of getting IE6 to emulate position: fixed. Meerkat depends on the same techniques used in that tutorial. Rather than rehashing the processes used, I will assume you either already understand the process or have followed that turorial. Let's get started.

    Noobnote:

    I'll be using my standard folder structure and assuming you're using it as well. Otherwise you'll need to make the necessary adjustments when saving, opening, and referring to file paths.

    meerkat/index.html
    meerkat/images/
    meerkat/css/
    meerkat/js/

    Create a basic layout

    We're going to start off with some basic content to start with. You can either use your own or use what I'm going to provide you with, either way will work.

    If you're using your own content, go ahead and skip to the next step. Otherwise let's get this basic layout done.

    Create a new blank file and save it as index.html in your root (meerkat) folder. Put the following markup in your new index file.

    <div id="container">
    	<div id="header">
    		<h1>Meerkat Header</h1>
    	</div>
    	<div id="content">
    		<h1>Sed ut perspiciatis unde</h1>
    		<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>
    		<h1>Lorem ipsum dolor sit amet</h1>
    		<p>Praesent tortor massa, ultrices in mattis non, viverra vitae eros. Fusce egestas suscipit nulla tincidunt cursus. Etiam eget tortor sit amet arcu bibendum bibendum nec in lorem. Phasellus posuere placerat mi, et consequat sem molestie ut. Sed eget sapien sed lacus laoreet vestibulum sit amet nec lectus. Aenean sed tortor turpis. Morbi consectetur diam quis augue convallis iaculis. Curabitur pulvinar scelerisque euismod. Cras et sagittis mauris. Mauris nisl ipsum, bibendum et congue vitae, blandit id sapien. Suspendisse ipsum metus, vehicula quis ultrices at, interdum quis nunc. Aenean fermentum hendrerit nisl vitae euismod. Morbi dictum mattis tellus, ac ornare sapien venenatis quis.</p>
    
    		<p>Aenean aliquam erat neque. Mauris scelerisque vestibulum posuere. Praesent aliquet, quam vel fermentum posuere, leo felis varius magna, in pretium arcu mi vel ipsum. Sed porttitor venenatis tortor, semper pellentesque nisl placerat quis. Etiam ornare turpis id massa consectetur vestibulum. Pellentesque vitae suscipit lectus. Pellentesque in nisi eget velit scelerisque placerat a vitae ipsum. Mauris eu diam tortor, at blandit felis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec vestibulum volutpat pulvinar. Etiam congue risus ut turpis dictum nec dictum ligula porta. Nulla sit amet ipsum at ligula vulputate imperdiet. Nulla posuere, justo commodo mattis hendrerit, leo dolor auctor ligula, sed accumsan tellus ligula eu eros. Fusce pulvinar risus sed sapien facilisis at scelerisque risus bibendum. Quisque orci quam, porta sed ultrices vitae, faucibus sed mauris.  </p>
    
    		<h1>At vero eos et accusamus</h1>
    		<p>Cras turpis nisi, condimentum nec convallis at, lacinia sit amet diam. Proin dapibus luctus quam ac varius. Sed ornare venenatis magna, vel mollis dui dapibus quis. Suspendisse nisl lectus, porta ac tempor vel, gravida et mi. Cras tristique nisl at dolor adipiscing fermentum. Curabitur vitae lacinia quam. Phasellus urna sem, condimentum ut sagittis sed, dictum at lacus. Pellentesque felis turpis, interdum a adipiscing id, ornare eget ipsum. Aenean scelerisque diam sed orci lacinia rutrum dictum nisl congue. Curabitur vitae nunc velit, a pulvinar magna. Etiam venenatis placerat justo, sed rhoncus lectus venenatis at. Ut sagittis diam eu libero volutpat tempor. Phasellus non quam orci, malesuada volutpat eros. Suspendisse malesuada bibendum aliquet. Donec auctor, justo ut luctus consectetur, diam neque pellentesque velit, eu vehicula mi neque sed sem. Pellentesque neque est, vulputate non euismod ut, accumsan ac nibh. Vivamus dignissim, sapien mollis eleifend tempor, tellus nulla ultrices velit, at tincidunt ligula sapien sed metus.</p>
    	</div>
    	<div id="sidebar">
    		<h2>Sed ut perspiciatis</h2>
    		<p>Nulla vehicula accumsan tincidunt. Nullam fermentum mi sit amet mauris viverra eleifend.</p>
    		<blockquote>
    			<p>Donec auctor, justo ut luctus consectetur, diam neque pellentesque velit, eu vehicula mi neque sed sem. Pellentesque neque est, vulputate non euismod ut, accumsan ac nibh.</p>
    		</blockquote>
    		<p>Proin dapibus luctus quam ac varius. Sed ornare venenatis magna, vel mollis dui dapibus quis.</p>
    		<h2>Nemo enim ipsam?</h2>
    		<p>Mauris pellentesque imperdiet gravida. Duis lobortis ornare auctor. Nulla vehicula accumsan tincidunt.</p>
    		<ol>
    			<li>Excepteur sint occaecat</li>
    			<li>Excepteur sint occaecat</li>
    			<li>Excepteur sint occaecat</li>
    			<li>Excepteur sint occaecat</li>
    			<li>Excepteur sint occaecat</li>
    		</ol>
    		<p>Donec quam magna, dignissim nec elementum sed, iaculis sed libero.</p>
    
    		<ul>
    			<li>Curabitur tempus tincidunt</li>
    			<li>Curabitur tempus tincidunt</li>
    			<li>Curabitur tempus tincidunt</li>
    			<li>Curabitur tempus tincidunt</li>
    			<li>Curabitur tempus tincidunt</li>
    		</ul>
    		<p>Vehicula, risus in suscipit aliquet, tellus diam elementum ante, quis interdum massa dolor a leo. </p>
    	</div>
    	<div id="footer">
    		©2009 Noobcube.com
    	</div>
    </div>
    

    Create a new blank file and save it as main.css in your /css folder. Put the following styles in your your new stylesheet.

    body {
    	font: 62.5% Arial, Helvetica, sans-serif;
    	color: #482932;
    	margin: 0;
    	padding: 0;
    	background: #fafafa;
    }
    
    h1, h2 {
    	color: #3F5A69;
    	font-family: Georgia, "Times New Roman", Times, serif;
    	margin: 20px 0 10px;
    }
    
    h1 {
    	font-size: 2.5em;
    }
    
    h2 {
    	font-size: 1.8em;	
    }
    
    p {
    	margin: 10px 0;
    	padding: 0;
    }
    
    blockquote {
    	font-style: italic;	
    }
    
    #container {
    	width: 940px;
    	margin: 0 auto;
    	font-size: 1.4em;
    	overflow: auto;
    }
    
    #header {
    	height: 100px;
    	background: url(../images/header-bg.png) repeat-x 0 0;
    }
    
    #header h1 {
    	color: #FAFAFA;
    	font-family: Tahoma, Arial, Helvetica, sans-serif;
    	text-transform: uppercase;
    	padding: 30px 0 0 10px;
    	margin: 0;
    }
    
    #content {
    	float: left;
    	width: 600px;
    	padding-left: 10px;
    	margin-bottom: 10px;
    }
    
    #sidebar {
    	float: right;
    	width: 275px;
    	margin-top: 10px;
    	padding-right: 10px;
    }
    
    #footer {
    	clear: both;
    	height: 23px;
    	padding: 7px 0 0 10px;
    	background: #556e7c;
    	color: #FAFAFA;
    	border-top: 2px solid #30434e;
    }
    

    Go ahead and include your new stylesheet (main.css) in the head of your index.html file and open it in your browser. You should have something like this.

    Add Meerkat Markup

    We're going to start out by adding the necessary markup for our meerkat to the index.html file. Place the following content below the rest of the content in index.html, just before the closing body tag.

    <div id="meerkat-wrap">
    	<div id="meerkat-container">
    		<div id="meerkat">
    		Meerkat Content
    		</div>
    	</div>
    </div>
    

    Create a new blank file and save it as meerkat.css in your /css folder. Put the following styles in your your new stylesheet.

    #meerkat-wrap {
    	width: 100%;
    	position: fixed;
    	bottom: 0;
    }
    
    #meerkat-container {
    	background: url(../images/meerkat-bg.png) repeat-x 0 0;
    	height: 100px;
    }
    
    #meerkat {
    	width: 940px;
    	margin: 0 auto;
    	color: #FAFAFA;
    	padding-top: 10px;
    }
    

    You may be asking, why do we have 3 divs for Meerkat? The first div (#meerkat-wrap) is going to be used to give it its 100% width and fixed position. This allows for you to center the Meerkat content div (#meerkat) in the browser using width and margin declarations. You may still be wondering, well, what's the meerkat-container being used for? Can't we just put all its styles in the meerkat-wrap? We could, but unfortunately, IE6 needs that container div and you'll see why later.

    Go ahead and include your new stylesheet (meerkat.css) in the head of your index.html file (under your main.css file) and open it in your browser. You should have something like this.

    In a perfect world, this would be it. We would just write some jQuery to automate the HTML and CSS and we'd be halfway done. But, and that's a big "BUT", this is not a perfect world. We live in a world of IE6, where position: fixed is treated as position: static . Open up your page in IE6 and you'll immediately notice the twinged failure. :(

    As I stated earlier, there's an easy fix that was discussed in the Fixed Header & Footer Layout: A Beginner’s Guide tutorial. What we need to do is wrap all the page content (except Meerkat) in a container and give it a width of 100%, a height of 100%, and an overflow property value of auto. We also need to set the html and body elements' overflow properties to hidden. This will hide the browsers typical scrollbar, and give our new page content container a scrollbar, giving it the effect of being the body's scrollbar.

    Let's open up the index.html file and wrap our content in a container div. I've highlighted the additions.

    <div id="ie6-content-container">
    	<div id="container">
    		<div id="header">
    			<h1>Meerkat Header</h1>
    		</div>
    		<div id="content">
    			<h1>Sed ut perspiciatis unde</h1>
    			<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>
    			<h1>Lorem ipsum dolor sit amet</h1>
    			<p>Praesent tortor massa, ultrices in mattis non, viverra vitae eros. Fusce egestas suscipit nulla tincidunt cursus. Etiam eget tortor sit amet arcu bibendum bibendum nec in lorem. Phasellus posuere placerat mi, et consequat sem molestie ut. Sed eget sapien sed lacus laoreet vestibulum sit amet nec lectus. Aenean sed tortor turpis. Morbi consectetur diam quis augue convallis iaculis. Curabitur pulvinar scelerisque euismod. Cras et sagittis mauris. Mauris nisl ipsum, bibendum et congue vitae, blandit id sapien. Suspendisse ipsum metus, vehicula quis ultrices at, interdum quis nunc. Aenean fermentum hendrerit nisl vitae euismod. Morbi dictum mattis tellus, ac ornare sapien venenatis quis.</p>
    		
    			<p>Aenean aliquam erat neque. Mauris scelerisque vestibulum posuere. Praesent aliquet, quam vel fermentum posuere, leo felis varius magna, in pretium arcu mi vel ipsum. Sed porttitor venenatis tortor, semper pellentesque nisl placerat quis. Etiam ornare turpis id massa consectetur vestibulum. Pellentesque vitae suscipit lectus. Pellentesque in nisi eget velit scelerisque placerat a vitae ipsum. Mauris eu diam tortor, at blandit felis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec vestibulum volutpat pulvinar. Etiam congue risus ut turpis dictum nec dictum ligula porta. Nulla sit amet ipsum at ligula vulputate imperdiet. Nulla posuere, justo commodo mattis hendrerit, leo dolor auctor ligula, sed accumsan tellus ligula eu eros. Fusce pulvinar risus sed sapien facilisis at scelerisque risus bibendum. Quisque orci quam, porta sed ultrices vitae, faucibus sed mauris.  </p>
    			
    			<h1>At vero eos et accusamus</h1>
    			<p>Cras turpis nisi, condimentum nec convallis at, lacinia sit amet diam. Proin dapibus luctus quam ac varius. Sed ornare venenatis magna, vel mollis dui dapibus quis. Suspendisse nisl lectus, porta ac tempor vel, gravida et mi. Cras tristique nisl at dolor adipiscing fermentum. Curabitur vitae lacinia quam. Phasellus urna sem, condimentum ut sagittis sed, dictum at lacus. Pellentesque felis turpis, interdum a adipiscing id, ornare eget ipsum. Aenean scelerisque diam sed orci lacinia rutrum dictum nisl congue. Curabitur vitae nunc velit, a pulvinar magna. Etiam venenatis placerat justo, sed rhoncus lectus venenatis at. Ut sagittis diam eu libero volutpat tempor. Phasellus non quam orci, malesuada volutpat eros. Suspendisse malesuada bibendum aliquet. Donec auctor, justo ut luctus consectetur, diam neque pellentesque velit, eu vehicula mi neque sed sem. Pellentesque neque est, vulputate non euismod ut, accumsan ac nibh. Vivamus dignissim, sapien mollis eleifend tempor, tellus nulla ultrices velit, at tincidunt ligula sapien sed metus.</p>
    		</div>
    		<div id="sidebar">
    			<h2>Sed ut perspiciatis</h2>
    			<p>Nulla vehicula accumsan tincidunt. Nullam fermentum mi sit amet mauris viverra eleifend.</p>
    			<blockquote>
    				<p>Donec auctor, justo ut luctus consectetur, diam neque pellentesque velit, eu vehicula mi neque sed sem. Pellentesque neque est, vulputate non euismod ut, accumsan ac nibh.</p>
    			</blockquote>
    			<p>Proin dapibus luctus quam ac varius. Sed ornare venenatis magna, vel mollis dui dapibus quis.</p>
    			<h2>Nemo enim ipsam?</h2>
    			<p>Mauris pellentesque imperdiet gravida. Duis lobortis ornare auctor. Nulla vehicula accumsan tincidunt.</p>
    			<ol>
    				<li>Excepteur sint occaecat</li>
    				<li>Excepteur sint occaecat</li>
    				<li>Excepteur sint occaecat</li>
    				<li>Excepteur sint occaecat</li>
    				<li>Excepteur sint occaecat</li>
    			</ol>
    			<p>Donec quam magna, dignissim nec elementum sed, iaculis sed libero.</p>
    			
    			<ul>
    				<li>Curabitur tempus tincidunt</li>
    				<li>Curabitur tempus tincidunt</li>
    				<li>Curabitur tempus tincidunt</li>
    				<li>Curabitur tempus tincidunt</li>
    				<li>Curabitur tempus tincidunt</li>
    			</ul>
    			<p>Vehicula, risus in suscipit aliquet, tellus diam elementum ante, quis interdum massa dolor a leo. </p>
    		</div>
    		<div id="footer">
    			©2009 Noobcube.com
    		</div>           
    	</div>
    </div>
    <div id="meerkat-wrap">
    	<div id="meerkat-container">
    		<div id="meerkat">
    		Meerkat Content
    		</div>
    	</div>
    </div>
    

    So, you'll see, we added a div with the id of ie6-content-container to our page, which is wrapping all of the page's content except the meerkat element.

    We now need to create a new blank file and save it as ie6.css in the /css folder. Put the following styles in the new ie6.css file.

    html, body {
    	height: 100%;
    	overflow: hidden;
    }
    
    #ie6-content-container {
    	width: 100%;
    	height: 100%;
    	overflow: auto;
    	position: absolute;
    }
    
    #meerkat-wrap {
    	position: absolute;
    	bottom: -1px;	
    }
    
    #meerkat-container {
    	margin-right: 17px;	
    }
    

    I don't want to repeat myself too much by explaining exactly what we're doing here with these styles, because it was explained in the Fixed Header & Footer Layout: A Beginner’s Guide tutorial, but I'll briefly explain what's going on here.

    In order for our ie6-content-container to understand 100% height, we needed to give both our html and body elements the height of 100% as well.

    We've given our ie6-content-container a height of 100%, a width of 100%, and an overflow value of auto. This gives our container the effect of emulating the body element.

    As I stated before, IE6 does not support position: fixed and treats our meerkat-wrap's position property as static. In order for us to achieve what we're wanting to achieve, we gave our meerkat-wrap a position declaration of absolute. This is much closer to position: fixed than static. We've also added a -1px bottom declaration due to IE6 leaving a 1px gap between Meerkat and the bottom of the page (for some reason unknown to me).

    As discussed in the Fixed Header and Footer tutorial, we need the additional div meerkat-container so we can shift our Meerkat to the left 17px, so it doesn't sit on top of our scrollbar.

    Go ahead and put a conditional comment in your header to include your new ie6.css stylesheet. Be sure to put it below your other stylesheets. It should look like this:

    <head>
    <title>Meerkat</title>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <link href="css/meerkat.css" rel="stylesheet" type="text/css" />
    <!--[if IE 6]>
    <link href="css/ie6.css" rel="stylesheet" type="text/css" />
    <![endif]-->
    </head>
    

    Open up your page in IE6 and you should now see it working like it should.

    Now that that's out of the way, what do you say we write some jQuery?

    Add Meerkat using jQuery

    We're going to now take everything we just did in our Meerkat markup and move it into a jquery script. That's right, all the CSS and most of the HTML is going to be added to our page using jQuery, rather than statically placing it in our HTML document. The reason is (as you can see when you view our page currently), the meerkat element obstructs the view of our page content. It's supposed to do that, but, it's also supposed to have a way for the user to close it. Therefore, we only want Meerkat to show if the user has javascript enabled, otherwise it will really make page viewers mad when they can't close it.

    First thing's first, we need to include the jQuery core into the header of our index.html file. Go ahead and include the script reference in your header, below your CSS files.

    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <link href="css/meerkat.css" rel="stylesheet" type="text/css" />
    <!--[if IE 6]>
    <link href="css/ie6.css" rel="stylesheet" type="text/css" />
    <![endif]-->
    <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
    

    To really understand what we are creating, we're going to start out by creating some inline jQuery. After we get things going, we'll move it into a javascript file. For now, go ahead and include the DOM ready function right below our jQuery core reference.

    <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function(){
    //jQuery Goes here
    });
    </script>
    

    What we need to do is save our index.html file as index-backup.html. This way we always have a fallback, should something get screwed up! Go ahead and remove all the meerkat HTML in your index.html file, except the <div id="meerkat"> element. We're going to create this content with jQuery instead. Your meerkat content on your index.html file should now look like mine.

    &lt;/div&gt;&lt;!-- END ie6-content-container --&gt;
    &lt;div id=&quot;meerkat&quot;&gt;
    	Meerkat Content
    &lt;/div&gt;
    &lt;/body&gt;
    

    Now, let's create the #meerkat-wrap and #meerkat-container divs using jQuery. Inbetween your jQuery DOM ready function add the highlighted code.

    $(document).ready(function(){
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    });
    

    What we're doing here is telling jQuery to find the element with the id #meerkat and wrap() the <div id="meerkat-wrap"> and <div id="meerkat-container"> elements around it.

    Take a look at your page now, and you'll see Meerkat is back. If you view-source, you'll only see the <div id="meerkat"><div> tags now. That's because we're adding the <div id="meerkat-wrap"> and <div id="meerkat-container"> tags with jQuery.

    Now let's do the same thing with the Meerkat styles. We need to remove the #meerkat-wrap and #meerkat-container styles from the meerkat.css file and add them with jQuery. Go ahead and remove them from your stylesheet and save your main.css file.

    Add the highlighted code to your jQuery script.

    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    });
    

    What we've done is removed the styles (#meerkat-wrap and #meerkat-container) from our meerkat.css stylesheet, and instead, used the jQuery function css() to do the dirty work for us. We also reset the body's margin to 0. Otherwise, Meerkat wouldn't stretch 100% of the browser window.

    Take a look at what we have now.

    If you were to open the page in IE6 right now, Meerkat would be missing. This is because our jQuery script is below our ie6.css file and it's overriding the styles. That's alright, we're gonna move its CSS to jQuery as well.

    Move IE6 Conditions to our jQuery

    So far we have wrapped our #meerkat element with its containing divs and added their respected styles. Now we need to move our IE6 styles and HTML to jQuery as well.

    We need to detect the user's browser, and if it's Internet Explorer 6, add the CSS using the same css() function we used in the last step.

    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});	
    	}
    });
    

    What we've used here is jQuery's utility $.browser to detect the user's browser type and version. If they are using IE6 or below, we're giving meerkat-wrap the position value of absolute and its bottom value of -1px. Now if you open our page in IE6, Meerkat is back.

    Noobnote:

    As of jQuery 1.3, the jQuery utility $.browser is considered "deprecated" and being replaced by $.support, but unfortunately it does not have a way of targeting IE6 alone. As of now (07/22/2009) the utility $.browser is still working in jQuery.

    Now that we've implemented a way of targeting IE6 in our jQuery, we need to go ahead and move the other IE6 conditional markup and styles to our script.

    tutorial image

    As you can see here, we can move all of Meerkat's IE6 conditional styles to jQuery and eliminate the need for the stylesheet completely. Also, only IE6 needs the div element ie6-content-container, because all the other major browsers support position: fixed, therefore, it's not needed in our markup unless the user is using IE6.

    Let's start by removing the ie6-content-container div from our index.html file and having jQuery do it for us.

    We know the function to use for this! We used it to wrap() the meerkat div with both <div id="meerkat-wrap"></div> and <div id="meerkat-container"></div>. There is one setback though. How will Meerkat know what to wrap()?

    tutorial image

    In this particular demonstration we could target the container div and wrap() it like this:

    $('#container').wrap('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    

    There are setbacks for doing this though. What if the site you're using Meerkat on doesn't have a #container div? Better yet, what if there were several children to the body element and ALL OF THEM needed to be wrapped?

    tutorial image

    This is where jQuery's trusty traversing function filter() comes in! Add the highlighted code to your jQuery script. I'll tell you what we're doing.

    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		$(&quot;body&quot;).children()
    			.filter(function (index) {
    				return $(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    	}
    });
    

    What we're telling jQuery to do here is this:

    1. Find all the children() of the body element
    2. Filter out any children that have an id of "meerkat-wrap"
    3. Then wrapAll() them with <div id="ie6-content-container"></div>

    Make sure you have removed the div ie6-content-container from index.html. We now have it being dynamically added using jQuery. Take a look at our page in IE6, view-source, and you'll see that ie6-content-container is no longer in our markup. We're letting jQuery do the dirty work for us. Now we need to move the CSS to our script!

    Go ahead and remove the ie6.css style sheet reference from the head of your index.html file. You should now have something like this:

    &lt;head&gt;
    &lt;title&gt;Meerkat&lt;/title&gt;
    &lt;link href=&quot;css/main.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
    &lt;link href=&quot;css/meerkat.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		$(&quot;body&quot;).children()
    			.filter(function (index) {
    				return $(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    	}
    });
    &lt;/script&gt;
    

    Let's put the IE6 styles right below our wrapAll() function.

    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		$(&quot;body&quot;).children()
    			.filter(function (index) {
    				return $(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    		//Add all the IE6 conditional CSS
    		$('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    		$('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    		$('#meerkat-container').css({'margin-right':'17px'});
    	}
    });
    

    We've used the css() function quite a bit thus far, so you should already have an idea what we just did. Take a look at our page in IE6 and you'll see everything is working the way it should be. Now all of our Meerkat content is being added dynamically to our page with jQuery.

    Before we go any further, there's something we need to consider. We are currently telling jQuery to shift our meerkat-container right 17px (in IE6 or below) to keep it from obstructing the view of our vertical scrollbar. What if there isn't enough content on the page to create a vertical scrollbar?

    Look what happens in IE6 if we remove enough of our page content to remove the vertical scrollbar. Our meerkat-container has shifted 17px and left a 17px gap. We never know what the person using Meerkat will have on there page so let's account for this situation and provide a javascript solution.

    We need to create a conditional statement simply stating:

    If there's a vertical scrollbar, move meerkat-container right 17px. If there isn't a vertical scrollbar, don't move meerkat-container at all.

    First of all, you need to remember where the scrollbars are actually coming from in IE6. Remember, we have hidden the browsers default scrollbars (body, html). In IE6, the vertical scrollbars you're actually seeing are from the ie6-content-container. So we need to detect if ie6-content-container has a vertical scrollbar or not.

    Find the line in your jQuery script where it shifts the meerkat-container right, by 17px. We're going to replace that line of code with this.

    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		$(&quot;body&quot;).children()
    			.filter(function (index) {
    				return $(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    		//Add all the conditional (to IE6 or below) CSS
    		$('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    		$('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    		//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    		var ie6ContentContainer = document.getElementById('ie6-content-container');
    		if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    			$('#meerkat-container').css({'margin-right':'17px'});		
    		}
    	}
    });
    

    Okay, let me explain what we're doing here.

    1. We're naming a variable ie6ContentContainer and assigning it the value of document.getElementById('ie6-content-container').
    2. We're then using that variable to target its clientHeight and scrollHeight.
    3. If the clientHeight is less than the scrollHeight (that means we have a scrollbar) add margin-right: 17px to #meerkat-container.
    Noobnote:

    clientHeight refers to the height of an element.

    scrollHeight refers to the height of the element's content.

    So if the clientHeight is 400px and the scrollHeight is 600px, you'd have a scrollbar.

    That's it! Take a look at the page in IE6 now. Because we don't have a scrollbar, our meerkat-container is staying put. If we add the content back, once again adding a vertical scrollbar, meerkat-container will shift right 17px.

    So far, we've created a jQuery script that will put Meerkat on our page, but there's no way for the user to close Meerkat. Let's do that next!

    Add a "close" option to Meerkat

    Open up your index.html file and add an anchor element inside the meerkat div with the class "close".

    &lt;/div&gt;&lt;!--End container--&gt;
    &lt;div id=&quot;meerkat&quot;&gt;
    	&lt;a class=&quot;close&quot;&gt;Close Meerkat&lt;/a&gt;
    &lt;/div&gt;
    &lt;/body&gt;
    
    Noobnote:

    There's no need to put a href="" on this anchor element. If you still want to create a pointer cursor and add "link like" styles to the anchor, simply do so in your meerkat.css file.

    This is my meerkat.css file styles (remember we removed the meerkat-wrap and meerkat-container styles):

    #meerkat {
    width: 940px;
    margin: 0 auto;
    color: #FAFAFA;
    padding: 10px 0 0 20px;
    }

    #meerkat a.close {
    cursor: pointer;
    color: #FFF;
    text-decoration: underline;
    }

    Now at the bottom of your jQuery script, add the highlighted code. Make sure you add it outside of the IE6 conditional scripts.

    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		$(&quot;body&quot;).children()
    			.filter(function (index) {
    				return $(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    		//Add all the conditional (to IE6 or below) CSS
    		$('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    		$('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    		//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    		var ie6ContentContainer = document.getElementById('ie6-content-container');
    		if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    			$('#meerkat-container').css({'margin-right':'17px'});		
    		}
    	}
    	//If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    	$(&quot;.close&quot;).click(function(){
    		$(&quot;#meerkat-wrap&quot;).hide();					   
    	});
    	
    });
    

    Here's what we're doing here:

    1. Add a click() event function to any element that has a class of "close".
    2. When this element is clicked, hide() meerkat-wrap.

    Go ahead and check out our page now. If you click "close-meerkat", it goes away.

    Awesome, now the user has a way of closing Meerkat! Next, we'll make it appear and disappear in a much sexier way!

    Make Meerkat appear and disappear sexier

    On our ".close" click event, change hide() to slideUp("slow").

    //If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    $(&quot;.close&quot;).click(function(){
    	$(&quot;#meerkat-wrap&quot;).slideUp(&quot;slow&quot;);					   
    });
    

    Now it closes with style.

    Noobnote:

    The slideUp() function takes a speed argument. We used slideUp("slow"), but you have a few choices.

    You could use the following values:

    • String: "slow", "normal", or "fast"
    • Integer or float: A number which will represent the milliseconds to run the animation (e.g. 1000)

    If you choose to use a number, be sure not to include it in quotes. It would be slideUp(500), not slideUp("500").

    Now our Meerkat, disappears much sexier, but we need it to appear sexier too! If we used slideUp() to make Meerkat disappear, we need to use slideDown() to make Meerkat appear.

    Add the highlighted code right above the click event code.

    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		$(&quot;body&quot;).children()
    			.filter(function (index) {
    				return $(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    		//Add all the conditional (to IE6 or below) CSS
    		$('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    		$('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    		//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    		var ie6ContentContainer = document.getElementById('ie6-content-container');
    		if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    			$('#meerkat-container').css({'margin-right':'17px'});		
    		}
    	}
    	//Get #meerkat-wrap to slide in
    	$(&quot;#meerkat-wrap&quot;).hide().slideDown(&quot;slow&quot;);
    	//If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    	$(&quot;.close&quot;).click(function(){
    		$(&quot;#meerkat-wrap&quot;).slideUp(&quot;slow&quot;);					   
    	});	
    });
    

    In order for us to animate Meerkat's appearance, we must hide() meerkat-wrap first, then use the slideDown() function. Otherwise, Meerkat would just appear quickly and slide down off the screen.

    Now take a look at our page. Mmm sexy..

    In Part 2 of this tutorial, we'll actually be using jQuery's animate() function to show and hide Meerkat, but we'll implement that once we start creating the actual plugin.

    Interlude (End Part One)

    We covered A LOT of ground today. We used jQuery to add all of our Meerkat content to our page. The only thing we have to include in our index.html file is the <div id="meerkat"></div> and jQuery does the rest. That's pretty cool if you ask me!

    A good way to test our script is to try and use it on a different file. Let's put it to the test now.

    1. Create a new html file
    2. Include the jQuery Core script
    3. Include the jQuery script we created
    4. Add content to the page
    5. Add <div id="meerkat"></div> just above the closing body tag and below your page content
    6. Test it and see if Meerkat works

    Here's what I used (notice I didn't use any stylesheets):

    &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
    &lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
    &lt;head&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
    &lt;title&gt;Meerkat Test&lt;/title&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	//Reset body and html margin to zero
    	$('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	$('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	//Add necessary styles to the two divs we just added
    	$('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	$('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if($.browser.msie &amp;&amp; $.browser.version &lt;= 6){
    		$('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		$(&quot;body&quot;).children()
    			.filter(function (index) {
    				return $(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    		//Add all the conditional (to IE6 or below) CSS
    		$('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    		$('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    		//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    		var ie6ContentContainer = document.getElementById('ie6-content-container');
    		if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    			$('#meerkat-container').css({'margin-right':'17px'});		
    		}
    	}
    	//Get #meerkat-wrap to slide in
    	$(&quot;#meerkat-wrap&quot;).hide().slideDown(&quot;slow&quot;);
    	//If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    	$(&quot;.close&quot;).click(function(){
    		$(&quot;#meerkat-wrap&quot;).slideUp(&quot;slow&quot;);					   
    	});	
    });
    &lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;div id=&quot;container&quot;&gt;
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt;
    	&lt;p&gt;This is content&lt;/p&gt; 
    	&lt;p&gt;This is content&lt;/p&gt; 
    &lt;/div&gt;
    &lt;div id=&quot;meerkat&quot;&gt;
    	&lt;a class=&quot;close&quot;&gt;Close Meerkat&lt;/a&gt;
    &lt;/div&gt;
    

    This is what I get.

    Awesome, works just like it should. I'll see you in Part 2!

    Introduction (Part Two)

    In Part 1, we created the layout of Meerkat and removed most of the HTML and CSS from its respected files (index.html & meerkat.css) and, instead, had our jQuery script dynamically add the HTML and CSS to our page for us. We also implemented the proper fixes for our beloved Internet Explorer 6, so that it too, could render Meerkat correctly. So, by the end of Part 1, we were at this stage of building Meerkat. A good start, but we have much work to do!

    In Part 2 of this tutorial we're going to start creating the actual Meerkat plugin. We'll be moving what we've already created into a separate file named jquery.meerkat.js, as well as adding all the bells and whistles. Before we dive into that, we need to first talk about jQuery plugins and common practices.

    Tutorial Navigation
    Part One
    1. Introduction (Part One)
    2. Create a basic layout for the demonstration
    3. Add Meerkat using HTML & CSS
    4. Add Meerkat using jQuery
    5. Move IE6 Conditions to our jQuery
    6. Add a "close" option to Meerkat
    7. Make Meerkat appear and disappear sexier
    8. Interlude (End Part One)
    Part Two
    1. Introduction (Part Two)
    2. The Anatomy of a jQuery plugin
    3. Turn our existing jQuery script into a plugin
    4. Add customizable selector to Meerkat
    5. Ode to a Cheeseburger
    6. Meerkat needs some options
    7. Meerkat's animation options
    8. Annoying page viewers is not a good idea
    9. Meerkat wants to reach higher heights
    10. IE6 body background fix
    11. Final Thoughts

    The Anatomy of a jQuery Plugin

    From what I've gathered in my journey to understand jQuery, I've noticed there are definitely more ways than 1 to achieve a lot of things in jQuery. Creating a plugin is no different. Rather than trying to explain all the differences (because I'm not 100% comfortable with understanding all the differences), I'm going to do a quick breakdown of what our jQuery plugin structure is going to be.

    $ or jQuery?

    As you probably know, jQuery uses the dollar symbol ($) in all of its API. The alternative to $ is using the actual word "jQuery". In all actuality, $ is just a shortcut for "jQuery".

    Both of these will work the same:

    $(&quot;#foo&quot;).hide();
    
    jQuery(&quot;#foo&quot;).hide;
    

    Unfortunately, other javascript libraries out there also use $, therefore, causing conflicts and ultimately failure in one or more of the scripts. There are a few ways of handling this. I'm not going to go into detail on this because there are already plenty resources on the jQuery site as well as others that explain the differences. To avoid confusion and too much added content to this tutorial, we're going to play it safe and replace all of our "$" symbols with "jQuery".

    Noobnote:

    If you're interested, there is a common method for creating plugins and keeping the shortcut ($) by using a Custom Alias.

    Before we go any further, let's go ahead and change our jQuery alias from "$" to "jQuery". You can either use your text-editor's "find and replace" method or simply copy my code below and replace what you have.

    index.html (our jQuery is still in the head of our index)
    jQuery(document).ready(function(){
    	jQuery('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    	jQuery('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    
    	//Add necessary styles to the two divs we just added
    	jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    	jQuery('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    	//If browser is Internet Explorer AND its version is less than or equal to 6
    	if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    		jQuery('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    		//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    		jQuery(&quot;body&quot;).children()
    			.filter(function (index) {
    				return jQuery(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    			})
    		.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    		//Add all the conditional (to IE6 or below) CSS
    		jQuery('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    		jQuery('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    		//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    		var ie6ContentContainer = document.getElementById('ie6-content-container');
    		if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    			jQuery('#meerkat-container').css({'margin-right':'17px'});		
    		}
    	}
    	//Get #meerkat-wrap to slide in
    	jQuery(&quot;#meerkat-wrap&quot;).hide().slideDown(&quot;slow&quot;);
    	//If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    	jQuery(&quot;.close&quot;).click(function(){
    		jQuery(&quot;#meerkat-wrap&quot;).slideUp(&quot;slow&quot;);					   
    	});	
    });
    
    jQuery.fn.extend

    jQuery.fn.extend attaches our jQuery plugin (as a method) to the jQuery Object. That may sound more confusing than it really is. Basically, it would be like saying "Yo jQuery, I'm about to create a plugin. Make sure you add this functionality (whatever is put between its curly braces) to your tool belt."

    jQuery.fn.extend({
         //plugin stuff here
    });
    
    Giving our plugin a Name

    After we've told jQuery to add our method to its toolbelt with jQuery.fn.extend, we need to declare our plugin's namespace.

    In our case, it's going to be "meerkat". So it would look like this:

    jQuery.fn.extend({
    	meerkat: function() {
    		 //plugin stuff here
    	}
    });
    
    return this.each(function(){...}

    First of all, if you're familiar with programming, return basically returns a value from a function. So it's like saying, "Do all this stuff and when you're done return something".

    In programming, "this" can be quite confusing. Mike Alsup does a pretty good job of explaining what "this" is here. Rather than trying to explain exactly what "return", "this", and "each" mean in return this.each(function(){...}, I'm going to briefly explain what it means in the context we're using it here.

    When we finish creating our plugin, we'll be able to call it like this:

    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	$(&quot;#foo&quot;).meerkat();
    });
    &lt;/script&gt;
    

    What this will do is attach Meerkat to whatever element has the id "foo". So in this particular case "this" would be referring to the element with the id "foo".

    So what is this.each? Well, let's say we build our plugin so it can be called like this:

    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	$(&quot;#foo&quot;).meerkat();
    	$(&quot;#foo2&quot;).meerkat();
    });
    &lt;/script&gt;
    

    There are two selectors (in this case id's) calling meerkat(). Which one does it attach to? Well, if we write the plugin correctly, it should attach to both of them. So, "this" refers to both of them.

    What each() does in jQuery is much like a loop does in any other programming language.

    So basically, this.each would be like saying "loop through each of these", these would be referring to "this". So in the above example it would return "#foo" and "#foo2".

    I know it's confusing. Trust me, I'm still confused by it.

    Nonetheless, this is where our function would be:

    jQuery.fn.extend({
    	meerkat: function() {
    		return this.each(function() {
    		 //plugin stuff here
    		});
    	}
    });
    

    So that's it. That's the outer shell of our plugin. I know it can be confusing, but the more you play with it and the more you read up on it, the more you start to understand. In a nutshell it's pretty much saying, "Yo jQuery, I'm about to create a plugin. Make sure you attach it to your toolbelt. By the way, you can refer to this tool by "meerkat". Each selector its attached to should do exactly what I say."

    Turn our existing jQuery script into a plugin

    In Part One we created Meerkat's basic layout with jQuery. What we need to do now is move what we have into a plugin.

    Create a new document and save it as jquery.meerkat.js in your /js folder. Put the following code in your new file.

    jquery.meerkat.js
    jQuery.fn.extend({
    	meerkat: function() {
    		return this.each(function() {
    		 //plugin stuff here
    		});
    	}
    });
    

    You should have already changed all your "$" symbols to "jQuery" in the script in your index.html file, but if you haven't, go ahead and do so now.

    Take all your jQuery code in index.html (just the code inbetween $(document).ready(function(){ });) and paste it into jquery.meerkat.js inbetween the return this.each function.

    I've highlighted the changes.

    jquery.meerkat.js
    //Attach our plugin to your toolbelt, jQuery
    jQuery.fn.extend({ 
    	
    	//My name is meerkat
    	meerkat: function() {
    		
    		//Loop through each 
    		return this.each(function() {
    								  
    			//Reset body and html margin to zero
    			jQuery('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    			//Find element in DOM with id &quot;meerkat&quot; and wrap the two wrapper and container divs around it
    			jQuery('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    		
    			//Add necessary styles to the two divs we just added
    			jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    			jQuery('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    			//If browser is Internet Explorer AND its version is less than or equal to 6
    			if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    				jQuery('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    				//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    				jQuery(&quot;body&quot;).children()
    					.filter(function (index) {
    						return jQuery(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    					})
    				.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    				//Add all the conditional (to IE6 or below) CSS
    				jQuery('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    				jQuery('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    				//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    				var ie6ContentContainer = document.getElementById('ie6-content-container');
    				if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    					jQuery('#meerkat-container').css({'margin-right':'17px'});		
    				}
    			}
    			//Get #meerkat-wrap to slide in
    			jQuery(&quot;#meerkat-wrap&quot;).hide().slideDown(&quot;slow&quot;);
    			//If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    			jQuery(&quot;.close&quot;).click(function(){
    				jQuery(&quot;#meerkat-wrap&quot;).slideUp(&quot;slow&quot;);					   
    			});
    		
    		});
    	}
    });
    

    Open your index.html file. Where you once had the jQuery script we created in Part One and now moved to our jquery.meerkat.js file, we need to call our new plugin. Before we do, we need to link to our new jquery file first. So the head of our index.html should now look something like this:

    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.meerkat.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	jQuery(&quot;#meerkat&quot;).meerkat();
    });
    &lt;/script&gt;
    

    Three important things are being done here (all in order).

    1. Include jQuery core file first
    2. Include jquery.meerkat.js file after
    3. Call meerkat() by attaching it to an HTML element with an id of "meerkat"

    Check out our page and you'll see that it works.

    Add customizable selector to Meerkat

    The way our plugin is currently set up, the user must attach the meerkat() function to an element that has the id of "meerkat". That's not what we want, right? I mean, if that were the case we'd just create a function and tell the user they have to call it using "#meerkat". We want our plugin to be more customizable.

    Change the selector in our plugin call from "#meerkat" to "#ad-promotion".

    index.html
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.meerkat.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	jQuery(&quot;#ad-promotion&quot;).meerkat();
    });
    &lt;/script&gt;
    

    Then go to the bottom of your index.html file and change the div id from "meerkat" to "ad-promotion".

    index.html
    &lt;/div&gt;&lt;!--END container--&gt;
    &lt;div id=&quot;ad-promotion&quot;&gt;
    	&lt;a class=&quot;close&quot;&gt;Close Meerkat&lt;/a&gt;
    &lt;/div&gt;
    &lt;/body&gt;
    

    Try our page now, and you'll see something's wrong with meerkat().

    Remember when we were talking about "this" in return this.each() in the last step? Well, when we called our meerkat() function by attaching it to jQuery("#ad-promotion"), "this" was referring to <div id="ad-promotion">. So, our meerkat() function was actually working. It just wasn't working completely. Let's take a look.

    tutorial image

    If meerkat() was in fact running, what could be wrong with our script?

    tutorial image

    We could change our script like the image suggests:

    //Change this
    jQuery('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    
    //To this
    jQuery('#ad-promotion').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    

    But, what if we want the element's id to be "adsense"? Then we'd have to go in and change the plugin again. There's a better, and much easier way.

    tutorial image

    How easy is that!? Because "return this.each()" will always refer to any element attached to "meerkat()" we can just change our script like this:

    //Change this
    jQuery('#meerkat').wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    
    //To this
    jQuery(this).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    

    If you test your page after making that change, it will work and if you have Firefox with Firebug installed, you'll be able to see that it is in fact wrapping "#ad-promotion".

    tutorial image

    If you were to change your "#ad-promotion" to "#adsense" in both your meerkat() function call as well as in the bottom div element, it would still work.

    Before we finish with this step, I want to talk about something. As you already know, "this" can be pretty confusing. What get's really confusing is when there are multiple uses of "this" throughout your plugin. They all may be referring to a completely different object and really confuse you. To avoid this, we could create a variable and assign it the value of "this" and avoid a lot of confusion. Take a look here.

    jquery.meerkat.js
    //Loop through each
    return this.each(function() {
    	var element = jQuery(this);
    	//Reset body and html margin to zero
    	jQuery('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    	//Find element in DOM attached to meerkat() and wrap the two wrapper and container divs around it
    	jQuery(element).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    

    What I did here was create a variable "element" and assign it the value of jQuery(this). Now I can put the variable (element) anywhere I need to refer to jQuery(this). This may not make sense to you now, but soon, as our plugin grows, you'll see what I mean by the amount of "this" instances being used.

    Ode to a Cheeseburger

    Let's say you go to a fast food joint and order a cheeseburger. If you don't specify what you want on that cheeseburger, it will come the way it normally comes, right (cheddar cheese, ketchup, pickles, etc)? If you decide to tell them what you want on it, they'll fix it that way. You could tell the person you want Swiss cheese, mayonnaise, and onions and they'll make it that way. Well, a plugin with options is very similar to that.

    Let's look at a hypothetical plugin called "cheeseburger" that gives you options of condiments.

    jQuery.fn.extend({ 
    
    	cheeseburger: function(condiments) {
    	
    		var options = {
    			cheese: &quot;cheddar&quot;,
    			bread: &quot;sesame bun&quot;,
    			ketchup : 'yes',
    			xtraCheese : 'no',
    			pickles: 'yes',
    			mayo: 'no'
    		}
    		
    		var condiment = jQuery.extend(options, condiments);
    
    		return this.each(function() {
    			jQuery(&quot;#my-cheeseburger&quot;).html(&quot;&lt;ul&gt;&lt;li&gt;Type of cheese: &quot;+condiment.cheese+&quot;&lt;/li&gt;&lt;/ul&gt;&quot;);					  
    		});
    	
    	}
    });
    
    cheeseburger: function(condiments)

    If you are familiar with any programming language, you've seen functions and you've seen how to provide functions with arguments. It's basically a way for us to communicate with the function by passing stuff in, and, it passing stuff out.

    var options

    We've created a variable named "options" and its value is our cheeseburger default toppings. The "options" are cheese, bread, ketchup, xtraCheese, pickles, and mayo. Each one of these options have default values ("cheddar", "sesame bun", "yes", "no", "yes", "no").

    jQuery.extend(options, condiments)

    What we're doing here is telling jQuery to extend or merge all of our options (cheese: "cheddar", bread: "sesame bun", etc.) with condiments. Remember "condiments" is our function's argument, so we're basically adding our "options" to the argument's value. But right now our function isn't doing anything with the argument . This is why we named a variable "condiment" and gave it the value of jQuery.extend(options, condiments). All we have to do to refer to one of our options (cheeseburger toppings) is use our new variable "condiment" (eg. condiment.cheese would return "cheddar").

    tutorial image

    So how do we change the options? Well, let's test it really quick. Create a new file and save it as cheeseburger.html in the same directory as your index.html. Copy and paste the following code into it.

    &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
    &lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
    &lt;head&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
    &lt;title&gt;Cheeseburger&lt;/title&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	
    	jQuery.fn.extend({ 
    
    	cheeseburger: function(condiments) {
    	
    		var options = {
    			cheese: &quot;cheddar&quot;,
    			bread: &quot;sesame bun&quot;,
    			ketchup : 'yes',
    			xtraCheese : 'no',
    			pickles: 'yes',
    			mayo: 'no'
    		}
    		
    		var condiment = jQuery.extend(options, condiments);
    
    		return this.each(function() {
    			jQuery(&quot;#my-cheeseburger&quot;).html(&quot;&lt;li&gt;Type of cheese: &quot;+condiment.cheese+&quot;&lt;/li&gt;&quot;);					  
    		});
    	
    	}
    });
    	jQuery(&quot;ul#my-cheeseburger&quot;).cheeseburger({cheese: &quot;swiss&quot;});
    });
    &lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;ul id=&quot;my-cheeseburger&quot;&gt;&lt;/ul&gt;
    &lt;/body&gt;
    &lt;/html&gt;
    

    You see how easy it is to call the function and customize your burger? It's just like Burger King, have it your way. We told our function that we wanted to overwrite our "cheese" option's default "cheddar" with "swiss".

    It's that simple! You could change another option like this:

    return this.each(function() {
         jQuery(this).html(&quot;&lt;li&gt;Type of cheese: &quot;+condiment.bread+&quot;&lt;/li&gt;&quot;);					  
    });
    

    And it would return "sesame bun", because we didn't change the default.

    I know that was kinda retarded, but I figured it might make it a bit easier to understand. Now, what do you say we add some options to Meerkat?

    Meerkat needs some options

    So far our plugin is adding Meerkat to our page based on the CSS we provided our jQuery script with. We need to add some options to our plugin. This way the user can decide what they want their Meerkat to look like. They'll want to be able to choose things like height, background colors, background images, etc. So let's take a look at our jquery.meerkat.js file up to this point.

    //Yo jQuery, attach our plugin to your toolbelt
    jQuery.fn.extend({ 
    
    	//My name is meerkat
    	meerkat: function() {
    
    		//Loop through each
    		return this.each(function() {
    			
    			//Creating a variable for &quot;this&quot; (referring to element attached to meerkat function) to avoid confusion later
    			var element = jQuery(this);
    			
    			//Reset body and html margin to zero
    			jQuery('html, body').css({&quot;margin&quot;:&quot;0&quot;});
    			
    			//Find element attached to meerkat() and wrap the wrapper and container divs around it
    			jQuery(element).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    
    			//Add necessary styles to the two divs we just added
    			jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    			jQuery('#meerkat-container').css({'background': 'url(images/meerkat-bg.png) repeat-x 0 0', 'height': '100px'});
    			
    			//If browser is Internet Explorer AND its version is less than or equal to 6
    			if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    				
    				//IE6 needs #meerkat-wrap to have a position of absolute because it doesn't support &quot;fixed&quot;
    				jQuery('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    				
    				//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    				jQuery(&quot;body&quot;).children()
    					.filter(function (index) {
    						return jQuery(this).attr(&quot;id&quot;) != &quot;meerkat-wrap&quot;;
    					})
    				.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    				
    				//Add all the conditional (to IE6 or below) CSS
    				jQuery('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    				jQuery('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    				
    				//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    				var ie6ContentContainer = document.getElementById('ie6-content-container');
    				if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    					jQuery('#meerkat-container').css({'margin-right':'17px'});
    				}
    			}
    			
    			//Get #meerkat-wrap to slide in
    			jQuery(&quot;#meerkat-wrap&quot;).hide().slideDown(&quot;slow&quot;);
    			
    			//If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    			jQuery(&quot;.close&quot;).click(function(){
    				jQuery(&quot;#meerkat-wrap&quot;).slideUp(&quot;slow&quot;);
    			});
    
    		});
    	}
    });
    

    So, what options can be added to our plugin immediately? We'll be creating more options later, as we build up our plugin's functionality, but, for now we need to focus on the appearance of Meerkat.

    tutorial image

    Alright, so the first 3 options we're going to give Meerkat are background, height, and position. We'll also assign it default values in case the user doesn't provide Meerkat() with any.

    1. background: "none"
    2. height: "auto"
    3. position: "bottom"

    So, if you remember from our cheeseburger() function, we need to first declare some default options in our Meerkat plugin. Open up jquery.meerkat.js and add the highlighted code.

    //Hi, I'm a plugin. My name is meerkat.
    meerkat: function(options) {
    	
    	//Create Meerkat's default options
    	var defaults = {
    		background: 'none',
    		height: 'auto',
    		position: 'bottom'
    	}
    	
    	//Extend &quot;defaults&quot; to Meerkat()'s argument &quot;options&quot;
    	//To refer to our default settings we can now use settings.defaultsname(eg. settings.background)
    	var settings = jQuery.extend(defaults, options);
    	
    	//Loop through each
    	return this.each(function() {
    
    

    We declared 3 default options background: 'none', height: 'auto', and position: 'bottom'. We used jQuery.extend to merge our "defaults" with the meerkat() argument "options" and assigned the values to a variable we named "settings".

    So, now, we can refer to the meerkat() options like this:

    • settings.background
    • settings.height
    • settings.position

    Let's try our options out! Let's go ahead and test our 3 options out by replacing the CSS property declarations with their respective settings.optionname.

    tutorial image

    Let's change the first two (background, height) because they're the easiest. If you look closely, there's a difference between the settings.background and settings.height options and the settings.position option. The height and background options are going to be used as CSS property values, where the position option is being used in place of a CSS property.

    So let's go ahead and replace the CSS property values for background and height in our jquery.meerkat.js file.

    //Creating a variable for &quot;this&quot; (referring to element attached to meerkat function) to avoid confusion later
    var element = jQuery(this);
    
    //Reset body and html margin to zero
    jQuery('html, body').css({'margin':'0'});
    
    //Find element attached to meerkat() and wrap the wrapper and container divs around it
    jQuery(element).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    
    //Add necessary styles to the two divs we just added
    jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    jQuery('#meerkat-container').css({'background': settings.background, 'height': settings.height});
    
    //If browser is Internet Explorer AND its version is less than or equal to 6
    if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    

    If you looked at your page now, it would look a little bit different because we set our background and height options at "none" and "auto". So, with these settings, Meerkat has a transparent background and a height value of "auto".

    Open up index.html and add some custom option values to our meerkat() function call.

    index.html
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.meerkat.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	jQuery(&quot;#meerkat&quot;).meerkat({
    		background: 'url(images/meerkat-bg.png) repeat-x 0 0',
    		height: '100px'
    	});
    });
    &lt;/script&gt;
    

    You'll notice that adding the custom options in our meerkat() function call is very similar to how we set our default options in our jquery.meerkat.js file. Remember, our "defaults" are only default settings, should the user not set any in the plugin function call. So anytime you set an option in your Meerkat() call, it will override the default settings.

    tutorial image

    In this particular case, we're only changing the background and height options, so Meerkat() will use the default position setting of "bottom" and place itself at the bottom of the browser window. Let's change that now.

    As I said, settings.position is going to be used in place of an actual CSS Property instead of its value, so we have to do this a little bit differently.

    For some reason, we cannot just do this:

    //We cannot just change this
    jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    
    //To this
    jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', settings.position:'0'});
    

    This will not work. For what reason, I do not know exactly. We have to do it like this instead:

    //Change this
    jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'bottom':'0'});
    
    //To this
    jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%'}).css(settings.position, &quot;0&quot;);
    

    We have to chain the second css() object with the first, in order for it to work. Unfortunately we cannot include it in the first css().

    Noobnote:

    I'm not quite sure why this is the way that it is, but it is. If you know of a way of achieving it differently, please let me know.

    Nonetheless, after you make the change, go ahead and open index.html and add our new option to the plugin call:

    index.html
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.meerkat03.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	jQuery(&quot;#meerkat&quot;).meerkat({
    		background: 'url(images/meerkat-bg.png) repeat-x 0 0',
    		height: '100px',
    		position: 'top'
    	});
    });
    &lt;/script&gt;
    

    Test your page now, and you'll see Meerkat is sliding in from the top!

    Meerkat's animation options

    Thus far, Meerkat's animation has been "sliding", when it loads and when it's closed. We want to give the user the option of it sliding, fading, or no animation at all. To give even more customization, we're going to give the user the option of setting the animation separately for when Meerkat "shows" and when Meerkat "hides". This way the user can choose to fade Meerkat in, but slide meerkat out when it's closed.

    First off let's go ahead and add the defaults to the plugin.

    //Create Meerkat's default options
    var defaults = {
    	background: 'none',
    	height: 'auto',
    	position: 'bottom',
    	showAnimation: 'fade',
    	hideAnimation: 'fade',
    	animationSpeed: 'normal'
    }
    

    Now, we can refer to our new options like this:

    • settings.showAnimation
    • settings.hideAnimation
    • settings.animationSpeed

    The showAnimation option will refer to how Meerkat loads (fade, slide, or none), the hideAnimation will refer to how Meerkat closes (fade, slide, none), and the animationSpeed option will accept "slow", "normal", "fast", or a number representing the duration of the sliding/fading animation (in milliseconds). The smaller the value, the faster the animation.

    Up to this point, our animation has consisted of a few lines of code:

    //Get #meerkat-wrap to slide in
    jQuery(&quot;#meerkat-wrap&quot;).hide().slideDown(&quot;slow&quot;);
    
    //If element with class name &quot;close&quot; is clicked, hide #meerkat-wrap
    jQuery(&quot;.close&quot;).click(function(){
    	jQuery(&quot;#meerkat-wrap&quot;).slideUp(&quot;slow&quot;);
    });
    
    Noobnote:

    You can achieve the same results as slideUp() and slideDown() using jQuery's animate() method. To keep this already long tutorial from getting even longer, we'll stick with slideUp and slideDown.

    Based on our current animation method, we need to create some conditions based on the user's input.

    if(settings.showAnimation == &quot;slide&quot;){
         jQuery('#meerkat-wrap').hide().slideDown(&quot;slow&quot;);
    } else if (settings.showAnimation == &quot;fade&quot;){
         jQuery('#meerkat-wrap').hide().fadeIn(&quot;slow&quot;);
    } else if(settings.showAnimation == &quot;none&quot;){
         jQuery('#meerkat-wrap').show();
    } else {
         alert(&quot;the showAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;);
    }
    

    If you replaced your current slideDown("slow") code with the above code, it would work, but I don't like using the if else statement over and over. This is perfect for using a switch() statement. It's much cleaner and easier to work with, in my opinion. We can achieve the above code the same way with this switch statement:

    switch (settings.showAnimation)
    {
    	case &quot;slide&quot;:
    		jQuery('#meerkat-wrap').hide().slideDown(&quot;slow&quot;);
    		break;
    	case &quot;fade&quot;:
    		jQuery('#meerkat-wrap').hide().fadeIn(&quot;slow&quot;);
    		break;
    	case &quot;none&quot;:
    		jQuery('#meerkat-wrap').show();
    		break;
    	default:
    		alert('The showAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    }
    

    The switch statement accepts an argument (in this case, settings.showAnimation) for it to test against. So it's going to test what the user inputs for the showAnimation option against each case. If it doesn't match any of the case statements, it will use the default case. In our default case we're letting the user know that The showAnimation option only accepts "slide", "fade", or "none".

    Noobnote:

    In a switch case statement, the "break;" simply tells the script to break out of the switch case if its case is true.

    In the slideDown() and fadeIn() methods, you can now put the settings.animationSpeed in place of "slow".

    switch (settings.showAnimation)
    {
    	case &quot;slide&quot;:
    		jQuery('#meerkat-wrap').hide().slideDown(settings.animationSpeed);
    		break;
    	case &quot;fade&quot;:
    		jQuery('#meerkat-wrap').hide().fadeIn(settings.animationSpeed);
    		break;
    	case &quot;none&quot;:
    		jQuery('#meerkat-wrap').show();
    		break;
    	default:
    		alert('The showAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    }
    

    We can do the same thing with a switch statement for settings.hideAnimation

    switch (settings.hideAnimation)
    {
    	case &quot;slide&quot;:
    		jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    		});
    		break;
    	
    	case &quot;fade&quot;:
    	  jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    		});
    		break;
    	
    	case &quot;none&quot;:
    	  jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').hide();
    		});
    		break;
    	
    	default:
    	  alert('The hideAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    }
    

    How easy was that?! Now you can open up your index.html file and set your options.

    index.html
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.meerkat.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	jQuery(&quot;#meerkat&quot;).meerkat({
    		background: '#3e5867 url(images/meerkat-bg.png) repeat-x 0 0',
    		height: '100px',
    		position: 'bottom',
    		showAnimation: 'fade',
    		hideAnimation: 'slide',
    		animationSpeed: 1000
    	});
    });
    &lt;/script&gt;
    

    Now the user has animation options. My settings render this.

    Our jquery.meerkat.js should now look like this (I've modified the defaults).

    jquery.meerkat.js
    //Yo jQuery, attach our plugin to your toolbelt.
    jQuery.fn.extend({ 
    
    	//Hi, I'm a plugin. My name is meerkat.
    	meerkat: function(options) {
    		
    		//Create Meerkat's default options
    		var defaults = {
    			background: 'none',
    			height: 'auto',
    			position: 'bottom',
    			showAnimation: 'none',
    			hideAnimation: 'none',
    			animationSpeed: 'normal'
    		}
    		
    		//Extend &quot;defaults&quot; to Meerkat()'s argument &quot;options&quot;
    		//To refer to our default settings we can now use settings.defaultsname(eg. settings.background)
    		var settings = jQuery.extend(defaults, options);
    		
    		//Loop through each
    		return this.each(function() {
    			
    			//Creating a variable for &quot;this&quot; (referring to element attached to meerkat function) to avoid confusion later
    			var element = jQuery(this);
    			
    			//Reset body and html margin to zero
    			jQuery('html, body').css({'margin':'0'});
    			
    			//Find element attached to meerkat() and wrap the wrapper and container divs around it
    			jQuery(element).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    
    			//Add necessary styles to the two divs we just added
    			jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%'}).css(settings.position, &quot;0&quot;);
    			jQuery('#meerkat-container').css({'background': settings.background, 'height': settings.height});
    			
    			//If browser is Internet Explorer AND its version is less than or equal to 6
    			if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    				
    				//IE6 needs #meerkat-wrap to have a position of absolute because it doesn't support &quot;fixed&quot;
    				jQuery('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    				
    				//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    				jQuery('body').children()
    					.filter(function (index) {
    						return jQuery(this).attr('id') != 'meerkat-wrap';
    					})
    				.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    				
    				//Add all the conditional (to IE6 or below) CSS
    				jQuery('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    				jQuery('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    				
    				//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    				var ie6ContentContainer = document.getElementById('ie6-content-container');
    				if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    					jQuery('#meerkat-container').css({'margin-right':'17px'});
    				}
    			}
    			
    			switch (settings.showAnimation)
    			{
    				case &quot;slide&quot;:
    					jQuery('#meerkat-wrap').hide().slideDown(settings.animationSpeed);
    					break;
    				case &quot;fade&quot;:
    					jQuery('#meerkat-wrap').hide().fadeIn(settings.animationSpeed);
    					break;
    				case &quot;none&quot;:
    					jQuery('#meerkat-wrap').show();
    					break;
    				default:
    					alert('The showAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    			}
    			
    			switch (settings.hideAnimation)
    			{
    				case &quot;slide&quot;:
    					jQuery(&quot;.close&quot;).click(function(){
    						jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    					});
    					break;
    				
    				case &quot;fade&quot;:
    				  jQuery(&quot;.close&quot;).click(function(){
    						jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    					});
    					break;
    				
    				case &quot;none&quot;:
    				  jQuery(&quot;.close&quot;).click(function(){
    						jQuery('#meerkat-wrap').hide();
    					});
    					break;
    				
    				default:
    				  alert('The hideAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    			}
    
    		});
    	}
    });
    

    Annoying page viewers is not a good idea

    Up to this point, we've provided users with a way of "closing" Meerkat, but as soon as they revisit, or refresh the page, they're presented with Meerkat, once again. This could really annoy people. What we need to do is provide an option to users for closing Meerkat for an extended period of time, or until the user has at least closed their browser. This way, when they "close" Meerkat, it won't pop-up again until they restart their browser, or even, a set amount of time, like 24 hours.

    To achieve this we need a way to write a cookie to the user's browser when they click "dontShowAgain", and then read the cookie we set, the next time they refresh their browser, to find out if it's supposed to load Meerkat again.

    We're going to do this by utilizing a technique explained on the Quirksmode site, where they explain how to set, read and erase cookies. I'm not going to go into detail on what we're doing here, because they already do a GREAT job of explaining what cookies are, how they're set, how they're read, and how they're erased.

    We're just going to start out by testing these functions out one by one.

    In your index.html file, within your script tags (where you have your Meerkat() call), go ahead and put the highlighted code below your Meerkat().

    index.html
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.meerkat.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	jQuery(&quot;#meerkat&quot;).meerkat({
    		background: '#3e5867 url(images/meerkat-bg.png) repeat-x 0 0',
    		height: '100px',
    		position: 'bottom',
    		showAnimation: 'fade',
    		hideAnimation: 'slide',
    		animationSpeed: 1000
    	});
    	
    	//Create Cookie
    	function createCookie(name,value,days) {
    		if (days) {
    			var date = new Date();
    			date.setTime(date.getTime()+(days*24*60*60*1000));
    			var expires = &quot;; expires=&quot;+date.toGMTString();
    		}
    		else { 
    			var expires = &quot;&quot;;
    		}
    		document.cookie = name+&quot;=&quot;+value+expires+&quot;; path=/&quot;;
    	}
    	
    	//Read Cookie
    	function readCookie(name) {
    		var nameEQ = name + &quot;=&quot;;
    		var ca = document.cookie.split(';');
    		for(var i=0;i &lt; ca.length;i++) {
    			var c = ca[i];
    			while (c.charAt(0)==' ') c = c.substring(1,c.length);
    			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    		}
    		return null;
    	}
    	
    	
    	jQuery(&quot;#dont-show&quot;).click(function () {
    		//Set a cookie with the name &quot;meerkat&quot;, a value of &quot;dontshow&quot;, until the browser session expires
    		createCookie('meerkat','dontshow', 0);
    		//Check that the cookie was created using the readCookie(name) function
    		alert(&quot;You have set your meerkat cookie as '&quot; +readCookie('meerkat')+ &quot;'&quot;);
    	});
    	
    });
    &lt;/script&gt;
    

    What we have done is created a function called createCookie() that takes 3 arguments:

    1. The cookie's name
    2. The cookie's value
    3. The cookie's expiration

    To use this function, we simply attached it to a click event on the selector "#dont-show" with the following value:

    createCookie('meerkat', 'dontshow', 0)
    1. The cookie's name is "meerkat"
    2. The cookie's value is "dontshow"
    3. The cookie's expiration is when the browser session expires (restarts)

    We also created a function called readCookie() that takes only 1 argument, the cookie's name. Basically, the function is used to read the cookie you set's value.

    We used this function to simply "alert" us with a javascript prompt letting us know that the cookie was set and its value.

    With this, as easy as it is, we simply need to move our createCookie() and readCookie() functions to our jquery.meerkat.js script.

    jquery.meerkat.js
    //Create Meerkat's default options
    var defaults = {
    	background: 'none',
    	height: 'auto',
    	position: 'bottom',
    	showAnimation: 'none',
    	hideAnimation: 'none',
    	animationSpeed: 'normal'
    }
    
    //Extend &quot;defaults&quot; to Meerkat()'s argument &quot;options&quot;
    //To refer to our default settings we can now use settings.defaultsname(eg. settings.background)
    var settings = jQuery.extend(defaults, options);
    
    //Create Cookie
    function createCookie(name,value,days) {
    	if (days) {
    		var date = new Date();
    		date.setTime(date.getTime()+(days*24*60*60*1000));
    		var expires = &quot;; expires=&quot;+date.toGMTString();
    	}
    	else { 
    		var expires = &quot;&quot;;
    	}
    	document.cookie = name+&quot;=&quot;+value+expires+&quot;; path=/&quot;;
    }
    
    //Read Cookie
    function readCookie(name) {
    	var nameEQ = name + &quot;=&quot;;
    	var ca = document.cookie.split(';');
    	for(var i=0;i &lt; ca.length;i++) {
    		var c = ca[i];
    		while (c.charAt(0)==' ') c = c.substring(1,c.length);
    		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    	}
    	return null;
    }
    

    Let's go to the bottom of our jquery.meerkat.js script where we have our animation options and createCookie() on the same selector we used in index.html, "#dont-show". Now, our "#dont-show" is going to share the same animation as our ".close" selector uses, so we'll put our code right inside the switch(settings.hideAnimation) statement.

    switch (settings.hideAnimation)
    {
    	case &quot;slide&quot;:
    		jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    		});
    		jQuery(&quot;#dont-show&quot;).click(function(){
    			jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    			createCookie('meerkat','dontshow', 0);
    		});
    		break;
    	
    	case &quot;fade&quot;:
    	  jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    		});
    	  jQuery(&quot;#dont-show&quot;).click(function(){
    			jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    			createCookie('meerkat','dontshow', 0);
    		});
    		break;
    	
    	case &quot;none&quot;:
    	  jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').hide();
    		});
    	  jQuery(&quot;#dont-show&quot;).click(function(){
    			jQuery('#meerkat-wrap').hide();
    			createCookie('meerkat','dontshow', 0);
    		});
    		break;
    	
    	default:
    	  alert('The hideAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    }
    

    Test your page now. You'll notice when you click the "Don't Show" text, Meerkat slides out the same way your "Close Meerkat" anchor does. The difference is, you've written a cookie to the browser.

    After clicking the "Don't Show" text, go ahead and check to see if your cookie was created. I'm using Firefox 3.5.1, so this is how I do it:

    1. Go to "Tools" from the Firefox top menu
    2. Select "Options"
    3. Click on the "Privacy" tab
    4. Click on "remove individual cookies"
    5. In the search box type "meerkat"
    tutorial image

    If you change the cookie's expiration from "0" to "1", the cookie expires in 1 day (24 hours) from when it was created.

    tutorial image

    This being said, I think the cookie expiration should be a Meerkat option! The user should be able to decide how much they want to annoy the page viewer. :)

    Let's create the default first.

    jquery.meerkat.js
    //Hi, I'm a plugin. My name is meerkat.
    meerkat: function(options) {
    
    //Create Meerkat's default options
    var defaults = {
    	background: 'none',
    	height: 'auto',
    	position: 'bottom',
    	showAnimation: 'none',
    	hideAnimation: 'none',
    	animationSpeed: 'normal',
    	cookieExpires: 0
    }
    
    //Extend &quot;defaults&quot; to Meerkat()'s argument &quot;options&quot;
    //To refer to our default settings we can now use settings.defaultsname(eg. settings.background)
    var settings = jQuery.extend(defaults, options);
    

    Now at the bottom of the script where we're using the createCookie() function, we'll replace the 0 with settings.cookieExpires.

    switch (settings.hideAnimation)
    {
    	case &quot;slide&quot;:
    		jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    		});
    		jQuery(&quot;#dont-show&quot;).click(function(){
    			jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    			createCookie('meerkat','dontshow', settings.cookieExpires);
    		});
    		break;
    	
    	case &quot;fade&quot;:
    	  jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    		});
    	  jQuery(&quot;#dont-show&quot;).click(function(){
    			jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    			createCookie('meerkat','dontshow', settings.cookieExpires);
    		});
    		break;
    	
    	case &quot;none&quot;:
    	  jQuery(&quot;.close&quot;).click(function(){
    			jQuery('#meerkat-wrap').hide();
    		});
    	  jQuery(&quot;#dont-show&quot;).click(function(){
    			jQuery('#meerkat-wrap').hide();
    			createCookie('meerkat','dontshow', settings.cookieExpires);
    		});
    		break;
    	
    	default:
    	  alert('The hideAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    }
    

    I'm sure you're sitting here thinking, "um, so when are we going to read the cookie and stop Meerkat from showing on page refresh?", and we're getting to that now!

    It's really simple actually. All we want to do is wrap all of our Meerkat script (from the "return this.each()" to the bottom its closing brace) in an if() statement.

    We want to test whether or not there's a cookie "meerkat" with the value "dontshow", if there isn't — show Meerkat. I've highlighted where the if() starts and where it ends.

    jquery.meerkat.js
    //Yo jQuery, attach our plugin to your toolbelt.
    jQuery.fn.extend({ 
    
    	//Hi, I'm a plugin. My name is meerkat.
    	meerkat: function(options) {
    		
    		//Create Meerkat's default options
    		var defaults = {
    			background: 'none',
    			height: 'auto',
    			position: 'bottom',
    			showAnimation: 'none',
    			hideAnimation: 'none',
    			animationSpeed: 'normal',
    			cookieExpires: 0
    		}
    		
    		//Extend &quot;defaults&quot; to Meerkat()'s argument &quot;options&quot;
    		//To refer to our default settings we can now use settings.defaultsname(eg. settings.background)
    		var settings = jQuery.extend(defaults, options);
    		
    		//Create Cookie
    		function createCookie(name,value,days) {
    			if (days) {
    				var date = new Date();
    				date.setTime(date.getTime()+(days*24*60*60*1000));
    				var expires = &quot;; expires=&quot;+date.toGMTString();
    			}
    			else { 
    				var expires = &quot;&quot;;
    			}
    			document.cookie = name+&quot;=&quot;+value+expires+&quot;; path=/&quot;;
    		}
    		
    		//Read Cookie
    		function readCookie(name) {
    			var nameEQ = name + &quot;=&quot;;
    			var ca = document.cookie.split(';');
    			for(var i=0;i &lt; ca.length;i++) {
    				var c = ca[i];
    				while (c.charAt(0)==' ') c = c.substring(1,c.length);
    				if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    			}
    			return null;
    		}
    		
    		if(readCookie('meerkat') != &quot;dontshow&quot;){
    			//Loop through each
    			return this.each(function() {
    				
    				//Creating a variable for &quot;this&quot; (referring to element attached to meerkat function) to avoid confusion later
    				var element = jQuery(this);
    				
    				//Reset body and html margin to zero
    				jQuery('html, body').css({'margin':'0'});
    				
    				//Find element attached to meerkat() and wrap the wrapper and container divs around it
    				jQuery(element).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	
    				//Add necessary styles to the two divs we just added
    				jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%'}).css(settings.position, &quot;0&quot;);
    				jQuery('#meerkat-container').css({'background': settings.background, 'height': settings.height});
    				
    				//If browser is Internet Explorer AND its version is less than or equal to 6
    				if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    					
    					//IE6 needs #meerkat-wrap to have a position of absolute because it doesn't support &quot;fixed&quot;
    					jQuery('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    					
    					//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    					jQuery('body').children()
    						.filter(function (index) {
    							return jQuery(this).attr('id') != 'meerkat-wrap';
    						})
    					.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    					
    					//Add all the conditional (to IE6 or below) CSS
    					jQuery('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    					jQuery('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    					
    					//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    					var ie6ContentContainer = document.getElementById('ie6-content-container');
    					if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    						jQuery('#meerkat-container').css({'margin-right':'17px'});
    					}
    				}
    				
    				switch (settings.showAnimation)
    				{
    					case &quot;slide&quot;:
    						jQuery('#meerkat-wrap').hide().slideDown(settings.animationSpeed);
    						break;
    					case &quot;fade&quot;:
    						jQuery('#meerkat-wrap').hide().fadeIn(settings.animationSpeed);
    						break;
    					case &quot;none&quot;:
    						jQuery('#meerkat-wrap').show();
    						break;
    					default:
    						alert('The showAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    				}
    				
    				switch (settings.hideAnimation)
    				{
    					case &quot;slide&quot;:
    						jQuery(&quot;.close&quot;).click(function(){
    							jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    						});
    						jQuery(&quot;#dont-show&quot;).click(function(){
    							jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    							createCookie('meerkat','dontshow', settings.cookieExpires);
    						});
    						break;
    					
    					case &quot;fade&quot;:
    					  jQuery(&quot;.close&quot;).click(function(){
    							jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    						});
    					  jQuery(&quot;#dont-show&quot;).click(function(){
    							jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    							createCookie('meerkat','dontshow', settings.cookieExpires);
    						});
    						break;
    					
    					case &quot;none&quot;:
    					  jQuery(&quot;.close&quot;).click(function(){
    							jQuery('#meerkat-wrap').hide();
    						});
    					  jQuery(&quot;#dont-show&quot;).click(function(){
    							jQuery('#meerkat-wrap').hide();
    							createCookie('meerkat','dontshow', settings.cookieExpires);
    						});
    						break;
    					
    					default:
    					  alert('The hideAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    				}
    	
    			});
    		} else {
    			jQuery(&quot;#meerkat&quot;).hide();	
    		}
    	}
    });
    

    We tested if there's a cookie named "meerkat", and if it's value was "dontshow". If it was, run all the stuff to load Meerkat, otherwise (else{}) hide meerkat.

    Now, if you test your page, click "Don't Show", and refresh the page you'll see Meerkat doesn't come back!

    Noobnote:

    If you test your page and Meerkat doesn't show, that's because you've set the meerkat cookie (dontshow). You will need to go into your browser cookies and delete the cookie.

    Before we finish this section of the tutorial, I think it would be better if we give our user the option of choosing their selectors for the close meerkat and don't show meerkat options. So let's go ahead and add the defaults to our plugin and change the ".close" and "#dont-show" selectors to their respective "settings.xxxxxxx".

    Let's set the defaults first.

    jquery.meerkat.js
    //Create Meerkat's default options
    var defaults = {
    	background: 'none',
    	height: 'auto',
    	position: 'bottom',
    	closeMeerkat: '.close',
    	dontShowMeerkat: '#dont-show',
    	showAnimation: 'none',
    	hideAnimation: 'none',
    	animationSpeed: 'normal',
    	cookieExpires: 0
    }
    

    Now let's use our new options as our selectors.

    jquery.meerkat.js
    switch (settings.hideAnimation)
    {
    	case &quot;slide&quot;:
    		jQuery(settings.closeMeerkat).click(function(){
    			jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    		});
    		jQuery(settings.dontShowMeerkat).click(function(){
    			jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    			createCookie('meerkat','dontshow', settings.cookieExpires);
    		});
    		break;
    	
    	case &quot;fade&quot;:
    	  jQuery(settings.closeMeerkat).click(function(){
    			jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    		});
    	  jQuery(settings.dontShowMeerkat).click(function(){
    			jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    			createCookie('meerkat','dontshow', settings.cookieExpires);
    		});
    		break;
    	
    	case &quot;none&quot;:
    	  jQuery(settings.closeMeerkat).click(function(){
    			jQuery('#meerkat-wrap').hide();
    		});
    	  jQuery(settings.dontShowMeerkat).click(function(){
    			jQuery('#meerkat-wrap').hide();
    			createCookie('meerkat','dontshow', settings.cookieExpires);
    		});
    		break;
    	
    	default:
    	  alert('The hideAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    }
    

    Now in our index.html file we can use all our new options.

    index.html
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.meerkat.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
    	jQuery(&quot;#meerkat&quot;).meerkat({
    		background: '#3e5867 url(images/meerkat-bg.png) repeat-x 0 0',
    		height: '200px',
    		position: 'bottom',
    		closeMeerkat: '.close-meerkat',
    		dontShowMeerkat: '#dont-show-meerkat',
    		showAnimation: 'slide',
    		hideAnimation: 'slide',
    		animationSpeed: 'slow',
    		cookieExpires: 1
    	});
    });
    
    

    With these options set, this is what we get.

    We have some fine tuning to do, but our Meerkat plugin is just about done!

    Meerkat wants to reach higher heights

    If a Meerkat user wants to utilize it as an alternative to a "splash page" or "entry page", they'd want Meerkat's height to reach 100% of the browser's height. Right now if you put "100%" in the height: option of meerkat(), it would be treated like setting it as "auto". This is because the height is being applied to the #meerkat-container div, which is wrapped by the #meerkat-wrap div. So, its 100% height is 100% of #meerkat-wrap which is set to "auto" by default. If we change our #meerkat-wrap height to 100%, it's going to be 100% of its container's height, which is the html and body element, which is also set to "auto" by default. In order to fix this, in our jquery.meerkat.js file, we need to first set our html and body element heights to 100%, then we need to apply whatever height is set on our #meerkat-container div (set by the meerkat option "height") to the #meerkat-wrap div as well.

    jquery.meerkat.js
    //Loop through each
    return this.each(function() {
    	
    	//Creating a variable for &quot;this&quot; (referring to element attached to meerkat function) to avoid confusion later
    	var element = jQuery(this);
    	
    	//Reset body and html margin to zero
    	jQuery('html, body').css({'margin':'0', 'height':'100%'});
    	
    	//Find element attached to meerkat() and wrap the wrapper and container divs around it
    	jQuery(element).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    
    	//Add necessary styles to the two divs we just added
    	jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'height': settings.height}).css(settings.position, &quot;0&quot;);
    	jQuery('#meerkat-container').css({'background': settings.background, 'height': settings.height});
    
    

    What we've done is set the html and body element heights' to 100%, and also copied the 'height': settings.height from the "#meerkat-container" CSS settings and put it in the "#meerkat-wrap" CSS settings as well.

    If you change your height option to 100%, you'll see it now works the way we want it to.

    IE6 body background fix

    If you opened up our page in IE6 right now, everything would seem to be working just right. Unfortunately, there's a little problem that needs to be addressed.

    If I add a background image to the body element, you'll notice in IE6 it acts strangely. You have to remember, IE6's "body" is essentially the "ie6-content-container". We have rendered the body overflow property "hidden", so when you are scrolling the page on IE6, you're actually scrolling the ie6-content-container, not the body. So if we use a body background image, IE6 will look as if we set our background-attachment to "fixed", while the other browsers are "scroll".

    What we need to do here, is detect the CSS settings for the background properties of the body element and add them to the ie6-content-container element.

    To get the body background properties, it's not an easy task. Every browser has a different way of referencing these properties. Luckily, we only need this information for Internet Explorer. So we'll use the Internet Explorer way of accessing styles.

    We can access these properties using document.body.currentStyle. This will return us a javascript object. To access the background properties, we'd use the following:

    • document.body.currentStyle.backgroundColor:
      returns the body's background color value (eg. #000)
    • document.body.currentStyle.backgroundImage:
      returns the body's background image value (eg. url(http://www.somesite.com/images/image.jpg) )
    • document.body.currentStyle.backgroundRepeat:
      returns the body's background repeat value (eg. repeat-x, repeat-y, or no-repeat)
    • document.body.currentStyle.backgroundAttachment: returns the body's background attachment value (eg. scroll or fixed)
    • document.body.currentStyle.backgroundPositionX:
      returns the body's background x-axis position value (eg. left, 10px, etc.)
    • document.body.currentStyle.backgroundPositionY:
      returns the body's background y-axis position value (eg. top, 10px, etc.)

    We need to add some code to our jquery.meerkat.js file, but we only want IE6 to use this, so we need to be sure to put it between our IE6 conditional statement.

    jquery.meerkat.js
    //If browser is Internet Explorer AND its version is less than or equal to 6
    if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    	
    	//IE6 needs #meerkat-wrap to have a position of absolute because it doesn't support &quot;fixed&quot;
    	jQuery('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    	
    	//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    	jQuery('body').children()
    		.filter(function (index) {
    			return jQuery(this).attr('id') != 'meerkat-wrap';
    		})
    	.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    	
    	//Add all the conditional (to IE6 or below) CSS
    	jQuery('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    	jQuery('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    	
    	//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    	var ie6ContentContainer = document.getElementById('ie6-content-container');
    	if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    		jQuery('#meerkat-container').css({'margin-right':'17px'});
    	}
    	
    	//Build up a string variable &quot;bgProperties&quot; to get the body's background property values
    	var bgProperties = document.body.currentStyle.backgroundColor+ &quot; &quot;;
    	bgProperties += document.body.currentStyle.backgroundImage+ &quot; &quot;;
    	bgProperties += document.body.currentStyle.backgroundRepeat+ &quot; &quot;;
    	bgProperties += document.body.currentStyle.backgroundAttachment+ &quot; &quot;;
    	bgProperties += document.body.currentStyle.backgroundPositionX+ &quot; &quot;;
    	bgProperties += document.body.currentStyle.backgroundPositionY;
    	
    	//Remove body background property values from IE6
    	jQuery(&quot;body&quot;).css({'background':'none'});
    	
    	//Move body background property values to #ie6-content-container
    	jQuery(&quot;#ie6-content-container&quot;).css({'background' : bgProperties});
    }
    

    What I did was build up a string variable with the name "bgProperties", removed the body's background properties, and applied them to the ie6-content-container. If you look at our page in IE6 now, you'll see it's behaving properly.

    I can't wait until the day comes when we don't have to support that crappy browser anymore, but until then, I'll be supporting it. If we weren't supporting it still, this script would be half the size it is and this tutorial would also be fraction of its length.

    Final Thoughts

    That's it! If you made it this far, you are a friggin' trooper, cause that is one LONG tutorial. Trust me, I know, I wrote it! But, it was well worth it. I learned a lot, and I hope you have learned a lot too.

    Here's our final Meerkat plugin script:

    jquery.meerkat.js
    //Yo jQuery, attach our plugin to your toolbelt.
    jQuery.fn.extend({ 
    
    	//Hi, I'm a plugin. My name is meerkat.
    	meerkat: function(options) {
    		
    		//Create Meerkat's default options
    		var defaults = {
    			background: 'none',
    			height: 'auto',
    			position: 'bottom',
    			closeMeerkat: '.close',
    			dontShowMeerkat: '#dont-show',
    			showAnimation: 'none',
    			hideAnimation: 'none',
    			animationSpeed: 'normal',
    			cookieExpires: 0
    		}
    				
    		//Extend &quot;defaults&quot; to Meerkat()'s argument &quot;options&quot;
    		//To refer to our default settings we can now use settings.defaultsname(eg. settings.background)
    		var settings = jQuery.extend(defaults, options);
    		
    		//Create Cookie
    		function createCookie(name,value,days) {
    			if (days) {
    				var date = new Date();
    				date.setTime(date.getTime()+(days*24*60*60*1000));
    				var expires = &quot;; expires=&quot;+date.toGMTString();
    			}
    			else { 
    				var expires = &quot;&quot;;
    			}
    			document.cookie = name+&quot;=&quot;+value+expires+&quot;; path=/&quot;;
    		}
    		
    		//Read Cookie
    		function readCookie(name) {
    			var nameEQ = name + &quot;=&quot;;
    			var ca = document.cookie.split(';');
    			for(var i=0;i &lt; ca.length;i++) {
    				var c = ca[i];
    				while (c.charAt(0)==' ') c = c.substring(1,c.length);
    				if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    			}
    			return null;
    		}
    		
    		if(readCookie('meerkat') != &quot;dontshow&quot;){
    			//Loop through each
    			return this.each(function() {
    				
    				//Creating a variable for &quot;this&quot; (referring to element attached to meerkat function) to avoid confusion later
    				var element = jQuery(this);
    				
    				//Reset body and html margin to zero
    				jQuery('html, body').css({'margin':'0', 'height':'100%'});
    				
    				//Find element attached to meerkat() and wrap the wrapper and container divs around it
    				jQuery(element).wrap('&lt;div id=&quot;meerkat-wrap&quot;&gt;&lt;div id=&quot;meerkat-container&quot;&gt;&lt;/div&gt;&lt;/div&gt;');
    	
    				//Add necessary styles to the two divs we just added
    				jQuery('#meerkat-wrap').css({'position':'fixed', 'width':'100%', 'height': settings.height}).css(settings.position, &quot;0&quot;);
    				jQuery('#meerkat-container').css({'background': settings.background, 'height': settings.height});
    				
    				//If browser is Internet Explorer AND its version is less than or equal to 6
    				if(jQuery.browser.msie &amp;&amp; jQuery.browser.version &lt;= 6){
    					
    					//IE6 needs #meerkat-wrap to have a position of absolute because it doesn't support &quot;fixed&quot;
    					jQuery('#meerkat-wrap').css({'position':'absolute', 'bottom':'-1px'});
    					
    					//Find all content to wrap in ie6-content-container but filter out meerkat-wrap
    					jQuery('body').children()
    						.filter(function (index) {
    							return jQuery(this).attr('id') != 'meerkat-wrap';
    						})
    					.wrapAll('&lt;div id=&quot;ie6-content-container&quot;&gt;&lt;/div&gt;');
    					
    					//Add all the conditional (to IE6 or below) CSS
    					jQuery('html, body').css({'height':'100%', 'width':'100%', 'overflow':'hidden'});
    					jQuery('#ie6-content-container').css({'overflow':'auto', 'width':'100%', 'height':'100%', 'position':'absolute'});
    					
    					//Check if ie6-content-container has a scrollbar present. If it does we need to move the meerkat container over 17px
    					var ie6ContentContainer = document.getElementById('ie6-content-container');
    					if(ie6ContentContainer.clientHeight &lt; ie6ContentContainer.scrollHeight) {
    						jQuery('#meerkat-container').css({'margin-right':'17px'});
    					}
    					
    					//Build up a string variable &quot;bgProperties&quot; to get the body's background property values
    					var bgProperties = document.body.currentStyle.backgroundColor+ &quot; &quot;;
    					bgProperties += document.body.currentStyle.backgroundImage+ &quot; &quot;;
    					bgProperties += document.body.currentStyle.backgroundRepeat+ &quot; &quot;;
    					bgProperties += document.body.currentStyle.backgroundAttachment+ &quot; &quot;;
    					bgProperties += document.body.currentStyle.backgroundPositionX+ &quot; &quot;;
    					bgProperties += document.body.currentStyle.backgroundPositionY;
    					
    					//Remove body background property values from IE6
    					jQuery(&quot;body&quot;).css({'background':'none'});
    					
    					//Move body background property values to #ie6-content-container
    					jQuery(&quot;#ie6-content-container&quot;).css({'background' : bgProperties});
    				}
    				
    				switch (settings.showAnimation)
    				{
    					case &quot;slide&quot;:
    						jQuery('#meerkat-wrap').hide().slideDown(settings.animationSpeed);
    						break;
    					case &quot;fade&quot;:
    						jQuery('#meerkat-wrap').hide().fadeIn(settings.animationSpeed);
    						break;
    					case &quot;none&quot;:
    						jQuery('#meerkat-wrap').show();
    						break;
    					default:
    						alert('The showAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    				}
    				
    				switch (settings.hideAnimation)
    				{
    					case &quot;slide&quot;:
    						jQuery(settings.closeMeerkat).click(function(){
    							jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    						});
    						jQuery(settings.dontShowMeerkat).click(function(){
    							jQuery('#meerkat-wrap').slideUp(settings.animationSpeed);
    							createCookie('meerkat','dontshow', settings.cookieExpires);
    						});
    						break;
    					
    					case &quot;fade&quot;:
    					  jQuery(settings.closeMeerkat).click(function(){
    							jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    						});
    					  jQuery(settings.dontShowMeerkat).click(function(){
    							jQuery('#meerkat-wrap').fadeOut(settings.animationSpeed);
    							createCookie('meerkat','dontshow', settings.cookieExpires);
    						});
    						break;
    					
    					case &quot;none&quot;:
    					  jQuery(settings.closeMeerkat).click(function(){
    							jQuery('#meerkat-wrap').hide();
    						});
    					  jQuery(settings.dontShowMeerkat).click(function(){
    							jQuery('#meerkat-wrap').hide();
    							createCookie('meerkat','dontshow', settings.cookieExpires);
    						});
    						break;
    					
    					default:
    					  alert('The hideAnimation option only accepts &quot;slide&quot;, &quot;fade&quot;, or &quot;none&quot;');
    				}
    	
    			});
    		} else {
    			jQuery(&quot;#meerkat&quot;).hide();	
    		}
    	}
    });
    

    If you have any problems with the plugin, or questions about this tutorial, please feel free to ask in the comments. I will address them as soon as I can.

    Thanks again for reading!