1 <?php rcs_id('$Id: HtmlElement.php,v 1.47 2005-08-06 12:53:36 rurban Exp $');
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 if (!class_exists("XmlElement"))
9 require_once(dirname(__FILE__)."/XmlElement.php");
10 if (class_exists("HtmlElement"))
16 //apd_set_session_trace(35);
18 class HtmlElement extends XmlElement
20 function __construct ($tagname /* , $attr_or_content , ...*/) {
21 $this->_init(func_get_args());
22 $this->_properties = HTML::getTagProperties($tagname);
25 function _init ($args) {
27 $args = func_get_args();
29 assert(count($args) >= 1);
30 assert(is_string($args[0]));
31 $this->_tag = array_shift($args);
33 if ($args && is_array($args[0]))
34 $this->_attr = array_shift($args);
36 $this->_attr = array();
37 if ($args && $args[0] === false)
40 $this->setContent($args);
41 $this->_properties = HTML::getTagProperties($this->_tag);
46 * This is used by the static factory methods is class HTML.
48 function _init2 ($args) {
50 if (is_array($args[0]))
51 $this->_attr = array_shift($args);
52 elseif ($args[0] === false)
56 if (count($args) == 1 && is_array($args[0]))
58 $this->_content = $args;
62 /** Add a "tooltip" to an element.
64 * @param $tooltip_text string The tooltip text.
66 function addTooltip ($tooltip_text) {
67 $this->setAttr('title', $tooltip_text);
69 // FIXME: this should be initialized from title by an onLoad() function.
70 // (though, that may not be possible.)
71 $qtooltip = str_replace("'", "\\'", $tooltip_text);
72 $this->setAttr('onmouseover',
73 sprintf('window.status="%s"; return true;',
74 addslashes($tooltip_text)));
75 $this->setAttr('onmouseout', "window.status='';return true;");
78 function emptyTag () {
79 if (($this->_properties & HTMLTAG_EMPTY) == 0)
80 return $this->startTag() . "</$this->_tag>";
82 return substr($this->startTag(), 0, -1) . " />";
85 function hasInlineContent () {
86 return ($this->_properties & HTMLTAG_ACCEPTS_INLINE) != 0;
89 function isInlineElement () {
90 return ($this->_properties & HTMLTAG_INLINE) != 0;
94 function HTML (/* $content, ... */) {
95 return new XmlContent(func_get_args());
98 class HTML extends HtmlElement {
99 function raw ($html_text) {
100 return new RawXml($html_text);
103 function getTagProperties($tag) {
104 $props = &$GLOBALS['HTML_TagProperties'];
105 return isset($props[$tag]) ? $props[$tag] : 0;
108 function _setTagProperty($prop_flag, $tags) {
109 $props = &$GLOBALS['HTML_TagProperties'];
110 if (is_string($tags))
111 $tags = preg_split('/\s+/', $tags);
112 foreach ($tags as $tag) {
115 if (isset($props[$tag]))
116 $props[$tag] |= $prop_flag;
118 $props[$tag] = $prop_flag;
123 // Shell script to generate the following static methods:
126 // function mkfuncs () {
129 // echo " function $tag (/*...*/) {"
130 // echo " \$el = new HtmlElement('$tag');"
131 // echo " return \$el->_init2(func_get_args());"
136 // /****************************************/'
137 // mkfuncs link meta style script noscript
139 // mkfuncs a img br span
141 // mkfuncs h1 h2 h3 h4 h5 h6
143 // mkfuncs hr div p pre blockquote
145 // mkfuncs em strong small
147 // mkfuncs tt u sup sub
149 // mkfuncs ul ol dl li dt dd
151 // mkfuncs table caption thead tbody tfoot tr td th colgroup col
153 // mkfuncs form input option select textarea
155 // mkfuncs area map frame frameset iframe nobody
157 function link (/*...*/) {
158 $el = new HtmlElement('link');
159 return $el->_init2(func_get_args());
161 function meta (/*...*/) {
162 $el = new HtmlElement('meta');
163 return $el->_init2(func_get_args());
165 function style (/*...*/) {
166 $el = new HtmlElement('style');
167 return $el->_init2(func_get_args());
169 function script (/*...*/) {
170 $el = new HtmlElement('script');
171 return $el->_init2(func_get_args());
173 function noscript (/*...*/) {
174 $el = new HtmlElement('noscript');
175 return $el->_init2(func_get_args());
178 /****************************************/
179 function a (/*...*/) {
180 $el = new HtmlElement('a');
181 return $el->_init2(func_get_args());
183 function img (/*...*/) {
184 $el = new HtmlElement('img');
185 return $el->_init2(func_get_args());
187 function br (/*...*/) {
188 $el = new HtmlElement('br');
189 return $el->_init2(func_get_args());
191 function span (/*...*/) {
192 $el = new HtmlElement('span');
193 return $el->_init2(func_get_args());
196 /****************************************/
197 function h1 (/*...*/) {
198 $el = new HtmlElement('h1');
199 return $el->_init2(func_get_args());
201 function h2 (/*...*/) {
202 $el = new HtmlElement('h2');
203 return $el->_init2(func_get_args());
205 function h3 (/*...*/) {
206 $el = new HtmlElement('h3');
207 return $el->_init2(func_get_args());
209 function h4 (/*...*/) {
210 $el = new HtmlElement('h4');
211 return $el->_init2(func_get_args());
213 function h5 (/*...*/) {
214 $el = new HtmlElement('h5');
215 return $el->_init2(func_get_args());
217 function h6 (/*...*/) {
218 $el = new HtmlElement('h6');
219 return $el->_init2(func_get_args());
222 /****************************************/
223 function hr (/*...*/) {
224 $el = new HtmlElement('hr');
225 return $el->_init2(func_get_args());
227 function div (/*...*/) {
228 $el = new HtmlElement('div');
229 return $el->_init2(func_get_args());
231 function p (/*...*/) {
232 $el = new HtmlElement('p');
233 return $el->_init2(func_get_args());
235 function pre (/*...*/) {
236 $el = new HtmlElement('pre');
237 return $el->_init2(func_get_args());
239 function blockquote (/*...*/) {
240 $el = new HtmlElement('blockquote');
241 return $el->_init2(func_get_args());
244 /****************************************/
245 function em (/*...*/) {
246 $el = new HtmlElement('em');
247 return $el->_init2(func_get_args());
249 function strong (/*...*/) {
250 $el = new HtmlElement('strong');
251 return $el->_init2(func_get_args());
253 function small (/*...*/) {
254 $el = new HtmlElement('small');
255 return $el->_init2(func_get_args());
258 /****************************************/
259 function tt (/*...*/) {
260 $el = new HtmlElement('tt');
261 return $el->_init2(func_get_args());
263 function u (/*...*/) {
264 $el = new HtmlElement('u');
265 return $el->_init2(func_get_args());
267 function sup (/*...*/) {
268 $el = new HtmlElement('sup');
269 return $el->_init2(func_get_args());
271 function sub (/*...*/) {
272 $el = new HtmlElement('sub');
273 return $el->_init2(func_get_args());
276 /****************************************/
277 function ul (/*...*/) {
278 $el = new HtmlElement('ul');
279 return $el->_init2(func_get_args());
281 function ol (/*...*/) {
282 $el = new HtmlElement('ol');
283 return $el->_init2(func_get_args());
285 function dl (/*...*/) {
286 $el = new HtmlElement('dl');
287 return $el->_init2(func_get_args());
289 function li (/*...*/) {
290 $el = new HtmlElement('li');
291 return $el->_init2(func_get_args());
293 function dt (/*...*/) {
294 $el = new HtmlElement('dt');
295 return $el->_init2(func_get_args());
297 function dd (/*...*/) {
298 $el = new HtmlElement('dd');
299 return $el->_init2(func_get_args());
302 /****************************************/
303 function table (/*...*/) {
304 $el = new HtmlElement('table');
305 return $el->_init2(func_get_args());
307 function caption (/*...*/) {
308 $el = new HtmlElement('caption');
309 return $el->_init2(func_get_args());
311 function thead (/*...*/) {
312 $el = new HtmlElement('thead');
313 return $el->_init2(func_get_args());
315 function tbody (/*...*/) {
316 $el = new HtmlElement('tbody');
317 return $el->_init2(func_get_args());
319 function tfoot (/*...*/) {
320 $el = new HtmlElement('tfoot');
321 return $el->_init2(func_get_args());
323 function tr (/*...*/) {
324 $el = new HtmlElement('tr');
325 return $el->_init2(func_get_args());
327 function td (/*...*/) {
328 $el = new HtmlElement('td');
329 return $el->_init2(func_get_args());
331 function th (/*...*/) {
332 $el = new HtmlElement('th');
333 return $el->_init2(func_get_args());
335 function colgroup (/*...*/) {
336 $el = new HtmlElement('colgroup');
337 return $el->_init2(func_get_args());
339 function col (/*...*/) {
340 $el = new HtmlElement('col');
341 return $el->_init2(func_get_args());
344 /****************************************/
345 function form (/*...*/) {
346 $el = new HtmlElement('form');
347 return $el->_init2(func_get_args());
349 function input (/*...*/) {
350 $el = new HtmlElement('input');
351 return $el->_init2(func_get_args());
353 function button (/*...*/) {
354 $el = new HtmlElement('button');
355 return $el->_init2(func_get_args());
357 function option (/*...*/) {
358 $el = new HtmlElement('option');
359 return $el->_init2(func_get_args());
361 function select (/*...*/) {
362 $el = new HtmlElement('select');
363 return $el->_init2(func_get_args());
365 function textarea (/*...*/) {
366 $el = new HtmlElement('textarea');
367 return $el->_init2(func_get_args());
369 function label (/*...*/) {
370 $el = new HtmlElement('label');
371 return $el->_init2(func_get_args());
374 /****************************************/
375 function area (/*...*/) {
376 $el = new HtmlElement('area');
377 return $el->_init2(func_get_args());
379 function map (/*...*/) {
380 $el = new HtmlElement('map');
381 return $el->_init2(func_get_args());
383 function frame (/*...*/) {
384 $el = new HtmlElement('frame');
385 return $el->_init2(func_get_args());
387 function frameset (/*...*/) {
388 $el = new HtmlElement('frameset');
389 return $el->_init2(func_get_args());
391 function iframe (/*...*/) {
392 $el = new HtmlElement('iframe');
393 return $el->_init2(func_get_args());
395 function nobody (/*...*/) {
396 $el = new HtmlElement('nobody');
397 return $el->_init2(func_get_args());
399 function object (/*...*/) {
400 $el = new HtmlElement('object');
401 return $el->_init2(func_get_args());
403 function embed (/*...*/) {
404 $el = new HtmlElement('embed');
405 return $el->_init2(func_get_args());
409 define('HTMLTAG_EMPTY', 1);
410 define('HTMLTAG_INLINE', 2);
411 define('HTMLTAG_ACCEPTS_INLINE', 4);
414 HTML::_setTagProperty(HTMLTAG_EMPTY,
415 'area base basefont br col frame hr img input isindex link meta param');
416 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
418 'b big i small tt ' // %fontstyle
419 . 's strike u ' // (deprecated)
420 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
421 . 'a img object embed br script map q sub sup span bdo '//%special
422 . 'button input label option select textarea label ' //%formctl
424 // %block elements which contain inline content
425 . 'address h1 h2 h3 h4 h5 h6 p pre '
426 // %block elements which contain either block or inline content
427 . 'div fieldset frameset'
429 // other with inline content
430 . 'caption dt label legend '
431 // other with either inline or block
432 . 'dd del ins li td th colgroup');
434 HTML::_setTagProperty(HTMLTAG_INLINE,
436 'b big i small tt ' // %fontstyle
437 . 's strike u ' // (deprecated)
438 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
439 . 'a img object br script map q sub sup span bdo '//%special
440 . 'button input label option select textarea ' //%formctl
445 * Generate hidden form input fields.
447 * @param $query_args hash A hash mapping names to values for the hidden inputs.
448 * Values in the hash can themselves be hashes. The will result in hidden inputs
449 * which will reconstruct the nested structure in the resulting query args as
454 * $args = array('x' => '2',
455 * 'y' => array('a' => 'aval', 'b' => 'bval'));
456 * $inputs = HiddenInputs($args);
460 * <input type="hidden" name="x" value = "2" />
461 * <input type="hidden" name="y[a]" value = "aval" />
462 * <input type="hidden" name="y[b]" value = "bval" />
464 * @return object An XmlContent object containing the inputs.
466 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
469 foreach ($query_args as $key => $val) {
470 if (in_array($key, $exclude)) continue;
471 $name = $pfx ? $pfx . "[$key]" : $key;
473 $inputs->pushContent(HiddenInputs($val, $name));
475 $inputs->pushContent(HTML::input(array('type' => 'hidden',
483 /** Generate a <script> tag containing javascript.
485 * @param string $js The javascript.
486 * @param string $script_args (optional) hash of script tags options
487 * e.g. to provide another version or the defer attr
488 * @return HtmlElement A <script> element.
490 function JavaScript ($js, $script_args = false) {
491 $default_script_args = array(//'version' => 'JavaScript', // not xhtml conformant
492 'type' => 'text/javascript');
493 $script_args = $script_args ? array_merge($default_script_args, $script_args)
494 : $default_script_args;
496 return HTML(HTML::script($script_args),"\n");
498 // see http://devedge.netscape.com/viewsource/2003/xhtml-style-script/
499 return HTML(HTML::script($script_args,
500 new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
501 . "\n".trim($js)."\n"
502 . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->"))),"\n");
505 /** Conditionally display content based of whether javascript is supported.
507 * This conditionally (on the client side) displays one of two alternate
508 * contents depending on whether the client supports javascript.
511 * The content you pass as arguments to this function must be block-level.
512 * (This is because the <noscript> tag is block-level.)
514 * @param mixed $if_content Content to display if the browser supports
517 * @param mixed $else_content Content to display if the browser does
518 * not support javascript.
522 function IfJavaScript($if_content = false, $else_content = false) {
525 $xml = AsXML($if_content);
526 $js = sprintf('document.write("%s");',
527 addcslashes($xml, "\0..\37!@\\\177..\377"));
528 $html[] = JavaScript($js);
531 $html[] = HTML::noscript(false, $else_content);
537 $Log: not supported by cvs2svn $
538 Revision 1.46 2005/01/25 06:50:33 rurban
541 Revision 1.45 2005/01/10 18:05:56 rurban
542 php5 case-sensitivity
544 Revision 1.44 2005/01/08 20:58:19 rurban
545 ending space after colgroup breaks _setTagProperty
547 Revision 1.43 2004/11/21 11:59:14 rurban
548 remove final \n to be ob_cache independent
550 Revision 1.42 2004/09/26 17:09:23 rurban
551 add SVG support for Ploticus (and hopefully all WikiPluginCached types)
554 Revision 1.41 2004/08/05 17:31:50 rurban
555 more xhtml conformance fixes
557 Revision 1.40 2004/06/25 14:29:17 rurban
558 WikiGroup refactoring:
559 global group attached to user, code for not_current user.
560 improved helpers for special groups (avoid double invocations)
561 new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
562 fixed a XHTML validation error on userprefs.tmpl
564 Revision 1.39 2004/05/17 13:36:49 rurban
565 Apply RFE #952323 "ExternalSearchPlugin improvement", but
566 with <button><img></button>
568 Revision 1.38 2004/05/12 10:49:54 rurban
569 require_once fix for those libs which are loaded before FileFinder and
570 its automatic include_path fix, and where require_once doesn't grok
571 dirname(__FILE__) != './lib'
572 upgrade fix with PearDB
573 navbar.tmpl: remove spaces for IE button alignment
575 Revision 1.37 2004/04/26 20:44:34 rurban
576 locking table specific for better databases
578 Revision 1.36 2004/04/19 21:51:41 rurban
579 php5 compatibility: it works!
581 Revision 1.35 2004/04/19 18:27:45 rurban
582 Prevent from some PHP5 warnings (ref args, no :: object init)
583 php5 runs now through, just one wrong XmlElement object init missing
584 Removed unneccesary UpgradeUser lines
585 Changed WikiLink to omit version if current (RecentChanges)
587 Revision 1.34 2004/03/24 19:39:02 rurban
588 php5 workaround code (plus some interim debugging code in XmlElement)
589 php5 doesn't work yet with the current XmlElement class constructors,
590 WikiUserNew does work better than php4.
591 rewrote WikiUserNew user upgrading to ease php5 update
592 fixed pref handling in WikiUserNew
593 added Email Notification
594 added simple Email verification
595 removed emailVerify userpref subclass: just a email property
596 changed pref binary storage layout: numarray => hash of non default values
597 print optimize message only if really done.
598 forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
599 prefs should be stored in db or homepage, besides the current session.
601 Revision 1.33 2004/03/18 22:32:33 rurban
602 work to make it php5 compatible
604 Revision 1.32 2004/02/15 21:34:37 rurban
605 PageList enhanced and improved.
606 fixed new WikiAdmin... plugins
607 editpage, Theme with exp. htmlarea framework
608 (htmlarea yet committed, this is really questionable)
609 WikiUser... code with better session handling for prefs
610 enhanced UserPreferences (again)
611 RecentChanges for show_deleted: how should pages be deleted then?
613 Revision 1.31 2003/02/27 22:47:26 dairiki
614 New functions in HtmlElement:
617 Helper for generating javascript.
619 IfJavaScript($if_content, $else_content)
620 Helper for generating
621 <script>document.write('...')</script><noscript>...</noscript>
624 Revision 1.30 2003/02/17 06:02:25 dairiki
625 Remove functions HiddenGets() and HiddenPosts().
627 These functions were evil. They didn't check the request method,
628 so they often resulted in GET args being converted to POST args,
631 One of these is still used in lib/plugin/WikiAdminSelect.php,
632 but, so far as I can tell, that code is both broken _and_ it
635 Revision 1.29 2003/02/15 01:54:19 dairiki
636 Added HTML::meta() for <meta> tag.
638 Revision 1.28 2003/01/04 02:32:30 carstenklapp
639 Added 'col' and 'colgroup' table elements used by PluginManager.
643 // (c-file-style: "gnu")
648 // c-hanging-comment-ender-p: nil
649 // indent-tabs-mode: nil