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 * php-5.3 uses now HtmlElement5.php with public static
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 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;
149 // See admin/mkfuncs shell script to generate the following static methods
151 function link (/*...*/) {
152 $el = new HtmlElement('link');
153 return $el->_init2(func_get_args());
155 function meta (/*...*/) {
156 $el = new HtmlElement('meta');
157 return $el->_init2(func_get_args());
159 function style (/*...*/) {
160 $el = new HtmlElement('style');
161 return $el->_init2(func_get_args());
163 function script (/*...*/) {
164 $el = new HtmlElement('script');
165 return $el->_init2(func_get_args());
167 function noscript (/*...*/) {
168 $el = new HtmlElement('noscript');
169 return $el->_init2(func_get_args());
172 /****************************************/
173 function a (/*...*/) {
174 $el = new HtmlElement('a');
175 return $el->_init2(func_get_args());
177 function img (/*...*/) {
178 $el = new HtmlElement('img');
179 return $el->_init2(func_get_args());
181 function br (/*...*/) {
182 $el = new HtmlElement('br');
183 return $el->_init2(func_get_args());
185 function span (/*...*/) {
186 $el = new HtmlElement('span');
187 return $el->_init2(func_get_args());
190 /****************************************/
191 function h1 (/*...*/) {
192 $el = new HtmlElement('h1');
193 return $el->_init2(func_get_args());
195 function h2 (/*...*/) {
196 $el = new HtmlElement('h2');
197 return $el->_init2(func_get_args());
199 function h3 (/*...*/) {
200 $el = new HtmlElement('h3');
201 return $el->_init2(func_get_args());
203 function h4 (/*...*/) {
204 $el = new HtmlElement('h4');
205 return $el->_init2(func_get_args());
207 function h5 (/*...*/) {
208 $el = new HtmlElement('h5');
209 return $el->_init2(func_get_args());
211 function h6 (/*...*/) {
212 $el = new HtmlElement('h6');
213 return $el->_init2(func_get_args());
216 /****************************************/
217 function hr (/*...*/) {
218 $el = new HtmlElement('hr');
219 return $el->_init2(func_get_args());
221 function div (/*...*/) {
222 $el = new HtmlElement('div');
223 return $el->_init2(func_get_args());
225 function p (/*...*/) {
226 $el = new HtmlElement('p');
227 return $el->_init2(func_get_args());
229 function pre (/*...*/) {
230 $el = new HtmlElement('pre');
231 return $el->_init2(func_get_args());
233 function blockquote (/*...*/) {
234 $el = new HtmlElement('blockquote');
235 return $el->_init2(func_get_args());
238 /****************************************/
239 function em (/*...*/) {
240 $el = new HtmlElement('em');
241 return $el->_init2(func_get_args());
243 function strong (/*...*/) {
244 $el = new HtmlElement('strong');
245 return $el->_init2(func_get_args());
247 function small (/*...*/) {
248 $el = new HtmlElement('small');
249 return $el->_init2(func_get_args());
252 /****************************************/
253 function tt (/*...*/) {
254 $el = new HtmlElement('tt');
255 return $el->_init2(func_get_args());
257 function u (/*...*/) {
258 $el = new HtmlElement('u');
259 return $el->_init2(func_get_args());
261 function sup (/*...*/) {
262 $el = new HtmlElement('sup');
263 return $el->_init2(func_get_args());
265 function sub (/*...*/) {
266 $el = new HtmlElement('sub');
267 return $el->_init2(func_get_args());
270 /****************************************/
271 function ul (/*...*/) {
272 $el = new HtmlElement('ul');
273 return $el->_init2(func_get_args());
275 function ol (/*...*/) {
276 $el = new HtmlElement('ol');
277 return $el->_init2(func_get_args());
279 function dl (/*...*/) {
280 $el = new HtmlElement('dl');
281 return $el->_init2(func_get_args());
283 function li (/*...*/) {
284 $el = new HtmlElement('li');
285 return $el->_init2(func_get_args());
287 function dt (/*...*/) {
288 $el = new HtmlElement('dt');
289 return $el->_init2(func_get_args());
291 function dd (/*...*/) {
292 $el = new HtmlElement('dd');
293 return $el->_init2(func_get_args());
296 /****************************************/
297 function table (/*...*/) {
298 $el = new HtmlElement('table');
299 return $el->_init2(func_get_args());
301 function caption (/*...*/) {
302 $el = new HtmlElement('caption');
303 return $el->_init2(func_get_args());
305 function thead (/*...*/) {
306 $el = new HtmlElement('thead');
307 return $el->_init2(func_get_args());
309 function tbody (/*...*/) {
310 $el = new HtmlElement('tbody');
311 return $el->_init2(func_get_args());
313 function tfoot (/*...*/) {
314 $el = new HtmlElement('tfoot');
315 return $el->_init2(func_get_args());
317 function tr (/*...*/) {
318 $el = new HtmlElement('tr');
319 return $el->_init2(func_get_args());
321 function td (/*...*/) {
322 $el = new HtmlElement('td');
323 return $el->_init2(func_get_args());
325 function th (/*...*/) {
326 $el = new HtmlElement('th');
327 return $el->_init2(func_get_args());
329 function colgroup (/*...*/) {
330 $el = new HtmlElement('colgroup');
331 return $el->_init2(func_get_args());
333 function col (/*...*/) {
334 $el = new HtmlElement('col');
335 return $el->_init2(func_get_args());
338 /****************************************/
339 function form (/*...*/) {
340 $el = new HtmlElement('form');
341 return $el->_init2(func_get_args());
343 function input (/*...*/) {
344 $el = new HtmlElement('input');
345 return $el->_init2(func_get_args());
347 function button (/*...*/) {
348 $el = new HtmlElement('button');
349 return $el->_init2(func_get_args());
351 function option (/*...*/) {
352 $el = new HtmlElement('option');
353 return $el->_init2(func_get_args());
355 function select (/*...*/) {
356 $el = new HtmlElement('select');
357 return $el->_init2(func_get_args());
359 function textarea (/*...*/) {
360 $el = new HtmlElement('textarea');
361 return $el->_init2(func_get_args());
363 function label (/*...*/) {
364 $el = new HtmlElement('label');
365 return $el->_init2(func_get_args());
368 /****************************************/
369 function area (/*...*/) {
370 $el = new HtmlElement('area');
371 return $el->_init2(func_get_args());
373 function map (/*...*/) {
374 $el = new HtmlElement('map');
375 return $el->_init2(func_get_args());
377 function frame (/*...*/) {
378 $el = new HtmlElement('frame');
379 return $el->_init2(func_get_args());
381 function frameset (/*...*/) {
382 $el = new HtmlElement('frameset');
383 return $el->_init2(func_get_args());
385 function iframe (/*...*/) {
386 $el = new HtmlElement('iframe');
387 return $el->_init2(func_get_args());
389 function nobody (/*...*/) {
390 $el = new HtmlElement('nobody');
391 return $el->_init2(func_get_args());
393 function object (/*...*/) {
394 $el = new HtmlElement('object');
395 return $el->_init2(func_get_args());
397 function embed (/*...*/) {
398 $el = new HtmlElement('embed');
399 return $el->_init2(func_get_args());
401 function param (/*...*/) {
402 $el = new HtmlElement('param');
403 return $el->_init2(func_get_args());
405 function fieldset (/*...*/) {
406 $el = new HtmlElement('fieldset');
407 return $el->_init2(func_get_args());
409 function legend (/*...*/) {
410 $el = new HtmlElement('legend');
411 return $el->_init2(func_get_args());
414 /****************************************/
415 function video (/*...*/) {
416 $el = new HtmlElement('video');
417 return $el->_init2(func_get_args());
421 define('HTMLTAG_EMPTY', 1);
422 define('HTMLTAG_INLINE', 2);
423 define('HTMLTAG_ACCEPTS_INLINE', 4);
425 HTML::_setTagProperty(HTMLTAG_EMPTY,
426 'area base basefont br col frame hr img input isindex link meta param');
427 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
429 'b big i small tt ' // %fontstyle
430 . 's strike u ' // (deprecated)
431 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
432 . 'a img object embed br script map q sub sup span bdo '//%special
433 . 'button input label option select textarea label ' //%formctl
435 // %block elements which contain inline content
436 . 'address h1 h2 h3 h4 h5 h6 p pre '
437 // %block elements which contain either block or inline content
438 . 'div fieldset frameset'
440 // other with inline content
441 . 'caption dt label legend video '
442 // other with either inline or block
443 . 'dd del ins li td th colgroup');
445 HTML::_setTagProperty(HTMLTAG_INLINE,
447 'b big i small tt ' // %fontstyle
448 . 's strike u ' // (deprecated)
449 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
450 . 'a img object br script map q sub sup span bdo '//%special
451 . 'button input label option select textarea ' //%formctl
456 * Generate hidden form input fields.
458 * @param $query_args hash A hash mapping names to values for the hidden inputs.
459 * Values in the hash can themselves be hashes. The will result in hidden inputs
460 * which will reconstruct the nested structure in the resulting query args as
465 * $args = array('x' => '2',
466 * 'y' => array('a' => 'aval', 'b' => 'bval'));
467 * $inputs = HiddenInputs($args);
471 * <input type="hidden" name="x" value = "2" />
472 * <input type="hidden" name="y[a]" value = "aval" />
473 * <input type="hidden" name="y[b]" value = "bval" />
475 * @return object An XmlContent object containing the inputs.
477 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
480 foreach ($query_args as $key => $val) {
481 if (in_array($key, $exclude)) continue;
482 $name = $pfx ? $pfx . "[$key]" : $key;
484 $inputs->pushContent(HiddenInputs($val, $name));
486 $inputs->pushContent(HTML::input(array('type' => 'hidden',
493 /** Generate a <script> tag containing javascript.
495 * @param string $js The javascript.
496 * @param string $script_args (optional) hash of script tags options
497 * e.g. to provide another version or the defer attr
498 * @return HtmlElement A <script> element.
500 function JavaScript ($js, $script_args = false) {
501 $default_script_args = array(//'version' => 'JavaScript', // not xhtml conformant
502 'type' => 'text/javascript');
503 $script_args = $script_args ? array_merge($default_script_args, $script_args)
504 : $default_script_args;
506 return HTML(HTML::script($script_args),"\n");
508 // see http://devedge.netscape.com/viewsource/2003/xhtml-style-script/
509 return HTML(HTML::script($script_args,
510 new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
511 . "\n".trim($js)."\n"
512 . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->"))),"\n");
515 /** Conditionally display content based of whether javascript is supported.
517 * This conditionally (on the client side) displays one of two alternate
518 * contents depending on whether the client supports javascript.
521 * The content you pass as arguments to this function must be block-level.
522 * (This is because the <noscript> tag is block-level.)
524 * @param mixed $if_content Content to display if the browser supports
527 * @param mixed $else_content Content to display if the browser does
528 * not support javascript.
532 function IfJavaScript($if_content = false, $else_content = false) {
535 $xml = AsXML($if_content);
536 $js = sprintf('document.write("%s");',
537 addcslashes($xml, "\0..\37!@\\\177..\377"));
538 $html[] = JavaScript($js);
541 $html[] = HTML::noscript(false, $else_content);
550 // c-hanging-comment-ender-p: nil
551 // indent-tabs-mode: nil