1 <?php // rcs_id('$Id$');
3 * Code for writing the HTML subset of XML.
4 * @author: Jeff Dairiki
6 * This code is now php5 compatible. --2004-04-19 23:51:43 rurban
8 * Todo: Add support for a JavaScript backend, a php2js compiler.
9 * HTML::div(array('onClick' => 'HTML::div(...)'))
11 if (!class_exists("XmlElement"))
12 require_once(dirname(__FILE__)."/XmlElement.php");
13 if (class_exists("HtmlElement"))
19 //apd_set_session_trace(35);
21 class HtmlElement extends XmlElement
23 function __construct ($tagname /* , $attr_or_content , ...*/) {
24 $this->_init(func_get_args());
25 $this->_properties = HTML::getTagProperties($tagname);
28 function _init ($args) {
30 $args = func_get_args();
32 assert(count($args) >= 1);
33 assert(is_string($args[0]));
34 $this->_tag = array_shift($args);
36 if ($args && is_array($args[0]))
37 $this->_attr = array_shift($args);
39 $this->_attr = array();
40 if ($args && $args[0] === false)
43 $this->setContent($args);
44 $this->_properties = HTML::getTagProperties($this->_tag);
49 * This is used by the static factory methods is class HTML.
51 function _init2 ($args) {
53 if (is_array($args[0]))
54 $this->_attr = array_shift($args);
55 elseif ($args[0] === false)
59 if (count($args) == 1 && is_array($args[0]))
61 $this->_content = $args;
65 /** Add a "tooltip" to an element.
67 * @param $tooltip_text string The tooltip text.
69 function addTooltip ($tooltip_text, $accesskey = null) {
70 $this->setAttr('title', $tooltip_text);
71 if ($accesskey) $this->setAccesskey($accesskey);
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;");
82 function setAccesskey ($key) {
84 if (strlen($key) != 1) return;
85 $this->setAttr("accesskey", $key);
87 if (!empty($this->_attr['title'])) {
88 if (preg_match("/\[(alt-)?(.)\]$/", $this->_attr['title'], $m))
90 $this->_attr['title'] = preg_replace("/\[(alt-)?(.)\]$/", "[".$WikiTheme->tooltipAccessKeyPrefix()."-\\2]", $this->_attr['title']);
92 $this->_attr['title'] .= " [".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
95 $this->_attr['title'] = "[".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
99 function emptyTag () {
100 if (($this->_properties & HTMLTAG_EMPTY) == 0)
101 return $this->startTag() . "</$this->_tag>";
103 return substr($this->startTag(), 0, -1) . " />";
106 function hasInlineContent () {
107 return ($this->_properties & HTMLTAG_ACCEPTS_INLINE) != 0;
110 function isInlineElement () {
111 return ($this->_properties & HTMLTAG_INLINE) != 0;
115 function HTML (/* $content, ... */) {
116 return new XmlContent(func_get_args());
119 class HTML extends HtmlElement {
120 function raw ($html_text) {
121 return new RawXml($html_text);
124 function getTagProperties($tag) {
125 $props = &$GLOBALS['HTML_TagProperties'];
126 return isset($props[$tag]) ? $props[$tag] : 0;
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) {
136 if (isset($props[$tag]))
137 $props[$tag] |= $prop_flag;
139 $props[$tag] = $prop_flag;
144 // Shell script to generate the following static methods:
147 // function mkfuncs () {
150 // echo " function $tag (/*...*/) {"
151 // echo " \$el = new HtmlElement('$tag');"
152 // echo " return \$el->_init2(func_get_args());"
157 // /****************************************/'
158 // mkfuncs link meta style script noscript
160 // mkfuncs a img br span
162 // mkfuncs h1 h2 h3 h4 h5 h6
164 // mkfuncs hr div p pre blockquote
166 // mkfuncs em strong small
168 // mkfuncs tt u sup sub
170 // mkfuncs ul ol dl li dt dd
172 // mkfuncs table caption thead tbody tfoot tr td th colgroup col
174 // mkfuncs form input option select textarea
176 // mkfuncs area map frame frameset iframe nobody
178 function link (/*...*/) {
179 $el = new HtmlElement('link');
180 return $el->_init2(func_get_args());
182 function meta (/*...*/) {
183 $el = new HtmlElement('meta');
184 return $el->_init2(func_get_args());
186 function style (/*...*/) {
187 $el = new HtmlElement('style');
188 return $el->_init2(func_get_args());
190 function script (/*...*/) {
191 $el = new HtmlElement('script');
192 return $el->_init2(func_get_args());
194 function noscript (/*...*/) {
195 $el = new HtmlElement('noscript');
196 return $el->_init2(func_get_args());
199 /****************************************/
200 function a (/*...*/) {
201 $el = new HtmlElement('a');
202 return $el->_init2(func_get_args());
204 function img (/*...*/) {
205 $el = new HtmlElement('img');
206 return $el->_init2(func_get_args());
208 function br (/*...*/) {
209 $el = new HtmlElement('br');
210 return $el->_init2(func_get_args());
212 function span (/*...*/) {
213 $el = new HtmlElement('span');
214 return $el->_init2(func_get_args());
217 /****************************************/
218 function h1 (/*...*/) {
219 $el = new HtmlElement('h1');
220 return $el->_init2(func_get_args());
222 function h2 (/*...*/) {
223 $el = new HtmlElement('h2');
224 return $el->_init2(func_get_args());
226 function h3 (/*...*/) {
227 $el = new HtmlElement('h3');
228 return $el->_init2(func_get_args());
230 function h4 (/*...*/) {
231 $el = new HtmlElement('h4');
232 return $el->_init2(func_get_args());
234 function h5 (/*...*/) {
235 $el = new HtmlElement('h5');
236 return $el->_init2(func_get_args());
238 function h6 (/*...*/) {
239 $el = new HtmlElement('h6');
240 return $el->_init2(func_get_args());
243 /****************************************/
244 function hr (/*...*/) {
245 $el = new HtmlElement('hr');
246 return $el->_init2(func_get_args());
248 function div (/*...*/) {
249 $el = new HtmlElement('div');
250 return $el->_init2(func_get_args());
252 function p (/*...*/) {
253 $el = new HtmlElement('p');
254 return $el->_init2(func_get_args());
256 function pre (/*...*/) {
257 $el = new HtmlElement('pre');
258 return $el->_init2(func_get_args());
260 function blockquote (/*...*/) {
261 $el = new HtmlElement('blockquote');
262 return $el->_init2(func_get_args());
265 /****************************************/
266 function em (/*...*/) {
267 $el = new HtmlElement('em');
268 return $el->_init2(func_get_args());
270 function strong (/*...*/) {
271 $el = new HtmlElement('strong');
272 return $el->_init2(func_get_args());
274 function small (/*...*/) {
275 $el = new HtmlElement('small');
276 return $el->_init2(func_get_args());
279 /****************************************/
280 function tt (/*...*/) {
281 $el = new HtmlElement('tt');
282 return $el->_init2(func_get_args());
284 function u (/*...*/) {
285 $el = new HtmlElement('u');
286 return $el->_init2(func_get_args());
288 function sup (/*...*/) {
289 $el = new HtmlElement('sup');
290 return $el->_init2(func_get_args());
292 function sub (/*...*/) {
293 $el = new HtmlElement('sub');
294 return $el->_init2(func_get_args());
297 /****************************************/
298 function ul (/*...*/) {
299 $el = new HtmlElement('ul');
300 return $el->_init2(func_get_args());
302 function ol (/*...*/) {
303 $el = new HtmlElement('ol');
304 return $el->_init2(func_get_args());
306 function dl (/*...*/) {
307 $el = new HtmlElement('dl');
308 return $el->_init2(func_get_args());
310 function li (/*...*/) {
311 $el = new HtmlElement('li');
312 return $el->_init2(func_get_args());
314 function dt (/*...*/) {
315 $el = new HtmlElement('dt');
316 return $el->_init2(func_get_args());
318 function dd (/*...*/) {
319 $el = new HtmlElement('dd');
320 return $el->_init2(func_get_args());
323 /****************************************/
324 function table (/*...*/) {
325 $el = new HtmlElement('table');
326 return $el->_init2(func_get_args());
328 function caption (/*...*/) {
329 $el = new HtmlElement('caption');
330 return $el->_init2(func_get_args());
332 function thead (/*...*/) {
333 $el = new HtmlElement('thead');
334 return $el->_init2(func_get_args());
336 function tbody (/*...*/) {
337 $el = new HtmlElement('tbody');
338 return $el->_init2(func_get_args());
340 function tfoot (/*...*/) {
341 $el = new HtmlElement('tfoot');
342 return $el->_init2(func_get_args());
344 function tr (/*...*/) {
345 $el = new HtmlElement('tr');
346 return $el->_init2(func_get_args());
348 function td (/*...*/) {
349 $el = new HtmlElement('td');
350 return $el->_init2(func_get_args());
352 function th (/*...*/) {
353 $el = new HtmlElement('th');
354 return $el->_init2(func_get_args());
356 function colgroup (/*...*/) {
357 $el = new HtmlElement('colgroup');
358 return $el->_init2(func_get_args());
360 function col (/*...*/) {
361 $el = new HtmlElement('col');
362 return $el->_init2(func_get_args());
365 /****************************************/
366 function form (/*...*/) {
367 $el = new HtmlElement('form');
368 return $el->_init2(func_get_args());
370 function input (/*...*/) {
371 $el = new HtmlElement('input');
372 return $el->_init2(func_get_args());
374 function button (/*...*/) {
375 $el = new HtmlElement('button');
376 return $el->_init2(func_get_args());
378 function option (/*...*/) {
379 $el = new HtmlElement('option');
380 return $el->_init2(func_get_args());
382 function select (/*...*/) {
383 $el = new HtmlElement('select');
384 return $el->_init2(func_get_args());
386 function textarea (/*...*/) {
387 $el = new HtmlElement('textarea');
388 return $el->_init2(func_get_args());
390 function label (/*...*/) {
391 $el = new HtmlElement('label');
392 return $el->_init2(func_get_args());
395 /****************************************/
396 function area (/*...*/) {
397 $el = new HtmlElement('area');
398 return $el->_init2(func_get_args());
400 function map (/*...*/) {
401 $el = new HtmlElement('map');
402 return $el->_init2(func_get_args());
404 function frame (/*...*/) {
405 $el = new HtmlElement('frame');
406 return $el->_init2(func_get_args());
408 function frameset (/*...*/) {
409 $el = new HtmlElement('frameset');
410 return $el->_init2(func_get_args());
412 function iframe (/*...*/) {
413 $el = new HtmlElement('iframe');
414 return $el->_init2(func_get_args());
416 function nobody (/*...*/) {
417 $el = new HtmlElement('nobody');
418 return $el->_init2(func_get_args());
420 function object (/*...*/) {
421 $el = new HtmlElement('object');
422 return $el->_init2(func_get_args());
424 function embed (/*...*/) {
425 $el = new HtmlElement('embed');
426 return $el->_init2(func_get_args());
428 function param (/*...*/) {
429 $el = new HtmlElement('param');
430 return $el->_init2(func_get_args());
432 function fieldset (/*...*/) {
433 $el = new HtmlElement('fieldset');
434 return $el->_init2(func_get_args());
436 function legend (/*...*/) {
437 $el = new HtmlElement('legend');
438 return $el->_init2(func_get_args());
441 /****************************************/
442 function video (/*...*/) {
443 $el = new HtmlElement('video');
444 return $el->_init2(func_get_args());
448 define('HTMLTAG_EMPTY', 1);
449 define('HTMLTAG_INLINE', 2);
450 define('HTMLTAG_ACCEPTS_INLINE', 4);
453 HTML::_setTagProperty(HTMLTAG_EMPTY,
454 'area base basefont br col frame hr img input isindex link meta param');
455 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
457 'b big i small tt ' // %fontstyle
458 . 's strike u ' // (deprecated)
459 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
460 . 'a img object embed br script map q sub sup span bdo '//%special
461 . 'button input label option select textarea label ' //%formctl
463 // %block elements which contain inline content
464 . 'address h1 h2 h3 h4 h5 h6 p pre '
465 // %block elements which contain either block or inline content
466 . 'div fieldset frameset'
468 // other with inline content
469 . 'caption dt label legend video '
470 // other with either inline or block
471 . 'dd del ins li td th colgroup');
473 HTML::_setTagProperty(HTMLTAG_INLINE,
475 'b big i small tt ' // %fontstyle
476 . 's strike u ' // (deprecated)
477 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
478 . 'a img object br script map q sub sup span bdo '//%special
479 . 'button input label option select textarea ' //%formctl
484 * Generate hidden form input fields.
486 * @param $query_args hash A hash mapping names to values for the hidden inputs.
487 * Values in the hash can themselves be hashes. The will result in hidden inputs
488 * which will reconstruct the nested structure in the resulting query args as
493 * $args = array('x' => '2',
494 * 'y' => array('a' => 'aval', 'b' => 'bval'));
495 * $inputs = HiddenInputs($args);
499 * <input type="hidden" name="x" value = "2" />
500 * <input type="hidden" name="y[a]" value = "aval" />
501 * <input type="hidden" name="y[b]" value = "bval" />
503 * @return object An XmlContent object containing the inputs.
505 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
508 foreach ($query_args as $key => $val) {
509 if (in_array($key, $exclude)) continue;
510 $name = $pfx ? $pfx . "[$key]" : $key;
512 $inputs->pushContent(HiddenInputs($val, $name));
514 $inputs->pushContent(HTML::input(array('type' => 'hidden',
522 /** Generate a <script> tag containing javascript.
524 * @param string $js The javascript.
525 * @param string $script_args (optional) hash of script tags options
526 * e.g. to provide another version or the defer attr
527 * @return HtmlElement A <script> element.
529 function JavaScript ($js, $script_args = false) {
530 $default_script_args = array(//'version' => 'JavaScript', // not xhtml conformant
531 'type' => 'text/javascript');
532 $script_args = $script_args ? array_merge($default_script_args, $script_args)
533 : $default_script_args;
535 return HTML(HTML::script($script_args),"\n");
537 // see http://devedge.netscape.com/viewsource/2003/xhtml-style-script/
538 return HTML(HTML::script($script_args,
539 new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
540 . "\n".trim($js)."\n"
541 . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->"))),"\n");
544 /** Conditionally display content based of whether javascript is supported.
546 * This conditionally (on the client side) displays one of two alternate
547 * contents depending on whether the client supports javascript.
550 * The content you pass as arguments to this function must be block-level.
551 * (This is because the <noscript> tag is block-level.)
553 * @param mixed $if_content Content to display if the browser supports
556 * @param mixed $else_content Content to display if the browser does
557 * not support javascript.
561 function IfJavaScript($if_content = false, $else_content = false) {
564 $xml = AsXML($if_content);
565 $js = sprintf('document.write("%s");',
566 addcslashes($xml, "\0..\37!@\\\177..\377"));
567 $html[] = JavaScript($js);
570 $html[] = HTML::noscript(false, $else_content);
575 // (c-file-style: "gnu")
580 // c-hanging-comment-ender-p: nil
581 // indent-tabs-mode: nil