Javascript, JQuery, Web Development

Summarise: A jQuery Plugin to make alerts easier

Quickly had a reason to make a small plugin that could handle making alerts within most generic apps a bit more responsive and easier to change and manipulate with Ajax requests.

It is really simple and easy to use for your alerts.

I should note I used Bootstrap CSS classes, syntax and styling for this plugin actually however, this plugin is not limited to Bootstrap in anyway and should provide configuration abilities for any site and CSS framework.

You can find more on this plugin on Github: https://github.com/Sammaye/summarise

Hope it helps,

JQuery

Amazon like Product Gallery with Prodigal

I recently had a need to create a product gallery lightbox like on Amazon capable of using images and videos and having a filter for showing one or the other or both. So I went off, procrastinated about it for about 3 days then made it in about 2.

I have called it, prodigal.

You can find the Github repo to fork, love etc here: https://github.com/Sammaye/prodigal.

The browsers I have tested this on as working are:

  • Firefox (latest)
  • IE (7 and above)
  • Safari 5.1 and above
  • Opera 12 and above
  • and Chrome (latest)

All you need to do to get started is to look at the example.html page within the repo and you can use it like:

$('.some-thumbs').prodigal({ //options });

With .some-thumbs being a class that is on all the thumbnails you wish to enter prodigal.

Enjoy,

JQuery

Facebook dropdown menu using Jdropdown

This now has a github home: here. I’m new to Github so sorry if it’s not done right 😛

Please Note: You must have the latest version of jQuery to use this plugin (v 1.7.x and above). Please get this before you attempt to use this plugin otherwise the plugin will not work.

Ok so here is an update to the article about facebook dropdowns.

This time I have made an actual plugin that can handle dropdown menus from a single anchor. I made this plugin since there was, tbh, no real decent plugin for it surprisingly. There are plugins for nav bars, select boxs, option boxes, etc but none for making a simple menu from a random anchor on your page.

So here it is, my plugin version of the facebook dropdown: facebook dropdown example. The first dropdown shows with items provided in the plugin declaration and the second shows the items provided in the html code of the anchor.

The page source code will show you everything you need to know about the how it is styled etc but I will walk you through a little of how the plugin works and how it actually does stuff.

So the plugin itself is called Jdropdown (can be written with upper and lowercase j), you can call the plugin on any element like so $(‘.someel’).jdropdown({ ‘container’: ‘somecontainer’ }) (And I mean almost any element, this thing has little restrictions) and it takes 3 params atm:

  • container – This is the jQuery selector (minus the $() around the selector since thats not actually part of the selector) for the item which the menu items will be put in.
  • orientation – This param tells the script whether to align the menu to the left or right of its anchor and it takes either “left” or “right” (will make this more comlpex soon but atm its just that).
  • items – This params is optional and it is to tell the widget what items will be in the menu. The value is an array of object arrays (i.e. [{//item one}, {//item two}]) and any data can be put into these items but there must be at least a “label” field if your not using your own renderItem function in which case anyhting can be done

Now the plugin has currently two functions you can override:

  • renderMenu – This basically gives off some html for the items to go into in the form $(‘<ul></ul>’)
  • renderItem – This works a lot like jQuery UI plugins and it just appends each item to the menu container

Please note: If you override the renderMenu function with complex html you may be required to also override the renderItem to append/prepend to the correct element within that menu.

Now the plugin also has a number of api functions which you can hook into:

  • open – is triggered when the menu opens. This has a $(this) of the anchor which holds all data in the data() function about the menu
  • selectItem – is triggered when an item in the menu is selected. It has a $(this) of the menu item , its parent <li/>
  • holds all information in its data() function about the item
  • close – This is triggered upon close the menu and because of its currently global scope, has no $(this)

Now for an example of how to use one of these events lets draw code from the example:

$(document).on('jdropdown.selectItem', '#fb_menu a', function(e){
    e.preventDefault();
    alert('You selected: '+$(this).parent().data('jdropdown.item').label);

    // Do some crazy AJAXy weirdy stuff here to make your app awesome
});

This function binds to document that when a item in the #fb_menu container is clicked it will run that function.

Ok so that is the basic description of the plugin. Now I will state a few last words and then leave any further definition upto comments.

  • As I said items is optional in the plugin definition this is because you can actually attach items to the anchors themselves allowing you to have the same styled menu with different options without having to have duplicated code etc etc. The simple way of doing this is to add a “data-items” attribute to your anchors html and make the value a (valid to: parseJSON Doc) JSON string. An example is shown in the example link at the top (its the second drop down, check its html).
  • Also note the item itself can take ANY data and the jdropdown plugin will just attach that data to the data() of the li for that item allowing you to access it when it is selected. So for example you can place “id” in there or “woop” with values of 3 and access it like so: $(this).parent().data(‘jdropdown.item’).id .
  • You must put the container into the HTML page first, best place is at the end of the doc just before the </body> tag
  • You can call this on almost any element so long as you have provided items in some manner by using (for example) $(‘.someel’).jdropdown({ ‘container’: ‘somecontainer’ })

I can’t think of anything else off the top my head. So I am gonna leave it at that for the minute.

The example shows two drop downs, top one with full constructor with items provided in it and the second having items in the html of the object.

Have fun and any questions or if you need clarification etc just post a comment.

P.S almost forgot the plugin source code:

/**
 * Jdropdown
 *
 * @author Sam Millman
 * @licence GNU or whatever
 *
 * This plugin basically allows you to connect a menu to an anchor.
 * This anchor can be literally anything, from a <div/> to an <a/> and even a <li/>.
 */
/**
 * Jdropdown
 *
 * @author Sam Millman
 * @licence GNU or whatever
 *
 * This plugin basically allows you to connect a menu to an anchor.
 * This anchor can be literally anything, from a <div/> to an <a/> and even a <li/>.
 */
(function($){
	var methods = {
		init: function(options){
			return this.each(function(){
				var $this = $(this),
				items = $this.data('items');

				if(!$this.data('jdropdown')){
					$(options.container).addClass("jdropdown-menu");
					$(this).addClass('jdropdown-anchor').data('jdropdown', {
						'items': typeof items === 'object' ? items : options.items,
						'anchor': $(this),
						'menu': $(options.container),
						'options': options
					}).on({ 'click': open });
				}
				return this;
			});
		},
		destroy: function(){}
	},
	open = function(event){
		event.preventDefault();
		if($(this).hasClass('jdropdown-active')){
			close();
			return;
		}else{
			close();
		}

		var data  = $(this).data('jdropdown'),
		offset = $(this).offset(),
		container = data.menu;
		container.data('jdropdown', data);
		container.empty();

		if($.isFunction(data.renderMenu)){
			if($.isFunction(data.renderItem)){
				var ul = data.renderItem(data.renderMenu(), data.items);
			}else{
				var ul = renderItem(data.renderMenu(), data.items);
			}
		}else{
			if($.isFunction(data.renderItem)){
				var ul = data.renderItem($( '<ul></ul>' ), data.items);
			}else{
				var ul = renderItem($( '<ul></ul>' ), data.items);
			}
		}
		ul.appendTo( container );

		if(data.options.orientation == 'left'){
			data.menu.css({
				'position': 'absolute',
				'left': offset.left,
				'top': (offset.top + $(this).outerHeight()),
				'display': 'block'
			});
		}else{
			data.menu.css({
				'position': 'absolute',
				'left': (offset.left - container.outerWidth()) + $(this).outerWidth(),
				'top': (offset.top + $(this).outerHeight()),
				'display': 'block'
			});
		}
		$(this).addClass('jdropdown-active').trigger('jdropdown.open');
	},
	renderItem = function(menu, items){
		$.each(items, function(i, item){
			$('<li></li>').data('jdropdown.item', item).append(
				$( "<a></a>" ).attr({
					'href': '#', 'class': item['class']
				}).text( item.label ).on({ 'click': selectItem })
			).appendTo( menu );
		});
		return menu;
	},
	selectItem = function(e){
		close();
		$(this).trigger('jdropdown.selectItem', e);
	},
	close = function(){
    	$('.jdropdown-menu').css({ 'display': 'none' }); //hide all drop downs
    	$('.jdropdown-anchor').removeClass("jdropdown-active");
		$(this).trigger('jdropdown.close');
	};

	$(document).on('click', function(e) {
	    // Lets hide the menu when the page is clicked anywhere but the menu.
	    var $clicked = $(e.target);
	    if (!$clicked.parents().hasClass("jdropdown-menu") && !$clicked.parents().hasClass("jdropdown-anchor") && !$clicked.hasClass("jdropdown-menu") && !$clicked.hasClass("jdropdown-anchor")){
	    	close();
		}
	});

	$(window).resize(function(){
		if($('.jdropdown-active').length > 0){
			var offset = $('.jdropdown-active').offset(),
				data  = $('.jdropdown-active').data('jdropdown'),
				container = data.menu;

			if(data.options.orientation == 'left'){
				data.menu.css({
					'position': 'absolute',
					'left': offset.left,
					'top': (offset.top + $('.jdropdown-active').outerHeight()),
					'display': 'block'
				});
			}else{
				data.menu.css({
					'position': 'absolute',
					'left': (offset.left - container.outerWidth()) + $('.jdropdown-active').outerWidth(),
					'top': (offset.top + $('.jdropdown-active').outerHeight()),
					'display': 'block'
				});
			}
		}
	});

	$.fn.jdropdown = function(method){
		// Method calling logic
		if ( methods[method] ) {
			return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
			return methods.init.apply( this, arguments );
		} else {
			$.error( 'Method ' +  method + ' does not exist on jQuery.j_slider' );
		}
	};
})(jQuery);

Notes:

Added bug fix for resizing the window.

JQuery

Creating a sometimes-postion-fixed top menu jQuery plugin

Since quite a few people have come here expecting some sort of genius I have decided to rewrite this post a little in an attempt to make me look like one. Of course the most likely out come is that I do not.

After reading Ben Nadels post (here: www.bennadel.com/blog/1810-Creating-A-Sometimes-Fixed-Position-Element-With-jQuery.htm) I decided that I wanted to implement his first example into my site. Only problem is that I didn’t want to write it out everytime I wanted to call a new sometimes-fixed-position-element so I decided to make a JQuery plugin called (wait for it…) “stickytoolbar” (…yep).

I have created the following pluign to do the job for me:

/**
 * @author Some guy in the back alley
 * @licence WTF? Like I care
 *
 * This plugin is basically designed to allow some one to widgetise the handling of sticky toolbars from the example on
 * http://www.bennadel.com/blog/1810-Creating-A-Sometimes-Fixed-Position-Element-With-jQuery.htm
 *
 * This plugin is very basic and does nothing special tbh.
 *
 */
(function($){
	$.fn.stickytoolbar = function(options){

		$(this).addClass( options.onStaticClass ).data('options', $.extend({
			'onStaticClass': '',
			'onFixedClass': ''
		}, options));

		$(window).bind(
			'scroll resize', function(){
				$('.stickytoolbar-placeholder').each(function(){

					var options = $(this).data().options,

					// Get the current offset of the placeholder.
					// Since the message might be in fixed
					// position, it is the plcaeholder that will
					// give us reliable offsets.
					placeholderTop = $(this).offset().top,

					// Gets the message element so it can be used
					bar = $(this).find('.stickytoolbar-bar'),

					// Get the current scroll of the window.
					viewTop = $(window).scrollTop();

					// Check to see if the view had scroll down
					// past the top of the placeholder AND that
					// the message is not yet fixed.
					if ((viewTop > placeholderTop) && !bar.hasClass( 'stickytoolbar-fixed' )){

						// The message needs to be fixed. Before
						// we change its positon, we need to re-
						// adjust the placeholder height to keep
						// the same space as the message.
						//
						// NOTE: All we're doing here is going
						// from auto height to explicit height.
						$(this).height($(this).height());

						// Make the message fixed.
						bar.addClass( 'stickytoolbar-fixed' )
							.css({ left: $(this).offset().left+'px', top: '0px', position: 'fixed', width: $(this).width()+'px' })
							.removeClass( options.onStaticClass )
							.addClass( options.onFixedClass );

						// Check to see if the view has scroll back up
						// above the message AND that the message is
						// currently fixed.
					} else if ((viewTop <= placeholderTop) && bar.hasClass( 'stickytoolbar-fixed' )){

						// Make the placeholder height auto again.
						$(this).css({ 'height': 'auto', 'width': 'auto' });

						// Remove the fixed position class on the
						// message. This will pop it back into its
						// static position.
						bar.removeClass( 'stickytoolbar-fixed' )
							.css({ left: 'auto', top: 'auto', position: 'static', width: 'auto' })
							.removeClass( options.onFixedClass )
							.addClass( options.onStaticClass );

					}
				});
			}
		);
	};
})(jQuery);

You can use this plugin like so (as an example I have also placed in a setting param):

$('.videos_toolbar').stickytoolbar({ onStaticClass: 'sticktoolbar-static' });

Using this html structure:

<div class='stickytoolbar-placeholder videos_toolbar'>
	<div class='stickytoolbar-bar'>
	</div>
</div>

You do not need to call your bar “videos_toolbar” but you get the idea.

JQuery

JQuery rotating banner slider with fade in/fade out effect

Note: This plugin still is not complete but it is ready for initial release but if you wish to get custom behaviour you will need to modify it yourself for the second. You will need at least JQuery v1.4 to use this plugin.

I have been making a little plugin for JQuery recently that allows for some one to make a fade in/out JQuery banner slider from a JSON source file. It can be viewed here: Test Page for j-slider (Yes I named it j-slider; I know, I’m a pikey).

This plugin is real simple all you need to make is a JSON data source like so:

[{"image":"slide_01.jpg"},{"image":"slide_02.jpg"},{"image":"slide_03.jpg"}]

This JSON file will be the source for all your slides. A you can see I have just specified 3 slides and 3 images, one image for each slide. After you have your source data you just need the CSS:

@CHARSET "ISO-8859-1";

.j-slider_outer{
}

.j-slider_inner{
	display:block;
	position:relative;
}

.j-slider_row{
	position:absolute;
}

.j_slider-slide_outer{
	position:absolute;
}

.j_slider-slide_active{
	display:block;
	z-index:45!important;
}

.j_slider-slide{
	display:block;
}

.j_slider-next, .j_slider-previous{
	overflow:hidden;
	font-size:15px;
	font-weight:bold;
	color:#ffffff;
}

.j_slider-next{
	display:block;
	position:absolute;
	right:0;
	z-index:45;
}

.j_slider-previous{
	display:block;
	position:absolute;
	left:0;
	z-index:45;
}

.j_slider-controls_outer{
	display:block;
	position:absolute;
	right:3px;
	bottom:5px;
	z-index:45;
}

.j_slider-controls_inner{
	float:left;
	height:16px;
	width:16px;
	font-size:12px;
	color:#ffffff;
	margin:0 3px;
	cursor:pointer;
	background:url("/images/j_slider/ibutton.png");
}

.j_slider-controls_active{
	background:url("/images/j_slider/button.png");
}

And the your actual page:

<html>
	<head>
		<title>Slider Test</title>
		<link rel='stylesheet' media='all' type='text/css' href='/css/j-slider.css' />
		<script type="text/javascript" src="/js/jquery.js" ></script>
		<script type="text/javascript" src="/js/j-slider.js" ></script>
	</head>

	<body>

	<script type="text/javascript">$(document).ready(function(){ $(".j-slider_outer").j_slider(); });</script>
	<div class="j-slider_outer"><div class="j-slider_inner"></div></div>


	</body>
</html>

And Ka POW! It is done! The plugin itself it really easy to understand but I have pasted a fully annotated version below:

(function($){
	var options = {
			"width":580,
			"height":164,
			"slide_speed":10000,
			"fade_speed":"slow",
			"json":"/modules/slider/data_source.json",
			"images":"/images/j_slider/",
			"side_nav":false,
			"bottom_nav":true,
			"cycle":true
	},
	methods = {
		init: function(opts){

			// Merge options so we have the users options
			options =  $.extend(options, opts);

			return this.each(function(){

				// Specify the variable required to make the slider
				var $this = $(this),
					thumbs = [],
					data = $this.data('j_slider');

				if(!data){
					// Get our source data
					$.getJSON(options.json, function(data){

						// Constrain the outer boxes
						$this.css({ "height": options.height+"px", "width": options.width+"px" });
						$this.children(".j-slider_inner").css({ "height": options.height+"px", "width": options.width+"px" });

						// Add our slider row (all our slides will go into here)
						$("<div class='j-slider_row'></div>").appendTo($this.children(".j-slider_inner").get());

						// Add the controls outer (all our slide controls go here)
						$this.children(".j-slider_inner").append("<div class='j_slider-controls_outer'></div>");

						// For each of the slides within the JSON file
						$.each(data, function(i, slide){

							// Form an ID
							id = "slide_"+(i+1);

							// Append the slkide itself
							$("<div class='j_slider-slide_outer j_slider-slide' id='slide_"+(i+1)+"'><img src='"+options.images+slide.image+"' alt=''/></div>").appendTo($this.find(".j-slider_row").get());

							// Add the slide to the buttons at the bottom (the white circle things)
							if(options.bottom_nav){
								if(slide.thumbnail && slide.thumbnail != undefined && slide.thumbnail != null){
									// Still needs to be done
								}else{
									$this.children(".j-slider_inner").find(".j_slider-controls_outer").append("<div class='j_slider-controls_inner j_slider-controls_active' id='"+i+"'></div>");
								}
							}
						});

						// Assign the controls an action.
						$this.children(".j-slider_inner").children(".j_slider-controls_outer").find(".j_slider-controls_inner").bind({ click: _goto });

						// Make first slide active
						$this.find(".j-slider_row").children("#slide_1").addClass("j_slider-slide_active");

						// Make all other slides hide
						$this.find(".j-slider_row").find("div:not(#slide_1)").css("display", "none");

						// Assign the inactive class to all control buttons that are not assigned to the first slide
						$this.find(".j_slider-controls_outer").children(".j_slider-controls_inner:not(#0)").removeClass("j_slider-controls_active");

						if(options.cycle){
							// If the user wants to cycle the slides then start the automated slider
							slider_timeout = setTimeout(next, options.slide_speed);
						}

						if(options.side_nav){
							// If user wants the slide menu navs then put them in
							$this.children(".j-slider_inner").append("<div class='j_slider-previous'><span><</span></div><div class='j_slider-next'><span>></span></div>");
							$this.children(".j-slider_inner").find(".j_slider-next").bind({ click: next });;
							$this.children(".j-slider_inner").find(".j_slider-previous").bind({ click: previous });
						}
					});
				}
			});
		},
		destroy: function(){
			return this.each(function(){

				// This function is kinda redundant and aint really needed
				var $this = $(this),
				data = $this.data('j_slider');

				// Namespacing FTW
				//$(window).unbind('.j_slider');
				data.j_slider.remove();
				$this.removeData('j_slider');

			});
		}
	},
	_goto = function(){
		// This function takes us to a specific slide
		// Stop the timeout to stop stupid clitches within animation.
		clearTimeout(slider_timeout);

		// Get the slide we are looking for
		var id = $(this).attr("id"), el = $(".j_slider-slide_outer:eq("+$(this).attr("id")+")").get();

		// Make it display (beneath the current one)
		$(el).css("display", "block");

		// Fade out the current slide
		$('.j_slider-slide_active').fadeOut(options.fade_speed, function() {

			// Take away the class from the one just faded out
			$(".j-slider_row").find(".j_slider-slide_active").removeClass("j_slider-slide_active");

			// Take the class away from the control button assigned to this slide
			$(".j_slider-controls_outer").find(".j_slider-controls_active").removeClass("j_slider-controls_active");

			// Add class assigned to goto slide to controls and show the slide
			$(".j_slider-controls_outer").find("div#"+id).addClass("j_slider-controls_active");
			$(el).addClass("j_slider-slide_active").show();
		});

		if(options.cycle){
			// Continue cycling if user wishes it
			slider_timeout = setTimeout(next, options.slide_speed);
		}
	},
	previous = function(){
		// This function goes to the previous slide
		// Lets clear timeout again
		clearTimeout(slider_timeout);

		// Get previous slide
		var index = 0, el = $(".j-slider_row").find(".j_slider-slide_active").prev();

		// If we are at the end show the last slide otherwise show the next one
		if(el.length > 0){
			index = $(".j_slider-slide_outer").index(el);
			el.css("display", "block");
		}else{
			index = $(".j_slider-slide_outer").index($(".j_slider-slide_outer").last());
			$(".j_slider-slide_outer").last().css("display", "block");
		}

		// Fade out the current slide
		$('.j_slider-slide_active').fadeOut(options.fade_speed, function() {

			// remove active class from current slide and remove the active class from the control button
			$(".j-slider_row").find(".j_slider-slide_active").removeClass("j_slider-slide_active");
			$(".j_slider-controls_outer").find(".j_slider-controls_active").removeClass("j_slider-controls_active");

			// If we are at the end we want to show the last one else show the next one
			if(el.length > 0){
				el.addClass("j_slider-slide_active").show();
			}else{
				$(".j_slider-slide_outer").last().addClass("j_slider-slide_active").show();
			}

			// Add active class to the control assigned with the index
			$(".j_slider-controls_outer").find("div#"+index).addClass("j_slider-controls_active");
		});

		if(options.cycle){
			//continue cycling if user wishes to
			slider_timeout = setTimeout(next, options.slide_speed);
		}
	},
	next = function(){
		// Same as the previous function only next instead of previous and first instead of last
		clearTimeout(slider_timeout);

		var index = 0, el = $(".j-slider_row").find(".j_slider-slide_active").next();

		if(el.length > 0){
			index = $(".j_slider-slide_outer").index(el);
			el.css("display", "block");
		}else{
			index = $(".j_slider-slide_outer").index($(".j_slider-slide_outer").first());
			$(".j_slider-slide_outer").first().css("display", "block");
		}

		$('.j_slider-slide_active').fadeOut(options.fade_speed, function() {
			$(".j-slider_row").find(".j_slider-slide_active").removeClass("j_slider-slide_active");
			$(".j_slider-controls_outer").find(".j_slider-controls_active").removeClass("j_slider-controls_active");

			if(el.length > 0){
				el.addClass("j_slider-slide_active").show();
			}else{
				$(".j_slider-slide_outer").first().addClass("j_slider-slide_active").show();
			}

			$(".j_slider-controls_outer").find("div#"+index).addClass("j_slider-controls_active");
		});

		if(options.cycle){
			slider_timeout = setTimeout(next, options.slide_speed);
		}
	},
	slider_timeout = null;

	$.fn.j_slider = function(method) {

		// Method calling logic
		if ( methods[method] ) {
			return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
			return methods.init.apply( this, arguments );
		} else {
			$.error( 'Method ' +  method + ' does not exist on jQuery.j_slider' );
		}

	};
})(jQuery);
JQuery

Facebook Style CSS JQuery drop down menus

THIS PAGE IS OUT OF DATE: This page has now become out of date. I have made a plugin to handle drop downs etc and done it in the good old facebook style. It can be found here: Facebook dropdown menu using Jdropdown. So pleae use this now…

Note: A Demo of this tutorial can be found here It is not perfect but it’s good enough to get you started. More elegant but complex version: Is Here Now

Showing the two drop down menus

I have been wondering for a whle now how facebook do those kool JQuery (I know they use JQuery, it’s no secret :P) drop downs where you click on them and they act like a drop down menu and if you click anywhere on the document whilst the menu is showing it will hide that menu out of many. You know the ones? they use them for the bottom bar and privacy functions…

I decided to make my own version of these menus for my new video site (figure to the right shows the end result).

As you can see the top version is what the menu looks like selected whilst the bottom shows the menu deselected. I will now show you how I did this…your gonna kick yourself when you find out how easy it is.

The JQuery I used was:

$(".dropdown dt a").click(function() {

        // Change the behaviour of onclick states for links within the menu.
	var toggleId = "#" + this.id.replace(/^link/,"ul");

        // Hides all other menus depending on JQuery id assigned to them
	$(".dropdown dd ul").not(toggleId).hide();

        //Only toggles the menu we want since the menu could be showing and we want to hide it.
	$(toggleId).toggle();

        //Change the css class on the menu header to show the selected class.
	if($(toggleId).css("display") == "none"){
		$(this).removeClass("selected");
	}else{
		$(this).addClass("selected");
	}

});

$(".dropdown dd ul li a").click(function() {

    // This is the default behaviour for all links within the menus
    var text = $(this).html();
    $(".dropdown dt a span").html(text);
    $(".dropdown dd ul").hide();
});

$(document).bind('click', function(e) {

    // Lets hide the menu when the page is clicked anywhere but the menu.
    var $clicked = $(e.target);
    if (! $clicked.parents().hasClass("dropdown")){
        $(".dropdown dd ul").hide();
		$(".dropdown dt a").removeClass("selected");
	}

});

I used this JQuery with this HTML:

             <dl style="" class="dropdown">
                <dt><a id="linkglobal" style="cursor:pointer;"></a></dt>
	        <dd>
                     <ul id="ulglobal">
                         <li><a href="#">Everyone</a></li>
                         <li><a href="#">Friends</a></li>
                         <li><a href="#">Only Me</a></li>
                         <li><a href="#">Customize</a></li>
                   </ul>
                </dd>
             </dl>

I built this CSS to style the entire widget to the view you see within the picture:

/* Grey Small Dropdown */

/* General dropdown styles */
.dropdown dl{ margin-left:5px; }
.dropdown dd, .dropdown dt, .dropdown ul { margin:0px; padding:0px; margin-left:5px; }
.dropdown dd { position:relative; }

/* DT styles for sliding doors */
.dropdown dt a {background:#EEEEEE url(/img/stage/x/privacyOff.png) no-repeat scroll right center;
    display:block; width:40px; height:22px; cursor:pointer;}

.dropdown dt a.selected{
	background:#EEEEEE url(/img/stage/x/privacyOn.png) no-repeat scroll right center;
}
.dropdown dt a span {cursor:pointer; display:block; padding:5px;}

/* UL styles */
.dropdown dd ul { background:#EEEEEE none repeat scroll 0 0; display:none;
    list-style:none; padding:3px 0; position:absolute;
    left:0px; width:160px; left:auto; right:0; border:1px solid #656565; cursor:pointer;}
.dropdown dd ul li{ background-color:#EEEEEE; margin:0; width:160px;}
.dropdown span.value { display:none;}
.dropdown dd ul li a { display:block; font-weight:normal; width:137px; text-align:left; overflow:hidden; padding:2px 4px 3px 19px; color:#111111; text-decoration:none;}
.dropdown dd ul li a:hover{ background:#656565; color:white; text-decoration:none; }
.dropdown dd ul li a:visited{ text-decoration:none; }

CSS Notes:
I used two images, one of the facebook grey button without being pressed and one of it being pressed (as shown in the picture) these two pictures within the CSS named privacyOff and privacyOn.

Additional Notes:
I basically took the basis of this from somewhere else which I didn’t bookmark (Closed the Firefox tab and lost the history record) and it came in the form of a tutorial on how to produce enhanced JQuery drop downs and I took this tutorial and facebookified it. The menu is not keyboard accessible but meh, facebook’s ain’t either.

If you want a full form version (that can go into CSS forms etc) then check this out I found it as a link on that site I didn’t bookmark: Scott Darby

JQuery

Facebook Style Expanding textareas

I found this plugin just now that works great at making Facebook style self expanding textareas:

Self expanding textareas

There is, however, one error in it. When you first download and use the extension you will realise that when the textarea is empty it shrinks below its defined height. I decided to look into this and it was as simple as the function not being implemented correctly so I added this line:

					if (scrollTop < $(this).height()) { toChange.height($(this).height()); return; }

Basically I check to see if the textarea will be changed to smaller than the predefined height and if it will be then I redefine textarea height to its original height and exit from the function to stop any further processing making the amended plugin:

/*
 * jQuery autoResize (textarea auto-resizer)
 * @copyright James Padolsey http://james.padolsey.com
 * @version 1.04
 */

(function($){
    
    $.fn.autoResize = function(options) {
        
        // Just some abstracted details,
        // to make plugin users happy:
        var settings = $.extend({
            onResize : function(){},
            animate : true,
            animateDuration : 150,
            animateCallback : function(){},
            extraSpace : 20,
            limit: 1000
        }, options);
        
        // Only textarea's auto-resize:
        this.filter('textarea').each(function(){
            
                // Get rid of scrollbars and disable WebKit resizing:
            var textarea = $(this).css({resize:'none','overflow-y':'hidden'}),
                // Cache original height, for use later:
            	origHeight = $(this).height(),
                
                // Need clone of textarea, hidden off screen:
                clone = (function(){
                    
                    // Properties which may effect space taken up by chracters:
                    var props = ['height','width','lineHeight','textDecoration','letterSpacing'],
                        propOb = {};
                        
                    // Create object of styles to apply:
                    $.each(props, function(i, prop){
                        propOb[prop] = textarea.css(prop);
                    });
                    
                    // Clone the actual textarea removing unique properties
                    // and insert before original textarea:
                    return textarea.clone().removeAttr('id').removeAttr('name').css({
                        position: 'absolute',
                        top: 0,
                        left: -9999
                    }).css(propOb).attr('tabIndex','-1').insertBefore(textarea);
					
                })(),
                lastScrollTop = null,
                updateSize = function() {
					
                    // Prepare the clone:
                    clone.height(0).val($(this).val()).scrollTop(10000);
					
                    // Find the height of text:
                    var scrollTop = Math.max(clone.scrollTop(), origHeight) + settings.extraSpace,
                        toChange = $(this).add(clone);
						
                    // Don't do anything if scrollTip hasen't changed:
                    if (lastScrollTop === scrollTop) { return; }
					if (scrollTop < $(this).height()) { toChange.height($(this).height()); return; }
                    lastScrollTop = scrollTop;
					
                    // Check for limit:
                    if ( scrollTop >= settings.limit ) {
                        $(this).css('overflow-y','');
                        return;
                    }
                    // Fire off callback:
                    settings.onResize.call(this);
					
                    // Either animate or directly apply height:
                    settings.animate && textarea.css('display') === 'block' ?
                        toChange.stop().animate({height:scrollTop}, settings.animateDuration, settings.animateCallback)
                        : toChange.height(scrollTop);
                };
            
            // Bind namespaced handlers to appropriate events:
            textarea
                .unbind('.dynSiz')
                .bind('keyup.dynSiz', updateSize)
                .bind('keydown.dynSiz', updateSize)
                .bind('change.dynSiz', updateSize);
            
        });
        
        // Chain:
        return this;
        
    };
    
    
    
})(jQuery);

This now works as shown in the demo on the programmers page for this plugin.