/** * Created by IntelliJ IDEA. * User: mcanas * Date: Oct 8, 2010 * Time: 9:34:07 AM * To change this template use File | Settings | File Templates. */ (function($) { var toggleDisplay; // Define the public methods var methods = { /* * The initializer method * Called automatically when no registered methods are passed to the $.jSelect function * */ init : function() { // Check if the object has a selector attached to it. if(!this.selector) { // If no selector is attached, return a collection of converted jSelect's, or a single jSelect return this.length > 1 ? this : this[0]; } else { /* * If a selector is attached, the SELECT object/s needs to be converted into a jSelect object/s * We use recursion to return jSelect's DOM instead of the replaced SELECT's DOM * */ return methods.init.apply(this.map(function() { var $this = $(this); // Store jSelect attribute data var attr = { name : $this.attr('name'), hoverState : 'out', menuState : 'closed', target : $this, type : $this.attr('type'), value : $this.val() }; // Build the DOM structure var $selectTag = $('
'), // The wrapper $selectedTag = $(''), // The tag used to display the current selection $menuTag = $(''), // The drop down wrapper $valueTag = $(''), // The form element to store the selected value $defaultOption; // Replacement for the default $selectTag.data('attributes', attr); $selectTag.append($selectedTag, $menuTag, $valueTag); // Grab the 's var $options = $this.find('option'); // Replace each with an tag $options.each(function() { var $opt = $(this); $(''+$opt.text()+'').appendTo($menuTag); // If exists, set it, or set to false $defaultOption = ( $opt.context.selected ) ? $opt : false; }); if($defaultOption === false) { // If no default, set the initial value to the first element $selectedTag.attr('href',$($options[0]).val()).children('span').text($($options[0]).text()); } else { // Otherwise, set the initial value to the default $selectedTag.attr('href',$defaultOption.val()).children('span').text($defaultOption.text()); } // Handle clicks outside of the jSelect tag (blur) $(document.body).click(function() { if(attr.hoverState == 'out' && attr.menuState == 'open') { attr.menuState = (toggleDisplay($menuTag) == 'block') ? 'open' : 'closed'; } }); // Track over state, needed to blur $selectTag.hover(function() { attr.hoverState = 'over'; },function() { attr.hoverState = 'out'; }); // Handle clicks on the select tag $selectTag.bind('click', function(e) { attr.menuState = (toggleDisplay($menuTag) == 'block') ? 'open' : 'closed'; }); // Ignore the selected tag click event $selectedTag.bind('click', function(e) { e.preventDefault(); }); // Handle clicks on the options $menuTag.children('a').bind('click', function(e) { e.preventDefault(); e.stopImmediatePropagation(); var $clicked = $(this); $valueTag.val($clicked.attr('href').match(/#(.*)$/)[1]); $selectedTag.attr('href',$clicked.attr('href')).children('span').text($clicked.text()); attr.menuState = (toggleDisplay($menuTag) == 'block') ? 'open' : 'closed'; attr.value = $valueTag.val(); $selectTag.trigger('change'); }); // Replace the original with the generated DOM elements $this.replaceWith($selectTag); return $selectTag; }), arguments); } } }; toggleDisplay = function( obj ) { var currentDisplay = obj.css('display'); currentDisplay = obj.css('display',((currentDisplay != 'block') ? 'block' : 'none')).css('display'); if(currentDisplay === 'block') { if((obj.offset().top + obj.outerHeight() - $(window).scrollTop()) > $(window).height()) { obj.css('bottom', obj.parent('.jSelect').height()); } else { obj.css('bottom','auto'); } } else { obj.css('bottom','auto'); } return currentDisplay; }; $.fn.jSelect = function( method ) { 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.jSelect'); } }; })(jQuery);