1 <?php rcs_id('$Id: HtmlElement.php,v 1.41 2004-08-05 17:31:50 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) {
113 if (isset($props[$tag]))
114 $props[$tag] |= $prop_flag;
116 $props[$tag] = $prop_flag;
121 // Shell script to generate the following static methods:
124 // function mkfuncs () {
127 // echo " function $tag (/*...*/) {"
128 // echo " \$el = new HtmlElement('$tag');"
129 // echo " return \$el->_init2(func_get_args());"
134 // /****************************************/'
135 // mkfuncs link meta style script noscript
137 // mkfuncs a img br span
139 // mkfuncs h1 h2 h3 h4 h5 h6
141 // mkfuncs hr div p pre blockquote
143 // mkfuncs em strong small
145 // mkfuncs tt u sup sub
147 // mkfuncs ul ol dl li dt dd
149 // mkfuncs table caption thead tbody tfoot tr td th colgroup col
151 // mkfuncs form input option select textarea
153 // mkfuncs area map frame frameset iframe nobody
155 function link (/*...*/) {
156 $el = new HtmlElement('link');
157 return $el->_init2(func_get_args());
159 function meta (/*...*/) {
160 $el = new HtmlElement('meta');
161 return $el->_init2(func_get_args());
163 function style (/*...*/) {
164 $el = new HtmlElement('style');
165 return $el->_init2(func_get_args());
167 function script (/*...*/) {
168 $el = new HtmlElement('script');
169 return $el->_init2(func_get_args());
171 function noscript (/*...*/) {
172 $el = new HtmlElement('noscript');
173 return $el->_init2(func_get_args());
176 /****************************************/
177 function a (/*...*/) {
178 $el = new HtmlElement('a');
179 return $el->_init2(func_get_args());
181 function img (/*...*/) {
182 $el = new HtmlElement('img');
183 return $el->_init2(func_get_args());
185 function br (/*...*/) {
186 $el = new HtmlElement('br');
187 return $el->_init2(func_get_args());
189 function span (/*...*/) {
190 $el = new HtmlElement('span');
191 return $el->_init2(func_get_args());
194 /****************************************/
195 function h1 (/*...*/) {
196 $el = new HtmlElement('h1');
197 return $el->_init2(func_get_args());
199 function h2 (/*...*/) {
200 $el = new HtmlElement('h2');
201 return $el->_init2(func_get_args());
203 function h3 (/*...*/) {
204 $el = new HtmlElement('h3');
205 return $el->_init2(func_get_args());
207 function h4 (/*...*/) {
208 $el = new HtmlElement('h4');
209 return $el->_init2(func_get_args());
211 function h5 (/*...*/) {
212 $el = new HtmlElement('h5');
213 return $el->_init2(func_get_args());
215 function h6 (/*...*/) {
216 $el = new HtmlElement('h6');
217 return $el->_init2(func_get_args());
220 /****************************************/
221 function hr (/*...*/) {
222 $el = new HtmlElement('hr');
223 return $el->_init2(func_get_args());
225 function div (/*...*/) {
226 $el = new HtmlElement('div');
227 return $el->_init2(func_get_args());
229 function p (/*...*/) {
230 $el = new HtmlElement('p');
231 return $el->_init2(func_get_args());
233 function pre (/*...*/) {
234 $el = new HtmlElement('pre');
235 return $el->_init2(func_get_args());
237 function blockquote (/*...*/) {
238 $el = new HtmlElement('blockquote');
239 return $el->_init2(func_get_args());
242 /****************************************/
243 function em (/*...*/) {
244 $el = new HtmlElement('em');
245 return $el->_init2(func_get_args());
247 function strong (/*...*/) {
248 $el = new HtmlElement('strong');
249 return $el->_init2(func_get_args());
251 function small (/*...*/) {
252 $el = new HtmlElement('small');
253 return $el->_init2(func_get_args());
256 /****************************************/
257 function tt (/*...*/) {
258 $el = new HtmlElement('tt');
259 return $el->_init2(func_get_args());
261 function u (/*...*/) {
262 $el = new HtmlElement('u');
263 return $el->_init2(func_get_args());
265 function sup (/*...*/) {
266 $el = new HtmlElement('sup');
267 return $el->_init2(func_get_args());
269 function sub (/*...*/) {
270 $el = new HtmlElement('sub');
271 return $el->_init2(func_get_args());
274 /****************************************/
275 function ul (/*...*/) {
276 $el = new HtmlElement('ul');
277 return $el->_init2(func_get_args());
279 function ol (/*...*/) {
280 $el = new HtmlElement('ol');
281 return $el->_init2(func_get_args());
283 function dl (/*...*/) {
284 $el = new HtmlElement('dl');
285 return $el->_init2(func_get_args());
287 function li (/*...*/) {
288 $el = new HtmlElement('li');
289 return $el->_init2(func_get_args());
291 function dt (/*...*/) {
292 $el = new HtmlElement('dt');
293 return $el->_init2(func_get_args());
295 function dd (/*...*/) {
296 $el = new HtmlElement('dd');
297 return $el->_init2(func_get_args());
300 /****************************************/
301 function table (/*...*/) {
302 $el = new HtmlElement('table');
303 return $el->_init2(func_get_args());
305 function caption (/*...*/) {
306 $el = new HtmlElement('caption');
307 return $el->_init2(func_get_args());
309 function thead (/*...*/) {
310 $el = new HtmlElement('thead');
311 return $el->_init2(func_get_args());
313 function tbody (/*...*/) {
314 $el = new HtmlElement('tbody');
315 return $el->_init2(func_get_args());
317 function tfoot (/*...*/) {
318 $el = new HtmlElement('tfoot');
319 return $el->_init2(func_get_args());
321 function tr (/*...*/) {
322 $el = new HtmlElement('tr');
323 return $el->_init2(func_get_args());
325 function td (/*...*/) {
326 $el = new HtmlElement('td');
327 return $el->_init2(func_get_args());
329 function th (/*...*/) {
330 $el = new HtmlElement('th');
331 return $el->_init2(func_get_args());
333 function colgroup (/*...*/) {
334 $el = new HtmlElement('colgroup');
335 return $el->_init2(func_get_args());
337 function col (/*...*/) {
338 $el = new HtmlElement('col');
339 return $el->_init2(func_get_args());
342 /****************************************/
343 function form (/*...*/) {
344 $el = new HtmlElement('form');
345 return $el->_init2(func_get_args());
347 function input (/*...*/) {
348 $el = new HtmlElement('input');
349 return $el->_init2(func_get_args());
351 function button (/*...*/) {
352 $el = new HtmlElement('button');
353 return $el->_init2(func_get_args());
355 function option (/*...*/) {
356 $el = new HtmlElement('option');
357 return $el->_init2(func_get_args());
359 function select (/*...*/) {
360 $el = new HtmlElement('select');
361 return $el->_init2(func_get_args());
363 function textarea (/*...*/) {
364 $el = new HtmlElement('textarea');
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());
395 define('HTMLTAG_EMPTY', 1);
396 define('HTMLTAG_INLINE', 2);
397 define('HTMLTAG_ACCEPTS_INLINE', 4);
400 HTML::_setTagProperty(HTMLTAG_EMPTY,
401 'area base basefont br col frame hr img input isindex link meta param');
402 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
404 'b big i small tt ' // %fontstyle
405 . 's strike u ' // (deprecated)
406 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
407 . 'a img object br script map q sub sup span bdo '//%special
408 . 'button input label option select textarea ' //%formctl
410 // %block elements which contain inline content
411 . 'address h1 h2 h3 h4 h5 h6 p pre '
412 // %block elements which contain either block or inline content
413 . 'div fieldset frameset'
415 // other with inline content
416 . 'caption dt label legend '
417 // other with either inline or block
418 . 'dd del ins li td th colgroup ');
420 HTML::_setTagProperty(HTMLTAG_INLINE,
422 'b big i small tt ' // %fontstyle
423 . 's strike u ' // (deprecated)
424 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
425 . 'a img object br script map q sub sup span bdo '//%special
426 . 'button input label option select textarea ' //%formctl
431 * Generate hidden form input fields.
433 * @param $query_args hash A hash mapping names to values for the hidden inputs.
434 * Values in the hash can themselves be hashes. The will result in hidden inputs
435 * which will reconstruct the nested structure in the resulting query args as
440 * $args = array('x' => '2',
441 * 'y' => array('a' => 'aval', 'b' => 'bval'));
442 * $inputs = HiddenInputs($args);
446 * <input type="hidden" name="x" value = "2" />
447 * <input type="hidden" name="y[a]" value = "aval" />
448 * <input type="hidden" name="y[b]" value = "bval" />
450 * @return object An XmlContent object containing the inputs.
452 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
455 foreach ($query_args as $key => $val) {
456 if (in_array($key,$exclude)) continue;
457 $name = $pfx ? $pfx . "[$key]" : $key;
459 $inputs->pushContent(HiddenInputs($val, $name));
461 $inputs->pushContent(HTML::input(array('type' => 'hidden',
469 /** Generate a <script> tag containing javascript.
471 * @param string $js The javascript.
472 * @param string $script_args (optional) hash of script tags options
473 * e.g. to provide another version or the defer attr
474 * @return HtmlElement A <script> element.
476 function JavaScript ($js, $script_args = false) {
477 $default_script_args = array(//'version' => 'JavaScript', // not xhtml conformant
478 'type' => 'text/javascript');
479 $script_args = $script_args ? array_merge($default_script_args,$script_args)
480 : $default_script_args;
482 return HTML::script($script_args);
484 // see http://devedge.netscape.com/viewsource/2003/xhtml-style-script/
485 return HTML::script($script_args,
486 new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
487 . "\n".rtrim($js)."\n"
488 . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->")));
491 /** Conditionally display content based of whether javascript is supported.
493 * This conditionally (on the client side) displays one of two alternate
494 * contents depending on whether the client supports javascript.
497 * The content you pass as arguments to this function must be block-level.
498 * (This is because the <noscript> tag is block-level.)
500 * @param mixed $if_content Content to display if the browser supports
503 * @param mixed $else_content Content to display if the browser does
504 * not support javascript.
508 function IfJavaScript($if_content = false, $else_content = false) {
511 $xml = AsXML($if_content);
512 $js = sprintf('document.write("%s");',
513 addcslashes($xml, "\0..\37!@\\\177..\377"));
514 $html[] = JavaScript($js);
517 $html[] = HTML::noscript(false, $else_content);
523 $Log: not supported by cvs2svn $
524 Revision 1.40 2004/06/25 14:29:17 rurban
525 WikiGroup refactoring:
526 global group attached to user, code for not_current user.
527 improved helpers for special groups (avoid double invocations)
528 new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
529 fixed a XHTML validation error on userprefs.tmpl
531 Revision 1.39 2004/05/17 13:36:49 rurban
532 Apply RFE #952323 "ExternalSearchPlugin improvement", but
533 with <button><img></button>
535 Revision 1.38 2004/05/12 10:49:54 rurban
536 require_once fix for those libs which are loaded before FileFinder and
537 its automatic include_path fix, and where require_once doesn't grok
538 dirname(__FILE__) != './lib'
539 upgrade fix with PearDB
540 navbar.tmpl: remove spaces for IE button alignment
542 Revision 1.37 2004/04/26 20:44:34 rurban
543 locking table specific for better databases
545 Revision 1.36 2004/04/19 21:51:41 rurban
546 php5 compatibility: it works!
548 Revision 1.35 2004/04/19 18:27:45 rurban
549 Prevent from some PHP5 warnings (ref args, no :: object init)
550 php5 runs now through, just one wrong XmlElement object init missing
551 Removed unneccesary UpgradeUser lines
552 Changed WikiLink to omit version if current (RecentChanges)
554 Revision 1.34 2004/03/24 19:39:02 rurban
555 php5 workaround code (plus some interim debugging code in XmlElement)
556 php5 doesn't work yet with the current XmlElement class constructors,
557 WikiUserNew does work better than php4.
558 rewrote WikiUserNew user upgrading to ease php5 update
559 fixed pref handling in WikiUserNew
560 added Email Notification
561 added simple Email verification
562 removed emailVerify userpref subclass: just a email property
563 changed pref binary storage layout: numarray => hash of non default values
564 print optimize message only if really done.
565 forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
566 prefs should be stored in db or homepage, besides the current session.
568 Revision 1.33 2004/03/18 22:32:33 rurban
569 work to make it php5 compatible
571 Revision 1.32 2004/02/15 21:34:37 rurban
572 PageList enhanced and improved.
573 fixed new WikiAdmin... plugins
574 editpage, Theme with exp. htmlarea framework
575 (htmlarea yet committed, this is really questionable)
576 WikiUser... code with better session handling for prefs
577 enhanced UserPreferences (again)
578 RecentChanges for show_deleted: how should pages be deleted then?
580 Revision 1.31 2003/02/27 22:47:26 dairiki
581 New functions in HtmlElement:
584 Helper for generating javascript.
586 IfJavaScript($if_content, $else_content)
587 Helper for generating
588 <script>document.write('...')</script><noscript>...</noscript>
591 Revision 1.30 2003/02/17 06:02:25 dairiki
592 Remove functions HiddenGets() and HiddenPosts().
594 These functions were evil. They didn't check the request method,
595 so they often resulted in GET args being converted to POST args,
598 One of these is still used in lib/plugin/WikiAdminSelect.php,
599 but, so far as I can tell, that code is both broken _and_ it
602 Revision 1.29 2003/02/15 01:54:19 dairiki
603 Added HTML::meta() for <meta> tag.
605 Revision 1.28 2003/01/04 02:32:30 carstenklapp
606 Added 'col' and 'colgroup' table elements used by PluginManager.
610 // (c-file-style: "gnu")
615 // c-hanging-comment-ender-p: nil
616 // indent-tabs-mode: nil