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