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