/* * jquery selectbox plugin * * copyright (c) 2007 sadri sahraoui (brainfault.com) * licensed under the gpl license and mit: * http://www.opensource.org/licenses/gpl-license.php * http://www.opensource.org/licenses/mit-license.php * * the code is inspired from autocomplete plugin (http://www.dyve.net/jquery/?autocomplete) * * revision: $id$ * version: 0.6 * * changelog : * version 0.6 * - fix ie scrolling problem * version 0.5 * - separate css style for current selected element and hover element which solve the highlight issue * version 0.4 * - fix width when the select is in a hidden div @pawel maziarz * - add a unique id for generated li to avoid conflict with other selects and empty values @pawel maziarz */ jquery.fn.extend({ selectbox: function(options) { return this.each(function() { new jquery.selectbox(this, options); }); } }); /* pawel maziarz: work around for ie logging */ if (!window.console) { var console = { log: function(msg) { } } } /* */ jquery.selectbox = function(selectobj, options) { var opt = options || {}; opt.inputclass = opt.inputclass || "selectbox"; opt.containerclass = opt.containerclass || "selectbox-wrapper"; opt.hoverclass = opt.hoverclass || "current"; opt.currentclass = opt.selectedclass || "selected" opt.debug = opt.debug || false; var elm_id = selectobj.id; var active = 0; var infocus = false; var hasfocus = 0; //jquery object for select element var $select = jquery(selectobj); // jquery container object var $container = setupcontainer(opt); //jquery input object var $input = setupinput(opt); // hide select and append newly created elements $select.hide().before($input).before($container); init(); $input .click(function(){ if (!infocus) { $container.toggle(); } }) .focus(function(){ if ($container.not(':visible')) { infocus = true; $container.show(); } }) .keydown(function(event) { switch(event.keycode) { case 38: // up event.preventdefault(); moveselect(-1); break; case 40: // down event.preventdefault(); moveselect(1); break; //case 9: // tab case 13: // return event.preventdefault(); // seems not working in mac ! jquery('li.'+opt.hoverclass).trigger('click'); break; case 27: //escape hideme(); break; } }) .blur(function() { if ($container.is(':visible') && hasfocus > 0 ) { if(opt.debug) console.log('container visible and has focus') } else { // workaround for ie scroll - thanks to bernd matzner if(jquery.browser.msie || jquery.browser.safari){ // check for safari too - workaround for webkit if(document.activeelement.getattribute('id').indexof('_container')==-1){ hideme(); } else { $input.focus(); } } else { hideme(); } } }); function hideme() { hasfocus = 0; $container.hide(); } function init() { $container.append(getselectoptions($input.attr('id'))).hide(); // var width = $input.css('width'); // width = $input.width; // $container.width(width); } function setupcontainer(options) { var container = document.createelement("div"); $container = jquery(container); $container.attr('id', elm_id+'_container'); $container.addclass(options.containerclass); return $container; } function setupinput(options) { var input = document.createelement("input"); var $input = jquery(input); $input.attr("id", elm_id+"_input"); $input.attr("type", "text"); $input.addclass(options.inputclass); $input.attr("autocomplete", "off"); $input.attr("readonly", "readonly"); $input.attr("tabindex", $select.attr("tabindex")); // "i" capital is important for ie return $input; } function moveselect(step) { var lis = jquery("li", $container); if (!lis || lis.length == 0) return false; active += step; //loop through list if (active < 0) { active = lis.size(); } else if (active > lis.size()) { active = 0; } scroll(lis, active); lis.removeclass(opt.hoverclass); jquery(lis[active]).addclass(opt.hoverclass); } function scroll(list, active) { var el = jquery(list[active]).get(0); var list = $container.get(0); if (el.offsettop + el.offsetheight > list.scrolltop + list.clientheight) { list.scrolltop = el.offsettop + el.offsetheight - list.clientheight; } else if(el.offsettop < list.scrolltop) { list.scrolltop = el.offsettop; } } function setcurrent() { var li = jquery("li."+opt.currentclass, $container).get(0); var ar = (''+li.id).split('_'); var el = ar[ar.length-1]; $select.val(el); $input.val(jquery(li).html()); return true; } // select value function getcurrentselected() { return $select.val(); } // input value function getcurrentvalue() { return $input.val(); } function getselectoptions(parentid) { var select_options = new array(); var ul = document.createelement('ul'); $select.children('option').each(function() { var li = document.createelement('li'); li.setattribute('id', parentid + '_' + jquery(this).val()); li.innerhtml = jquery(this).html(); if (jquery(this).is(':selected')) { $input.val(jquery(this).html()); jquery(li).addclass(opt.currentclass); } ul.appendchild(li); jquery(li) .mouseover(function(event) { hasfocus = 1; if (opt.debug) console.log('over on : '+this.id); jquery(event.target, $container).addclass(opt.hoverclass); }) .mouseout(function(event) { hasfocus = -1; if (opt.debug) console.log('out on : '+this.id); jquery(event.target, $container).removeclass(opt.hoverclass); }) .click(function(event) { var fl = jquery('li.'+opt.hoverclass, $container).get(0); if (opt.debug) console.log('click on :'+this.id); jquery('li.'+opt.currentclass).removeclass(opt.currentclass); jquery(this).addclass(opt.currentclass); setcurrent(); //$select.change(); $select.get(0).blur(); hideme(); }); }); return ul; } };