1 <?php rcs_id('$Id: HtmlElement.php,v 1.42 2004-09-26 17:09:23 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());
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());
403 define('HTMLTAG_EMPTY', 1);
404 define('HTMLTAG_INLINE', 2);
405 define('HTMLTAG_ACCEPTS_INLINE', 4);
408 HTML::_setTagProperty(HTMLTAG_EMPTY,
409 'area base basefont br col frame hr img input isindex link meta param');
410 HTML::_setTagProperty(HTMLTAG_ACCEPTS_INLINE,
412 'b big i small tt ' // %fontstyle
413 . 's strike u ' // (deprecated)
414 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
415 . 'a img object embed br script map q sub sup span bdo '//%special
416 . 'button input label option select textarea ' //%formctl
418 // %block elements which contain inline content
419 . 'address h1 h2 h3 h4 h5 h6 p pre '
420 // %block elements which contain either block or inline content
421 . 'div fieldset frameset'
423 // other with inline content
424 . 'caption dt label legend '
425 // other with either inline or block
426 . 'dd del ins li td th colgroup ');
428 HTML::_setTagProperty(HTMLTAG_INLINE,
430 'b big i small tt ' // %fontstyle
431 . 's strike u ' // (deprecated)
432 . 'abbr acronym cite code dfn em kbd samp strong var ' //%phrase
433 . 'a img object br script map q sub sup span bdo '//%special
434 . 'button input label option select textarea ' //%formctl
439 * Generate hidden form input fields.
441 * @param $query_args hash A hash mapping names to values for the hidden inputs.
442 * Values in the hash can themselves be hashes. The will result in hidden inputs
443 * which will reconstruct the nested structure in the resulting query args as
448 * $args = array('x' => '2',
449 * 'y' => array('a' => 'aval', 'b' => 'bval'));
450 * $inputs = HiddenInputs($args);
454 * <input type="hidden" name="x" value = "2" />
455 * <input type="hidden" name="y[a]" value = "aval" />
456 * <input type="hidden" name="y[b]" value = "bval" />
458 * @return object An XmlContent object containing the inputs.
460 function HiddenInputs ($query_args, $pfx = false, $exclude = array()) {
463 foreach ($query_args as $key => $val) {
464 if (in_array($key,$exclude)) continue;
465 $name = $pfx ? $pfx . "[$key]" : $key;
467 $inputs->pushContent(HiddenInputs($val, $name));
469 $inputs->pushContent(HTML::input(array('type' => 'hidden',
477 /** Generate a <script> tag containing javascript.
479 * @param string $js The javascript.
480 * @param string $script_args (optional) hash of script tags options
481 * e.g. to provide another version or the defer attr
482 * @return HtmlElement A <script> element.
484 function JavaScript ($js, $script_args = false) {
485 $default_script_args = array(//'version' => 'JavaScript', // not xhtml conformant
486 'type' => 'text/javascript');
487 $script_args = $script_args ? array_merge($default_script_args,$script_args)
488 : $default_script_args;
490 return HTML::script($script_args);
492 // see http://devedge.netscape.com/viewsource/2003/xhtml-style-script/
493 return HTML::script($script_args,
494 new RawXml((ENABLE_XHTML_XML ? "\n//<![CDATA[" : "\n<!--//")
495 . "\n".rtrim($js)."\n"
496 . (ENABLE_XHTML_XML ? "//]]>\n" : "// -->")));
499 /** Conditionally display content based of whether javascript is supported.
501 * This conditionally (on the client side) displays one of two alternate
502 * contents depending on whether the client supports javascript.
505 * The content you pass as arguments to this function must be block-level.
506 * (This is because the <noscript> tag is block-level.)
508 * @param mixed $if_content Content to display if the browser supports
511 * @param mixed $else_content Content to display if the browser does
512 * not support javascript.
516 function IfJavaScript($if_content = false, $else_content = false) {
519 $xml = AsXML($if_content);
520 $js = sprintf('document.write("%s");',
521 addcslashes($xml, "\0..\37!@\\\177..\377"));
522 $html[] = JavaScript($js);
525 $html[] = HTML::noscript(false, $else_content);
531 $Log: not supported by cvs2svn $
532 Revision 1.41 2004/08/05 17:31:50 rurban
533 more xhtml conformance fixes
535 Revision 1.40 2004/06/25 14:29:17 rurban
536 WikiGroup refactoring:
537 global group attached to user, code for not_current user.
538 improved helpers for special groups (avoid double invocations)
539 new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
540 fixed a XHTML validation error on userprefs.tmpl
542 Revision 1.39 2004/05/17 13:36:49 rurban
543 Apply RFE #952323 "ExternalSearchPlugin improvement", but
544 with <button><img></button>
546 Revision 1.38 2004/05/12 10:49:54 rurban
547 require_once fix for those libs which are loaded before FileFinder and
548 its automatic include_path fix, and where require_once doesn't grok
549 dirname(__FILE__) != './lib'
550 upgrade fix with PearDB
551 navbar.tmpl: remove spaces for IE button alignment
553 Revision 1.37 2004/04/26 20:44:34 rurban
554 locking table specific for better databases
556 Revision 1.36 2004/04/19 21:51:41 rurban
557 php5 compatibility: it works!
559 Revision 1.35 2004/04/19 18:27:45 rurban
560 Prevent from some PHP5 warnings (ref args, no :: object init)
561 php5 runs now through, just one wrong XmlElement object init missing
562 Removed unneccesary UpgradeUser lines
563 Changed WikiLink to omit version if current (RecentChanges)
565 Revision 1.34 2004/03/24 19:39:02 rurban
566 php5 workaround code (plus some interim debugging code in XmlElement)
567 php5 doesn't work yet with the current XmlElement class constructors,
568 WikiUserNew does work better than php4.
569 rewrote WikiUserNew user upgrading to ease php5 update
570 fixed pref handling in WikiUserNew
571 added Email Notification
572 added simple Email verification
573 removed emailVerify userpref subclass: just a email property
574 changed pref binary storage layout: numarray => hash of non default values
575 print optimize message only if really done.
576 forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
577 prefs should be stored in db or homepage, besides the current session.
579 Revision 1.33 2004/03/18 22:32:33 rurban
580 work to make it php5 compatible
582 Revision 1.32 2004/02/15 21:34:37 rurban
583 PageList enhanced and improved.
584 fixed new WikiAdmin... plugins
585 editpage, Theme with exp. htmlarea framework
586 (htmlarea yet committed, this is really questionable)
587 WikiUser... code with better session handling for prefs
588 enhanced UserPreferences (again)
589 RecentChanges for show_deleted: how should pages be deleted then?
591 Revision 1.31 2003/02/27 22:47:26 dairiki
592 New functions in HtmlElement:
595 Helper for generating javascript.
597 IfJavaScript($if_content, $else_content)
598 Helper for generating
599 <script>document.write('...')</script><noscript>...</noscript>
602 Revision 1.30 2003/02/17 06:02:25 dairiki
603 Remove functions HiddenGets() and HiddenPosts().
605 These functions were evil. They didn't check the request method,
606 so they often resulted in GET args being converted to POST args,
609 One of these is still used in lib/plugin/WikiAdminSelect.php,
610 but, so far as I can tell, that code is both broken _and_ it
613 Revision 1.29 2003/02/15 01:54:19 dairiki
614 Added HTML::meta() for <meta> tag.
616 Revision 1.28 2003/01/04 02:32:30 carstenklapp
617 Added 'col' and 'colgroup' table elements used by PluginManager.
621 // (c-file-style: "gnu")
626 // c-hanging-comment-ender-p: nil
627 // indent-tabs-mode: nil