diff options
author | Christian Weber | 2007-08-31 17:04:04 +0000 |
---|---|---|
committer | Christian Weber | 2007-08-31 17:04:04 +0000 |
commit | 6487a8beebb126105c3fd1efa748a936bd8a67af (patch) | |
tree | dea524a9f3f6c12e73fa99133e048155cc959aea | |
parent | 941e3752edc6b09777b5388a07ae093c05538dcd (diff) | |
download | itools-6487a8beebb126105c3fd1efa748a936bd8a67af.tar.gz itools-6487a8beebb126105c3fd1efa748a936bd8a67af.tar.bz2 itools-6487a8beebb126105c3fd1efa748a936bd8a67af.zip |
Great cleanup, get rid of this->_* vars in favor of p[], add method html() to output entire page, got rid of asymmetric endhtml()
-rw-r--r-- | it_html.class | 494 |
1 files changed, 232 insertions, 262 deletions
diff --git a/it_html.class b/it_html.class index f05003d..af31ee5 100644 --- a/it_html.class +++ b/it_html.class @@ -2,121 +2,201 @@ /* ** $Id$ ** -** ITools - the Internet Tools Library +** Copyright (C) 1995-2007 by the ITools Authors. +** This file is part of ITools - the Internet Tools Library ** -** Copyright (C) 1995-2003 by the ITools Authors. -** This program is free software; you can redistribute it and/or -** modify it under the terms of either the GNU General Public License -** or the GNU Lesser General Public License, as published by the Free -** Software Foundation. See http://www.gnu.org/licenses/ for details. +** ITools is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or +** (at your option) any later version. +** +** ITools is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see <http://www.gnu.org/licenses/>. ** ** UltraHTML 3000 tool layer. Create functions for html tags. ** ** new it_html; -** echo h1('hello.php') . div('contents', 'Hello world!'); +** echo html(head('title' => 'hello'), body(h1('hello'), p('Hello world!'))); **/ class it_html { - # Default configuration of html class - var $_defaultconfig = array - ( - 'name' => 'it_html', # Name of global variable to use - 'oldhtml' => false, - 'prettyprint' => false, - 'tags' => 'a,br,form,h1,h2,h3,h4,input,li,meta,table,td,th,tr,ul', - 'moretags' => '', - 'nonewlinetags' => 'a,img,span', - 'preprocess_attr' => array(), - 'charset' => "iso-8859-1", - 'ie_png_fix' => false, # To enable, supply URL of a transparent gif (like /images/0.gif) - 'show_content_type' => true, - 'show_favicon' => true, - 'show_boot_dom' => true, - 'staticallycallable' => "q,u,select", # Those methods are statically callable (have same arguments as global stubs) but are a bit slower - 'notexported' => "sanitize", # Those methods are not exported - ); - var $tags_seen = array('body' => true); # body always counts as seen - var $_hasnonewline = array(); /** * Create a HTML object and global functions for all methods (exlcluding * methods starting with '_') in this class plus the default tags (see below). * - * @param $config Configuration settings: - * name => Name of global variable $this is assigned to (string) - * prettyprint => Should output be indented? (bool) - * oldhtml => Should output be in old-style html? (bool) - * tags => Comma-separated list of default tag-functions to generate (string) - * moretags => Comma-separated list of tag-functions to generate additionally to 'tags' (string) - * nonewlinetags => Comma-separated list of tags that do not like newlines before/after them - * use_it_state => If true, generate code needed by state.js (aka 'history iframe') + * @param $p Configuration settings. Can be set/overridden in constructor, html() or head(). + * See source code for a list of supported values */ -function it_html($config = array()) +function it_html($p = array()) { - # Create current setting vars - foreach ($config + $this->_defaultconfig as $key => $value) - { - $var = "_$key"; - $this->$var = $value; - } + # Default configuration of html class + $this->p = $p + array( + 'charset' => 'iso-8859-1', + 'doctype' => null, # Custom doctype (will usually be calculated from htmltype) + 'htmltype' => 'html', # 'html' (=old-style), 'xhtml' or 'xhtml-mobile' + 'lang' => 'de', # Language code to use in <html lang="..."> tag + 'ie_png_fix' => false, # To enable, supply URL of a transparent gif (like /images/0.gif) + 'moretags' => '', # Comma-separated list of tag-functions to generate additionally to 'tags' + 'name' => 'it_html', # Name of global variable $this is assigned to (string) + 'nonewlinetags' => 'a,b,em,img,input,span', # tags that do not like newlines after them + 'notexported' => 'sanitize', # Those methods are not exported + 'prettyprint' => false, # Should output be prettily indented? + 'show_boot_dom' => false, # If true, append invisible <div id="it_boot_dom"> at the end of body + 'show_content_type' => true, # If true, add <meta http-equiv="Content-Type" ...> header + 'show_favicon' => true, # If true, add <link> tag to /favicon.ico if it exists + 'staticallycallable' => 'q,u,select', # Those methods are statically callable (have same arguments as global stubs) but are a bit slower + 'use_it_state' => false, # If true, generate code needed by state.js (aka 'history iframe') + 'tags' => 'a,b,br,button,div,em,form,h1,h2,h3,h4,h5,h6,hr,input,label,li,meta,p,span,table,td,textarea,th,tr,ul', + ); - if (isset($this->_oldhtml) && !$this->_htmltype) - $this->_htmltype = $this->_oldhtml ? "html" : "xhtml"; - $this->_oldhtml = $this->_htmltype == "html"; - $this->_hasnonewline = array_flip(explode(',', "dummy," . $this->_nonewlinetags)); # dummy keeps values >0 - $notexported = array_flip(explode(',', "dummy," . $this->_notexported)); # dummy keeps values >0 + # We know these doctypes. If you need something else, supply 'doctype' in p + $this->doctypes = array( + 'html' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">', + 'xhtml' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">', + 'xhtml-mobile' => '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">' + ); + + $this->p['oldhtml'] = $this->p['htmltype'] == "html"; + + $this->hasnonewline = array_flip(explode(',', "dummy," . $this->p['nonewlinetags'])); # dummy keeps values > 0 + $notexported = array_flip(explode(',', "dummy," . $this->p['notexported'])); # dummy keeps values > 0 # Create global functions for _tags - foreach (array_merge(explode(',', $this->_tags), explode(',', $this->_moretags)) as $func) + foreach (array_merge(explode(',', $this->p['tags']), explode(',', $this->p['moretags'])) as $func) { if (!function_exists($func) && $func) - $code[$func] = "function $func() { \$args = func_get_args(); return \$GLOBALS['$this->_name']->_tag('$func', \$args);}"; + $code[$func] = "function $func() { \$args = func_get_args(); return \$GLOBALS['{$this->p['name']}']->_tag('$func', \$args); }"; } # Create global functions for it_html methods foreach (get_class_methods(get_class($this)) as $func) { if (!preg_match('/^_/', $func) && !is_a($this, $func) && $func && !function_exists($func) && !$notexported[$func]) - $code[$func] = "function $func() { \$args = func_get_args(); return \$GLOBALS['$this->_name']->$func(\$args); }"; + $code[$func] = "function $func() { \$args = func_get_args(); return \$GLOBALS['{$this->p['name']}']->$func(\$args); }"; } # Create global functions for methods that are statically callable (have same arguments as global stubs) - foreach (explode(",", $this->_staticallycallable) as $func) + foreach (explode(',', $this->p['staticallycallable']) as $func) { if ($func && !function_exists($func)) - $code[$func] = "function $func() { \$args = func_get_args(); return call_user_func_array(array(&\$GLOBALS['$this->_name'], '$func'), \$args); }"; + $code[$func] = "function $func() { \$args = func_get_args(); return call_user_func_array(array(&\$GLOBALS['{$this->p['name']}'], '$func'), \$args); }"; } - eval(join("", (array)$code)); + eval(join('', (array)$code)); # Since name is given as param, it is our duty to store it, not our caller's. - $GLOBALS[$this->_name] =& $this; + $GLOBALS[$this->p['name']] =& $this; } /** - * Return a <tag> containing optional data. - * @param $name tag name ('h1', 'div' etc.) - * @param ... any number optional data or array of key => value arguments - * @return string containing XML/HTML tag + * Return doctype and entire HTML page. + * Example application code to render page: + * echo html(head(...), body(...)); + * + * @param any number of text args or array of key => value for $p (see constructor for list) */ -function tag($args) +function html($args) { - $name = array_shift($args); + list($data, $p) = $this->_parse_args($args); + $p += $this->p; - return $this->_tag($name, $args); + return ($p['doctype'] ? $p['doctype'] : $this->doctypes[$p['htmltype']]) . "\n" . + '<html ' . ($p['htmltype'] == "xhtml-mobile" ? 'xml:lang' : 'lang') . "=\"{$p['lang']}\">\n" . $data . ($p['omit_endhtml'] ? '' : "</html>\n"); } + /** - * Internal: Create html tag from name and args array + * Return HTML header on first call or empty string on subsequent calls + * + * @param any number of text args or array of key => value: + * 'content-type' optional content type (default: "text/html; charset=iso-8859-1") + * 'description' optional data for <meta name="description"> tag + * 'keywords' optional data for <meta name="keywords"> tag + * 'lang' optional language (defaults to 'de') + * 'stylesheets' optional array mediatype => url of styleshests + * 'title' optional HTML title tag (default: empty title) */ -function _tag($name, $args) +function head($args = array()) { - $data = null; - $attr = array(); + if (!$this->head_sent++) + { + list($data, $p) = $this->_parse_args($args); - foreach($args as $arg) + $p += $this->p; + $this->p = $p += array( + 'content-type' => "text/html; charset={$p['charset']}", + 'title' => tag('title', Q($p['title'])) + ); + + $header = $p['show_content_type'] ? meta(array('http-equiv' => "Content-Type", 'content' => $p['content-type'])) : ""; + + foreach(array('description', 'keywords') as $name) + if (!empty($p[$name])) + $header .= meta(array('name' => $name, 'content' => $p[$name])); + + # Add favicon if file exists + if ($p['show_favicon'] && @file_exists($_SERVER['DOCUMENT_ROOT'] . '/favicon.ico')) + $header .= tag('link', array('rel' => "shortcut icon", 'href' => "/favicon.ico")); + + foreach((array)$p['stylesheets'] as $type => $url) + $header .= tag('link', array('rel' => "stylesheet", 'type' => "text/css", 'href' => $url) + (is_int($type) ? array() : array('media' => $type))); + + if (!empty($p['cssinline'])) + $header .= tag('style', array('type' => "text/css", "\n" . preg_replace(array('/\s*\/\*[^\*]+\*\//Um', '/\s*\{\s*/', '/;\s+/'), array('', '{', ';'), $p['cssinline']))); + + if($this->p['htmltype'] == "xhtml-mobile" && strpos($_SERVER['HTTP_USER_AGENT'], 'W3C_Validator')) + header("Content-Type: application/xhtml+xml; charset={$this->p['charset']}"); # for validation + else if (!headers_sent()) # prevent warnings when ED() in use + header("Content-Type: " . $p['content-type']); + + $js = $p['jsenv'] ? "var env = " . itjs::serialize($p['jsenv']) . ";\n" : ''; + + if ($p['js']) + { + $checksum = itjs::checksum(itjs::filenames($p['js'])); + $js .= $this->_itjs("boot.js", "inline"); + $js .= "function it_boot_start(){ " . trim($p['jsboot']) . " }\n"; + $js .= "it_boot('/itjs/" . U($p['js'], array('s' => $checksum)) . "');\n"; + } + + $js .= $this->_itjs($p['jsinline'], 'inline'); + + if ($js) + $header .= $this->js(array($js)); + + return tag('head', $header, $data); + } +} + + +/** + * Return HTML head (if not already sent) and body with it_state and it_boot magic code + */ +function body($args) +{ + return $this->head() . + ($this->p['use_it_state'] ? tag('iframe', array('id' => "it_state", 'src' => "/itjs/state.html", 'width' => 1, 'height' => 1, 'frameborder' => 0)) : '') . + $this->_tag('body', $args) . + ($this->p['show_boot_dom'] ? div(array('id' => "it_boot_dom", 'style' => "visibility:hidden")) : ''); +} + + +/** + * INTERNAL: Parse an arg array (mixed key=>value pairs and strings) and return it + * as array(0 => all numerical args concatenated, 1 => array(key=>value pairs) + */ +function _parse_args($args) +{ + $p = array(); + foreach ($args as $arg) { if (is_array($arg)) { @@ -124,21 +204,30 @@ function _tag($name, $args) { if (is_int($key)) $data .= $value; - else if ($this->_preprocess_attr[$key]) - $attr[$key] = call_user_func(($this->_preprocess_attr[$key]), $value, $name); else - $attr[$key] = $value; + $p[$key] = $value; } } else $data .= $arg; } - $newline = $this->_hasnonewline[$name] ? "" : "\n"; + return array($data, $p); +} + + +/** + * INTERNAL: Create html tag from name and args array + */ +function _tag($name, $args) +{ + list($data, $attr) = $this->_parse_args($args); + + $newline = $this->hasnonewline[$name] ? "" : "\n"; # Ultra XML PrettyPrinter 3000 [\] by SCA - if ($this->_prettyprint && $newline && (substr($data, -1, 1) == "\n") && (strpos($data, '<textarea') === false) && ($data != strip_tags($data))) - $data = str_replace("\n", "\n ", "\n".trim($data))."\n"; + if ($this->p['prettyprint'] && $newline && (substr($data, -1, 1) == "\n") && (strpos($data, '<textarea') === false) && ($data != strip_tags($data))) + $data = str_replace("\n", "\n ", "\n" . trim($data)) . "\n"; $result = "<$name"; @@ -148,15 +237,15 @@ function _tag($name, $args) if (($value === null) || ($value === false)) # null or false: omit whole tag ; else if (isset($value) && $value !== true) # normal case: value - $result .= " $key=\"" . (preg_match("/[<>&\"'\n\x80-\x9f]/", $value) ? str_replace("\n", " ", it_html::Q($value)) : $value) . '"'; + $result .= " $key=\"" . (preg_match("/[<>&\"'\n\x80-\x9f]/", $value) ? str_replace("\n", " ", Q($value)) : $value) . '"'; else # true: tag without value - $result .= $this->_oldhtml ? " $key" : " $key=\"$key\""; + $result .= $this->p['oldhtml'] ? " $key" : " $key=\"$key\""; } # Apply a kind of magic... this needs further investigation if (isset($data) || preg_match('/^(a|div|iframe|script|span|td|textarea)$/i', $name)) $result .= ">$data</$name>$newline"; - elseif ($this->_oldhtml) + elseif ($this->p['oldhtml']) $result .= ">$newline"; else $result .= " />$newline"; @@ -168,14 +257,25 @@ function _tag($name, $args) $result = "<!-- " . basename($trace['file']) . ":" . $trace['line'] . " -->" . $result; } - $this->tags_seen[$name] = true; - return $result; } /** - * Shortcut: return a div of a specific class + * Return a <tag> containing optional data. + * @param $name tag name ('h1', 'div' etc.) + * @param ... any number optional data or array of key => value arguments + * @return string containing XML/HTML tag + */ +function tag($args) +{ + $name = array_shift($args); + return $this->_tag($name, $args); +} + + +/** + * OBSOLETE Shortcut: return a div of a specific class * @param $class class name or null for no class= tag * @param ... any number optional data or array of key => value arguments * @return <div class="$class"...>...</div> @@ -183,7 +283,10 @@ function _tag($name, $args) function div($args) { if (!is_array($args[0]) && ($class = array_shift($args)) !== null) + { array_unshift($args, compact('class')); + ###it::error("deprecated usage of div"); + } return $this->_tag("div", $args); } @@ -196,13 +299,13 @@ function div($args) */ function img($args) { - if ($this->_ie_png_fix && preg_match('/MSIE [56]/', $_SERVER['HTTP_USER_AGENT'])) + if ($this->p['ie_png_fix'] && preg_match('/MSIE [56]/', $_SERVER['HTTP_USER_AGENT'])) { foreach($args as $id => $arg) if (preg_match('/\.png(\?.*)?$/', $arg['src'])) { $args[$id]['style'] = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='{$arg['src']}',sizingMethod='scale');" . $arg['style']; - $args[$id]['src'] = $this->_ie_png_fix; + $args[$id]['src'] = $this->p['ie_png_fix']; } } @@ -211,7 +314,48 @@ function img($args) /** - * Shortcut: return a span of a specific class + * Create a dropdown menu object. Warning: encodes html code within options! + * @param $tags key => value pairs of <select> tag + * @param $options array (value => text) of available options or + * string key:val{,key:val} where key will be rawurldecoded so it may contain %2C as comma + * supports optgroups as array (value => optgroup => array(value => text)) + * @param $selected optional currently selected value + */ +function select($tags, $options, $selected = null) +{ + # Transmogrify key:val{,key:val} to array(key => val) + if (!is_array($options)) + { + $opts = explode(',', $options); + $options = array(); + + foreach($opts as $opt) + { + list($key, $value) = explode(':', $opt); + $options[rawurldecode($key)] = $value; + } + } + + $html = ""; + foreach($options as $value => $option) + { + if (is_array($option)) + { + $grouphtml = ""; + foreach($option as $optval => $opt) + $grouphtml .= $this->_tag("option", array(array('value' => $optval, 'selected' => isset($selected) ? $optval == $selected : false), Q($opt))); + $html .= $this->_tag("optgroup", array(array('label' => $value, $grouphtml))); + } + else + $html .= $this->_tag("option", array(array('value' => $value, 'selected' => isset($selected) ? $value == $selected : false, 'disabled' => $option === ""), (trim($option) === "") ? " " : Q($option))); + } + + return $this->_tag("select", array($tags, $html)); +} + + +/** + * OBSOLETE Shortcut: return a span of a specific class * @param $class class name or null for no class= tag * @param ... any number optional data or array of key => value arguments * @return <span class="$class"...>...</span> @@ -219,7 +363,10 @@ function img($args) function span($args) { if (!is_array($args[0]) && ($class = array_shift($args)) !== null) + { array_unshift($args, compact('class')); + ###it::error("deprecated usage of span"); + } return $this->_tag("span", $args); } @@ -270,14 +417,14 @@ function sanitize($html) /** - * Shortcut: return htmlspecialchars($string); + * Shortcut: return htmlspecialchars($string) and encode forbidden characters 80-9f if latin1 is output * @param $string String to encode with htmlspecialchars() * @return htmlspecialchars($string) */ function q($string) { if ($GLOBALS['it_html']->_charset == "iso-8859-1") - $string = preg_replace('/[\x80-\x9f]/', ' ', strtr($string, array("\x80"=>"EUR", "\x82"=>"'", "\x84"=>"\"", "\x85"=>"...", "\x8a"=>"S", "\x8c"=>"OE", "\x8e"=>"Z", "\x91"=>"'", "\x92"=>"'", "\x93"=>"\"", "\x94"=>"\"", "\x96"=>"-", "\x97"=>"-", "\x9a"=>"s", "\x9e"=>"z"))); + $string = preg_replace('/[\x80-\x9f]/', ' ', strtr($string, array("\x80" => "EUR", "\x82" => "'", "\x84" => "\"", "\x85" => "...", "\x8a" => "S", "\x8c" => "OE", "\x8e" => "Z", "\x91" => "'", "\x92" => "'", "\x93" => "\"", "\x94" => "\"", "\x96" => "-", "\x97" => "-", "\x9a" => "s", "\x9e" => "z"))); return htmlspecialchars($string); } @@ -323,61 +470,20 @@ function u(/* ... */) /** - * Create a dropdown menu object. Warning: encodes html code within options! - * @param $tags key => value pairs of <select> tag - * @param $options array (value => text) of available options or - * string key:val{,key:val} where key will be rawurldecoded so it may contain %2C as comma - * supports optgroups as array (value => optgroup => array(value => text)) - * @param $selected optional currently selected value - */ -function select($tags, $options, $selected = null) -{ - # Transmogrify key:val{,key:val} to array(key => val) - if (!is_array($options)) - { - $opts = explode(',', $options); - $options = array(); - - foreach($opts as $opt) - { - list($key, $value) = explode(':', $opt); - $options[rawurldecode($key)] = $value; - } - } - - $html = ""; - foreach($options as $value => $option) - { - if (is_array($option)) - { - $grouphtml = ""; - foreach($option as $optval => $opt) - $grouphtml .= $this->_tag("option", array(array('value' => $optval, 'selected' => isset($selected) ? $optval == $selected : false), it_html::Q($opt))); - $html .= $this->_tag("optgroup", array(array('label' => $value, $grouphtml))); - } - else - $html .= $this->_tag("option", array(array('value' => $value, 'selected' => isset($selected) ? $value == $selected : false, 'disabled' => $option === ""), (trim($option) === "") ? " " : it_html::Q($option))); - } - - return $this->_tag("select", array($tags, $html)); -} - - -/** * Insert a javascript script * @param ... any number optional data or array of key => value arguments * @return <script type="text/javascript"...>...</script> */ function js($args) { - if (!$this->_oldhtml && isset($args[0])) + if (!$this->p['oldhtml'] && isset($args[0])) { array_unshift($args, "<!--//--><![CDATA[//><!--\n"); $args[] = "\n//--><!]]>"; } array_unshift($args, array('type' => 'text/javascript')); - return $this->_tag("script", $args); + return $this->_tag('script', $args); } @@ -413,141 +519,5 @@ function _itjs($files, $mode) return $result; } - -/** - * Return HTML header with correct doctype. - * - * @param any number of text args or array of key => value: - * 'title' optional HTML title tag - * 'content-type' optional content type (default: "text/html; charset=iso-8859-1") - * 'description' optional data for <meta name="description"> tag - * 'doctype' optional <!DOCTYPE HTML PUBLIC...> tag - * 'keywords' optional data for <meta name="keywords"> tag - * 'lang' optional language (defaults to 'de') - * 'stylesheets' optional array mediatype => url of styleshests - */ -function head($args = array()) -{ - if (!$this->head_sent++) - { - $p = array(); - - foreach ($args as $arg) - { - if (is_array($arg)) - { - foreach ($arg as $key => $value) - { - if (is_int($key)) - $data .= $value; - else - $p[$key] = $value; - } - } - else - $data .= $arg; - } - - if ($this->_htmltype == "xhtml-mobile") - $defdoctype = '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">'; - else if ($this->_htmltype == "xhtml") - $defdoctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'; - else - $defdoctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">'; - - $p += array - ( - 'content-type' => "text/html; charset=$this->_charset", - 'doctype' => $defdoctype, - 'lang' => "de", - 'js' => $this->_js, - 'jsboot' => $this->_jsboot, - 'jsinline' => $this->_jsinline, - ); - - $header = $p['show_content_type'] ? meta(array('http-equiv' => "Content-Type", 'content' => $p['content-type'])) : ""; - - if (isset($p['title'])) - $header .= tag('title', it_html::Q($p['title'])); - - foreach(array('description', 'keywords') as $name) - if (!empty($p[$name])) - $header .= meta(array('name' => $name, 'content' => $p[$name])); - - # Add favicon if file exists - if ($p['show_favicon'] && @file_exists($_SERVER['DOCUMENT_ROOT'].'/favicon.ico')) - $header .= tag('link', array('rel' => "shortcut icon", 'href' => "/favicon.ico")); - - foreach((array)$p['stylesheets'] as $type => $url) - $header .= tag('link', array('rel' => "stylesheet", 'type' => "text/css", 'href' => $url) + (is_int($type) ? array() : array('media' => $type))); - - if (!empty($p['cssinline'])) - $header .= tag('style', array('type' => "text/css", "\n" . preg_replace(array('/\s*\/\*[^\*]+\*\//Um', '/\s*\{\s*/', '/;\s+/'), array('', '{', ';'), $p['cssinline']))); - - if($this->_htmltype == "xhtml-mobile" && ereg('W3C_Validator', $_SERVER['HTTP_USER_AGENT'])) - header("Content-Type: application/xhtml+xml; charset=$this->_charset"); # for validation - else if (!headers_sent()) # prevent warnings when ED() in use - header("Content-Type: " . $p['content-type']); - - $langvar = $this->_htmltype == "xhtml-mobile" ? "xml:lang" : "lang"; - $prefix = $GLOBALS['SENT_PREAMBLE'] ? "" : $p['doctype'] . "\n<html $langvar=\"" . it_html::Q($p['lang']) . "\"><head>"; - - # override use_it_state property - if (isset($p['use_it_state'])) - $this->_use_it_state = $p['use_it_state']; - - $js = ""; - - if ($p['jsenv']) - $js .= "var env = " . itjs::serialize($p['jsenv']) . ";\n"; - - if ($p['js']) - { - $checksum = itjs::checksum(itjs::filenames($p['js'])); - $js .= $this->_itjs("boot.js", "inline"); - $js .= "function it_boot_start(){ " . trim($p['jsboot']) . " }\n"; - $js .= "it_boot('/itjs/" . it_html::U($p['js'], array('s' => $checksum)) . "');\n"; - } - - $js .= $this->_itjs($p['jsinline'], 'inline'); - - if ($js) - $header .= $this->js(array($js)); - - return "$prefix$header$data</head>"; - } -} - -function body($args) -{ - foreach ($args as $arg) - { - if (is_array($arg)) - { - foreach ($arg as $key => $value) - { - if (is_int($key)) - $body .= $value; - else - $attributes .= " $key=\"" . it_html::Q($value) . '"'; - } - } - else - $body .= $arg; - } - - if ($this->_use_it_state) - $body = tag('iframe', array('id' => "it_state", 'src' => "/itjs/state.html", 'width' => 1, 'height' => 1, 'frameborder' => 0)) . $body; - - $body .= $this->_show_boot_dom ? div(array('id' => "it_boot_dom", 'style' => "visibility:hidden")) : ""; - - return $this->head() . ($this->in_body++ ? "" : "<body$attributes>$body"); -} - -function endhtml() -{ - return $this->head() . ($this->in_body ? "</body>" : "") . "</html>"; -} - } ?> |