From a5a19fd672bc0b8113d620669b557f17dccd343a Mon Sep 17 00:00:00 2001 From: Christian Schneider Date: Thu, 26 Oct 2006 13:35:12 +0000 Subject: Moved itools to live branch --- html.class | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 html.class (limited to 'html.class') diff --git a/html.class b/html.class new file mode 100644 index 0000000..a437d54 --- /dev/null +++ b/html.class @@ -0,0 +1,516 @@ + 'it_html', # Name of global variable to use + 'oldhtml' => false, + 'prettyprint' => false, + 'tags' => 'a,br,form,h1,h2,h3,h4,img,input,li,meta,table,td,th,tr,ul', + 'moretags' => '', + 'nonewlinetags' => 'a,img,span', + 'preprocess_attr' => array(), + 'charset' => "iso-8859-1", + 'show_content_type' => true, + 'show_favicon' => true, + 'show_boot_dom' => true, + ); + var $tags_seen = array('body' => true); # body always counts as seen + +/** + * 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') + */ +function it_html($config = array()) +{ + # Create current setting vars + foreach ($config + $this->_defaultconfig as $key => $value) + { + $var = "_$key"; + $this->$var = $value; + } + + if (isset($this->_oldhtml) && !$this->_htmltype) + $this->_htmltype = $this->_oldhtml ? "html" : "xhtml"; + $this->_oldhtml = $this->_htmltype == "html"; + + # Create global functions from all methods and names in $config['tags'] and $config['moretags'] + $methods = get_class_methods(get_class($this)); + $funcs = array_unique(array_merge($methods, explode(',', $this->_tags), explode(',', $this->_moretags))); + $nonewlinetags = explode(',', $this->_nonewlinetags); + + foreach($funcs as $func) + { + # Do not globalise 'private' functions starting in '_' or for our constructor + if (preg_match('/^_/', $func) || is_a($this, $func) || empty($func)) + continue; + + $funcargs = array(); + if (in_array($func, $nonewlinetags)) + $funcargs += array('nonewline' => true); + + $funcconfig = $funcargs ? 'array_push($args, '.strtr(var_export($funcargs, true), array("\n" => '')).'); ' : ''; + + $code = "function $func() { \$args = func_get_args(); $funcconfig"; + if (!in_array($func, $methods)) # No special case: generate call to tag() + { + $code .= "array_unshift(\$args, '$func');"; + $func = 'tag'; + } + + $code .= "return call_user_func_array(array(&\$GLOBALS['$this->_name'], '$func'), \$args); }"; + + debug(get_class($this).': code: '.$code, 8); + eval($code); + } + + # Since name is given as param, it is our duty to store it, not our caller's. + $GLOBALS[$this->_name] =& $this; +} + + +/** + * Return a 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(/* $name, ... */) +{ + $args = func_get_args(); + $name = array_shift($args); + + $data = null; + $attr = array(); + + foreach($args as $arg) + { + if (is_array($arg)) + { + foreach ($arg as $key => $value) + { + 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; + } + } + else + $data .= $arg; + } + + $newline = empty($attr['nonewline']) ? "\n" : ""; + unset($attr['nonewline']); + + # Ultra XML PrettyPrinter 3000 [\] by SCA + if ($this->_prettyprint && $newline && (substr($data, -1, 1) == "\n") && (strpos($data, ' instead of for old html, for xhtml style) + foreach($attr as $key => $value) + { + if ($value === false) # omit whole tag + ; + else if (isset($value) && $value !== true) + $result .= " $key=\"" . it_html::Q($value) . '"'; + else if ($this->_oldhtml) + $result .= " $key"; + else + $result .= " $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$newline"; + elseif ($this->_oldhtml) + $result .= ">$newline"; + else + $result .= " />$newline"; + + if (EDC('srclines')) + { + $trace = debug_backtrace(); + $trace = $trace[2]; + $result = "" . $result; + } + + $this->tags_seen[$name] = true; + + return $result; +} + + +/** + * 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
...
+ */ +function div(/* $class, ... */) +{ + $args = func_get_args(); + + if (!is_array($args[0]) && ($class = array_shift($args)) !== null) + array_unshift($args, compact('class')); + + array_unshift($args, 'div'); + return call_user_func_array(array(&$this, 'tag'), $args); +} + + +/** + * 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 ... + */ +function span(/* $class, ... */) +{ + $args = func_get_args(); + + if (!is_array($args[0]) && ($class = array_shift($args)) !== null) + array_unshift($args, compact('class')); + + array_unshift($args, 'span'); + return call_user_func_array(array(&$this, 'tag'), $args); +} + + +/** + * Shortcut: return htmlspecialchars($string); + * @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"))); + + return str_replace("\n", " ", htmlspecialchars($string)); +} + + +/** + * Build a complete url from base-url and params + * @param ... scalar args and numeric indices build base-url, rest as params + */ +function U(/* ... */) +{ + $args = func_get_args(); + $base = null; + $params = array(); + + foreach($args as $arg) + { + if (is_array($arg)) + { + foreach ($arg as $key => $value) + { + if (is_int($key)) + $base .= $value; + else + $params[$key] = $value; + } + } + else + $base .= $arg; + } + + if (!isset($base)) + $base = $_SERVER['PHP_SELF']; + + $base = preg_replace('|\0|', '', $base); + $base = preg_replace('|[^\w.+!*(),:@&=/~$-]|e', 'urlencode("$0")', $base); + $base = preg_replace('|^(\w+:)?//[^/]*$|', '$0/', $base); # Add slash if absolute url without a path, e.g. http://gna.ch + $queryparams = array(); + + foreach ($params as $key => $value) + { + if (is_array($value)) + { + foreach ($value as $arrkey => $arrvalue) + { + if (strlen($arrvalue)) + $queryparams[] = urlencode($key) . "[" . urlencode($arrkey) . "]=" . it_url::encode($arrvalue); + } + } + else if (strlen($value)) + $queryparams[] = urlencode($key) . "=" . it_url::encode($value); + } + + return $base . ($queryparams ? ("?" . join("&", $queryparams)) : ""); +} + + +/** + * Create a dropdown menu object + * @param $tags key => value pairs of