]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/HtmlElement.php
Renamed class Theme to WikiTheme to avoid Gforge name clash
[SourceForge/phpwiki.git] / lib / HtmlElement.php
1 <?php rcs_id('$Id$');
2 /**
3  * Code for writing the HTML subset of XML.
4  * @author: Jeff Dairiki
5  *
6  * This code is now php5 compatible. --2004-04-19 23:51:43 rurban
7  */
8 if (!class_exists("XmlElement"))
9     require_once(dirname(__FILE__)."/XmlElement.php");
10 if (class_exists("HtmlElement"))
11     return;
12
13 /**
14  * An XML element.
15  */
16 //apd_set_session_trace(35);
17
18 class HtmlElement extends XmlElement
19 {
20     function __construct ($tagname /* , $attr_or_content , ...*/) {
21         $this->_init(func_get_args());
22         $this->_properties = HTML::getTagProperties($tagname);
23     }
24
25     function _init ($args) {
26         if (!is_array($args))
27             $args = func_get_args();
28
29         assert(count($args) >= 1);
30         assert(is_string($args[0]));
31         $this->_tag = array_shift($args);
32         
33         if ($args && is_array($args[0]))
34             $this->_attr = array_shift($args);
35         else {
36             $this->_attr = array();
37             if ($args && $args[0] === false)
38                 array_shift($args);
39         }
40         $this->setContent($args);
41         $this->_properties = HTML::getTagProperties($this->_tag);
42     }
43
44     /**
45      * @access protected
46      * This is used by the static factory methods is class HTML.
47      */
48     function _init2 ($args) {
49         if ($args) {
50             if (is_array($args[0]))
51                 $this->_attr = array_shift($args);
52             elseif ($args[0] === false)
53                 array_shift($args);
54         }
55         
56         if (count($args) == 1 && is_array($args[0]))
57             $args = $args[0];
58         $this->_content = $args;
59         return $this;
60     }
61
62     /** Add a "tooltip" to an element.
63      *
64      * @param $tooltip_text string The tooltip text.
65      */
66     function addTooltip ($tooltip_text, $accesskey = null) {
67         $this->setAttr('title', $tooltip_text);
68         if ($accesskey) $this->setAccesskey($accesskey);
69
70         // FIXME: this should be initialized from title by an onLoad() function.
71         //        (though, that may not be possible.)
72         $qtooltip = str_replace("'", "\\'", $tooltip_text);
73         $this->setAttr('onmouseover',
74                        sprintf('window.status="%s"; return true;',
75                                addslashes($tooltip_text)));
76         $this->setAttr('onmouseout', "window.status='';return true;");
77     }
78
79     function setAccesskey ($key) {
80         global $WikiTheme;
81         if (strlen($key) != 1) return;
82         $this->setAttr("accesskey", $key);
83
84         if (!empty($this->_attr['title'])) {
85             if (preg_match("/\[(alt-)?(.)\]$/", $this->_attr['title'], $m))
86             {
87                 $this->_attr['title'] = preg_replace("/\[(alt-)?(.)\]$/", "[".$WikiTheme->tooltipAccessKeyPrefix()."-\\2]", $this->_attr['title']);
88             } else  {
89                 $this->_attr['title'] .= " [".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
90             }
91         } else {
92             $this->_attr['title'] = "[".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
93         }
94     }
95
96     function emptyTag () {
97         if (($this->_properties & HTMLTAG_EMPTY) == 0)
98             return $this->startTag() . "</$this->_tag>";
99
100         return substr($this->startTag(), 0, -1) . " />";
101     }
102
103     function hasInlineContent () {
104         return ($this->_properties & HTMLTAG_ACCEPTS_INLINE) != 0;
105     }
106
107     function isInlineElement () {
108         return ($this->_properties & HTMLTAG_INLINE) != 0;
109     }
110 };
111
112 function HTML (/* $content, ... */) {
113     return new XmlContent(func_get_args());
114 }
115
116 class HTML extends HtmlElement {
117     function raw ($html_text) {
118         return new RawXml($html_text);
119     }
120     
121     function getTagProperties($tag) {
122         $props = &$GLOBALS['HTML_TagProperties'];
123         return isset($props[$tag]) ? $props[$tag] : 0;
124     }
125
126     function _setTagProperty($prop_flag, $tags) {
127         $props = &$GLOBALS['HTML_TagProperties'];
128         if (is_string($tags))
129             $tags = preg_split('/\s+/', $tags);
130         foreach ($tags as $tag) {
131             $tag = trim($tag);
132             if ($tag)
133                 if (isset($props[$tag]))
134                     $props[$tag] |= $prop_flag;
135                 else
136                     $props[$tag] = $prop_flag;
137         }
138     }
139
140     //
141     // Shell script to generate the following static methods:
142     //
143     // #!/bin/sh
144     // function mkfuncs () {
145     //     for tag in "$@"
146     //     do
147     //         echo "    function $tag (/*...*/) {"
148     //         echo "        \$el = new HtmlElement('$tag');"
149     //         echo "        return \$el->_init2(func_get_args());"
150     //         echo "    }"
151     //     done
152     // }
153     // d='
154     //     /****************************************/'
155     // mkfuncs link meta style script noscript
156     // echo "$d"
157     // mkfuncs a img br span
158     // echo "$d"
159     // mkfuncs h1 h2 h3 h4 h5 h6
160     // echo "$d"
161     // mkfuncs hr div p pre blockquote
162     // echo "$d"
163     // mkfuncs em strong small
164     // echo "$d"
165     // mkfuncs tt u sup sub
166     // echo "$d"
167     // mkfuncs ul ol dl li dt dd
168     // echo "$d"
169     // mkfuncs table caption thead tbody tfoot tr td th colgroup col
170     // echo "$d"
171     // mkfuncs form input option select textarea
172     // echo "$d"
173     // mkfuncs area map frame frameset iframe nobody
174
175     function link (/*...*/) {
176         $el = new HtmlElement('link');
177         return $el->_init2(func_get_args());
178     }
179     function meta (/*...*/) {
180         $el = new HtmlElement('meta');
181         return $el->_init2(func_get_args());
182     }
183     function style (/*...*/) {
184         $el = new HtmlElement('style');
185         return $el->_init2(func_get_args());
186     }
187     function script (/*...*/) {
188         $el = new HtmlElement('script');
189         return $el->_init2(func_get_args());
190     }
191     function noscript (/*...*/) {
192         $el = new HtmlElement('noscript');
193         return $el->_init2(func_get_args());
194     }
195
196     /****************************************/
197     function a (/*...*/) {
198         $el = new HtmlElement('a');
199         return $el->_init2(func_get_args());
200     }
201     function img (/*...*/) {
202         $el = new HtmlElement('img');
203         return $el->_init2(func_get_args());
204     }
205     function br (/*...*/) {
206         $el = new HtmlElement('br');
207         return $el->_init2(func_get_args());
208     }
209     function span (/*...*/) {
210         $el = new HtmlElement('span');
211         return $el->_init2(func_get_args());
212     }
213
214     /****************************************/
215     function h1 (/*...*/) {
216         $el = new HtmlElement('h1');
217         return $el->_init2(func_get_args());
218     }
219     function h2 (/*...*/) {
220         $el = new HtmlElement('h2');
221         return $el->_init2(func_get_args());
222     }
223     function h3 (/*...*/) {
224         $el = new HtmlElement('h3');
225         return $el->_init2(func_get_args());
226     }
227     function h4 (/*...*/) {
228         $el = new HtmlElement('h4');
229         return $el->_init2(func_get_args());
230     }
231     function h5 (/*...*/) {
232         $el = new HtmlElement('h5');
233         return $el->_init2(func_get_args());
234     }
235     function h6 (/*...*/) {
236         $el = new HtmlElement('h6');
237         return $el->_init2(func_get_args());
238     }
239
240     /****************************************/
241     function hr (/*...*/) {
242         $el = new HtmlElement('hr');
243         return $el->_init2(func_get_args());
244     }
245     function div (/*...*/) {
246         $el = new HtmlElement('div');
247         return $el->_init2(func_get_args());
248     }
249     function p (/*...*/) {
250         $el = new HtmlElement('p');
251         return $el->_init2(func_get_args());
252     }
253     function pre (/*...*/) {
254         $el = new HtmlElement('pre');
255         return $el->_init2(func_get_args());
256     }
257     function blockquote (/*...*/) {
258         $el = new HtmlElement('blockquote');
259         return $el->_init2(func_get_args());
260     }
261
262     /****************************************/
263     function em (/*...*/) {
264         $el = new HtmlElement('em');
265         return $el->_init2(func_get_args());
266     }
267     function strong (/*...*/) {
268         $el = new HtmlElement('strong');
269         return $el->_init2(func_get_args());
270     }
271     function small (/*...*/) {
272         $el = new HtmlElement('small');
273         return $el->_init2(func_get_args());
274     }
275
276     /****************************************/
277     function tt (/*...*/) {
278         $el = new HtmlElement('tt');
279         return $el->_init2(func_get_args());
280     }
281     function u (/*...*/) {
282         $el = new HtmlElement('u');
283         return $el->_init2(func_get_args());
284     }
285     function sup (/*...*/) {
286         $el = new HtmlElement('sup');
287         return $el->_init2(func_get_args());
288     }
289     function sub (/*...*/) {
290         $el = new HtmlElement('sub');
291         return $el->_init2(func_get_args());
292     }
293
294     /****************************************/
295     function ul (/*...*/) {
296         $el = new HtmlElement('ul');
297         return $el->_init2(func_get_args());
298     }
299     function ol (/*...*/) {
300         $el = new HtmlElement('ol');
301         return $el->_init2(func_get_args());
302     }
303     function dl (/*...*/) {
304         $el = new HtmlElement('dl');
305         return $el->_init2(func_get_args());
306     }
307     function li (/*...*/) {
308         $el = new HtmlElement('li');
309         return $el->_init2(func_get_args());
310     }
311     function dt (/*...*/) {
312         $el = new HtmlElement('dt');
313         return $el->_init2(func_get_args());
314     }
315     function dd (/*...*/) {
316         $el = new HtmlElement('dd');
317         return $el->_init2(func_get_args());
318     }
319
320     /****************************************/
321     function table (/*...*/) {
322         $el = new HtmlElement('table');
323         return $el->_init2(func_get_args());
324     }
325     function caption (/*...*/) {
326         $el = new HtmlElement('caption');
327         return $el->_init2(func_get_args());
328     }
329     function thead (/*...*/) {
330         $el = new HtmlElement('thead');
331         return $el->_init2(func_get_args());
332     }
333     function tbody (/*...*/) {
334         $el = new HtmlElement('tbody');
335         return $el->_init2(func_get_args());
336     }
337     function tfoot (/*...*/) {
338         $el = new HtmlElement('tfoot');
339         return $el->_init2(func_get_args());
340     }
341     function tr (/*...*/) {
342         $el = new HtmlElement('tr');
343         return $el->_init2(func_get_args());
344     }
345     function td (/*...*/) {
346         $el = new HtmlElement('td');
347         return $el->_init2(func_get_args());
348     }
349     function th (/*...*/) {
350         $el = new HtmlElement('th');
351         return $el->_init2(func_get_args());
352     }
353     function colgroup (/*...*/) {
354         $el = new HtmlElement('colgroup');
355         return $el->_init2(func_get_args());
356     }
357     function col (/*...*/) {
358         $el = new HtmlElement('col');
359         return $el->_init2(func_get_args());
360     }
361
362     /****************************************/
363     function form (/*...*/) {
364         $el = new HtmlElement('form');
365         return $el->_init2(func_get_args());
366     }
367     function input (/*...*/) {
368         $el = new HtmlElement('input');
369         return $el->_init2(func_get_args());
370     }
371     function button (/*...*/) {
372         $el = new HtmlElement('button');
373         return $el->_init2(func_get_args());
374     }
375     function option (/*...*/) {
376         $el = new HtmlElement('option');
377         return $el->_init2(func_get_args());
378     }
379     function select (/*...*/) {
380         $el = new HtmlElement('select');
381         return $el->_init2(func_get_args());
382     }
383     function textarea (/*...*/) {
384         $el = new HtmlElement('textarea');
385         return $el->_init2(func_get_args());
386     }
387     function label (/*...*/) {
388         $el = new HtmlElement('label');
389         return $el->_init2(func_get_args());
390     }
391
392     /****************************************/
393     function area (/*...*/) {
394         $el = new HtmlElement('area');
395         return $el->_init2(func_get_args());
396     }
397     function map (/*...*/) {
398         $el = new HtmlElement('map');
399         return $el->_init2(func_get_args());
400     }
401     function frame (/*...*/) {
402         $el = new HtmlElement('frame');
403         return $el->_init2(func_get_args());
404     }
405     function frameset (/*...*/) {
406         $el = new HtmlElement('frameset');
407         return $el->_init2(func_get_args());
408     }
409     function iframe (/*...*/) {
410         $el = new HtmlElement('iframe');
411         return $el->_init2(func_get_args());
412     }
413     function nobody (/*...*/) {
414         $el = new HtmlElement('nobody');
415         return $el->_init2(func_get_args());
416     }
417     function object (/*...*/) {
418         $el = new HtmlElement('object');
419         return $el->_init2(func_get_args());
420     }
421     function embed (/*...*/) {
422         $el = new HtmlElement('embed');
423         return $el->_init2(func_get_args());
424     }
425     function param (/*...*/) {
426         $el = new HtmlElement('param');
427         return $el->_init2(func_get_args());
428     }
429     function legend (/*...*/) {
430         $el = new HtmlElement('legend');
431         return $el->_init2(func_get_args());
432     }
433 }
434
435 define('HTMLTAG_EMPTY', 1);
436 define('HTMLTAG_INLINE', 2);
437 define('HTMLTAG_ACCEPTS_INLINE', 4);
438
439
440 HTML::_setTagProperty(HTMLTAG_EMPTY,
441                       'area base basefont br col frame hr img input isindex link meta param');
442 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
443                       // %inline elements:
444                       'b big i small tt ' // %fontstyle
445                       . 's strike u ' // (deprecated)
446                       . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
447                       . 'a img object embed br script map q sub sup span bdo '//%special
448                       . 'button input label option select textarea label ' //%formctl
449
450                       // %block elements which contain inline content
451                       . 'address h1 h2 h3 h4 h5 h6 p pre '
452                       // %block elements which contain either block or inline content
453                       . 'div fieldset frameset'
454
455                       // other with inline content
456                       . 'caption dt label legend '
457                       // other with either inline or block
458                       . 'dd del ins li td th colgroup');
459
460 HTML::_setTagProperty(HTMLTAG_INLINE,
461                       // %inline elements:
462                       'b big i small tt ' // %fontstyle
463                       . 's strike u ' // (deprecated)
464                       . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
465                       . 'a img object br script map q sub sup span bdo '//%special
466                       . 'button input label option select textarea ' //%formctl
467                       . 'nobody iframe'
468                       );
469
470 /**
471  * Generate hidden form input fields.
472  *
473  * @param $query_args hash  A hash mapping names to values for the hidden inputs.
474  * Values in the hash can themselves be hashes.  The will result in hidden inputs
475  * which will reconstruct the nested structure in the resulting query args as
476  * processed by PHP.
477  *
478  * Example:
479  *
480  * $args = array('x' => '2',
481  *               'y' => array('a' => 'aval', 'b' => 'bval'));
482  * $inputs = HiddenInputs($args);
483  *
484  * Will result in:
485  *
486  *  <input type="hidden" name="x" value = "2" />
487  *  <input type="hidden" name="y[a]" value = "aval" />
488  *  <input type="hidden" name="y[b]" value = "bval" />
489  *
490  * @return object An XmlContent object containing the inputs.
491  */
492 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
493     $inputs = HTML();
494
495     foreach ($query_args as $key => $val) {
496         if (in_array($key, $exclude)) continue;
497         $name = $pfx ? $pfx . "[$key]" : $key;
498         if (is_array($val))
499             $inputs->pushContent(HiddenInputs($val, $name));
500         else
501             $inputs->pushContent(HTML::input(array('type' => 'hidden',
502                                                    'name' => $name,
503                                                    'value' => $val)));
504     }
505     return $inputs;
506 }
507
508
509 /** Generate a <script> tag containing javascript.
510  *
511  * @param string $js  The javascript.
512  * @param string $script_args  (optional) hash of script tags options
513  *                             e.g. to provide another version or the defer attr
514  * @return HtmlElement A <script> element.
515  */
516 function JavaScript ($js, $script_args = false) {
517     $default_script_args = array(//'version' => 'JavaScript', // not xhtml conformant
518                                  'type' => 'text/javascript');
519     $script_args = $script_args ? array_merge($default_script_args, $script_args)
520                                 : $default_script_args;
521     if (empty($js))
522         return HTML(HTML::script($script_args),"\n");
523     else
524         // see http://devedge.netscape.com/viewsource/2003/xhtml-style-script/
525         return HTML(HTML::script($script_args,
526                             new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
527                                        . "\n".trim($js)."\n"
528                                        . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->"))),"\n");
529 }
530
531 /** Conditionally display content based of whether javascript is supported.
532  *
533  * This conditionally (on the client side) displays one of two alternate
534  * contents depending on whether the client supports javascript.
535  *
536  * NOTE:
537  * The content you pass as arguments to this function must be block-level.
538  * (This is because the <noscript> tag is block-level.)
539  *
540  * @param mixed $if_content Content to display if the browser supports
541  * javascript.
542  *
543  * @param mixed $else_content Content to display if the browser does
544  * not support javascript.
545  *
546  * @return XmlContent
547  */
548 function IfJavaScript($if_content = false, $else_content = false) {
549     $html = array();
550     if ($if_content) {
551         $xml = AsXML($if_content);
552         $js = sprintf('document.write("%s");',
553                       addcslashes($xml, "\0..\37!@\\\177..\377"));
554         $html[] = JavaScript($js);
555     }
556     if ($else_content) {
557         $html[] = HTML::noscript(false, $else_content);
558     }
559     return HTML($html);
560 }
561     
562 // (c-file-style: "gnu")
563 // Local Variables:
564 // mode: php
565 // tab-width: 8
566 // c-basic-offset: 4
567 // c-hanging-comment-ender-p: nil
568 // indent-tabs-mode: nil
569 // End:
570 ?>