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
92 "[".$WikiTheme->tooltipAccessKeyPrefix()."-\\2]",
93 $this->_attr['title']);
95 $this->_attr['title'] .=
96 " [".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
99 $this->_attr['title'] =
100 "[".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
104 function emptyTag () {
105 if (($this->_properties & HTMLTAG_EMPTY) == 0)
106 return $this->startTag() . "</$this->_tag>";
108 return substr($this->startTag(), 0, -1) . " />";
111 function hasInlineContent () {
112 return ($this->_properties & HTMLTAG_ACCEPTS_INLINE) != 0;
115 function isInlineElement () {
116 return ($this->_properties & HTMLTAG_INLINE) != 0;
120 function HTML (/* $content, ... */) {
121 return new XmlContent(func_get_args());
124 class HTML extends HtmlElement {
125 function raw ($html_text) {
126 return new RawXml($html_text);
129 function getTagProperties($tag) {
130 $props = &$GLOBALS['HTML_TagProperties'];
131 return isset($props[$tag]) ? $props[$tag] : 0;
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) {
141 if (isset($props[$tag]))
142 $props[$tag] |= $prop_flag;
144 $props[$tag] = $prop_flag;
149 // Shell script to generate the following static methods:
156 echo " public static function $tag (/*...*/) {"
157 echo " \$el = new HtmlElement('$tag');"
158 echo " return \$el->_init2(func_get_args());"
163 /****************************************/'
164 mkfuncs link meta style script noscript
166 mkfuncs a img br span
168 mkfuncs h1 h2 h3 h4 h5 h6
170 mkfuncs hr div p pre blockquote
172 mkfuncs em strong small
176 mkfuncs ul ol dl li dt dd
178 mkfuncs table caption thead tbody tfoot tr td th colgroup col
180 mkfuncs form input option select textarea label fieldset legend
182 mkfuncs area map frame frameset iframe nobody object embed param
187 function link (/*...*/) {
188 $el = new HtmlElement('link');
189 return $el->_init2(func_get_args());
191 function meta (/*...*/) {
192 $el = new HtmlElement('meta');
193 return $el->_init2(func_get_args());
195 function style (/*...*/) {
196 $el = new HtmlElement('style');
197 return $el->_init2(func_get_args());
199 function script (/*...*/) {
200 $el = new HtmlElement('script');
201 return $el->_init2(func_get_args());
203 function noscript (/*...*/) {
204 $el = new HtmlElement('noscript');
205 return $el->_init2(func_get_args());
208 /****************************************/
209 function a (/*...*/) {
210 $el = new HtmlElement('a');
211 return $el->_init2(func_get_args());
213 function img (/*...*/) {
214 $el = new HtmlElement('img');
215 return $el->_init2(func_get_args());
217 function br (/*...*/) {
218 $el = new HtmlElement('br');
219 return $el->_init2(func_get_args());
221 function span (/*...*/) {
222 $el = new HtmlElement('span');
223 return $el->_init2(func_get_args());
226 /****************************************/
227 function h1 (/*...*/) {
228 $el = new HtmlElement('h1');
229 return $el->_init2(func_get_args());
231 function h2 (/*...*/) {
232 $el = new HtmlElement('h2');
233 return $el->_init2(func_get_args());
235 function h3 (/*...*/) {
236 $el = new HtmlElement('h3');
237 return $el->_init2(func_get_args());
239 function h4 (/*...*/) {
240 $el = new HtmlElement('h4');
241 return $el->_init2(func_get_args());
243 function h5 (/*...*/) {
244 $el = new HtmlElement('h5');
245 return $el->_init2(func_get_args());
247 function h6 (/*...*/) {
248 $el = new HtmlElement('h6');
249 return $el->_init2(func_get_args());
252 /****************************************/
253 function hr (/*...*/) {
254 $el = new HtmlElement('hr');
255 return $el->_init2(func_get_args());
257 function div (/*...*/) {
258 $el = new HtmlElement('div');
259 return $el->_init2(func_get_args());
261 function p (/*...*/) {
262 $el = new HtmlElement('p');
263 return $el->_init2(func_get_args());
265 function pre (/*...*/) {
266 $el = new HtmlElement('pre');
267 return $el->_init2(func_get_args());
269 function blockquote (/*...*/) {
270 $el = new HtmlElement('blockquote');
271 return $el->_init2(func_get_args());
274 /****************************************/
275 function em (/*...*/) {
276 $el = new HtmlElement('em');
277 return $el->_init2(func_get_args());
279 function strong (/*...*/) {
280 $el = new HtmlElement('strong');
281 return $el->_init2(func_get_args());
283 function small (/*...*/) {
284 $el = new HtmlElement('small');
285 return $el->_init2(func_get_args());
288 /****************************************/
289 function tt (/*...*/) {
290 $el = new HtmlElement('tt');
291 return $el->_init2(func_get_args());
293 function u (/*...*/) {
294 $el = new HtmlElement('u');
295 return $el->_init2(func_get_args());
297 function sup (/*...*/) {
298 $el = new HtmlElement('sup');
299 return $el->_init2(func_get_args());
301 function sub (/*...*/) {
302 $el = new HtmlElement('sub');
303 return $el->_init2(func_get_args());
306 /****************************************/
307 function ul (/*...*/) {
308 $el = new HtmlElement('ul');
309 return $el->_init2(func_get_args());
311 function ol (/*...*/) {
312 $el = new HtmlElement('ol');
313 return $el->_init2(func_get_args());
315 function dl (/*...*/) {
316 $el = new HtmlElement('dl');
317 return $el->_init2(func_get_args());
319 function li (/*...*/) {
320 $el = new HtmlElement('li');
321 return $el->_init2(func_get_args());
323 function dt (/*...*/) {
324 $el = new HtmlElement('dt');
325 return $el->_init2(func_get_args());
327 function dd (/*...*/) {
328 $el = new HtmlElement('dd');
329 return $el->_init2(func_get_args());
332 /****************************************/
333 function table (/*...*/) {
334 $el = new HtmlElement('table');
335 return $el->_init2(func_get_args());
337 function caption (/*...*/) {
338 $el = new HtmlElement('caption');
339 return $el->_init2(func_get_args());
341 function thead (/*...*/) {
342 $el = new HtmlElement('thead');
343 return $el->_init2(func_get_args());
345 function tbody (/*...*/) {
346 $el = new HtmlElement('tbody');
347 return $el->_init2(func_get_args());
349 function tfoot (/*...*/) {
350 $el = new HtmlElement('tfoot');
351 return $el->_init2(func_get_args());
353 function tr (/*...*/) {
354 $el = new HtmlElement('tr');
355 return $el->_init2(func_get_args());
357 function td (/*...*/) {
358 $el = new HtmlElement('td');
359 return $el->_init2(func_get_args());
361 function th (/*...*/) {
362 $el = new HtmlElement('th');
363 return $el->_init2(func_get_args());
365 function colgroup (/*...*/) {
366 $el = new HtmlElement('colgroup');
367 return $el->_init2(func_get_args());
369 function col (/*...*/) {
370 $el = new HtmlElement('col');
371 return $el->_init2(func_get_args());
374 /****************************************/
375 function form (/*...*/) {
376 $el = new HtmlElement('form');
377 return $el->_init2(func_get_args());
379 function input (/*...*/) {
380 $el = new HtmlElement('input');
381 return $el->_init2(func_get_args());
383 function button (/*...*/) {
384 $el = new HtmlElement('button');
385 return $el->_init2(func_get_args());
387 function option (/*...*/) {
388 $el = new HtmlElement('option');
389 return $el->_init2(func_get_args());
391 function select (/*...*/) {
392 $el = new HtmlElement('select');
393 return $el->_init2(func_get_args());
395 function textarea (/*...*/) {
396 $el = new HtmlElement('textarea');
397 return $el->_init2(func_get_args());
399 function label (/*...*/) {
400 $el = new HtmlElement('label');
401 return $el->_init2(func_get_args());
404 /****************************************/
405 function area (/*...*/) {
406 $el = new HtmlElement('area');
407 return $el->_init2(func_get_args());
409 function map (/*...*/) {
410 $el = new HtmlElement('map');
411 return $el->_init2(func_get_args());
413 function frame (/*...*/) {
414 $el = new HtmlElement('frame');
415 return $el->_init2(func_get_args());
417 function frameset (/*...*/) {
418 $el = new HtmlElement('frameset');
419 return $el->_init2(func_get_args());
421 function iframe (/*...*/) {
422 $el = new HtmlElement('iframe');
423 return $el->_init2(func_get_args());
425 function nobody (/*...*/) {
426 $el = new HtmlElement('nobody');
427 return $el->_init2(func_get_args());
429 function object (/*...*/) {
430 $el = new HtmlElement('object');
431 return $el->_init2(func_get_args());
433 function embed (/*...*/) {
434 $el = new HtmlElement('embed');
435 return $el->_init2(func_get_args());
437 function param (/*...*/) {
438 $el = new HtmlElement('param');
439 return $el->_init2(func_get_args());
441 function fieldset (/*...*/) {
442 $el = new HtmlElement('fieldset');
443 return $el->_init2(func_get_args());
445 function legend (/*...*/) {
446 $el = new HtmlElement('legend');
447 return $el->_init2(func_get_args());
450 /****************************************/
451 function video (/*...*/) {
452 $el = new HtmlElement('video');
453 return $el->_init2(func_get_args());
457 define('HTMLTAG_EMPTY', 1);
458 define('HTMLTAG_INLINE', 2);
459 define('HTMLTAG_ACCEPTS_INLINE', 4);
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,
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
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'
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');
482 HTML::_setTagProperty(HTMLTAG_INLINE,
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
493 * Generate hidden form input fields.
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
502 * $args = array('x' => '2',
503 * 'y' => array('a' => 'aval', 'b' => 'bval'));
504 * $inputs = HiddenInputs($args);
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" />
512 * @return object An XmlContent object containing the inputs.
514 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
517 foreach ($query_args as $key => $val) {
518 if (in_array($key, $exclude)) continue;
519 $name = $pfx ? $pfx . "[$key]" : $key;
521 $inputs->pushContent(HiddenInputs($val, $name));
523 $inputs->pushContent(HTML::input(array('type' => 'hidden',
531 /** Generate a <script> tag containing javascript.
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.
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;
544 return HTML(HTML::script($script_args),"\n");
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");
553 /** Conditionally display content based of whether javascript is supported.
555 * This conditionally (on the client side) displays one of two alternate
556 * contents depending on whether the client supports javascript.
559 * The content you pass as arguments to this function must be block-level.
560 * (This is because the <noscript> tag is block-level.)
562 * @param mixed $if_content Content to display if the browser supports
565 * @param mixed $else_content Content to display if the browser does
566 * not support javascript.
570 function IfJavaScript($if_content = false, $else_content = false) {
573 $xml = AsXML($if_content);
574 $js = sprintf('document.write("%s");',
575 addcslashes($xml, "\0..\37!@\\\177..\377"));
576 $html[] = JavaScript($js);
579 $html[] = HTML::noscript(false, $else_content);
584 // (c-file-style: "gnu")
589 // c-hanging-comment-ender-p: nil
590 // indent-tabs-mode: nil