Revision [8910]

This is an old revision of ArrayToList made by JavaWoman on 2005-06-07 11:24:19.

 

Generating a List from an Array


See also:
This page presents new code for the WikkaCore Wikka Core to generate well-structured lists from an array of items to be presented.

Why?


In many cases we get an array back from some procedure and want to display the result in the form of a list. In several places in the Wikka code this now happens "manually" in that each uses its own code to build the HTML to present the list. This is not only inefficient, but also leads to inconsistent and sometimes not even well-structured code. (Example: the TextSearch produces a numbered list of matching page names - but it is not only not sorted, it is not even an ordered list.)

Using a standard way to generate lists is more efficient, can ensure consistent code and makes it easier to write methods that need some kind of list as output.

How?


Two separate methods were written to make it easy to generate well-structured lists with 'hooks' for styling: the first does nothing but generate a list from an array (with an id); the second wraps that in a bit of code with a heading and a bit of text instead of the list if the array happens to be empty.

The Code


makeList()

This method does the hard work of creating an unordered or ordered list. It requires the makeId() method to be already present - see GenerateUniqueId.

Add the following code in the //MISC section right after the makeId() method:

makeList()
  1.     /**
  2.      * Build a list from an array.
  3.      *
  4.      * Given an array, this method builds a simple unordered or ordered list
  5.      * with an id.
  6.      * Only a (simple) array is required which will generate an
  7.      * unordered list; optionally id, class, type of list and an indent level
  8.      * can be specified. For type 'menu' an unordered list is generated but
  9.      * with an id in group 'menu' instead of 'ul' or 'ol': this enables the
  10.      * list being styled as a menu.
  11.      *
  12.      * @author      {@link http://wikka.jsnx.com/JavaWoman JavaWoman}
  13.      * @copyright   Copyright © 2005, Marjolein Katsma
  14.      * @license     http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  15.      * @version     0.8
  16.      *
  17.      * @todo    _ make maximum indent configurable
  18.      *          - support for nested lists (same type)
  19.      *          - support for definition lists
  20.      *          - support for internationalization (replace hard-coded strings)
  21.      *
  22.      * @access  public
  23.      * @uses    makeId()
  24.      *
  25.      * @param   array   $array  required: flat array with content items
  26.      * @param   mixed   $id     optional: id for the list, will be treated with makeId()
  27.      *                          or FALSE which suppresses id (for multiple-use elements)
  28.      * @param   string  $class  optional: class for (extra) styling
  29.      * @param   string  $type   optional: type of list to generate; default: ul
  30.      * @param   integer $indent optional: indent level
  31.      * @return  string  generated list
  32.      */
  33.     function makeList($array,$id='',$class='',$type='ul',$indent=0)
  34.     {
  35.         static $validate = TRUE;                                    # need to validate input
  36.         if (!defined('MAX_INDENT')) define('MAX_INDENT',20);        # @@@ make max configurable)
  37.         // definition
  38.         $aTypes = array('ul','ol','menu');                          # @@@ add dl later (menu generates ul)
  39.         // validate/treat input
  40.         if ($validate)
  41.         {
  42.             if (!is_array($array))
  43.             {
  44.                 return '<p class="error">Could not generate list: array required</p>'."\n";     # @@@ i18n
  45.             }
  46.             $type = (!in_array($type,$aTypes)) ? 'ul' : $type;
  47.             $class = trim(strip_tags($class));                      # minimum protection for user-supplied input
  48.             $indent = min(MAX_INDENT,abs((int)$indent));            # positive integer no larger than MAX_INDENT
  49.             $validate = FALSE;                                      # validation done: no need to repeat for recursion
  50.         }
  51.         // build element
  52.         $tag = ('menu' == $type) ? 'ul' : $type;
  53.         $ind = str_repeat("\t",$indent);
  54.         $attrId = (FALSE !== $id) ? ' id="'.$id = $this->makeId($type,$id).'"' : '';
  55.         $attrClass = ('' != $class) ? ' class="'.$class.'"' : '';
  56.         $out = $ind.'<'.$tag.$attrClass.$attrId.">\n";
  57.         foreach ($array as $item)
  58.         {
  59.             $out .= $ind.'  <li>';
  60.             if (!is_array($item))
  61.             {
  62.                 $out .= $item;
  63.             }
  64.             else
  65.             {
  66.                 # @@@ add recursion for nested lists
  67.                 $out .= 'nested list not yet supported';            # @@@ i18n;
  68.             }
  69.             $out .= "</li>\n";
  70.         }
  71.         $out .= $ind.'</'.$tag.">\n";
  72.         // return result
  73.         return $out;
  74.     }


makeMemberList()

This method is a wrapper around the makeList() method: it wraps the output in a div and adds a heading or outputs a paragraph of text in case the array turns out to be empty. It's meant for cases where items are to be presented as "members" of a collection; the heading is used to indicate the number of members.

There is deliberately no 'outer' div with an id: this is so a wrapper div may be created with a single heading containing several occurrences of the output of this method. Such a wrapper should be generated in the calling code.

Add the following code in the //MISC section right after the makeList() method:

makeMemberList()
  1.     /**
  2.      * Display members of a collection in a list. Wrapped in a div with a heading;
  3.      * alternatively output is just a paragraph of text in case the
  4.      * array provided turns out to be empty.
  5.      *
  6.      * There is deliberately no 'outer' div with an id: this is so a div may be
  7.      * created with a single heading containing several occurrences of the
  8.      * output of this method. Such a wrapper should be generated in the calling code.
  9.      *
  10.      * @todo    - allow suppression of the heading
  11.      *          - allow specification of list type (uses hardcoded 'menu' now)
  12.      *
  13.      * @author      {@link http://wikka.jsnx.com/JavaWoman JavaWoman}
  14.      * @copyright   Copyright © 2005, Marjolein Katsma
  15.      * @license     http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  16.      * @version     0.5
  17.      *
  18.      * @access  public
  19.      * @uses    makeId()
  20.      * @uses    makeList()
  21.      *
  22.      * @param   array   $array      required: flat array with collection items
  23.      * @param   string  $hd         required: heading for the list;
  24.      *                              should contain a %d placeholder for the number of items
  25.      * @param   string  $hdid       required: id for the heading (should be a constant,
  26.      *                              because the heading itself has variable content)
  27.      * @param   string  $id         required: id for the list itself
  28.      * @param   string  $txtnone    required: text to display when the array is empty
  29.      * @return  string  div containing heading and list, or paragraph
  30.      */
  31.     function makeMemberList($array,$hd,$hdid,$id,$txtnone)
  32.     {
  33.         $count = count($array);
  34.         $out = '';
  35.         if ($count > 0)
  36.         {
  37.             $out .= "   <div>\n";
  38.             $out .= '       <h6 id="'.$this->makeId('hn',$hdid).'">'.sprintf($hd,$count).'</h6>'."\n";
  39.             $out .= $this->makeList($array,$id,'','menu',2);
  40.             $out .= "   </div>\n";
  41.         }
  42.         else
  43.         {
  44.             $out .= '   <p>'.$txtnone.'</p>'."\n";
  45.         }
  46.         return $out;
  47.     }



When and where to use



Status


As can be seen from the @version numbers and @todo items in the docblocks, the code is far from "finished". An additional idea that just came up on TheLounge #wikka is to be able to specify the level of the heading generated by makeMemberList() (given that a page should already contain a h1 and h2 heading, only 3-6 should be allowed). However, the methods are quite functional to use as is.


CategoryDevelopmentCore
There are no comments on this page.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki