3 * Copyright © 2010 Reini Urban
4 * Copyright © 2014 Marc-Etienne Vargenau, Alcatel-Lucent
6 * This file is part of PhpWiki.
8 * PhpWiki is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * PhpWiki is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * SPDX-License-Identifier: GPL-2.0-or-later
27 * Code for writing the HTML subset of XML.
28 * @author: Jeff Dairiki
30 * Todo: Add support for a JavaScript backend, a php2js compiler.
31 * HTML::div(array('onclick' => 'HTML::div(...)'))
33 if (!class_exists("XmlElement"))
34 require_once(dirname(__FILE__) . "/XmlElement.php");
35 if (class_exists("HtmlElement"))
42 class HtmlElement extends XmlElement
47 function __construct($tagname /* , $attr_or_content , ...*/)
49 $this->_init(func_get_args());
50 $this->_properties = HTML::getTagProperties($tagname);
56 $args = func_get_args();
58 assert(count($args) >= 1);
59 assert(is_string($args[0]));
60 $this->_tag = array_shift($args);
62 if ($args && is_array($args[0]))
63 $this->_attr = array_shift($args);
65 $this->_attr = array();
66 if ($args && $args[0] === false)
69 $this->setContent($args);
70 $this->_properties = HTML::getTagProperties($this->_tag);
74 * This is used by the static factory methods is class HTML.
79 protected function _init2($args)
82 if (is_array($args[0]))
83 $this->_attr = array_shift($args);
84 elseif ($args[0] === false)
88 if (count($args) == 1 && is_array($args[0]))
90 $this->_content = $args;
94 /** Add a "tooltip" to an element.
96 * @param string $tooltip_text The tooltip text.
98 function addTooltip($tooltip_text)
100 $this->setAttr('title', $tooltip_text);
102 // FIXME: this should be initialized from title by an onLoad() function.
103 // (though, that may not be possible.)
104 $this->setAttr('onmouseover',
105 sprintf('window.status="%s"; return true;',
106 addslashes($tooltip_text)));
107 $this->setAttr('onmouseout', "window.status='';return true;");
112 if (($this->_properties & HTMLTAG_EMPTY) == 0)
113 return $this->startTag() . "</$this->_tag>";
115 return substr($this->startTag(), 0, -1) . " />";
118 function hasInlineContent()
120 return ($this->_properties & HTMLTAG_ACCEPTS_INLINE) != 0;
123 function isInlineElement()
125 return ($this->_properties & HTMLTAG_INLINE) != 0;
129 function HTML( /* $content, ... */)
131 return new XmlContent(func_get_args());
134 class HTML extends HtmlElement
136 public static function raw($html_text)
138 return new RawXml($html_text);
141 public static function getTagProperties($tag)
143 $props = &$GLOBALS['HTML_TagProperties'];
144 return isset($props[$tag]) ? $props[$tag] : 0;
147 public static function _setTagProperty($prop_flag, $tags)
149 $props = &$GLOBALS['HTML_TagProperties'];
150 if (is_string($tags))
151 $tags = preg_split('/\s+/', $tags);
152 foreach ($tags as $tag) {
155 if (isset($props[$tag]))
156 $props[$tag] |= $prop_flag;
158 $props[$tag] = $prop_flag;
162 // See admin/mkfuncs shell script to generate the following static methods
164 public static function link( /*...*/)
166 $el = new HtmlElement('link');
167 return $el->_init2(func_get_args());
170 public static function meta( /*...*/)
172 $el = new HtmlElement('meta');
173 return $el->_init2(func_get_args());
176 public static function style( /*...*/)
178 $el = new HtmlElement('style');
179 return $el->_init2(func_get_args());
182 public static function script( /*...*/)
184 $el = new HtmlElement('script');
185 return $el->_init2(func_get_args());
188 public static function noscript( /*...*/)
190 $el = new HtmlElement('noscript');
191 return $el->_init2(func_get_args());
194 /****************************************/
195 public static function a( /*...*/)
197 $el = new HtmlElement('a');
198 return $el->_init2(func_get_args());
201 public static function img( /*...*/)
203 $el = new HtmlElement('img');
204 return $el->_init2(func_get_args());
207 public static function br( /*...*/)
209 $el = new HtmlElement('br');
210 return $el->_init2(func_get_args());
213 public static function span( /*...*/)
215 $el = new HtmlElement('span');
216 return $el->_init2(func_get_args());
219 /****************************************/
220 public static function h1( /*...*/)
222 $el = new HtmlElement('h1');
223 return $el->_init2(func_get_args());
226 public static function h2( /*...*/)
228 $el = new HtmlElement('h2');
229 return $el->_init2(func_get_args());
232 public static function h3( /*...*/)
234 $el = new HtmlElement('h3');
235 return $el->_init2(func_get_args());
238 public static function h4( /*...*/)
240 $el = new HtmlElement('h4');
241 return $el->_init2(func_get_args());
244 public static function h5( /*...*/)
246 $el = new HtmlElement('h5');
247 return $el->_init2(func_get_args());
250 public static function h6( /*...*/)
252 $el = new HtmlElement('h6');
253 return $el->_init2(func_get_args());
256 /****************************************/
257 public static function hr( /*...*/)
259 $el = new HtmlElement('hr');
260 return $el->_init2(func_get_args());
263 public static function div( /*...*/)
265 $el = new HtmlElement('div');
266 return $el->_init2(func_get_args());
269 public static function p( /*...*/)
271 $el = new HtmlElement('p');
272 return $el->_init2(func_get_args());
275 public static function pre( /*...*/)
277 $el = new HtmlElement('pre');
278 return $el->_init2(func_get_args());
281 public static function blockquote( /*...*/)
283 $el = new HtmlElement('blockquote');
284 return $el->_init2(func_get_args());
287 /****************************************/
288 public static function em( /*...*/)
290 $el = new HtmlElement('em');
291 return $el->_init2(func_get_args());
294 public static function strong( /*...*/)
296 $el = new HtmlElement('strong');
297 return $el->_init2(func_get_args());
300 public static function small( /*...*/)
302 $el = new HtmlElement('small');
303 return $el->_init2(func_get_args());
306 public static function abbr( /*...*/)
308 $el = new HtmlElement('abbr');
309 return $el->_init2(func_get_args());
312 public static function acronym( /*...*/)
314 $el = new HtmlElement('acronym');
315 return $el->_init2(func_get_args());
318 public static function cite( /*...*/)
320 $el = new HtmlElement('cite');
321 return $el->_init2(func_get_args());
324 public static function code( /*...*/)
326 $el = new HtmlElement('code');
327 return $el->_init2(func_get_args());
330 public static function dfn( /*...*/)
332 $el = new HtmlElement('dfn');
333 return $el->_init2(func_get_args());
336 public static function kbd( /*...*/)
338 $el = new HtmlElement('kbd');
339 return $el->_init2(func_get_args());
342 public static function samp( /*...*/)
344 $el = new HtmlElement('samp');
345 return $el->_init2(func_get_args());
348 /****************************************/
349 public static function tt( /*...*/)
351 $el = new HtmlElement('tt');
352 return $el->_init2(func_get_args());
355 public static function u( /*...*/)
357 $el = new HtmlElement('u');
358 return $el->_init2(func_get_args());
361 public static function sup( /*...*/)
363 $el = new HtmlElement('sup');
364 return $el->_init2(func_get_args());
367 public static function sub( /*...*/)
369 $el = new HtmlElement('sub');
370 return $el->_init2(func_get_args());
373 /****************************************/
374 public static function ul( /*...*/)
376 $el = new HtmlElement('ul');
377 return $el->_init2(func_get_args());
380 public static function ol( /*...*/)
382 $el = new HtmlElement('ol');
383 return $el->_init2(func_get_args());
386 public static function dl( /*...*/)
388 $el = new HtmlElement('dl');
389 return $el->_init2(func_get_args());
392 public static function li( /*...*/)
394 $el = new HtmlElement('li');
395 return $el->_init2(func_get_args());
398 public static function dt( /*...*/)
400 $el = new HtmlElement('dt');
401 return $el->_init2(func_get_args());
404 public static function dd( /*...*/)
406 $el = new HtmlElement('dd');
407 return $el->_init2(func_get_args());
410 /****************************************/
411 public static function table( /*...*/)
413 $el = new HtmlElement('table');
414 return $el->_init2(func_get_args());
417 public static function caption( /*...*/)
419 $el = new HtmlElement('caption');
420 return $el->_init2(func_get_args());
423 public static function thead( /*...*/)
425 $el = new HtmlElement('thead');
426 return $el->_init2(func_get_args());
429 public static function tbody( /*...*/)
431 $el = new HtmlElement('tbody');
432 return $el->_init2(func_get_args());
435 public static function tfoot( /*...*/)
437 $el = new HtmlElement('tfoot');
438 return $el->_init2(func_get_args());
441 public static function tr( /*...*/)
443 $el = new HtmlElement('tr');
444 return $el->_init2(func_get_args());
447 public static function td( /*...*/)
449 $el = new HtmlElement('td');
450 return $el->_init2(func_get_args());
453 public static function th( /*...*/)
455 $el = new HtmlElement('th');
456 return $el->_init2(func_get_args());
459 public static function colgroup( /*...*/)
461 $el = new HtmlElement('colgroup');
462 return $el->_init2(func_get_args());
465 public static function col( /*...*/)
467 $el = new HtmlElement('col');
468 return $el->_init2(func_get_args());
471 /****************************************/
472 public static function form( /*...*/)
474 $el = new HtmlElement('form');
475 return $el->_init2(func_get_args());
478 public static function input( /*...*/)
480 $el = new HtmlElement('input');
481 return $el->_init2(func_get_args());
484 public static function button( /*...*/)
486 $el = new HtmlElement('button');
487 return $el->_init2(func_get_args());
490 public static function option( /*...*/)
492 $el = new HtmlElement('option');
493 return $el->_init2(func_get_args());
496 public static function select( /*...*/)
498 $el = new HtmlElement('select');
499 return $el->_init2(func_get_args());
502 public static function textarea( /*...*/)
504 $el = new HtmlElement('textarea');
505 return $el->_init2(func_get_args());
508 public static function label( /*...*/)
510 $el = new HtmlElement('label');
511 return $el->_init2(func_get_args());
514 /****************************************/
515 public static function area( /*...*/)
517 $el = new HtmlElement('area');
518 return $el->_init2(func_get_args());
521 public static function map( /*...*/)
523 $el = new HtmlElement('map');
524 return $el->_init2(func_get_args());
527 public static function iframe( /*...*/)
529 $el = new HtmlElement('iframe');
530 return $el->_init2(func_get_args());
533 public static function nobody( /*...*/)
535 $el = new HtmlElement('nobody');
536 return $el->_init2(func_get_args());
539 public static function object( /*...*/)
541 $el = new HtmlElement('object');
542 return $el->_init2(func_get_args());
545 public static function embed( /*...*/)
547 $el = new HtmlElement('embed');
548 return $el->_init2(func_get_args());
551 public static function param( /*...*/)
553 $el = new HtmlElement('param');
554 return $el->_init2(func_get_args());
557 public static function fieldset( /*...*/)
559 $el = new HtmlElement('fieldset');
560 return $el->_init2(func_get_args());
563 public static function legend( /*...*/)
565 $el = new HtmlElement('legend');
566 return $el->_init2(func_get_args());
569 /****************************************/
570 public static function video( /*...*/)
572 $el = new HtmlElement('video');
573 return $el->_init2(func_get_args());
577 define('HTMLTAG_EMPTY', 1);
578 define('HTMLTAG_INLINE', 2);
579 define('HTMLTAG_ACCEPTS_INLINE', 4);
581 HTML::_setTagProperty(HTMLTAG_EMPTY,
582 'area base basefont br col embed hr img input isindex link meta param');
583 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
585 'b big i small tt ' // %fontstyle
586 . 's strike u ' // (deprecated)
587 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
588 . 'a img object embed br script map q sub sup span bdo ' //%special
589 . 'button input label option select textarea label ' //%formctl
591 // %block elements which contain inline content
592 . 'address h1 h2 h3 h4 h5 h6 p pre '
593 // %block elements which contain either block or inline content
596 // other with inline content
597 . 'caption dt label legend video '
598 // other with either inline or block
599 . 'dd del ins li td th colgroup');
601 HTML::_setTagProperty(HTMLTAG_INLINE,
603 'b big i small tt ' // %fontstyle
604 . 's strike u ' // (deprecated)
605 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
606 . 'a img object br script map q sub sup span bdo ' //%special
607 . 'button input label option select textarea ' //%formctl
612 * Generate hidden form input fields.
614 * @param array $query_args A hash mapping names to values for the hidden inputs.
615 * Values in the hash can themselves be hashes. The will result in hidden inputs
616 * which will reconstruct the nested structure in the resulting query args as
621 * $args = array('x' => '2',
622 * 'y' => array('a' => 'aval', 'b' => 'bval'));
623 * $inputs = HiddenInputs($args);
627 * <input type="hidden" name="x" value = "2" />
628 * <input type="hidden" name="y[a]" value = "aval" />
629 * <input type="hidden" name="y[b]" value = "bval" />
632 * @param array $exclude
633 * @return object An XmlContent object containing the inputs.
635 function HiddenInputs($query_args, $pfx = false, $exclude = array())
639 foreach ($query_args as $key => $val) {
640 if (in_array($key, $exclude)) continue;
641 $name = $pfx ? $pfx . "[$key]" : $key;
643 $inputs->pushContent(HiddenInputs($val, $name));
645 $inputs->pushContent(HTML::input(array('type' => 'hidden',
652 /** Generate a <script> tag containing javascript.
654 * @param string $js The javascript.
655 * @param array $script_args (optional) hash of script tags options
656 * e.g. to provide another version or the defer attr
657 * @return HtmlElement A <script> element.
659 function JavaScript($js, $script_args = array())
661 $default_script_args = array('type' => 'text/javascript');
662 $script_args = $script_args ? array_merge($default_script_args, $script_args)
663 : $default_script_args;
665 return HTML(HTML::script($script_args), "\n");
667 return HTML(HTML::script($script_args,
668 new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
669 . "\n" . trim($js) . "\n"
670 . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->"))), "\n");
673 /** Conditionally display content based of whether javascript is supported.
675 * This conditionally (on the client side) displays one of two alternate
676 * contents depending on whether the client supports javascript.
679 * The content you pass as arguments to this function must be block-level.
680 * (This is because the <noscript> tag is block-level.)
682 * @param mixed $if_content Content to display if the browser supports
685 * @param mixed $else_content Content to display if the browser does
686 * not support javascript.
690 function IfJavaScript($if_content = false, $else_content = false)
694 $xml = AsXML($if_content);
695 $js = sprintf('document.write("%s");',
696 addcslashes($xml, "\0..\37!@\\\177..\377"));
697 $html[] = JavaScript($js);
700 $html[] = HTML::noscript(false, $else_content);