(function($){ //add class to html tag $('html').addClass('stylish-select'); //utility methods $.fn.extend({ getSsklSelectValue: function(value){ if (value){ //set value and trigger change event //$(this).val(value).change(); return this; } else { var $item = $('input[id*=_ddValue]', $(this)); return $item.val(); } } }); $.fn.ssklSelect = function(options) { return this.each(function(){ var defaults = { defaultText: 'Please select', animationSpeed: 0, //set speed of dropdown ddMaxHeight: '180px' //set css max-height value of dropdown }; //initial variables //alert(options) var opts = $.extend(defaults, options), $input = $('input[id*=_ddValue]', $(this)), $inputtext = $('input[id*=_ddText]', $(this)), $containerDivText = $('div[id*=_divText]', $(this)), $containerDiv = $(this), $newUl = $('ul', $(this)), itemIndex = -1, currentIndex = -1, prevented = false, onchange = null, $newLi = $('ul li', $(this)); var newUlHeight = $newUl.height(), containerHeight = $containerDiv.height(), newLiLength = $newLi.length; //decide if to place the new list above or below the drop-down function newUlPos(){ var containerPosY = $containerDiv.offset().top, docHeight = jQuery(window).height(), scrollTop = jQuery(window).scrollTop(); //if height of list is greater then max height, set list height to max height value //alert(newUlHeight) if (newUlHeight > parseInt(opts.ddMaxHeight)) { newUlHeight = parseInt(opts.ddMaxHeight); } containerPosY = containerPosY-scrollTop; if (containerPosY+newUlHeight >= docHeight){ $newUl.css({ top: '-'+newUlHeight+'px', height: newUlHeight }); $input.onTop = true; } else { $newUl.css({ top: containerHeight+'px', height: newUlHeight }); $input.onTop = false; } } //run function on page load newUlPos(); //run function on browser window resize $(window).bind('resize.ssklSelect',function(){ newUlPos(); }); $(window).bind('scroll.ssklSelect',function(){ newUlPos(); }); //positioning function positionFix(){ $containerDiv.css('position','relative'); } function positionHideFix(){ $containerDiv.css('position','static'); } $containerDivText.bind('click.ssklSelect',function(event){ event.stopPropagation(); //hide all menus apart from this one $('.newList').not($(this).next()).hide().parent().removeClass('newListSelFocus'); //show/hide this menu $containerDiv.focus(); $newUl.toggle(); positionFix(); $newUl.scrollTop($input.liOffsetTop); }); $newLi.bind('click.ssklSelect',function(e){ var $clickedLi = $(e.target); //update counter currentIndex = $newLi.index($clickedLi); //remove all hilites, then add hilite to selected item prevented = true; navigateList(currentIndex); $newUl.hide(); $containerDiv.css('position','static');//ie }); $newLi.bind('focus.ssklSelect',function(e){ //alert('focus'); }); $newLi.bind('mouseenter.ssklSelect', function(e) { var $hoveredLi = $(e.target); $hoveredLi.addClass('newListHover'); } ).bind('mouseleave.ssklSelect', function(e) { var $hoveredLi = $(e.target); $hoveredLi.removeClass('newListHover'); } ); function navigateList(currentIndex, init){ //get offsets var containerOffsetTop = $containerDiv.offset().top, liOffsetTop = $newLi.eq(currentIndex).offset().top, ulScrollTop = $newUl.scrollTop(); //get distance of current li from top of list if ($input.onTop == true){ //if list is above select box, add max height value $input.liOffsetTop = (((liOffsetTop-containerOffsetTop)-containerHeight)+ulScrollTop)+parseInt(opts.ddMaxHeight); } else { $input.liOffsetTop = ((liOffsetTop-containerOffsetTop)-containerHeight)+ulScrollTop; } //scroll list to focus on current item $newUl.scrollTop($input.liOffsetTop); $newLi.removeClass('hiLite') .eq(currentIndex) .addClass('hiLite'); var text = $newLi.eq(currentIndex).text(); var val = $newLi.eq(currentIndex).attr("itemVal"); currentIndex = $newLi.eq(currentIndex).attr("itemindex"); //page load if (init == true){ $input.val(val); $inputtext.val(text); $containerDivText.text(text); return false; } $input.val(val) $input.change(); $containerDivText.text(text); }; $input.bind('change.ssklSelect',function(event){ $targetInput = $(event.target); //stop change function from firing if(opts.onchange!=null){ opts.onchange($containerDiv,$inputtext.val(),$input.val()); } if (prevented == true){ prevented = false; return false; } navigateList(currentIndex, true); }); //handle up and down keys function keyPress(element) { //when keys are pressed $(element).unbind('keydown.ssklSelect').bind('keydown.ssklSelect',function(e){ var keycode = e.which; //prevent change function from firing prevented = true; switch(keycode) { case 40: //down case 39: //right incrementList(); return false; break; case 38: //up case 37: //left decrementList(); return false; break; case 33: //page up case 36: //home gotoFirst(); return false; break; case 34: //page down case 35: //end gotoLast(); return false; break; case 13: case 27: $newUl.hide(); positionHideFix(); return false; break; } //check for keyboard shortcuts var lang = 'en'; if(lang=="el") keyPressed = String.fromCharCode(keycode + (913 - 65)).toLowerCase(); else keyPressed = String.fromCharCode(keycode).toLowerCase(); currentIndex = $newLi.index($newLi.filter(':contains('+keyPressed+')')); if(currentIndex!=-1) { navigateList(currentIndex); prevKey = keyPressed; } }); } function incrementList(){ if (currentIndex < (newLiLength-1)) { ++currentIndex; navigateList(currentIndex); } } function decrementList(){ if (currentIndex > 0) { --currentIndex; navigateList(currentIndex); } } function gotoFirst(){ currentIndex = 0; navigateList(currentIndex); } function gotoLast(){ currentIndex = newLiLength-1; navigateList(currentIndex); } $containerDiv.bind('click.ssklSelect',function(){ keyPress(this); }); $containerDiv.bind('focus.ssklSelect',function(){ $(this).addClass('newListSelFocus'); keyPress(this); }); $containerDiv.bind('blur.ssklSelect',function(){ $(this).removeClass('newListSelFocus'); }); //hide list on blur $('body').bind('click.ssklSelect',function(){ $containerDiv.removeClass('newListSelFocus'); $newUl.hide(); positionHideFix(); }); //add classes on hover $containerDivText.bind('mouseenter.ssklSelect', function(e) { var $hoveredTxt = $(e.target); $hoveredTxt.parent().addClass('newListSelHover'); } ).bind('mouseleave.ssklSelect', function(e) { var $hoveredTxt = $(e.target); $hoveredTxt.parent().removeClass('newListSelHover'); } ); //reset left property and hide $newUl.css('left','0').hide(); }); }; })(jQuery);