]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/HtmlElement.php
TODO comment about php2js (not yet written)
[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 define('HTMLTAG_EMPTY', 1);
443 define('HTMLTAG_INLINE', 2);
444 define('HTMLTAG_ACCEPTS_INLINE', 4);
445
446
447 HTML::_setTagProperty(HTMLTAG_EMPTY,
448                       'area base basefont br col frame hr img input isindex link meta param');
449 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
450                       // %inline elements:
451                       'b big i small tt ' // %fontstyle
452                       . 's strike u ' // (deprecated)
453                       . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
454                       . 'a img object embed br script map q sub sup span bdo '//%special
455                       . 'button input label option select textarea label ' //%formctl
456
457                       // %block elements which contain inline content
458                       . 'address h1 h2 h3 h4 h5 h6 p pre '
459                       // %block elements which contain either block or inline content
460                       . 'div fieldset frameset'
461
462                       // other with inline content
463                       . 'caption dt label legend '
464                       // other with either inline or block
465                       . 'dd del ins li td th colgroup');
466
467 HTML::_setTagProperty(HTMLTAG_INLINE,
468                       // %inline elements:
469                       'b big i small tt ' // %fontstyle
470                       . 's strike u ' // (deprecated)
471                       . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
472                       . 'a img object br script map q sub sup span bdo '//%special
473                       . 'button input label option select textarea ' //%formctl
474                       . 'nobody iframe'
475                       );
476
477 /**
478  * Generate hidden form input fields.
479  *
480  * @param $query_args hash  A hash mapping names to values for the hidden inputs.
481  * Values in the hash can themselves be hashes.  The will result in hidden inputs
482  * which will reconstruct the nested structure in the resulting query args as
483  * processed by PHP.
484  *
485  * Example:
486  *
487  * $args = array('x' => '2',
488  *               'y' => array('a' => 'aval', 'b' => 'bval'));
489  * $inputs = HiddenInputs($args);
490  *
491  * Will result in:
492  *
493  *  <input type="hidden" name="x" value = "2" />
494  *  <input type="hidden" name="y[a]" value = "aval" />
495  *  <input type="hidden" name="y[b]" value = "bval" />
496  *
497  * @return object An XmlContent object containing the inputs.
498  */
499 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
500     $inputs = HTML();
501
502     foreach ($query_args as $key => $val) {
503         if (in_array($key, $exclude)) continue;
504         $name = $pfx ? $pfx . "[$key]" : $key;
505         if (is_array($val))
506             $inputs->pushContent(HiddenInputs($val, $name));
507         else
508             $inputs->pushContent(HTML::input(array('type' => 'hidden',
509                                                    'name' => $name,
510                                                    'value' => $val)));
511     }
512     return $inputs;
513 }
514
515
516 /** Generate a <script> tag containing javascript.
517  *
518  * @param string $js  The javascript.
519  * @param string $script_args  (optional) hash of script tags options
520  *                             e.g. to provide another version or the defer attr
521  * @return HtmlElement A <script> element.
522  */
523 function JavaScript ($js, $script_args = false) {
524     $default_script_args = array(//'version' => 'JavaScript', // not xhtml conformant
525                                  'type' => 'text/javascript');
526     $script_args = $script_args ? array_merge($default_script_args, $script_args)
527                                 : $default_script_args;
528     if (empty($js))
529         return HTML(HTML::script($script_args),"\n");
530     else
531         // see http://devedge.netscape.com/viewsource/2003/xhtml-style-script/
532         return HTML(HTML::script($script_args,
533                             new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
534                                        . "\n".trim($js)."\n"
535                                        . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->"))),"\n");
536 }
537
538 /** Conditionally display content based of whether javascript is supported.
539  *
540  * This conditionally (on the client side) displays one of two alternate
541  * contents depending on whether the client supports javascript.
542  *
543  * NOTE:
544  * The content you pass as arguments to this function must be block-level.
545  * (This is because the <noscript> tag is block-level.)
546  *
547  * @param mixed $if_content Content to display if the browser supports
548  * javascript.
549  *
550  * @param mixed $else_content Content to display if the browser does
551  * not support javascript.
552  *
553  * @return XmlContent
554  */
555 function IfJavaScript($if_content = false, $else_content = false) {
556     $html = array();
557     if ($if_content) {
558         $xml = AsXML($if_content);
559         $js = sprintf('document.write("%s");',
560                       addcslashes($xml, "\0..\37!@\\\177..\377"));
561         $html[] = JavaScript($js);
562     }
563     if ($else_content) {
564         $html[] = HTML::noscript(false, $else_content);
565     }
566     return HTML($html);
567 }
568     
569 // (c-file-style: "gnu")
570 // Local Variables:
571 // mode: php
572 // tab-width: 8
573 // c-basic-offset: 4
574 // c-hanging-comment-ender-p: nil
575 // indent-tabs-mode: nil
576 // End:
577 ?>