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