
	/**
	 * dTselect - the jquery plugin
	 *
	 * this text should tell you how the plugin works. too bad it doesn't.
	 */
	(function( $ ){
			
		//
		// Default settings
		var defaultSettings = {
			'hover'	: 0,
			'open'	: false
		};
		
		//
		// Methods
		var methods = {
		
			//
			// Initialize
			init : function( options ) {
			
				return this.each(function() {
				
					var $this = $(this);
					
					//
					// Apply settings
					var settings = $.extend( {}, defaultSettings, options );
					settings.total = $this.find('option').length;
					$this.data( 'dTselect', settings );
					
					$this.hide();
					
					var selected = $this.find('option:selected').text();
					if( !selected.length ) selected = $this.find('option:first').text();
					if( !selected.length ) selected = '&nbsp;';
					
					$this.before(
						$('<div class="select" />')
							.append(
								$('<span>' + selected + '</span>')
									.bind( 'click.dTselect', function(e) { e.preventDefault(); methods.expand.call($this); })
									.bind( 'mousedown.dTselect', function() { return false; })
							)
							.append( 
								$('<a href="#" class="sprite expand">expand</a>')
									.bind( 'click.dTselect', function(e) { e.preventDefault(); methods.expand.call($this); })
									.bind( 'mousedown.dTselect', function() { return false; })
							)
							.append(
								$('<ul />').hide()
							)
							.width( $this.outerWidth() )
							.css({ 
									marginTop: $this.css('marginTop'),
									marginRight: $this.css('marginRight'),
									marginBottom: $this.css('marginBottom'),
									marginLeft: $this.css('marginLeft')
								})
					);
					
					var $select = $this.prev('div.select');
					
					$select.find('ul:first').append(
							$('<li />')
								.append(
									$('<a href="#" data-eq="0">&nbsp;</a>')
										.bind( 'mousedown.dTselect', function(e) {
												e.preventDefault();
												methods.select.call($this,this);
												return false;
											})
								)
						);
					
					var items = $this.find('option');
					for( var i = 0; i < items.length; i++ ) {
						if( $(items[i]).text().length && ( $(items[i]).attr('visible') == undefined || $(items[i]).attr('visible') != 'false' ) ) {
							$select.find('ul:first')
								.append(
									$('<li />')
										.append(
											$('<a href="#" data-eq="' + i + '">' + $(items[i]).text() + '</a>')
												.bind( 'mousedown.dTselect', function(e) {
														e.preventDefault();
														methods.select.call($this,this);
														return false;
													})
										)
								)
						}
					}
					
					if( $select.find('ul:first li').length > 10 ) {
						$select.find('ul:first').css({ height: '200px', overflow: 'auto' });
					}
					
					/*$this.bind( 'focus.dTselect', function() { methods.expand.call($this); });
					$this.bind( 'blur.dTselect', function() { methods.close.call($this); });
					$select.find('a.expand').bind( 'focus.dTselect', function() { methods.expand.call($this); });
					$select.find('a.expand').bind( 'blur.dTselect', function() { methods.close.call($this); });*/
					
					$select.find('li a').bind( 'mouseover.dTselect', function() { methods.hover.call( $this, this ); });
					
				});
				
			},
			
			//
			// Select
			select : function(a) {
			
				return this.each(function() {
				
					var $this = $(this);
					var $select = $this.prev('div.select');
					
					$select.find('span:first').text($(a).text());
					methods.close.call($this);
					$this.find('option:selected').removeAttr('selected');
					$this.find('option').eq($(a).data('eq')).attr('selected','selected');
				
					$(a).addClass('hover');
				
					$this.change();
				
				});
			
			},
			
			//
			// Expand
			expand : function() {
			
				return this.each(function() {
				
					var $this = $(this);
					var settings = $this.data('dTselect');
					var $select = $this.prev('div.select');
					
					if( settings.open ) {
					
						methods.close.call($this);
						
					} else {
					
						$select.css({ zIndex: 15 });
						$select.find('ul').show();
						
						//
						// Scoll to selected
						if( $select.find('li a.hover').length ) {
							methods.scroll.call( $this, $select.find('li a.hover') );
						}
						
						//
						// Close the dropdown on body clicks
						$('body').bind( 'mousedown.dTselect', function() { methods.close.call($this); } );
						
						//
						// Catch keyboard events
						$(window).bind( 'keydown.dTselect', function(e) {
								e.preventDefault();
								methods.keydown.call( $this, e.keyCode );
							});
						
						//
						// Unbind body click when hovering select
						$select.bind( 'mousemove.dTselect', function() {
								$('body').unbind('mousedown.dTselect');
							});
						$select.bind( 'mouseout.dTselect', function() {
								if( $select.find('ul:first').is(':visible') ) {
									$('body').unbind('mousedown.dTselect');
									$('body').bind( 'mousedown.dTselect', function() { methods.close.call($this); } );
								}
							});
						
						settings.open = true;
					
						$this.data( 'dTselect', settings );
						
					}
				
				});
			
			},
			
			//
			// Close
			close : function() {
			
				return this.each(function() {
				
					var $this = $(this);
					var settings = $this.data('dTselect');
					var $select = $this.prev('div.select');
					
					$select.css({ zIndex: 'auto' }).find('ul').hide().unbind('mousemove.dTselect').unbind('mouseout.dTselect');
					$('body').unbind('mousedown.dTselect');
					$(window).unbind('keydown.dTselect');
				
					settings.open = false;
					
					$this.data( 'dTselect', settings );
				
				});
			
			},
			
			//
			// Scroll
			scroll : function() {
			
				return this.each(function() {
				
					var $this = $(this);
					var $select = $this.prev('div.select');
					var settings = $this.data('dTselect');
					
					var $ul = $select.find('ul:first');
					
					var height = $ul.outerHeight();
					var itemheight = $ul.find('li:first').outerHeight();
					var first = $ul.find('li:first').offset().top;
					var last = $ul.find('li:last').offset().top;
					var current = ( $ul.find('li').eq(settings.hover).offset().top - first );
					var listheight = ( last + itemheight ) - first;
					
					//
					// Lock to top
					if( current < ( height / 2 ) ) {
						$ul.scrollTop(0);
					
					//
					// Lock to bottom
					} else if( current > ( listheight - ( height / 2 ) ) ) {
						$ul.scrollTop( listheight - height );
					
					//
					// Center
					} else {
						var offset = ( current + ( itemheight / 2 ) ) - ( height / 2 );
						$ul.scrollTop( offset );
					}
					
					$select.find('li a').unbind('mouseover.dTselect');
					$select.bind( 'mouseover.dTselect', function() { $select.find('li a').bind( 'mouseover.dTselect', function() { methods.hover.call( $this, this ); }); $select.unbind('mouseover.dTselect'); } );
				
				});
			
			},
			
			//
			// Destroy
			destroy : function() {
			
				return this.each(function() {
				
					var $this = $(this);
					var $select = $this.prev('div.select');
					
					$this.unbind('.dTselect').removeData('dTselect').show();
					$select.remove();
				
				});
			
			},
			
			//
			// Hover element
			hover : function( a, type ) {
			
				return this.each(function() {
				
					var $this = $(this);
					var settings = $this.data('dTselect');
					var $select = $this.prev('div.select');
					
					$select.find('li a.hover').removeClass('hover');
					$(a).addClass('hover');
					
					settings.hover = $(a).parents('li').index();
					
					if( type == 'keyboard' )
						methods.scroll.call($this);
					
					$this.data( 'dTselect', settings );
				
				});
			
			},
			
			//
			// Keydown
			keydown : function(key) {
			
				return this.each(function() {
				
					var $this = $(this);
					var settings = $this.data('dTselect');
					var $select = $this.prev('div.select');
					
					//
					// Close (ESC)
					if( key == 27 ) {
						methods.close.call($this);
						
					//
					// Go up (38)
					} else if( key == 38 ) {
						methods.hover.call( $this, $select.find('li a').eq( ( settings.hover > 0 )? (parseInt(settings.hover)-1) : 0 ), 'keyboard' );
					
					//
					// Go down (40)
					} else if( key == 40 ) {
						methods.hover.call( $this, $select.find('li a').eq( ( settings.hover < (settings.total-1) )? (parseInt(settings.hover)+1) : (settings.total-1) ), 'keyboard' );
					
					//
					// Select (13)
					} else if( key == 13 || key == 9 ) {
						if( $select.find('a.hover').length ) {
							methods.select.call( $this, $select.find('a.hover').removeClass('hover') );
						} else {
							methods.close.call($this);
						}
					
					//
					// Go to letter
					} else {
					
						var char = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
						key = key - 65;
						if( key >= 0 && key <= 25 ) {
							
							var letter = char[key];
							var items = $select.find('li a');
							for( var i=0; i<items.length; i++ ) {
								var label = $(items[i]).text();
								if( label.length && label[0] != undefined && label[0].toLowerCase() == letter ) {
									methods.hover.call( $this, $(items[i]), 'keyboard' );
									break;
								}
							}
							
						}
					
					}
					
					$this.data( 'dTslider', settings );
				
				});
			
			}
					
		}
	  
		$.fn.dTselect = function( method ) {
			
			//
			// Method call
			if ( methods[method] ) {
				return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
			
			//
			// Default init call
			} else if ( typeof method === 'object' || ! method ) {
				return methods.init.apply( this, arguments );
			
			//
			// Method doesn't exist
			} else {
				$.error( 'Method ' +  method + ' does not exist on jQuery.dTselect' );
			}
		
		};
	  
	})( jQuery );
	
