Joomla Select Options with Style

add Style and Attributes to Joomla Select Options.

A brief tutorial to show how to style individual options within a select.genericlist.

The Joomla html library includes the class select which can be used to generate groups of radio or combo buttons and select boxes.

With increasing ajax requirements it is often necessary to perform some logic on the client forms.

When selects come into play, we often have to resort to ajax calls to update some controls depending on which option is selected.

Adding some extra params to the options allows to create easier interactive code that manipulates them with a single jQuery('option.myclass'), in combination with some css.

To create a select box we use the function:

PHP Code:
JHTML::_('select.genericlist',...);

which invokes the method genericlist() in /libraries/joomla/html/html/select.php

and we have two ways of providing the structure which holds the options:

a) create an array of objects each having, at least, two properties: value and text;

b) create individual options with a call to JHTML:: _('select.option',...);

While the first approach is very handy when creating a lookup list straight from the database:

PHP Code:
  1. $db->setQuery('SELECT alias AS value, title AS text FROM #__content ');
  2. $arts = $db->loadObjectList();
  3. echo JHTML::_('select.genericlist','','article',array('class'=>'arts');

the second is by far more common:

PHP Code:
  1. $listOptions[] = JHTML::_('select.option', '1', 'some text n.1' );
  2. echo JHTML::_('select.genericlist', $listingTypesOptions, 'article',

Get to the point. How do I style the options?

Depending on your situation (case a. or case b.) you need to follow a different approach.

The solution to case a. was presented http://stackoverflow.com/questions/10918584/adding-attributes-to-select-options-in-joomla.

Regarding case b., I wasn't able to find a satisfactory (i.e. Working) answer anywhere, so I gathered some tips here http://joomla-support.ru/archive/index.php/t-29437.html and looking at the source code of select.php. Without further ado, the code:

This comes from a real project, loading the listing types of the joomlistings component.

PHP Code:
  1. /**
  2.  * Builds the select and options for the listing types.
  3.  * the listing types are styled based on their aliases for usage by jQuery in the
  4.  * gshare module's view and adcustom's view post.
  5.  *
  6.  * @param unknown_type $selectName
  7.  * @param unknown_type $listingTypes the array coming from a db query -
  8.  loadObjectList which holds the values of the listing types.
  9.  * @param unknown_type $selectedValue the (pre)selected value
  10.  * @param unknown_type $tooltip the tooltip for the select;
  11.  * @param unknown_type $extraClass an extra css class (or classes) to be added to the select
  12.  * @param unknown_type $translatePrefix the alias will be prefixed by this string before attempting to translate it
  13.  * @param unknown_type $createEmpty should I create an empty option at the very top? this would be its text.
  14.  * @return Ambigous <mixed, boolean>
  15.  */
  16. function getListingTypesHTML($selectName,$listingTypes,$selectedValue,$tooltip,$extraClass,$createEmpty=false) {
  17. $listsHTMLAttrs = array('title'=>$tooltip, 'class'=>$extraClass);
  18. /* the options.attr is tricky: it needs to be a string token and it must be identical
  19.   * for each option and the select attributes. Here I chose extraOptionAttributes,
  20.   * all that's required is that the two match. */
  21. $listsAttrs = array('id'=>$selectName,'list.attr'=>$listsHTMLAttrs,
  22. 'list.select'=>$selectedValue,
  23. 'option.attr'=>'extraOptionAttributes');
  24. $listingTypesOptions = array();
  25. if ($createEmpty) {
  26. // style the first option control:
  27. $optionsHTMLAttrs = array('class'=>'emptyoption');
  28. //, 'title'=>'option sample title');
  29. $optionsAttrs = array('attr'=>$optionsHTMLAttrs,
  30. 'option.attr'=>'extraOptionAttributes');
  31. $listingTypesOptions[] = JHTML::_('select.option', '', $createEmpty,
  32. $optionsAttrs );
  33. }
  34. foreach ($listingTypes as $listingType) {
  35. /**
  36.   * To make selections simpler in the jQuery manipulations, I need to
  37.   * - preselect the right options based on tourist / residential current option
  38.   * - add a meaningful class to options so I may add/remove top level classes and
  39.   * automatically show/hide
  40.   * the options (much like price_to extra-7 is toggled in the gshare.php view)
  41.   */
  42. $alias = $listingType->alias;
  43. if (strpos($alias,'search_')===0) {
  44. // only residential:
  45. $className = 'search residential';
  46. } else { // both tourist and residential:
  47. $className = 'rent ';
  48. if (strpos($alias,'_bb') || strpos($alias,'_couch')) {
  49. $className .= 'tourist';
  50. } else {
  51. $className .= 'residential';
  52. }
  53. }
  54. $className .= " $alias";
  55. $optionsHTMLAttrs = array('class'=>$className);
  56. $optionsAttrs = array('attr'=>$optionsHTMLAttrs,
  57. 'option.attr'=>'extraOptionAttributes');
  58. $listingTypesOptions[] = JHTML::_('select.option', $listingType->alias,
  59. $listingType->alias, $optionsAttrs );
  60. }
  61. return JHTML::_('select.genericlist', $listingTypesOptions,
  62. $selectName, $listsAttrs);
  63. }

Invoking this function

This function is invoked like this:

PHP Code:
  1. $listingTypes=modJLGshareSearchHelper::getListingTypes();
  2. $selectName = 'listingtype';
  3. $listingTypesHTML = modJLGshareSearchHelper::getListingTypesHTML('listingtype',$listingTypes,JRequest::getVar('listingtype',''),JText::_('SEARCHBOX_LISTINGTYPE_DESC',''),'styled',JText::_('SEARCH_LISTING_TYPE'));



And the $listingTypes is the result of loadObjectList() from the database:

PHP Code:
  1. /**
  2.  * return a list of available Listing Types (see administrator>listings->listing types
  3.  * @return Ambigous <mixed, NULL, multitype:unknown mixed >
  4.  */
  5. function getListingTypes()
  6. {
  7. $db=JFactory::getDBO();
  8. $query="SELECT id, title, alias, description FROM #__jltypes
  9. WHERE published='1' ORDER BY ordering";
  10. $db->setQuery($query);
  11. return $db->loadObjectList();
  12. }

HTML representation:

This piece of code generates the following markup

HTML Code:
  1. <select id="listingtype" class="styled emptyoption custom-hidden-select" style="width: 99px;" title="Choose the listing type you are searching" name="listingtype"><option class="emptyoption" selected="selected" value="">what...</option><option class="rent residential rent_room" value="rent_room">Room in shared house</option><option class="rent residential rent_house" value="rent_house">Whole apartment</option><option class="search residential search_room" value="search_room">People with whom I will share my house</option><option class="search residential search_house" value="search_house">Tenants for an empty house</option><option class="rent tourist rent_bb" value="rent_bb">Bed &amp; breakfast</option><option class="rent tourist rent_couch" value="rent_couch">Couch Surfing</option>
  2. </select>

The result:

This is what I achieve with a simple jQuery script which toggles a class on the form container and a css which – based on the classes combination – shows or hides selected options:

As you can see, some options are toggled (shown/hidden) when the radio button above are clicked.

The radio button is bound to a jQuery function which will toggle the class of the div containing the select:

Javascript Code:
  1. jQuery("div.topsearchbuttons input").change(function(obj) {
  2. isTourist = (jQuery("div.topsearchbuttons input[name='srctourist']:checked").val()=='tourist');
  3. if (isTourist) {
  4. jQuery("div#searchconditions").addClass('style-tourist').removeClass('style-residential');
  5. } else {
  6. jQuery("div#searchconditions").removeClass('style-tourist').addClass('style-residential');
  7. }
  8. });

The css does the rest:

CSS Code:
div#searchconditions.style-residential select#listingtype option.tourist {display:none}

See it in action

Live on www.gay-houseshare.com

A word of caution

While this approach is effective, the way different browsers display styled options varies, so you should use a different type of control to ensure proper display. Even at the end of 2012 most browsers don't support transparent colors (rgba) as background of options.

If you choose to use a select box, which is excellent for accessibility and compatibility, there are neat scripts that will replace the select with different components, often inheriting the classes and behaviour (click etc.) of the original selects and options, making these approaches very compatible with the code presented. Some of these tools include jquery.ui.cutom.select
http://www.georgepaterson.com/sandbox/jquery-ui-custom-select-demo/

and selectBox:

http://labs.abeautifulsite.net/jquery-selectBox/