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