Hey there..

I've made a bunch of javascript related posts lately... sorry to bother you so much but I'm in development on another site and had to make a lot of additions/fixes to the script to make it usable. I was also thinking it might also be helpful for theming if there were more markup in the <li> that replaces the <select>

Below is an updated jquery_dropdown.js file, with the following fixes/additions:

  • Use of Drupal.behaviors
  • Fixed Regex on "select_name_nice" to allow arrayed field items
  • <h3> tags and <span> "indicator" with no break space (for down arrow?) markup
  • IE7 fix (hover out shouldn't close <ul>, because it triggers incorrectly in IE7
  • Click outside of <ul> closes box

Perhaps worth integrating?

/**
 * Steps:
 *
 * 1. Output a drupal select box by default so that if js is turned off the user would have a normal dropdown + submit form
 * 2. Give drupal a class of "jquery_dropdown"  
 * 3. Have jquery convert it to a hidden input and hide the submit
 * 4. Have jquery grab all the key/values from the select build the css/html markup that 'looks' like a dropdown
 * 5. Add a listener so when an item gets selected and populate the hidden value and submit the form to achieve the same functionality
 *
 **/
Drupal.behaviors.jquery_dropdown = function(context){
  //this does the actual css/html replacement of the select dropdown
  $("select.jquery_dropdown:not('.behaviors-processed')").each(function(){
    $(this).load_jquery_dropdown();//load jquery dropdowns
  }).addClass('behaviors-processed');
};


/**
 * Load jquery dropdown for a select
 *
 * This is a re-usable function for select elements that don't have the .jquery_dropdown class
 */
$.fn.load_jquery_dropdown = function(options) {
  if (!$(this).html()) return;
    
  $(this).hide();//hide this select
  
  //hide elements with jquery_dropdown class (in case you want to hide the submit button for instance)
  //for a better hide we have included .jquery_dropdown { display: none; } in the default css which keeps
  //the select from "flashing" on and off, the noscript tag inserted in hook_footer() keeps it from hiding
  //those elements when javascript is disabled to make it degrade gracefully
  $(".jquery_dropdown").hide();
  
  var select_id = $(this).attr('id');  
  var select_name = $(this).attr('name');
  var select_name_nice = select_name.replace(/[\[\"\]]/g,'-');//strip out [], replace with '-'
  console.log(select_name_nice);
  var select_default_value = $(this).val();
  var select_default_text = $(this).find('option[value='+select_default_value+']').text();
  
  var select_values = new Array();
  var c = 0;
  
  var output = '<div class="jquery_dropdown_container jquery_dropdown_'+select_name_nice+'">';
  
  var is_jumpdown = ($(this).attr('class').match("jquery_dropdown_jump")) ? 1 : 0;//for adding jump class if applicable
    
  //start with the first option
  output += '<div class="jquery_dropdown_header jquery_dropdown_header_'+select_name_nice+'"><h3><a href="javascript:void(0)">'+$(this).find("option:first").text()+'<span class="jquery_dropdown_indicator">&nbsp;</span></a></h3></div>';
  output += '<ul class="jquery_dropdown_list '+((is_jumpdown) ? 'jquery_dropdown_jump' : '') +'">';//start unordered list
  
  //build <ul> list here
  $(this).find("option").each(function(){
	var this_class="jquery_dropdown_option";
	if($(this).val()==select_default_value)
		this_class += " jquery_dropdown_option_selected";
		
    output += '<li class="'+this_class+'"><a href="#" class="'+select_id+'" rel="'+$(this).val()+'">'+$(this).text().replace(/ /g, '&nbsp;')+'</a></li>';
      
    c++;
  });
    
  output += '</ul></div>';
    
  $(this).after(output);
  
  
  
  //this is the click event for when you click the fake select, it shows the options below
  $("div.jquery_dropdown_header_"+select_name_nice).click(function(){
    console.log('clicked');
    if ($(this).parent("div.jquery_dropdown_container").find("ul.jquery_dropdown_list").css('display') == 'block') {
      $(this).parent("div.jquery_dropdown_container").find("ul.jquery_dropdown_list").attr('style', 'display:none');
    }
    else {
      $(this).parent("div.jquery_dropdown_container").find("ul.jquery_dropdown_list").attr('style', 'display:block');
	  $(document).click(function(y) {
		var $tgt = $(y.target);
			if (!$tgt.parents().is(".jquery_dropdown_container")) {
			   $("div.jquery_dropdown_container ul.jquery_dropdown_list").hide();
			   $(document).unbind("click");
			}
      });
    }
  });
  
  //this is the event for when you select a fake option
  $("ul.jquery_dropdown_list li a").click(function(){

    $(this).parent("li").parent('ul').parent("div.jquery_dropdown_container").find("div.jquery_dropdown_header h3 a").html($(this).html()+'<span class="jquery_dropdown_indicator">&nbsp;</span>');
    $(this).parent("li").parent('ul').parent("div.jquery_dropdown_container").find("ul.jquery_dropdown_list").hide();

    $("#"+$(this).attr('class')).val($(this).attr('rel'));//set value to select
   
    $(this).trigger("jquery_dropdown_list_refreshed");//trigger the onchange event of our drop down when we click a fake option
    $('#'+select_id).trigger("onchange");
	$(document).unbind("click");
   
    return false;
  });


  //set initial header value
  $("div.jquery_dropdown_header_"+select_name_nice+' a').html(select_default_text+'<span class="jquery_dropdown_indicator">&nbsp;</span>');
};

Comments

tmsimont’s picture

hmm I left a console.log in there.. also this update on the clic event of the header will cause other selects to collapse:

  //this is the click event for when you click the fake select, it shows the options below
  $("div.jquery_dropdown_header_"+select_name_nice).click(function(){
	  $("div.jquery_dropdown_container ul.jquery_dropdown_list").hide();
      $(this).parent("div.jquery_dropdown_container").find("ul.jquery_dropdown_list").attr('style', 'display:block');
	  $(document).click(function(y) {
		var $tgt = $(y.target);
			if (!$tgt.parents().is(".jquery_dropdown_container")) {
			   $("div.jquery_dropdown_container ul.jquery_dropdown_list").hide();
			   $(document).unbind("click");
			}
      });
  });