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
7 * Specialized for php-5.3: added public static 2010-06-07 09:51:37 rurban
9 * Todo: Add support for a JavaScript backend, a php2js compiler.
10 * HTML::div(array('onclick' => 'HTML::div(...)'))
12 if (!class_exists("XmlElement"))
13 require_once(dirname(__FILE__)."/XmlElement.php");
14 if (class_exists("HtmlElement"))
20 //apd_set_session_trace(35);
22 class HtmlElement extends XmlElement
24 function __construct ($tagname /* , $attr_or_content , ...*/) {
25 $this->_init(func_get_args());
26 $this->_properties = HTML::getTagProperties($tagname);
29 function _init ($args) {
31 $args = func_get_args();
33 assert(count($args) >= 1);
34 assert(is_string($args[0]));
35 $this->_tag = array_shift($args);
37 if ($args && is_array($args[0]))
38 $this->_attr = array_shift($args);
40 $this->_attr = array();
41 if ($args && $args[0] === false)
44 $this->setContent($args);
45 $this->_properties = HTML::getTagProperties($this->_tag);
50 * This is used by the static factory methods is class HTML.
52 function _init2 ($args) {
54 if (is_array($args[0]))
55 $this->_attr = array_shift($args);
56 elseif ($args[0] === false)
60 if (count($args) == 1 && is_array($args[0]))
62 $this->_content = $args;
66 /** Add a "tooltip" to an element.
68 * @param $tooltip_text string The tooltip text.
70 function addTooltip ($tooltip_text, $accesskey = null) {
71 $this->setAttr('title', $tooltip_text);
72 if ($accesskey) $this->setAccesskey($accesskey);
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;");
83 function setAccesskey ($key) {
85 if (strlen($key) != 1) return;
86 $this->setAttr("accesskey", $key);
88 if (!empty($this->_attr['title'])) {
89 if (preg_match("/\[(alt-)?(.)\]$/", $this->_attr['title'], $m))
91 $this->_attr['title'] = preg_replace
93 "[".$WikiTheme->tooltipAccessKeyPrefix()."-\\2]",
94 $this->_attr['title']);
96 $this->_attr['title'] .=
97 " [".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
100 $this->_attr['title'] =
101 "[".$WikiTheme->tooltipAccessKeyPrefix()."-$key]";
105 function emptyTag () {
106 if (($this->_properties & HTMLTAG_EMPTY) == 0)
107 return $this->startTag() . "</$this->_tag>";
109 return substr($this->startTag(), 0, -1) . " />";
112 function hasInlineContent () {
113 return ($this->_properties & HTMLTAG_ACCEPTS_INLINE) != 0;
116 function isInlineElement () {
117 return ($this->_properties & HTMLTAG_INLINE) != 0;
121 function HTML (/* $content, ... */) {
122 return new XmlContent(func_get_args());
125 class HTML extends HtmlElement {
126 public static function raw ($html_text) {
127 return new RawXml($html_text);
130 function getTagProperties($tag) {
131 $props = &$GLOBALS['HTML_TagProperties'];
132 return isset($props[$tag]) ? $props[$tag] : 0;
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) {
142 if (isset($props[$tag]))
143 $props[$tag] |= $prop_flag;
145 $props[$tag] = $prop_flag;
150 // Shell script to generate the following static methods:
157 echo " public static function $tag (/*...*/) {"
158 echo " \$el = new HtmlElement('$tag');"
159 echo " return \$el->_init2(func_get_args());"
164 /****************************************/'
165 mkfuncs link meta style script noscript
167 mkfuncs a img br span
169 mkfuncs h1 h2 h3 h4 h5 h6
171 mkfuncs hr div p pre blockquote
173 mkfuncs em strong small
177 mkfuncs ul ol dl li dt dd
179 mkfuncs table caption thead tbody tfoot tr td th colgroup col
181 mkfuncs form input option select textarea label fieldset legend
183 mkfuncs area map frame frameset iframe nobody object embed param
188 public static function link (/*...*/) {
189 $el = new HtmlElement('link');
190 return $el->_init2(func_get_args());
192 public static function meta (/*...*/) {
193 $el = new HtmlElement('meta');
194 return $el->_init2(func_get_args());
196 public static function style (/*...*/) {
197 $el = new HtmlElement('style');
198 return $el->_init2(func_get_args());
200 public static function script (/*...*/) {
201 $el = new HtmlElement('script');
202 return $el->_init2(func_get_args());
204 public static function noscript (/*...*/) {
205 $el = new HtmlElement('noscript');
206 return $el->_init2(func_get_args());
209 /****************************************/
210 public static function a (/*...*/) {
211 $el = new HtmlElement('a');
212 return $el->_init2(func_get_args());
214 public static function img (/*...*/) {
215 $el = new HtmlElement('img');
216 return $el->_init2(func_get_args());
218 public static function br (/*...*/) {
219 $el = new HtmlElement('br');
220 return $el->_init2(func_get_args());
222 public static function span (/*...*/) {
223 $el = new HtmlElement('span');
224 return $el->_init2(func_get_args());
227 /****************************************/
228 public static function h1 (/*...*/) {
229 $el = new HtmlElement('h1');
230 return $el->_init2(func_get_args());
232 public static function h2 (/*...*/) {
233 $el = new HtmlElement('h2');
234 return $el->_init2(func_get_args());
236 public static function h3 (/*...*/) {
237 $el = new HtmlElement('h3');
238 return $el->_init2(func_get_args());
240 public static function h4 (/*...*/) {
241 $el = new HtmlElement('h4');
242 return $el->_init2(func_get_args());
244 public static function h5 (/*...*/) {
245 $el = new HtmlElement('h5');
246 return $el->_init2(func_get_args());
248 public static function h6 (/*...*/) {
249 $el = new HtmlElement('h6');
250 return $el->_init2(func_get_args());
253 /****************************************/
254 public static function hr (/*...*/) {
255 $el = new HtmlElement('hr');
256 return $el->_init2(func_get_args());
258 public static function div (/*...*/) {
259 $el = new HtmlElement('div');
260 return $el->_init2(func_get_args());
262 public static function p (/*...*/) {
263 $el = new HtmlElement('p');
264 return $el->_init2(func_get_args());
266 public static function pre (/*...*/) {
267 $el = new HtmlElement('pre');
268 return $el->_init2(func_get_args());
270 public static function blockquote (/*...*/) {
271 $el = new HtmlElement('blockquote');
272 return $el->_init2(func_get_args());
275 /****************************************/
276 public static function em (/*...*/) {
277 $el = new HtmlElement('em');
278 return $el->_init2(func_get_args());
280 public static function strong (/*...*/) {
281 $el = new HtmlElement('strong');
282 return $el->_init2(func_get_args());
284 public static function small (/*...*/) {
285 $el = new HtmlElement('small');
286 return $el->_init2(func_get_args());
289 /****************************************/
290 public static function tt (/*...*/) {
291 $el = new HtmlElement('tt');
292 return $el->_init2(func_get_args());
294 public static function u (/*...*/) {
295 $el = new HtmlElement('u');
296 return $el->_init2(func_get_args());
298 public static function sup (/*...*/) {
299 $el = new HtmlElement('sup');
300 return $el->_init2(func_get_args());
302 public static function sub (/*...*/) {
303 $el = new HtmlElement('sub');
304 return $el->_init2(func_get_args());
307 /****************************************/
308 public static function ul (/*...*/) {
309 $el = new HtmlElement('ul');
310 return $el->_init2(func_get_args());
312 public static function ol (/*...*/) {
313 $el = new HtmlElement('ol');
314 return $el->_init2(func_get_args());
316 public static function dl (/*...*/) {
317 $el = new HtmlElement('dl');
318 return $el->_init2(func_get_args());
320 public static function li (/*...*/) {
321 $el = new HtmlElement('li');
322 return $el->_init2(func_get_args());
324 public static function dt (/*...*/) {
325 $el = new HtmlElement('dt');
326 return $el->_init2(func_get_args());
328 public static function dd (/*...*/) {
329 $el = new HtmlElement('dd');
330 return $el->_init2(func_get_args());
333 /****************************************/
334 public static function table (/*...*/) {
335 $el = new HtmlElement('table');
336 return $el->_init2(func_get_args());
338 public static function caption (/*...*/) {
339 $el = new HtmlElement('caption');
340 return $el->_init2(func_get_args());
342 public static function thead (/*...*/) {
343 $el = new HtmlElement('thead');
344 return $el->_init2(func_get_args());
346 public static function tbody (/*...*/) {
347 $el = new HtmlElement('tbody');
348 return $el->_init2(func_get_args());
350 public static function tfoot (/*...*/) {
351 $el = new HtmlElement('tfoot');
352 return $el->_init2(func_get_args());
354 public static function tr (/*...*/) {
355 $el = new HtmlElement('tr');
356 return $el->_init2(func_get_args());
358 public static function td (/*...*/) {
359 $el = new HtmlElement('td');
360 return $el->_init2(func_get_args());
362 public static function th (/*...*/) {
363 $el = new HtmlElement('th');
364 return $el->_init2(func_get_args());
366 public static function colgroup (/*...*/) {
367 $el = new HtmlElement('colgroup');
368 return $el->_init2(func_get_args());
370 public static function col (/*...*/) {
371 $el = new HtmlElement('col');
372 return $el->_init2(func_get_args());
375 /****************************************/
376 public static function form (/*...*/) {
377 $el = new HtmlElement('form');
378 return $el->_init2(func_get_args());
380 public static function input (/*...*/) {
381 $el = new HtmlElement('input');
382 return $el->_init2(func_get_args());
384 public static function button (/*...*/) {
385 $el = new HtmlElement('button');
386 return $el->_init2(func_get_args());
388 public static function option (/*...*/) {
389 $el = new HtmlElement('option');
390 return $el->_init2(func_get_args());
392 public static function select (/*...*/) {
393 $el = new HtmlElement('select');
394 return $el->_init2(func_get_args());
396 public static function textarea (/*...*/) {
397 $el = new HtmlElement('textarea');
398 return $el->_init2(func_get_args());
400 public static function label (/*...*/) {
401 $el = new HtmlElement('label');
402 return $el->_init2(func_get_args());
405 /****************************************/
406 public static function area (/*...*/) {
407 $el = new HtmlElement('area');
408 return $el->_init2(func_get_args());
410 public static function map (/*...*/) {
411 $el = new HtmlElement('map');
412 return $el->_init2(func_get_args());
414 public static function frame (/*...*/) {
415 $el = new HtmlElement('frame');
416 return $el->_init2(func_get_args());
418 public static function frameset (/*...*/) {
419 $el = new HtmlElement('frameset');
420 return $el->_init2(func_get_args());
422 public static function iframe (/*...*/) {
423 $el = new HtmlElement('iframe');
424 return $el->_init2(func_get_args());
426 public static function nobody (/*...*/) {
427 $el = new HtmlElement('nobody');
428 return $el->_init2(func_get_args());
430 public static function object (/*...*/) {
431 $el = new HtmlElement('object');
432 return $el->_init2(func_get_args());
434 public static function embed (/*...*/) {
435 $el = new HtmlElement('embed');
436 return $el->_init2(func_get_args());
438 public static function param (/*...*/) {
439 $el = new HtmlElement('param');
440 return $el->_init2(func_get_args());
442 public static function fieldset (/*...*/) {
443 $el = new HtmlElement('fieldset');
444 return $el->_init2(func_get_args());
446 public static function legend (/*...*/) {
447 $el = new HtmlElement('legend');
448 return $el->_init2(func_get_args());
451 /****************************************/
452 public static function video (/*...*/) {
453 $el = new HtmlElement('video');
454 return $el->_init2(func_get_args());
458 define('HTMLTAG_EMPTY', 1);
459 define('HTMLTAG_INLINE', 2);
460 define('HTMLTAG_ACCEPTS_INLINE', 4);
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,
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
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'
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');
483 HTML::_setTagProperty(HTMLTAG_INLINE,
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
494 * Generate hidden form input fields.
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
503 * $args = array('x' => '2',
504 * 'y' => array('a' => 'aval', 'b' => 'bval'));
505 * $inputs = HiddenInputs($args);
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" />
513 * @return object An XmlContent object containing the inputs.
515 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
518 foreach ($query_args as $key => $val) {
519 if (in_array($key, $exclude)) continue;
520 $name = $pfx ? $pfx . "[$key]" : $key;
522 $inputs->pushContent(HiddenInputs($val, $name));
524 $inputs->pushContent(HTML::input(array('type' => 'hidden',
532 /** Generate a <script> tag containing javascript.
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.
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;
545 return HTML(HTML::script($script_args),"\n");
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");
554 /** Conditionally display content based of whether javascript is supported.
556 * This conditionally (on the client side) displays one of two alternate
557 * contents depending on whether the client supports javascript.
560 * The content you pass as arguments to this function must be block-level.
561 * (This is because the <noscript> tag is block-level.)
563 * @param mixed $if_content Content to display if the browser supports
566 * @param mixed $else_content Content to display if the browser does
567 * not support javascript.
571 function IfJavaScript($if_content = false, $else_content = false) {
574 $xml = AsXML($if_content);
575 $js = sprintf('document.write("%s");',
576 addcslashes($xml, "\0..\37!@\\\177..\377"));
577 $html[] = JavaScript($js);
580 $html[] = HTML::noscript(false, $else_content);
585 // (c-file-style: "gnu")
590 // c-hanging-comment-ender-p: nil
591 // indent-tabs-mode: nil