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