]> git.llucax.com Git - mecon/meconlib.git/blob - pear_lib_tmp/HTML/Page.php
Se arreglan bugs y se hace que en el addBodyContent() se busquen metodos
[mecon/meconlib.git] / pear_lib_tmp / HTML / Page.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997 - 2003 The PHP Group                              |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 3.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/3_0.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 // |          Klaus Guenther <klaus@capitalfocus.org>                     |
18 // +----------------------------------------------------------------------+
19 //
20 // $Id$
21
22 require_once 'PEAR.php';
23 require_once 'HTML/Common.php';
24 // HTML/Page/Doctypes.php is required in _getDoctype()
25
26 /**
27  * Base class for XHTML pages
28  *
29  * This class handles the details for creating a properly constructed XHTML page.
30  * Page caching, stylesheets, client side script, and Meta tags can be
31  * managed using this class.
32  * 
33  * The body may be a string, object, or array of objects or strings. Objects with
34  * toHtml() and toString() methods are supported.
35  * 
36  *
37  * XHTML Examples:
38  * ---------------
39  *
40  * Simplest example:
41  * -----------------
42  * <code>
43  * // the default doctype is XHTML 1.0 Transitional
44  * // All doctypes and defaults are set in HTML/Page/Doctypes.php
45  * $p = new HTML_Page();
46  *
47  * //add some content
48  * $p->addBodyContent("<p>some text</p>");
49  *
50  * // print to browser
51  * $p->display();
52  * </code>
53  * 
54  * Complex XHTML example:
55  * ----------------------
56  * <code>
57  * // The initializing code can also be in in the form of an HTML
58  * // attr="value" string.
59  * // Possible attributes are: charset, lineend, tab, doctype, language and cache
60  * 
61  * $p = new HTML_Page(array (
62  *
63  *                          // Sets the charset encoding
64  *                          // utf-8 is default
65  *                          'charset'  => 'utf-8',
66  *
67  *                          // Sets the line end character
68  *                          // unix (\n) is default
69  *                          'lineend'  => 'unix',
70  *
71  *                          // Sets the tab string for autoindent
72  *                          // tab (\t) is default
73  *                          'tab'  => '  ',
74  *
75  *                          // This is where you define the doctype
76  *                          'doctype'  => "XHTML 1.0 Strict",
77  *
78  *                          // Global page language setting
79  *                          'language' => 'en',
80  *
81  *                          // If cache is set to true, the browser may
82  *                          // cache the output. Else 
83  *                          'cache'    => 'false'
84  *                          ));
85  *
86  * // Here we go
87  *
88  * // Set the page title
89  * $p->setTitle("My page");
90  * 
91  * // Add optional meta data
92  * $p->addMetaData("author", "My Name");
93  * 
94  * // Put something into the body
95  * $p->addBodyContent = "<p>some text</p>";
96  *
97  * // If at some point you want to clear the page content
98  * // and output an error message, you can easily do that
99  * // See the source for {@link toHtml} and {@link _getDoctype}
100  * // for more details
101  * if ($error) {
102  *     $p->setTitle("Error!");
103  *     $p->setBodyContent("<p>oops, we have an error: $error</p>");
104  *     $p->display();
105  *     die;
106  * } // end error handling
107  *
108  * // print to browser
109  * $p->display();
110  * </code>
111  * 
112  * Simple XHTML declaration example:
113  * <code>
114  * $p = new HTML_Page();
115  * // An XHTML compliant page (with title) is automatically generated
116  *
117  * // This overrides the XHTML 1.0 Transitional default
118  * $p->setDoctype('XHTML 1.0 Strict');
119  * 
120  * // Put some content in here
121  * $p->addBodyContent("<p>some text</p>");
122  *
123  * // print to browser
124  * $p->display();
125  * </code>
126  * 
127  *
128  * HTML examples:
129  * --------------
130  *
131  * HTML 4.01 example:
132  * ------------------
133  * <code>
134  * $p = new HTML_Page('doctype="HTML 4.01 Strict"');
135  * $p->addBodyContent = "<p>some text</p>";
136  * $p->display();
137  * </code>
138  * 
139  * nuke doctype declaration:
140  * -------------------------
141  * <code>
142  * $p = new HTML_Page('doctype="none"');
143  * $p->addBodyContent = "<p>some text</p>";
144  * $p->display();
145  * </code>
146  * 
147  * @author       Adam Daniel <adaniel1@eesus.jnj.com>
148  * @author       Klaus Guenther <klaus@capitalfocus.org>
149  * @version      2.0
150  * @since        PHP 4.0.3pl1
151  */
152 class HTML_Page extends HTML_Common {
153     
154     /**
155      * Contains the content of the &lt;body&gt; tag.
156      * 
157      * @var     array
158      * @access  private
159      */
160     var $_body = array();
161     
162     /**
163      * Controls caching of the page
164      * 
165      * @var     bool
166      * @access  private
167      */
168     var $_cache = false;
169     
170     /**
171      * Contains the character encoding string
172      * 
173      * @var     string
174      * @access  private
175      */
176     var $_charset = 'utf-8';
177     
178     /**
179      * Contains the !DOCTYPE definition
180      * 
181      * @var array
182      * @access private
183      */
184     var $_doctype = array('type'=>'xhtml','version'=>'1.0','variant'=>'transitional');
185     
186     /**
187      * Contains the page language setting
188      * 
189      * @var     string
190      * @access  private
191      */
192     var $_language = 'en';
193     
194     /**
195      * Array of meta tags
196      * 
197      * @var     array
198      * @access  private
199      */
200     var $_metaTags = array( 'standard' => array ( 'Generator' => 'PEAR HTML_Page' ) );
201     
202     /**
203      * Array of linked scripts
204      * 
205      * @var  array
206      * @access   private
207      */
208     var $_scripts = array();
209     
210     /**
211      * Array of linked scripts
212      * 
213      * @var     array
214      * @access  private
215      */
216     var $_simple = false;
217     
218     /**
219      * Array of included style declarations
220      * 
221      * @var     array
222      * @access  private
223      */
224     var $_style = array();
225     
226     /**
227      * Array of linked style sheets
228      * 
229      * @var     array
230      * @access  private
231      */
232     var $_styleSheets = array();
233     
234     /**
235      * HTML page title
236      * 
237      * @var     string
238      * @access  private
239      */
240     var $_title = '';
241     
242     /**
243      * Class constructor
244      * Possible attributes are:
245      * - general options:
246      *     - "lineend" => "unix|win|mac" (Sets line ending style; defaults to unix.)
247      *     - "tab" => string (Sets line ending style; defaults to \t.)
248      *     - "cache"   => "false|true"
249      *     - "charset" => charset string (Sets charset encoding; defaults to utf-8)
250      * - XHTML specific:
251      *     - "doctype"  => mixed (Sets XHTML doctype; defaults to XHTML 1.0 Transitional.)
252      *     - "language" => two letter language designation. (Defines global document language; defaults to "en".)
253      * 
254      * @param   mixed   $attributes     Associative array of table tag attributes
255      *                                  or HTML attributes name="value" pairs
256      * @access  public
257      */
258     function HTML_Page($attributes = "")
259     {
260         $commonVersion = 1.7;
261         if (HTML_Common::apiVersion() < $commonVersion) {
262             return PEAR::raiseError("HTML_Page version " . $this->apiVersion() . " requires " .
263                 "HTML_Common version 1.2 or greater.", 0, PEAR_ERROR_TRIGGER);
264         }
265         
266         if ($attributes) {
267             $attributes = $this->_parseAttributes($attributes);
268         }
269         
270         if (isset($attributes['lineend'])) {
271             $this->setLineEnd($attributes['lineend']);
272         }
273         
274         if (isset($attributes['charset'])) {
275             $this->setCharset($attributes['charset']);
276         }
277         
278         if (isset($attributes['doctype'])){
279             if ($attributes['doctype'] == 'none') {
280                 $this->_simple = true;
281             } elseif ($attributes['doctype']) {
282                 $this->setDoctype($attributes['doctype']);
283             }
284         }
285         
286         if (isset($attributes['language'])) {
287             $this->setLang($attributes['language']);
288         }
289         
290         if (isset($attributes['cache'])) {
291             $this->setCache($attributes['cache']);
292         }
293         
294     }
295     
296     /**
297      * Generates the HTML string for the &lt;body&lt; tag
298      * 
299      * @access  private
300      * @return  string
301      */
302     function _generateBody()
303     {
304         
305         // get line endings
306         $lnEnd = $this->_getLineEnd();
307         $tab = $this->_getTab();
308         
309         // If body attributes exist, add them to the body tag.
310         // Depreciated because of CSS
311         $strAttr = $this->_getAttrString($this->_attributes);
312         
313         if ($strAttr) {
314             $strHtml = "<body $strAttr>" . $lnEnd;
315         } else {
316             $strHtml = '<body>' . $lnEnd;
317         }
318         
319         // Allow for mixed content in the body array
320         // Iterate through the array and process each element
321         foreach ($this->_body as $element) {
322             if (is_object($element)) {
323                 if (is_subclass_of($element, "html_common")) {
324                     $element->setTab($tab);
325                     $element->setTabOffset(1);
326                     $element->setLineEnd($lnEnd);
327                 }
328                 if (method_exists($element, "toHtml")) {
329                     $strHtml .= $element->toHtml() . $lnEnd;
330                 } elseif (method_exists($element, "toString")) {
331                     $strHtml .= $element->toString() . $lnEnd;
332                 }
333             } elseif (is_array($element)) {
334                 foreach ($element as $level2) {
335                     if (is_subclass_of($level2, "html_common")) {
336                         $level2->setTabOffset(1);
337                         $level2->setTab($tab);
338                         $level2->setLineEnd($lnEnd);
339                     }
340                     if (is_object($level2)) {
341                         if (method_exists($level2, "toHtml")) {
342                             $strHtml .= $level2->toHtml() . $lnEnd;
343                         } elseif (method_exists($level2, "toString")) {
344                             $strHtml .= $level2->toString() . $lnEnd;
345                         }
346                     } else {
347                         $strHtml .= $tab . $level2 . $lnEnd;
348                     }
349                 }
350             } else {
351                 $strHtml .= $tab . $element . $lnEnd;
352             }
353         }
354         
355         // Close tag
356         $strHtml .= '</body>' . $lnEnd;
357         
358         // Let's roll!
359         return $strHtml;
360     } // end func _generateHead
361     
362     /**
363      * Generates the HTML string for the &lt;head&lt; tag
364      * 
365      * @return string
366      * @access private
367      */
368     function _generateHead()
369     {
370         
371         // get line endings
372         $lnEnd = $this->_getLineEnd();
373         $tab = $this->_getTab();
374         
375         $strHtml  = '<head>' . $lnEnd;
376         $strHtml .= $tab . '<title>' . $this->getTitle() . '</title>' . $lnEnd;
377         
378         // Generate META tags
379         foreach ($this->_metaTags as $type => $tag) {
380             foreach ($tag as $name => $content) {
381                 if ($type == 'http-equiv') {
382                     $strHtml .= $tab . "<meta http-equiv=\"$name\" content=\"$content\" />" . $lnEnd;
383                 } elseif ($type == 'standard') {
384                     $strHtml .= $tab . "<meta name=\"$name\" content=\"$content\" />" . $lnEnd;
385                 }
386             }
387         }
388         
389         // Generate stylesheet links
390         foreach ($this->_styleSheets as $strStyleSheet) {
391             $strHtml .= $tab . "<link rel=\"stylesheet\" href=\"$strStyleSheet\" type=\"text/css\" />" . $lnEnd;
392         }
393         
394         // Generate stylesheet declarations
395         foreach ($this->_style as $type => $content) {
396             $strHtml .= $tab . '<style type="' . $type . '">' . $lnEnd;
397             $strHtml .= $tab . $tab . '<!--' . $lnEnd;
398             if (is_object($content)) {
399                 
400                 // first let's propagate line endings and tabs for other HTML_Common-based objects
401                 if (is_subclass_of($content, "html_common")) {
402                     $content->setTab($tab);
403                     $content->setTabOffset(3);
404                     $content->setLineEnd($lnEnd);
405                 }
406                 
407                 // now let's get a string from the object
408                 if (method_exists($content, "toString")) {
409                     $strHtml .= $content->toString() . $lnEnd;
410                 } else {
411                     return PEAR::raiseError('Error: Body content object does not support  method toString().',
412                     0,PEAR_ERROR_TRIGGER);
413                 }
414                 
415             } else {
416                 $strHtml .= $content . $lnEnd;
417             }
418             $strHtml .= $tab . $spacer . "-->" . $lnEnd;
419             $strHtml .= $tab . "</style>" . $lnEnd;
420         }
421         
422         // Generate script file links
423         foreach ($this->_scripts as $strSrc => $strType) {
424             $strHtml .= $tab . "<script type=\"$strType\" src=\"$strSrc\"></script>" . $lnEnd;
425         }
426         
427         // Close tag
428         $strHtml .=  '</head>' . $lnEnd;
429         
430         // Let's roll!
431         return $strHtml;
432     } // end func _generateHead
433     
434     /**
435      * Returns the doctype declaration
436      *
437      * @return string
438      * @access private
439      */
440     function _getDoctype()
441     {
442         require('HTML/Page/Doctypes.php');
443         
444         $type = $this->_doctype['type'];
445         $version = $this->_doctype['version'];
446         $variant = $this->_doctype['variant'];
447         
448         $strDoctype = '';
449         
450         if ($variant != '') {
451             if (isset($doctype[$type][$version][$variant][0])) {
452                 foreach ( $doctype[$type][$version][$variant] as $string) {
453                     $strDoctype .= $string.$this->_getLineEnd();
454                 }
455             }
456         } elseif ($version != '') {
457             if (isset($doctype[$type][$version][0])) {
458                 foreach ( $doctype[$type][$version] as $string) {
459                     $strDoctype .= $string.$this->_getLineEnd();
460                 }
461             } else {
462                 if (isset($default[$type][$version][0])) {
463                     $this->_doctype = $this->_parseDoctypeString($default[$type][$version][0]);
464                     $strDoctype = $this->_getDoctype();
465                 }
466             }
467         } elseif ($type != '') {
468             if (isset($default[$type][0])){
469                 $this->_doctype = $this->_parseDoctypeString($default[$type][0]);
470                 $strDoctype = $this->_getDoctype();
471             }
472         } else {
473             $this->_doctype = $this->_parseDoctypeString($default['default'][0]);
474             $strDoctype = $this->_getDoctype();
475         }
476         
477         if ($strDoctype) {
478             return $strDoctype;
479         } else {
480             return PEAR::raiseError('Error: "'.$this->getDoctypeString().'" is an unsupported or illegal document type.',
481                                     0,PEAR_ERROR_TRIGGER);
482         }
483         
484     } // end func _getDoctype
485     
486     /**
487      * Parses a doctype declaration like "XHTML 1.0 Strict" to an array
488      *
489      * @param   string  $string     The string to be parsed
490      * @return string
491      * @access private
492      */
493     function _parseDoctypeString($string)
494     {
495         $split = explode(' ',strtolower($string));
496         $elements = count($split);
497         
498         $array = array('type'=>$split[0],'version'=>$split[1],'variant'=>$split[2]);
499         
500         return $array;
501     } // end func _parseDoctypeString
502     
503     /**
504      * Sets the content of the &lt;body&gt; tag. If content already exists,
505      * the new content is appended.
506      * If you wish to overwrite whatever is in the body, use {@link setBody};
507      * {@link unsetBody} completely empties the body without inserting new content.
508      * It is possible to add objects, strings or an array of strings and/or objects
509      * Objects must have a toString method.
510      * 
511      * @param mixed $content  New &lt;body&gt; tag content (may be passed as a reference)
512      * @access public
513      */
514     function addBodyContent($content)
515     {
516         $this->_body[] =& $content;
517         if (is_object($content)) {
518             if (method_exists($content, "toStyleSheet")) {
519                 $this->addStyleSheet($content->toStyleSheet());
520             }
521             if (method_exists($content, "toScript")) {
522                                 $script = $content->toScript();
523                                 if (is_array($script)) {
524                                         $this->addScript($script[0], $script[1]);
525                                 } else {
526                                         $this->addScript($script);
527                                 }
528             }
529         } elseif (is_array($content)) {
530                         foreach ($content as $element) {
531                         if (is_object($content)) {
532                                         if (method_exists($element, "toStyleSheet")) {
533                                                 $this->addStyleSheet($element->toStyleSheet());
534                                         }
535                                         if (method_exists($element, "toScript")) {
536                                                 $script = $element->toScript();
537                                                 if (is_array($script)) {
538                                                         $this->addScript($script[0], $script[1]);
539                                                 } else {
540                                                         $this->addScript($script);
541                                                 }
542                                         }
543                                 }
544                         }
545                 }
546     } // end addBodyContent    
547     
548     /**
549      * Adds a linked script to the page
550      * 
551      * @param    string  $url        URL to the linked style sheet
552      * @param    string  $type       Type of script. Defaults to 'text/javascript'
553      * @access   public
554      */
555     function addScript($url, $type="text/javascript")
556     {
557         $this->_scripts[$url] = $type;
558     } // end func addScript
559     
560     /**
561      * Adds a linked stylesheet to the page
562      * 
563      * @param    string  $url    URL to the linked style sheet
564      * @access   public
565      * @return   void
566      */
567     function addStyleSheet($url)
568     {
569         $this->_styleSheets[$url] = $url;
570     } // end func addStyleSheet
571     
572     /**
573      * Adds a stylesheet declaration to the page.
574      * Content can be a string or an object with a toString method.
575      * Defaults to text/css.
576      * 
577      * @access   public
578      * @param    mixed   $content   Style declarations (may be passed as a reference)
579      * @param    string  $type      Type of stylesheet (defaults to 'text/css')
580      * @return   void
581      */
582     function addStyleDeclaration($content, $type = 'text/css')
583     {
584         $this->_style[$type] =& $content;
585     } // end func addStyleDeclaration
586     
587     /**
588      * Returns the current API version
589      * 
590      * @access   public
591      * @returns  double
592      */
593     function apiVersion()
594     {
595         return 2.0;
596     } // end func apiVersion
597     
598     /**
599      * Returns the document charset encoding.
600      * 
601      * @access public
602      * @returns string
603      */
604     function getCharset()
605     {
606         return $this->_charset;
607     } // end setCache
608     
609     /**
610      * Returns the document type string
611      *
612      * @access private
613      * @return string
614      */
615     function getDoctypeString()
616     {
617         $strDoctype = strtoupper($this->_doctype['type']);
618         $strDoctype .= ' '.ucfirst(strtolower($this->_doctype['version']));
619         if ($this->_doctype['variant']) {
620             $strDoctype .= ' ' . ucfirst(strtolower($this->_doctype['variant']));
621         }
622         return trim($strDoctype);
623     } // end func getDoctypeString
624     
625     /**
626      * Returns the document language.
627      * 
628      * @return string
629      * @access public
630      */
631     function getLang ()
632     {
633         return $this->_language;
634     } // end func getLang
635     
636     /**
637      * Return the title of the page.
638      * 
639      * @returns  string
640      * @access   public
641      */
642     function getTitle()
643     {
644         if (!$this->_title){
645             if ($this->_simple) {
646                 return 'New Page';
647             } else {
648                 return 'New '. $this->getDoctypeString() . ' Compliant Page';
649             }
650         } else {
651             return $this->_title;
652         }
653     } // end func getTitle
654     
655     /**
656      * Sets the content of the &lt;body&gt; tag. If content exists, it is overwritten.
657      * If you wish to use a "safe" version, use {@link addBodyContent}
658      * Objects must have a toString method.
659      * 
660      * @param mixed $content New &lt;body&gt; tag content. May be an object. (may be passed as a reference)
661      * @access public
662      */
663     function setBody($content)
664     {
665         $this->unsetBody();
666         $this->addBodyContent($content);
667     } // end setBody
668     
669     /**
670      * Unsets the content of the &lt;body&gt; tag.
671      * 
672      * @access public
673      */
674     function unsetBody()
675     {
676         $this->_body = '';
677     } // end unsetBody
678         
679     /**
680      * Defines if the document should be cached by the browser. Defaults to false.
681      * 
682      * @param string $cache Options are currently 'true' or 'false'. Defaults to 'false'.
683      * @access public
684      */
685     function setCache($cache = 'false')
686     {
687         if ($cache == 'true'){
688             $this->_cache = true;
689         } else {
690             $this->_cache = false;
691         }
692     } // end setCache
693     
694     /**
695      * Defines if the document should be cached by the browser. Defaults to false.
696      * 
697      * @param string $cache Options are currently 'true' or 'false'. Defaults to 'false'.
698      * @access public
699      * @returns void
700      */
701     function setCharset($type = 'utf-8')
702     {
703         $this->_charset = $type;
704     } // end setCache
705     
706     /**
707      * Sets or alters the XHTML !DOCTYPE declaration. Can be set to "strict",
708      * "transitional" or "frameset". Defaults to "transitional". This must come
709      * _after_ declaring the character encoding with {@link setCharset} or directly
710      * when the class is initiated {@link HTML_Page}.
711      * 
712      * @param string $type   String containing a document type. Defaults to "XHTML 1.0 Transitional"
713      * @access public
714      * @returns void
715      */
716     function setDoctype($type = "XHTML 1.0 Transitional")
717     {
718         $this->_doctype = $this->_parseDoctypeString($type);
719     } // end func setDoctype
720     
721     /**
722      * Sets the global document language declaration. Default is English.
723      * 
724      * @access public
725      * @param string $lang Two-letter language designation.
726      */
727     function setLang($lang = "en")
728     {
729         $this->_language = strtolower($lang);
730     } // end setLang
731     
732     /**
733      * Sets or alters a meta tag.
734      * 
735      * @param string  $name     Value of name or http-equiv tag
736      * @param string  $content  Value of the content tag
737      * @param bool    $http_equiv     META type "http-equiv" defaults to NULL
738      * @return void
739      * @access public
740      */
741     function setMetaData($name, $content, $http_equiv = false)
742     {
743         if ($http_equiv == true) {
744             $this->_metaTags['http-equiv'][$name] = $content;
745         } else {
746             $this->_metaTags['standard'][$name] = $content;
747         }
748     } // end func setMetaData
749     
750     /**
751      * Easily sets or alters a refresh meta tag. 
752      * If no $url is passed, "self" is presupposed, and the appropriate URL
753      * will be automatically generated.
754      * 
755      * @param string  $time    Time till refresh (in seconds)
756      * @param string  $url     Absolute URL or "self"
757      * @param bool    $https   If $url = self, this allows for the https protocol defaults to NULL
758      * @return void
759      * @access public
760      */
761     function setMetaRefresh($time, $url = 'self', $https = false)
762     {
763         if ($url == 'self') {
764             if ($https) { 
765                 $protocol = 'https://';
766             } else {
767                 $protocol = 'http://';
768             }
769             $url = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
770         }
771         $this->setMetaData("Refresh", "$time; url=$url", true);
772     } // end func setMetaRefresh
773     
774     /**
775      * Sets the title of the page
776      * 
777      * @param    string    $title
778      * @access   public
779      * @returns  void
780      */
781     function setTitle($title)
782     {
783         $this->_title = $title;
784     } // end func setTitle
785     
786     /**
787      * Generates and returns the complete page as a string.
788      * 
789      * @return string
790      * @access private
791      */
792     function toHTML()
793     {
794         
795         // get line endings
796         $lnEnd = $this->_getLineEnd();
797         
798         // get the doctype declaration
799         $strDoctype = $this->_getDoctype();
800         
801         //
802         if ($this->_simple) {
803             $strHtml = '<html>' . $lnEnd;
804         } elseif ($this->_doctype['type'] == 'xhtml') {
805             $strHtml  = '<?xml version="1.0" encoding="' . $this->_charset . '"?>' . $lnEnd;
806             $strHtml .= $strDoctype . $lnEnd;
807             $strHtml .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$this->_language.'">';
808         } else {
809             $strHtml  = $strDoctype . $lnEnd;
810             $strHtml .= '<html>' . $lnEnd;
811         }
812         $strHtml .= $this->_generateHead();
813         $strHtml .= $this->_generateBody();
814         $strHtml .= '</html>';
815         return $strHtml;
816     } // end func toHtml
817
818     /**
819      * Outputs the HTML content to the screen.
820      * 
821      * @access    public
822      */
823     function display()
824     {
825         if(! $this->_cache) {
826             header("Expires: Tue, 1 Jan 1980 12:00:00 GMT");
827             header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
828             header("Cache-Control: no-cache");
829             header("Pragma: no-cache");
830         }
831         
832         // set character encoding
833         header("Content-Type: text/html; charset=" . $this->_charset);
834         
835         $strHtml = $this->toHTML();
836         print $strHtml;
837     } // end func display
838     
839 }
840 ?>