]> git.llucax.com Git - mecon/meconlib.git/blob - pear_lib_tmp/HTML/Table.php
9ea3fd2576c4bef6d178d6328287de468d779f9d
[mecon/meconlib.git] / pear_lib_tmp / HTML / Table.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.0 of the PHP license,       |
9 // | that is bundled with this package in the file LICENSE, and is        |
10 // | available at through the world-wide-web at                           |
11 // | http://www.php.net/license/2_02.txt.                                 |
12 // | If you did not receive a copy of the PHP license and are unable to   |
13 // | obtain it through the world-wide-web, please send a note to          |
14 // | license@php.net so we can mail you a copy immediately.               |
15 // +----------------------------------------------------------------------+
16 // | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
17 // |          Bertrand Mansion <bmansion@mamasam.com>                     |
18 // +----------------------------------------------------------------------+
19 //
20 // $Id$
21
22 require_once "PEAR.php";
23 require_once "HTML/Common.php";
24
25 /**
26  * Builds an HTML table
27  * @author        Adam Daniel <adaniel1@eesus.jnj.com>
28  * @author        Bertrand Mansion <bmansion@mamasam.com>
29  * @version       1.7
30  * @since         PHP 4.0.3pl1
31  */
32 class HTML_Table extends HTML_Common {
33
34     /**
35      * Automatically adds a new row or column if a given row or column index does not exist
36      * @var    bool
37      * @access private
38      */
39     var $_autoGrow = true;
40
41     /**
42      * Value to insert into empty cells
43      * @var    string
44      * @access private
45      */
46     var $_autoFill = "&nbsp;";
47
48     /**
49      * Array containing the table structure
50      * @var     array
51      * @access  private
52      */
53     var $_structure = array();
54
55     /**
56      * Number of rows composing in the table
57      * @var     int
58      * @access  private
59      */
60     var $_rows = 0;
61
62     /**
63      * Number of column composing the table
64      * @var     int
65      * @access  private
66      */
67     var $_cols = 0;
68
69     /**
70      * Tracks the level of nested tables
71      * @var    int
72      * @access private
73      */
74     var $_nestLevel = 0;
75
76     /**
77      * Class constructor
78      * @param    array    $attributes        Associative array of table tag attributes
79      * @param    int      $tabOffset
80      * @access   public
81      */
82     function HTML_Table($attributes = null, $tabOffset = 0)
83     {
84         $commonVersion = 1.7;
85         if (HTML_Common::apiVersion() < $commonVersion) {
86             return PEAR::raiseError("HTML_Table version " . $this->apiVersion() . " requires " .
87                 "HTML_Common version $commonVersion or greater.", 0, PEAR_ERROR_TRIGGER);
88         }
89         HTML_Common::HTML_Common($attributes, $tabOffset);
90     } // end constructor
91
92     /**
93      * Returns the API version
94      * @access  public
95      * @return  double
96      */
97     function apiVersion()
98     {
99         return 1.7;
100     } // end func apiVersion
101
102     /**
103      * Sets the table caption
104      * @param   string    $caption
105      * @param   mixed     $attributes        Associative array or string of table row attributes
106      * @access  public
107      */
108     function setCaption($caption, $attributes = null)
109     {
110         $attributes = $this->_parseAttributes($attributes);
111         $this->_structure["caption"] = array("attr" => $attributes, "contents" => $caption);
112     } // end func setCaption
113
114     /**
115      * Sets the autoFill value
116      * @param   mixed   $fill
117      * @access  public
118      */
119     function setAutoFill($fill)
120     {
121         $this->_autoFill = $fill;
122     } // end func setAutoFill
123
124     /**
125      * Returns the autoFill value
126      * @access   public
127      * @return   mixed
128      */
129     function getAutoFill()
130     {
131         return $this->_autoFill;
132     } // end func getAutoFill
133
134     /**
135      * Sets the autoGrow value
136      * @param    bool   $fill
137      * @access   public
138      */
139     function setAutoGrow($grow)
140     {
141         $this->_autoGrow = $grow;
142     } // end func setAutoGrow
143
144     /**
145      * Returns the autoGrow value
146      * @access   public
147      * @return   mixed
148      */
149     function getAutoGrow()
150     {
151         return $this->_autoGrow;
152     } // end func getAutoGrow
153
154     /**
155      * Sets the number of rows in the table
156      * @param    int     $rows
157      * @access   public
158      */
159     function setRowCount($rows)
160     {
161         $this->_rows = $rows;
162     } // end func setRowCount
163
164     /**
165      * Sets the number of columns in the table
166      * @param    int     $cols
167      * @access   public
168      */
169     function setColCount($cols)
170     {
171         $this->_cols = $cols;
172     } // end func setColCount
173
174     /**
175      * Returns the number of rows in the table
176      * @access   public
177      * @return   int
178      */
179     function getRowCount()
180     {
181         return $this->_rows;
182     } // end func getRowCount
183
184     /**
185      * Sets the number of columns in the table
186      * @access   public
187      * @return   int
188      */
189     function getColCount()
190     {
191         return $this->_cols;
192     } // end func getColCount
193
194     /**
195      * Sets a rows type 'TH' or 'TD'
196      * @param    int         $row    Row index
197      * @param    string      $type   'TH' or 'TD'
198      * @access   public
199      */
200
201     function setRowType($row, $type)
202     {
203         for ($counter = 0; $counter < $this->_cols; $counter++) {
204             $this->_structure[$row][$counter]["type"] = $type;
205         }
206     } // end func setRowType
207
208     /**
209      * Sets a columns type 'TH' or 'TD'
210      * @param    int         $col    Column index
211      * @param    string      $type   'TH' or 'TD'
212      * @access   public
213      */
214     function setColType($col, $type)
215     {
216         for ($counter = 0; $counter < $this->_rows; $counter++) {
217             $this->_structure[$counter][$col]["type"] = $type;
218         }
219     } // end func setColType
220
221     /**
222      * Sets the cell attributes for an existing cell.
223      *
224      * If the given indices do not exist and autoGrow is true then the given
225      * row and/or col is automatically added.  If autoGrow is false then an
226      * error is returned.
227      * @param    int        $row         Row index
228      * @param    int        $col         Column index
229      * @param    mixed      $attributes  Associative array or string of table row attributes
230      * @access   public
231      * @throws   PEAR_Error
232      */
233     function setCellAttributes($row, $col, $attributes)
234     {
235         if (isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return;
236         $attributes = $this->_parseAttributes($attributes);
237         $err = $this->_adjustEnds($row, $col, 'setCellAttributes', $attributes);
238         if (PEAR::isError($err)) {
239             return $err;
240         }
241         $this->_structure[$row][$col]["attr"] = $attributes;
242         $this->_updateSpanGrid($row, $col);
243     } // end func setCellAttributes
244
245     /**
246      * Updates the cell attributes passed but leaves other existing attributes in tact
247      * @param    int     $row         Row index
248      * @param    int     $col         Column index
249      * @param    mixed   $attributes  Associative array or string of table row attributes
250      * @access   public
251      */
252     function updateCellAttributes($row, $col, $attributes)
253     {
254         if (isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return;
255         $attributes = $this->_parseAttributes($attributes);
256         $err = $this->_adjustEnds($row, $col, 'updateCellAttributes', $attributes);
257         if (PEAR::isError($err)) {
258             return $err;
259         }
260         $this->_updateAttrArray($this->_structure[$row][$col]["attr"], $attributes);
261         $this->_updateSpanGrid($row, $col);
262     } // end func updateCellAttributes
263
264     /**
265      * Returns the attributes for a given cell
266      * @param    int     $row         Row index
267      * @param    int     $col         Column index
268      * @return   array
269      * @access   public
270      */
271     function getCellAttributes($row, $col)
272     {
273         if (isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] != '__SPANNED__') {
274             return $this->_structure[$row][$col]['attr'];
275         } elseif (!isset($this->_structure[$row][$col])) {
276             return PEAR::raiseError('Invalid table cell reference[' .
277                 $row . '][' . $col . '] in HTML_Table::getCellAttributes');
278         }
279         return;
280     } // end func getCellAttributes
281
282     /**
283      * Sets the cell contents for an existing cell
284      *
285      * If the given indices do not exist and autoGrow is true then the given
286      * row and/or col is automatically added.  If autoGrow is false then an
287      * error is returned.
288      * @param    int      $row        Row index
289      * @param    int      $col        Column index
290      * @param    mixed    $contents   May contain html or any object with a toHTML method
291      * @param    string   $type       (optional) Cell type either 'TH' or 'TD'
292      * @access   public
293      * @throws   PEAR_Error
294      */
295     function setCellContents($row, $col, $contents, $type = 'TD')
296     {
297         if(isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return;
298         $err = $this->_adjustEnds($row, $col, 'setCellContents');
299         if (PEAR::isError($err)) {
300             return $err;
301         }
302         $this->_structure[$row][$col]['contents'] = $contents;
303         $this->_structure[$row][$col]['type'] = $type;
304     } // end func setCellContents
305
306     /**
307      * Returns the cell contents for an existing cell
308      * @param    int        $row    Row index
309      * @param    int        $col    Column index
310      * @access   public
311      * @return   mixed
312      */
313     function getCellContents($row, $col)
314     {
315         if (isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return;
316         return $this->_structure[$row][$col]["contents"];
317     } // end func getCellContents
318
319     /**
320      * Sets the contents of a header cell
321      * @param    int     $row
322      * @param    int     $col
323      * @param    mixed   $contents
324      * @access   public
325      */
326     function setHeaderContents($row, $col, $contents)
327     {
328         $this->setCellContents($row, $col, $contents, 'TH');
329     } // end func setHeaderContents
330
331     /**
332      * Adds a table row and returns the row identifier
333      * @param    array    $contents   (optional) Must be a indexed array of valid cell contents
334      * @param    mixed    $attributes (optional) Associative array or string of table row attributes
335      *                                This can also be an array of attributes, in which case the attributes
336      *                                will be repeated in a loop.
337      * @param    string   $type       (optional) Cell type either 'TH' or 'TD'
338      * @param    bool     $inTR           false if attributes are to be applied in TD tags
339      *                                    true if attributes are to be applied in TR tag
340      * @return   int
341      * @access   public
342      */
343     function addRow($contents = null, $attributes = null, $type = 'TD', $inTR = false)
344     {
345         if (isset($contents) && !is_array($contents)) {
346             return PEAR::raiseError("First parameter to HTML_Table::addRow must be an array");
347         }
348         $row = $this->_rows++;
349         for ($counter = 0; $counter < count($contents); $counter++) {
350             if ($type == 'TD') {
351                 $this->setCellContents($row, $counter, $contents[$counter]);
352             } elseif ($type == 'TH') {
353                 $this->setHeaderContents($row, $counter, $contents[$counter]);
354             }
355         }
356         $this->setRowAttributes($row, $attributes, $inTR);
357         return $row;
358     } // end func addRow
359
360     /**
361      * Sets the row attributes for an existing row
362      * @param    int      $row            Row index
363      * @param    mixed    $attributes     Associative array or string of table row attributes
364      *                                    This can also be an array of attributes, in which case the attributes
365      *                                    will be repeated in a loop.
366      * @param    bool     $inTR           false if attributes are to be applied in TD tags
367      *                                    true if attributes are to be applied in TR tag
368      * @access   public
369      * @throws   PEAR_Error
370      */
371     function setRowAttributes($row, $attributes, $inTR = false)
372     {
373         $multiAttr = $this->_isAttributesArray($attributes);
374         if (!$inTR) {
375             for ($i = 0; $i < $this->_cols; $i++) {
376                 if ($multiAttr) {
377                     $this->setCellAttributes($row, $i,
378                         $attributes[$i - ((ceil(($i+1) / count($attributes)))-1) * count($attributes)]);
379                 } else {
380                     $this->setCellAttributes($row, $i, $attributes);
381                 }
382             }
383         } else {
384             $attributes = $this->_parseAttributes($attributes);
385             $err = $this->_adjustEnds($row, 1, 'setRowAttributes', $attributes);
386             if (PEAR::isError($err)) {
387                 return $err;
388             }
389             $this->_structure[$row]['attr'] = $attributes;
390         }
391     } // end func setRowAttributes
392
393     /**
394      * Updates the row attributes for an existing row
395      * @param    int      $row            Row index
396      * @param    mixed    $attributes     Associative array or string of table row attributes
397      * @param    bool     $inTR           false if attributes are to be applied in TD tags
398      *                                    true if attributes are to be applied in TR tag
399      * @access   public
400      * @throws   PEAR_Error
401      */
402     function updateRowAttributes($row, $attributes = null, $inTR = false)
403     {
404         $multiAttr = $this->_isAttributesArray($attributes);
405         if (!$inTR) {
406             for ($i = 0; $i < $this->_cols; $i++) {
407                 if ($multiAttr) {
408                     $this->updateCellAttributes($row, $i,
409                         $attributes[$i - ((ceil(($i+1) / count($attributes)))-1) * count($attributes)]);
410                 } else {
411                     $this->updateCellAttributes($row, $i, $attributes);
412                 }
413             }
414         } else {
415             $attributes = $this->_parseAttributes($attributes);
416             $err = $this->_adjustEnds($row, 1, 'updateRowAttributes', $attributes);
417             if (PEAR::isError($err)) {
418                 return $err;
419             }
420             $this->_updateAttrArray($this->_structure[$row]['attr'], $attributes);
421         }
422     } // end func updateRowAttributes
423
424     /**
425      * Returns the attributes for a given row as contained in the TR tag
426      * @param    int     $row         Row index
427      * @return   array
428      * @access   public
429      */
430     function getRowAttributes($row)
431     {
432         if (isset($this->_structure[$row]['attr'])) {
433             return $this->_structure[$row]['attr'];
434         }
435         return;
436     } // end func getRowAttributes
437
438     /**
439      * Alternates the row attributes starting at $start
440      * @param    int      $start          Row index of row in which alternating begins
441      * @param    mixed    $attributes1    Associative array or string of table row attributes
442      * @param    mixed    $attributes2    Associative array or string of table row attributes
443      * @param    bool     $inTR           false if attributes are to be applied in TD tags
444      *                                    true if attributes are to be applied in TR tag
445      * @access   public
446      */
447     function altRowAttributes($start, $attributes1, $attributes2, $inTR = false)
448     {
449         for ($row = $start ; $row < $this->_rows ; $row++) {
450             $attributes = ( ($row+$start)%2 == 0 ) ? $attributes1 : $attributes2;
451             $this->updateRowAttributes($row, $attributes, $inTR);
452         }
453     } // end func altRowAttributes
454
455     /**
456      * Adds a table column and returns the column identifier
457      * @param    array    $contents   (optional) Must be a indexed array of valid cell contents
458      * @param    mixed    $attributes (optional) Associative array or string of table row attributes
459      * @param    string   $type       (optional) Cell type either 'TH' or 'TD'
460      * @return   int
461      * @access   public
462      */
463     function addCol($contents = null, $attributes = null, $type = 'TD')
464     {
465         if (isset($contents) && !is_array($contents)) {
466             return PEAR::raiseError("First parameter to HTML_Table::addCol must be an array");
467         }
468         $col = $this->_cols++;
469         for ($counter = 0; $counter < count($contents); $counter++) {
470             $this->setCellContents($counter, $col, $contents[$counter], $type);
471         }
472         $this->setColAttributes($col, $attributes);
473         return $col;
474     } // end func addCol
475
476     /**
477      * Sets the column attributes for an existing column
478      * @param    int      $col            Column index
479      * @param    mixed    $attributes     (optional) Associative array or string of table row attributes
480      * @access   public
481      */
482     function setColAttributes($col, $attributes = null)
483     {
484         $multiAttr = $this->_isAttributesArray($attributes);
485         for ($i = 0; $i < $this->_rows; $i++) {
486             if ($multiAttr) {
487                 $this->setCellAttributes($i, $col,
488                     $attributes[$i - ((ceil(($i+1) / count($attributes)))-1) * count($attributes)]);
489             } else {
490                 $this->setCellAttributes($i, $col, $attributes);
491             }
492         }
493     } // end func setColAttributes
494
495     /**
496      * Updates the column attributes for an existing column
497      * @param    int      $col            Column index
498      * @param    mixed    $attributes     (optional) Associative array or string of table row attributes
499      * @access   public
500      */
501     function updateColAttributes($col, $attributes = null)
502     {
503         $multiAttr = $this->_isAttributesArray($attributes);
504         for ($i = 0; $i < $this->_rows; $i++) {
505             if ($multiAttr) {
506                 $this->updateCellAttributes($i, $col,
507                     $attributes[$i - ((ceil(($i+1) / count($attributes)))-1) * count($attributes)]);
508             } else {
509                 $this->updateCellAttributes($i, $col, $attributes);
510             }
511         }
512     } // end func updateColAttributes
513
514     /**
515      * Sets the attributes for all cells
516      * @param    mixed    $attributes        (optional) Associative array or string of table row attributes
517      * @access   public
518      */
519     function setAllAttributes($attributes = null)
520     {
521         for ($i = 0; $i < $this->_rows; $i++) {
522             $this->setRowAttributes($i, $attributes);
523         }
524     } // end func setAllAttributes
525
526     /**
527      * Updates the attributes for all cells
528      * @param    mixed    $attributes        (optional) Associative array or string of table row attributes
529      * @access   public
530      */
531     function updateAllAttributes($attributes = null)
532     {
533         for ($i = 0; $i < $this->_rows; $i++) {
534             $this->updateRowAttributes($i, $attributes);
535         }
536     } // end func updateAllAttributes
537
538     /**
539      * Returns the table structure as HTML
540      * @access  public
541      * @return  string
542      */
543     function toHtml()
544     {
545         $strHtml = '';
546         $tabs = $this->_getTabs();
547         $tab = $this->_getTab();
548         $lnEnd = $this->_getLineEnd();
549         if ($this->_comment) {
550             $strHtml .= $tabs . "<!-- $this->_comment -->" . $lnEnd;
551         }
552         $strHtml .=
553             $tabs . "<table" . $this->_getAttrString($this->_attributes) . ">" . $lnEnd;
554         if (!empty($this->_structure["caption"])) {
555             $attr = $this->_structure["caption"]["attr"];
556             $contents = $this->_structure["caption"]["contents"];
557             $strHtml .= $tabs . $tab . "<caption" . $this->_getAttrString($attr) . ">";
558             if (is_array($contents)) $contents = implode(", ", $contents);
559             $strHtml .= $contents;
560             $strHtml .= "</caption>" . $lnEnd;
561         }
562         for ($i = 0 ; $i < $this->_rows ; $i++) {
563             if (isset($this->_structure[$i]['attr'])) {
564                 $strHtml .= $tabs . $tab . "<tr".$this->_getAttrString($this->_structure[$i]['attr']).">" . $lnEnd;
565             } else {
566                 $strHtml .= $tabs .$tab . "<tr>" . $lnEnd;
567             }
568             for ($j = 0 ; $j < $this->_cols ; $j++) {
569                 if (isset($this -> _structure[$i][$j]) && $this->_structure[$i][$j] == "__SPANNED__") {
570                     $strHtml .= $tabs . $tab . $tab ."<!-- span -->" . $lnEnd;
571                     continue;
572                 }
573                 if (isset($this->_structure[$i][$j]["type"])) {
574                     $type = (strtoupper($this->_structure[$i][$j]["type"]) == "TH" ? "th" : "td");
575                 } else {
576                     $type = "td";
577                 }
578                 if (isset($this->_structure[$i][$j]["attr"])) {
579                     $attr = $this->_structure[$i][$j]["attr"];
580                 } else {
581                     $attr = "";
582                 }
583                 if (isset($this->_structure[$i][$j]["contents"])) {
584                     $contents = $this->_structure[$i][$j]["contents"];
585                 } else {
586                     $contents = "";
587                 }
588                 $strHtml .= $tabs . $tab . $tab . "<$type" . $this->_getAttrString($attr) . ">";
589                 if (is_object($contents)) {
590                     // changes indent and line end settings on nested tables
591                     if (is_subclass_of($contents, "html_common")) {
592                         $contents->setTab($tab);
593                         $contents->setTabOffset($this->_tabOffset + 3);
594                         $contents->_nestLevel = $this->_nestLevel + 1;
595                         $contents->setLineEnd($this->_getLineEnd());
596                     }
597                     if (method_exists($contents, "toHtml")) {
598                         $contents = $contents->toHtml();
599                     } elseif (method_exists($contents, "toString")) {
600                         $contents = $contents->toString();
601                     }
602                 }
603                 if (is_array($contents)) {
604                     $contents = implode(", ",$contents);
605                 }
606                 if (isset($this->_autoFill) && $contents == "") {
607                     $contents = $this->_autoFill;
608                 }
609                 $strHtml .= $contents;
610                 $strHtml .= "</$type>" . $lnEnd;
611             }
612             $strHtml .= $tabs . $tab . "</tr>" . $lnEnd;
613         }
614         $strHtml .= $tabs . "</table>" . $lnEnd;
615         return $strHtml;
616     } // end func toHtml
617
618     /**
619      * Checks if rows or columns are spanned
620      * @param    int        $row            Row index
621      * @param    int        $col            Column index
622      * @access   private
623      */
624     function _updateSpanGrid($row, $col)
625     {
626         if (isset($this->_structure[$row][$col]["attr"]["colspan"])) {
627             $colspan = $this->_structure[$row][$col]["attr"]["colspan"];
628         }
629         if (isset($this->_structure[$row][$col]["attr"]["rowspan"])) {
630             $rowspan = $this->_structure[$row][$col]["attr"]["rowspan"];
631         }
632         if (isset($colspan)) {
633             for ($j = $col+1; (($j < $this->_cols) && ($j <= ($col + $colspan - 1))); $j++) {
634                 $this->_structure[$row][$j] = "__SPANNED__";
635             }
636         }
637         if (isset($rowspan)) {
638             for ($i = $row+1; (($i < $this->_rows) && ($i <= ($row + $rowspan - 1))); $i++) {
639                 $this->_structure[$i][$col] = "__SPANNED__";
640             }
641         }
642         if (isset($colspan) && isset($rowspan)) {
643             for ($i = $row+1; (($i < $this->_rows) && ($i <= ($row + $rowspan - 1))); $i++) {
644                 for ($j = $col+1; (($j <= $this->_cols) && ($j <= ($col + $colspan - 1))); $j++) {
645                     $this->_structure[$i][$j] = "__SPANNED__";
646                 }
647             }
648         }
649     } // end func _updateSpanGrid
650
651     /**
652     * Adjusts ends (total number of rows and columns)
653     * @param    int     $row        Row index
654     * @param    int     $col        Column index
655     * @param    string  $method     Method name of caller
656     *                               Used to populate PEAR_Error if thrown.
657     * @param    array   $attributes Assoc array of attributes
658     *                               Default is an empty array.
659     * @access   private
660     * @throws   PEAR_Error
661     */
662     function _adjustEnds($row, $col, $method, $attributes = array())
663     {
664         $colspan = isset($attributes['colspan']) ? $attributes['colspan'] : 1;
665         $rowspan = isset($attributes['rowspan']) ? $attributes['rowspan'] : 1;
666         if (($row + $rowspan - 1) >= $this->_rows) {
667             if ($this->_autoGrow) {
668                 $this->_rows = $row + $rowspan;
669             } else {
670                 return PEAR::raiseError('Invalid table row reference[' .
671                     $row . '] in HTML_Table::' . $method);
672             }
673         }
674         if (($col + $colspan - 1) >= $this->_cols) {
675             if ($this->_autoGrow) {
676                 $this->_cols = $col + $colspan;
677             } else {
678                 return PEAR::raiseError('Invalid table column reference[' .
679                     $col . '] in HTML_Table::' . $method);
680             }
681         }
682     } // end func _adjustEnds
683
684     /**
685     * Tells if the parameter is an array of attribute arrays/strings
686     * @param    mixed   $attributes Variable to test
687     * @access   private
688     * @return   bool
689     */
690     function _isAttributesArray($attributes)
691     {
692         if (is_array($attributes) && isset($attributes[0])) {
693             if (is_array($attributes[0]) || (is_string($attributes[0]) && count($attributes) > 1)) {
694                 return true;
695             }
696         }
697         return false;
698     } // end func _isAttributesArray
699 } // end class HTML_Table
700 ?>