phpgroupware-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Phpgroupware-cvs] sitemgr inc/class.Categories_BO.inc.php inc/cla... [s


From: Dave Hall
Subject: [Phpgroupware-cvs] sitemgr inc/class.Categories_BO.inc.php inc/cla... [skwashd-16-compat]
Date: Mon, 27 Mar 2006 13:13:25 +0000

CVSROOT:        /cvsroot/phpgroupware
Module name:    sitemgr
Branch:         skwashd-16-compat
Changes by:     Dave Hall <address@hidden>      06/03/27 13:13:24

Modified files:
        inc            : class.Categories_BO.inc.php 
                         class.Categories_SO.inc.php 
                         class.Categories_UI.inc.php 
                         class.Category_SO.inc.php 
                         class.Content_BO.inc.php 
                         class.Content_UI.inc.php class.Sites_BO.inc.php 
                         class.Sites_SO.inc.php class.module.inc.php 
        modules        : class.module_html.inc.php 
        setup          : setup.inc.php tables_current.inc.php 
                         tables_update.inc.php 
        sitemgr-site   : index.php 
        sitemgr-site/inc: class.sitebo.inc.php 
        templates/default: edit_category.tpl 
Added files:
        inc/api        : README class.javascript.inc.php 
                         class.richtext.inc.php 
        js/columnlist  : columnlist.css columnlist.js sortabletable.js 
        js/columnlist/original: api.html api.xml columnlist.html 
                                demo.html demo2.html implementation.html 
                                usage.html 
        js/columnlist/original/article-images: ie.png moz.png 
        js/columnlist/original/images: asc.png desc.png 
        js/columnlist/original/includes: columnlist.css columnlist.js 
                                         sortabletable.js 
        js/columnlist/original/local: helptip.css helptip.js 
                                      title-background.png webfxapi.css 
                                      webfxapi.js webfxlayout.css 
                                      webfxlayout.js 

Log message:
        A few changes:
        * multiple wysiwyg editor support
        * template by cat option
        * better cats editor (WIP)
        * little bit of polish here and there

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Categories_BO.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.6.2.2.4.1&tr2=1.6.2.2.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Categories_SO.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.13.2.5.4.1&tr2=1.13.2.5.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Categories_UI.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.1.2.1.4.1&tr2=1.1.2.1.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Category_SO.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.4.10.1&tr2=1.4.10.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Content_BO.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.2.2.1&tr2=1.2.2.1.4.1&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Content_UI.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.3.2.4.2.2&tr2=1.3.2.4.2.3&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Sites_BO.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.7.2.1&tr2=1.7.2.1.4.1&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.Sites_SO.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.2.2.3&tr2=1.2.2.3.4.1&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/class.module.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.8.2.2.4.1&tr2=1.8.2.2.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/api/README?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/api/class.javascript.inc.php?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/inc/api/class.richtext.inc.php?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/columnlist.css?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/columnlist.js?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/sortabletable.js?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/api.html?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/api.xml?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/columnlist.html?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/demo.html?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/demo2.html?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/implementation.html?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/usage.html?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/article-images/ie.png?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/article-images/moz.png?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/images/asc.png?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/images/desc.png?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/includes/columnlist.css?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/includes/columnlist.js?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/includes/sortabletable.js?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/local/helptip.css?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/local/helptip.js?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/local/title-background.png?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/local/webfxapi.css?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/local/webfxapi.js?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/local/webfxlayout.css?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/js/columnlist/original/local/webfxlayout.js?only_with_tag=skwashd-16-compat&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/modules/class.module_html.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.1.2.2.4.1&tr2=1.1.2.2.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/setup/setup.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.12.2.2.4.2&tr2=1.12.2.2.4.3&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/setup/tables_current.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.11.2.1.4.1&tr2=1.11.2.1.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/setup/tables_update.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.11.2.4.4.1&tr2=1.11.2.4.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/sitemgr-site/index.php.diff?only_with_tag=skwashd-16-compat&tr1=1.7.2.2.4.1&tr2=1.7.2.2.4.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/sitemgr-site/inc/class.sitebo.inc.php.diff?only_with_tag=skwashd-16-compat&tr1=1.1.2.3&tr2=1.1.2.3.4.1&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/phpgroupware/sitemgr/templates/default/edit_category.tpl.diff?only_with_tag=skwashd-16-compat&tr1=1.6.2.2.4.1&tr2=1.6.2.2.4.2&r1=text&r2=text

Patches:
Index: sitemgr/inc/api/README
diff -u /dev/null sitemgr/inc/api/README:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/inc/api/README      Mon Mar 27 13:13:24 2006
@@ -0,0 +1,3 @@
+These files need to be copied to phpgwapi/inc
+
+richtext is new and javascript is a drop in replacement
Index: sitemgr/inc/api/class.javascript.inc.php
diff -u /dev/null sitemgr/inc/api/class.javascript.inc.php:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/inc/api/class.javascript.inc.php    Mon Mar 27 13:13:24 2006
@@ -0,0 +1,241 @@
+<?php
+       /**
+       * Javascript support class
+       * @author Dave Hall <address@hidden>
+       * @copyright Portions Copyright (C) 2003,2004 Free Software Foundation, 
Inc http://www.fsf.org/
+       * @license http://www.fsf.org/licenses/gpl.html GNU General Public 
License
+       * @package phpgwapi
+       * @subpackage gui
+       * @version $Id: class.javascript.inc.php,v 1.1.2.1 2006/03/27 13:13:24 
skwashd Exp $
+       * @link http://docs.phpgroupware.org/wiki/classJavaScript
+       */
+
+       /**
+       * phpGroupWare javascript support class
+       *
+       * Only instanstiate this class using:
+       * <code>
+       *  if(address@hidden($GLOBALS['phpgw']->js))
+       *  {
+       *    $GLOBALS['phpgw']->js = CreateObject('phpgwapi.javascript');
+       *  }
+       * </code>
+       *
+       * This way a theme can see if this is a defined object and include the 
data,
+       * while the is_object() wrapper prevents whiping out existing data held 
in 
+       * this instance variables, primarily the $files variable.
+       *
+       * Note: The package arguement is the subdirectory of js - all js should 
live in subdirectories
+       *
+       * @package phpgwapi
+       * @subpackage gui
+       * @uses template
+       */
+       class javascript
+       {
+               /**
+               * @var array elements to be used for the window.on* events
+               */
+               var $win_events = array
+                               (
+                                       'load'          => array(),
+                                       'unload'        => array()
+                               );
+
+               /**
+               * @var array list of validated files to be included in the head 
section of a page
+               */
+               var $files;
+
+               /**
+               * @var object used for holding an instance of the Template class
+               */
+               var $t;
+               
+               /**
+               * Constructor
+               *
+               * Initialize the instance variables
+               */
+               function javascript()
+               {
+               }
+
+               /**
+               * Set a window.on?? event
+               *
+               * @param string $event the name of the event
+               * @param string $code the code to be called
+               */
+               function add_event($event, $code)
+               {
+                       if ( !isset($this->win_events[$event]) )
+                       {
+                               $this->win_events[$event] = array();
+                       }
+                       $this->win_events[$event][] = $code;
+               }
+               
+               /**
+               * Returns the javascript required for displaying a popup 
message box
+               *
+               * @param string $msg the message to be displayed to user
+               * @returns string the javascript to be used for displaying the 
message
+               */
+               function get_alert($msg)
+               {
+                 return 'return alert("'.lang($msg).'");';
+               }
+
+               /**
+               * Returns the javascript required for displaying a confirmation 
message box
+               *
+               * @param string $msg the message to be displayed to user
+               * @returns string the javascript to be used for displaying the 
message
+               */
+               function get_confirm($msg)
+               {
+                       return 'return confirm("'.lang($msg).'");';
+               }
+               
+               /**
+               * Used for generating the list of external js files to be 
included in the head of a page
+               *
+               * NOTE: This method should only be called by the template class.
+               * The validation is done when the file is added so we don't 
have to worry now
+               *
+               * @returns string the html needed for importing the js into a 
page
+               */
+               function get_script_links()
+               {
+                       $links = '';
+                       if(!empty($this->files) && is_array($this->files))
+                       {
+                               $links = "<!--JS Imports from phpGW javascript 
class -->\n";
+                               foreach($this->files as $app => $packages)
+                               {
+                                       if(!empty($packages) && 
is_array($packages))
+                                       {
+                                               foreach($packages as $pkg => 
$files)
+                                               {
+                                                       if(!empty($files) && 
is_array($files))
+                                                       {
+                                                               foreach($files 
as $file => $ignored)
+                                                               {
+                                                                       $links 
.= '<script type="text/javascript" '
+                                                                       . 
"src=\"{$GLOBALS['phpgw_info']['server']['webserver_url']}/{$app}/js/{$pkg}/{$file}.js\">"
+                                                                       . 
"</script>\n";
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       $links .= "<script type=\"text/javascript\">\n" . 
$this->get_win_on_events() . "\n</script>\n";
+                       return $links;
+               }
+
+               /**
+               * @deprecated
+               */
+               function get_body_attribs()
+               {
+                       return '';
+               }
+
+
+               /**
+               * Creates the javascript for handling window.on* events
+               *
+               * @returns string the attributes to be used
+               */
+               function get_win_on_events()
+               {
+                       $ret_str = "\n//<![CDATA[\n// start phpGW javascript 
class imported window.on* event handlers\n";
+                       foreach ( $this->win_events as $win_event => $actions )
+                       {
+                               if ( is_array($actions) && count($actions) )
+                               {
+                                       $ret_str .= "window.on{$win_event} = 
function()\n{\n";
+                                       foreach ( $actions as $action )
+                                       {
+                                               $ret_str .= "\t$action\n";
+                                       }
+                                       $ret_str .= "}\n";
+                               }
+                       }
+                       $ret_str .= "\n// end phpGW javascript class imported 
window.on* event handlers\n//]]>\n\n";
+                       return $ret_str;
+               }
+
+               /**
+               * Sets an onLoad action for a page
+               *
+               * @deprecated
+               * @param string javascript to be used
+               */
+               function set_onload($code)
+               {
+                       $this->win_events['load'][] = $code;
+               }
+
+               /**
+               * Sets an onUnload action for a page
+               *
+               * @deprecated
+               * @param string javascript to be used
+               */
+               function set_onunload($code)
+               {
+                       $this->events['unload'][] = $code;
+               }
+
+               /**
+               * DO NOT USE - NOT SURE IF I AM GOING TO USE IT - ALSO IT NEEDS 
SOME CHANGES!!!!
+               * Used for removing a file or package of files to be included 
in the head section of a page
+               *
+               * @param string $app application to use
+               * @param string $package the name of the package to be removed
+               * @param string $file the name of a file in the package to be 
removed - if ommitted package is removed
+               */
+               function unset_script_link($app, $package, $file=False)
+               {
+                       /* THIS DOES NOTHING ATM :P
+                       if($file !== False)
+                       {
+                               unset($this->files[$app][$package][$file]);
+                       }
+                       else
+                       {
+                               unset($this->files[$app][$package]);
+                       }
+                       */
+               }
+
+               /**
+               * Checks to make sure a valid package and file name is provided
+               *
+               * @param string $package package to be included
+               * @param string $file file to be included - no ".js" on the end
+               * @param string $app application directory to search - default 
= phpgwapi
+               * @returns bool was the file found?
+               */
+               function validate_file($package, $file, $app='phpgwapi')
+               {
+                       if(is_readable(PHPGW_INCLUDE_ROOT . 
"/$app/js/$package/$file.js"))
+                       {
+                               $this->files[$app][$package][$file] = True;
+                               return True;
+                       }
+                       elseif($app != 'phpgwapi')
+                       {
+                               if(is_readable(PHPGW_INCLUDE_ROOT . 
"/phpgwapi/js/$package/$file.js"))
+                               {
+                                       
$this->files['phpgwapi'][$package][$file] = True;
+                                       return True;
+                               }
+                               return False;
+                       }
+               }
+       }
+?>
Index: sitemgr/inc/api/class.richtext.inc.php
diff -u /dev/null sitemgr/inc/api/class.richtext.inc.php:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/inc/api/class.richtext.inc.php      Mon Mar 27 13:13:24 2006
@@ -0,0 +1,276 @@
+<?php
+       /**
+       * Rich Text Editor Handler class
+       *
+       * Allows different rich text wysiwyg html editors to be used within 
phpgw
+       *
+       * @author Dave Hall skwashd at phpgroupware.org
+       * @copyright Copyright (C) 2006 Free Software Foundation, Inc. 
http://www.fsf.org/
+       * @license http://www.fsf.org/licenses/gpl.html GNU General Public 
License
+       * @package phpgwapi
+       * @subpackage gui
+       * @version $Id: class.richtext.inc.php,v 1.1.2.1 2006/03/27 13:13:24 
skwashd Exp $
+       */
+
+       //This is done here for 16 support
+       $GLOBALS['phpgw_info']['server']['enable_fckeditor'] = true;
+       $GLOBALS['phpgw_info']['server']['enable_tinymce'] = true;
+       $GLOBALS['phpgw_info']['user']['preferences']['common']['rteditor'] = 
'tinymce';
+
+       /**
+       * Rich Text Editor Handler class
+       *
+       * @package phpgwapi
+       * @subpackage gui
+       */
+       class richtext
+       {
+               /**
+                * @var the base URL for all links, defaults to phpgw url
+                */
+                var $base_url;
+                
+               /**
+               * @var string $rte which rich text editor will be used
+               */
+               var $rte;
+
+               /**
+               * @var array $targets the targets which will be replaced by the 
rich text editor
+               */
+               var $targets = array();
+               
+               /**
+               * @constructor
+               */
+               function richtext()
+               {
+                       $this->base_url = 
$GLOBALS['phpgw_info']['server']['webserver_url'];
+                       $this->rte = '';
+                       if(!is_object($GLOBALS['phpgw']->js))
+                       {
+                               $GLOBALS['phpgw']->js = 
createObject('phpgwapi.javascript');
+                       }
+                       $this->_init_head();
+                       $GLOBALS['phpgw']->js->validate_file('jscalendar', 
'calendar_stripped');
+               }
+
+               /**
+               * Generate the dynamic script content for the header
+               */
+               function generate_script()
+               {
+                       if ( count($this>targets) )
+                       {
+                               switch($this->rte)
+                               {
+                                       case 'fckeditor':
+                                               
$this->_generate_script_fckeditor();
+                                               break;
+                                       
+                                       case 'tinymce':
+                                               
$this->_generate_script_tinymce();
+                                               break;
+                                       default:
+                                               //do nothing
+                               }
+                       }
+               }
+
+               /**
+               * Replaces an element with a rich text editor instance
+               */
+               function replace_element($html_id)
+               {
+                       $this->targets[$html_id] = true; //stops duplicates :)
+               }
+
+               /**
+                * Set the base URL for all links
+                */
+                function set_base_url($url)
+                {
+                       $this->base_url = $url;
+                }
+
+               /**
+                * Generate the js needed for FCKeditor to function properly 
+                */
+                function _generate_script_fckeditor()
+                {
+                       $str = '';
+                       
+                       foreach ( $this->targets as $target => $crap )
+                       {
+                               $str .=  "var oFCKeditor_{$target} = new 
FCKeditor( '{$target}' ) ;\n" .
+                                               
"oFCKeditor_{$target}.AutoDetectLanguage = false;\n" .
+                                               "oFCKeditor_{$target}.BaseHref 
= '{$this->base_url}';\n" .
+                                               "oFCKeditor_{$target}.BasePath 
= 
'{$GLOBALS['phpgw_info']['server']['webserver_url']}/phpgwapi/js/fckeditor/';\n"
 .
+                                               
"oFCKeditor_{$target}.DefaultLanguage = 
'{$GLOBALS['phpgw_info']['user']['preferences']['common']['lang']}';\n" .
+                                               
"oFCKeditor_{$target}.GeckoUseSPAN = false;\n" .
+                                               
"oFCKeditor_{$target}.SpellChecker = '" . (extension_loaded('pspell') ? 
'SpellerPages' : 'ieSpell') . "';\n" .
+                                               
"oFCKeditor_{$target}.ReplaceTextarea();\n\n";
+                       }
+                       $GLOBALS['phpgw']->js->add_event('load', $str);
+                }
+
+               /**
+                * Generate the js needed for tiny to function properly 
+                */
+               function _generate_script_tinymce()
+               {
+                       $str = "<script 
type=\"text/javascript\">\n//<![CDATA[\n" .
+                               "tinyMCE.init({\n" .
+                                       "\t\tdocument_base_url : 
'{$this->base_url}',\n" .
+                                       "\t\tinline_styles : false,\n" .
+                                       "\t\tlanguage : 
'{$GLOBALS['phpgw_info']['user']['preferences']['common']['lang']}',\n" .
+                                       "\t\tmode : 'none',\n" .
+                                       "\t\ttheme : 'advanced',\n" .
+                                       "\t\ttheme_advanced_toolbar_align : 
'left',\n" .
+                                       "\t\ttheme_advanced_toolbar_location : 
'top',\n" .
+                                       //FIXME make this more configrable 
(using array? and unset?)
+                                       "\t\tvalid_elements : ''" . '
++"a[accesskey|charset|class|coords|dir<ltr?rtl|href|hreflang|id|lang|name|rel|rev|shape<circle?default?poly?rect|tabindex|title|target|type],"
++"abbr[class|dir<ltr?rtl|id|lang|title],"
++"acronym[class|dir<ltr?rtl|id|id|lang|title],"
++"address[class|align|dir<ltr?rtl|id|lang|title],"
++"area[accesskey|alt|class|coords|dir<ltr?rtl|href|id|lang|nohref<nohref|shape<circle?default?poly?rect|tabindex|title|target],"
++"bdo[class|dir<ltr?rtl|id|lang|title],"
++"big[class|dir<ltr?rtl|id|lang|title],"
++"blockquote[dir|cite|class|dir<ltr?rtl|id|lang|title],"
++"body[alink|background|bgcolor|class|dir<ltr?rtl|id|lang|link|title|text|vlink],"
++"br[class|clear<all?left?none?right|id|title],"
++"button[accesskey|class|dir<ltr?rtl|disabled<disabled|id|lang|name|tabindex|title|type|value],"
++"caption[align<bottom?left?right?top|class|dir<ltr?rtl|id|lang|title],"
++"cite[class|dir<ltr?rtl|id|lang|title],"
++"code[class|dir<ltr?rtl|id|lang|title],"
++"col[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id|lang|span|title|valign<baseline?bottom?middle?top|width],"
++"colgroup[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id|lang|span|title|valign<baseline?bottom?middle?top|width],"
++"dd[class|dir<ltr?rtl|id|lang|title],"
++"del[cite|class|datetime|dir<ltr?rtl|id|lang|title],"
++"dfn[class|dir<ltr?rtl|id|lang|title],"
++"dir[class|compact<compact|dir<ltr?rtl|id|lang|title],"
++"div[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"dl[class|compact<compact|dir<ltr?rtl|id|lang|title],"
++"dt[class|dir<ltr?rtl|id|lang|title],"
++"em/i[class|dir<ltr?rtl|id|lang|title],"
++"fieldset[class|dir<ltr?rtl|id|lang|title],"
++"font[class|color|dir<ltr?rtl|face|id|lang|size|title],"
++"form[accept|accept-charset|action|class|dir<ltr?rtl|enctype|id|lang|method<get?post|name|title|target],"
++"h1[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"h2[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"h3[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"h4[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"h5[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"h6[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"hr[align<center?left?right|class|dir<ltr?rtl|id|lang|noshade<noshade|size|title|width],"
++"img[align<bottom?left?middle?right?top|alt|border|class|dir<ltr?rtl|height|hspace|id|ismap<ismap|lang|longdesc|name|src|title|usemap|vspace|width],"
++"input[accept|accesskey|align<bottom?left?middle?right?top|alt|checked<checked|class|dir<ltr?rtl|disabled<disabled|id|ismap<ismap|lang|maxlength|name|readonly<readonly|size|src|tabindex|title|type<button?checkbox?file?hidden?image?password?radio?reset?submit?text|usemap|value],"
++"ins[cite|class|datetime|dir<ltr?rtl|id|lang|title],"
++"isindex[class|dir<ltr?rtl|id|lang|prompt|title],"
++"kbd[class|dir<ltr?rtl|id|lang|title],"
++"label[accesskey|class|dir<ltr?rtl|for|id|lang|title],"
++"legend[align<bottom?left?right?top|accesskey|class|dir<ltr?rtl|id|lang|title],"
++"li[class|dir<ltr?rtl|id|lang|title|type|value],"
++"link[charset|class|dir<ltr?rtl|href|hreflang|id|lang|media|rel|rev|title|target|type],"
++"map[class|dir<ltr?rtl|id|lang|name|title],"
++"menu[class|compact<compact|dir<ltr?rtl|id|lang|title],"
++"object[align<bottom?left?middle?right?top|archive|border|class|classid|codebase|codetype|data|declare|dir<ltr?rtl|height|hspace|id|lang|name|standby|tabindex|title|type|usemap|vspace|width],"
++"ol[class|compact<compact|dir<ltr?rtl|id|lang|start|title|type],"
++"optgroup[class|dir<ltr?rtl|disabled<disabled|id|label|lang|title],"
++"option[class|dir<ltr?rtl|disabled<disabled|id|label|lang|selected<selected|title|value],"
++"p[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"param[id|name|type|value|valuetype<DATA?OBJECT?REF],"
++"pre/listing/plaintext/xmp[align|class|dir<ltr?rtl|id|lang|title|width],"
++"q[cite|class|dir<ltr?rtl|id|lang|title],"
++"s[class|dir<ltr?rtl|id|lang|title],"
++"samp[class|dir<ltr?rtl|id|lang|title],"
++"select[class|dir<ltr?rtl|disabled<disabled|id|lang|multiple<multiple|name|size|tabindex|title],"
++"small[class|dir<ltr?rtl|id|lang|title],"
++"span[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|title],"
++"strike[class|class|dir<ltr?rtl|id|lang|title],"
++"strong/b[class|dir<ltr?rtl|id|lang|title],"
++"style[dir<ltr?rtl|lang|media|title|type],"
++"sub[class|dir<ltr?rtl|id|lang|title],"
++"sup[class|dir<ltr?rtl|id|lang|title],"
++"table[align<center?left?right|bgcolor|border|cellpadding|cellspacing|class|dir<ltr?rtl|frame|height|id|lang|rules|summary|title|width],"
++"tbody[align<center?char?justify?left?right|char|class|charoff|dir<ltr?rtl|id|lang|title|valign<baseline?bottom?middle?top],"
++"td[abbr|align<center?char?justify?left?right|axis|bgcolor|char|charoff|class|colspan|dir<ltr?rtl|headers|height|id|lang|nowrap<nowrap|rowspan|scope<col?colgroup?row?rowgroup|title|valign<baseline?bottom?middle?top|width],"
++"textarea[accesskey|class|cols|dir<ltr?rtl|disabled<disabled|id|lang|name|readonly<readonly|rows|tabindex|title],"
++"tfoot[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id|lang|title|valign<baseline?bottom?middle?top],"
++"th[abbr|align<center?char?justify?left?right|axis|bgcolor|char|charoff|class|colspan|dir<ltr?rtl|headers|height|id|lang|nowrap<nowrap|rowspan|scope<col?colgroup?row?rowgroup|title|valign<baseline?bottom?middle?top|width],"
++"thead[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id|lang|title|valign<baseline?bottom?middle?top],"
++"title[dir<ltr?rtl|lang],"
++"tr[abbr|align<center?char?justify?left?right|bgcolor|char|charoff|class|rowspan|dir<ltr?rtl|id|lang|title|valign<baseline?bottom?middle?top],"
++"tt[class|dir<ltr?rtl|id|lang|title],"
++"u[class|dir<ltr?rtl|id|lang|title],"
++"ul[class|compact<compact|dir<ltr?rtl|id|lang|title|type],"
++"var[class|dir<ltr?rtl|id|lang|title]"'
+                                       . "});\n"
+                                       .  "\n//]]>\n</script>\n";
+                       foreach ( $this->targets as $target => $crap )
+                       {
+                               //$str .= 
"\ttinyMCE.execCommand('mceAddControl', true, {$target});\n";
+                       }
+                       $str .= "\n\n";
+
+                       $GLOBALS['phpgw_info']['flags']['java_script'] .= $str;
+                       //$GLOBALS['phpgw']->js->add_event('load', $str);
+
+                       foreach ( $this->targets as $target => $crap )
+                       {
+                               $GLOBALS['phpgw']->js->add_event('load', 
"\ttinyMCE.execCommand('mceAddControl', true, '{$target}');\n");
+                       }
+               }
+
+               /**
+               * Add the appropriate <script>s to the <head> section
+               *
+               * @access private
+               */
+               function _init_head()
+               {
+                       if ( 
!isset($GLOBALS['phpgw_info']['user']['preferences']['common']['rteditor'])
+                               || 
$GLOBALS['phpgw_info']['user']['preferences']['common']['rteditor'] == 'none' )
+                       {
+                               //nothing to do here as the user doesn't want 
to use a rte
+                               return true;
+                       }
+                       $rte_name = 
$GLOBALS['phpgw_info']['user']['preferences']['common']['rteditor'];
+                       
+                       if ( isset($GLOBALS['phpgw_info']['server']['enable_' . 
$rte_name]) )
+                       {
+                               //now that we know that the user is allowed to 
use it we init it
+                               switch($rte_name)
+                               {
+                                       case 'fckeditor':
+                                               $this->_init_fckeditor();
+                                               break;
+                                       case 'tinymce':
+                                               $this->_init_tinymce();
+                                               break;
+                                       default:
+                                               //do nothing
+                               }
+                       }
+               }
+
+               /**
+               * Prepare FCKeditor to be used in a page
+               */
+               function _init_fckeditor()
+               {
+                       $GLOBALS['phpgw']->js->validate_file('fckeditor', 
'fckeditor');
+                       $this->rte = 'fckeditor';
+               }
+
+               /**
+               * Prepare tinymce to be used in a page
+               */
+               function _init_tinymce()
+               {
+                       $GLOBALS['phpgw']->js->validate_file('tinymce', 
'tiny_mce');
+                       $this->rte = 'tinymce';
+               }
+       }
+?>
Index: sitemgr/inc/class.Categories_BO.inc.php
diff -u sitemgr/inc/class.Categories_BO.inc.php:1.6.2.2.4.1 
sitemgr/inc/class.Categories_BO.inc.php:1.6.2.2.4.2
--- sitemgr/inc/class.Categories_BO.inc.php:1.6.2.2.4.1 Sat Nov 12 13:15:37 2005
+++ sitemgr/inc/class.Categories_BO.inc.php     Mon Mar 27 13:13:24 2006
@@ -170,7 +170,7 @@
                        return True;
                }
 
-               function saveCategoryInfo($cat_id, $cat_name, $cat_description, 
$lang, $sort_order, $state, $parent=False, $old_parent=False, $def_page = 0)
+               function saveCategoryInfo($cat_id, $cat_name, $cat_description, 
$lang, $sort_order, $state, $parent=False, $old_parent=False, $def_page = 0, 
$cat_tpl = '')
                {
                        if (!$parent)
                        {
@@ -185,6 +185,7 @@
                        $cat_info->parent = $parent;
                        $cat_info->old_parent = $old_parent ? $old_parent : 
$parent;
                        $cat_info->def_page = $def_page;
+                       $cat_info->cat_tpl = $cat_tpl;
 
                        if 
($GLOBALS['Common_BO']->acl->can_write_category($cat_id))
                        {
Index: sitemgr/inc/class.Categories_SO.inc.php
diff -u sitemgr/inc/class.Categories_SO.inc.php:1.13.2.5.4.1 
sitemgr/inc/class.Categories_SO.inc.php:1.13.2.5.4.2
--- sitemgr/inc/class.Categories_SO.inc.php:1.13.2.5.4.1        Sat Nov 12 
13:15:37 2005
+++ sitemgr/inc/class.Categories_SO.inc.php     Mon Mar 27 13:13:24 2006
@@ -82,7 +82,8 @@
                        $this->cats->edit($data);
                        $this->db->query('UPDATE phpgw_sitemgr_categories_state'
                                        . ' SET state = ' . 
intval($cat_info->state) . ','
-                                               . ' def_page = ' . 
intval($cat_info->def_page)
+                                               . ' def_page = ' . 
intval($cat_info->def_page) . ','
+                                               . " template_set = '" . 
$this->db->db_addslashes($cat_info->cat_tpl) . "'"
                                        . ' WHERE cat_id = ' . 
intval($cat_info->id), __LINE__,__FILE__);
                }
 
@@ -138,14 +139,16 @@
                                $cat_info->root         = $cat[0]['main'];
                                $cat_info->state        = 0;
                                $cat_info->def_page     = 0;
+                               $cat_info->cat_tpl      = '';
 
-                               $this->db->query('SELECT state, def_page FROM 
phpgw_sitemgr_categories_state'
+                               $this->db->query('SELECT state, def_page, 
template_set FROM phpgw_sitemgr_categories_state'
                                                . ' WHERE cat_id=' . 
intval($cat_id), __LINE__, __FILE__);
 
                                if ( $this->db->next_record() )
                                {
                                        $cat_info->state = 
$this->db->f('state');
                                        $cat_info->def_page = 
$this->db->f('def_page');
+                                       $cat_info->cat_tpl = 
$this->db->f('template_set');
                                }
 
                                if ($lang)
@@ -157,8 +160,8 @@
 
                                        if ($this->db->next_record())
                                        {
-                                               $cat_info->name = 
$this->db->f('name');
-                                               $cat_info->description = 
$this->db->f('description');
+                                               $cat_info->name = 
$this->db->f('name', true);
+                                               $cat_info->description = 
$this->db->f('description', true);
                                        }
 //                                     else
 //                                     {
@@ -174,9 +177,9 @@
                                                        . ' WHERE cat_id=' . 
intval($cat_id), __LINE__, __FILE__);
                                        if ($this->db->next_record())
                                        {
-                                               $cat_info->name = 
$this->db->f('name');
-                                               $cat_info->description = 
$this->db->f('description');
-                                               $cat_info->lang = 
$this->db->f('lang');
+                                               $cat_info->name = 
$this->db->f('name', true);
+                                               $cat_info->description = 
$this->db->f('description', true);
+                                               $cat_info->lang = 
$this->db->f('lang', true);
                                        }
                                        else
                                        {
Index: sitemgr/inc/class.Categories_UI.inc.php
diff -u sitemgr/inc/class.Categories_UI.inc.php:1.1.2.1.4.1 
sitemgr/inc/class.Categories_UI.inc.php:1.1.2.1.4.2
--- sitemgr/inc/class.Categories_UI.inc.php:1.1.2.1.4.1 Sat Nov 12 13:15:37 2005
+++ sitemgr/inc/class.Categories_UI.inc.php     Mon Mar 27 13:13:24 2006
@@ -35,6 +35,41 @@
                        $this->sitelanguages = 
$GLOBALS['Common_BO']->sites->current_site['sitelanguages'];
                }
 
+               function delete()
+               {
+                       if (!$this->isadmin)
+                       {
+                               
$GLOBALS['phpgw']->redirect($GLOBALS['phpgw']->link('/index.php','menuaction=sitemgr.Outline_UI.manage'));
+                               return;
+                       }
+
+                       
$GLOBALS['Common_BO']->globalize(array('btnDelete','btnCancel'));
+                       global $btnDelete,$btnCancel;
+                       $cat_id = $_GET['cat_id'];
+
+                       if ($btnDelete)
+                       {
+                               $this->cat_bo->removeCategory($cat_id);
+                               
$GLOBALS['phpgw']->redirect($GLOBALS['phpgw']->link('/index.php','menuaction=sitemgr.Outline_UI.manage'));
+                               return;
+                       }
+                       if ($btnCancel)
+                       {
+                               
$GLOBALS['phpgw']->redirect($GLOBALS['phpgw']->link('/index.php','menuaction=sitemgr.Outline_UI.manage'));
+                               return;
+                       }
+
+                       $this->common_ui->DisplayHeader();
+
+                       $cat = 
$this->cat_bo->getCategory($cat_id,$this->sitelanguages[0]);
+                       $this->t->set_file('ConfirmDelete','confirmdelete.tpl');
+                       $this->t->set_var('deleteheader',lang('Are you sure you 
want to delete the category %1 and all of its associated pages?  You cannot 
retrieve the deleted pages if you continue.',$cat->name));
+                       $this->t->set_var('cat_id',$cat_id);
+                       $this->t->set_var('lang_yes',lang('Yes, please delete 
it'));
+                       $this->t->set_var('lang_no',lang('Cancel the delete'));
+                       $this->t->pfp('out','ConfirmDelete');
+               }
+
                function edit()
                {
                        if (!$this->isadmin)
@@ -46,19 +81,23 @@
                        $cat_id = isset($_REQUEST['cat_id']) && 
$_REQUEST['cat_id'] ? $_REQUEST['cat_id'] : 0;
                        $cat_id = isset($_REQUEST['inputcatid']) && 
$_REQUEST['inputcatid'] ? $_REQUEST['inputcatid'] : $cat_id;
 
-                       if (isset($_POST['btnSave']) && $_POST['btnSave'] 
-                               && isset($_POST['inputcatname']) && 
$_POST['inputcatname'] 
-                               && isset($_POST['inputcatdesc']) && 
$_POST['inputcatdesc'] )
+                       if (isset($_POST['btnSave']) && $_POST['btnSave'] )
                        {
                                if ( $_POST['inputcatname'] == '' || 
$_POST['inputcatdesc'] == '')
                                {
                                        $error = lang('You failed to fill in 
one or more required fields.');
                                        $this->t->set_var('message', $error);
+                                        $cat = new Category_SO();
+                                        $cat->id = $cat_id;
+                                        $cat->name = $_POST['inputcatname'];
+                                        $cat->description = 
$_POST['inputcatdesc'];
+                                        $cat->sort_order = 
$_POST['inputsortorder'];
+                                        $cat->parent = $_POST['inputparent'];
+                                        $cat->state = $_POST['inputstate'];
                                }
                                else
                                {
                                        $cat_id =  $cat_id ? $cat_id : 
$this->cat_bo->addCategory('','');
-
                                        $groupaccess = 
array_merge_recursive($_POST['inputgroupaccessread'], 
$_POST['inputgroupaccesswrite']);
                                        $individualaccess = 
array_merge_recursive($_POST['inputindividualaccessread'], 
$_POST['inputindividualaccesswrite']);
                                        $savelanguage = 
isset($_POST['savelanguage']) && $_POST['savelanguage'] ? 
$_POST['savelanguage'] : $this->sitelanguages[0];
@@ -70,10 +109,11 @@
                                                                        
$_POST['inputstate'], 
                                                                        
$_POST['inputparent'], 
                                                                        
$_POST['inputparentold'], 
-                                                                       
$_POST['def_page']
+                                                                       
$_POST['def_page'],
+                                                                       
$_POST['cat_tpl']
                                                                        );
 
-                                       if ( 
isset($_POST['inputgetparentpermissions']) && 
$_POST['inputgetparentpermissions'] )
+                                       if ( isset($_POST['permissions']) && 
$_POST['permissions'] == 'parent' )
                                        {
                                                
$this->cat_bo->saveCategoryPermsfromparent($cat_id);
                                        }
@@ -82,7 +122,7 @@
                                                
$this->cat_bo->saveCategoryPerms($cat_id, $groupaccess, $individualaccess);
                                        }
 
-                                       if ( 
isset($_POST['inputapplypermissionstosubs']) && 
$_POST['inputapplypermissionstosubs'] )
+                                       if ( isset($_POST['permissionstosubs']) 
&& $_POST['permissionstosubs'] )
                                        {
                                                
$this->cat_bo->applyCategoryPermstosubs($cat_id);
                                        }
@@ -95,7 +135,7 @@
                                //we use force here since we might edit an 
archive category
                                $cat = 
$this->cat_bo->getCategory($cat_id,$this->sitelanguages[0],True);
                        }
-
+                       
                        $this->t->set_file('EditCategory', 'edit_category.tpl');
                        $this->t->set_block('EditCategory','GroupBlock', 
'GBlock');
 
@@ -127,12 +167,14 @@
                                        'cat_id'                => $cat_id,
                                        'catname'               => $cat->name,
                                        'catdesc'               => 
$cat->description,
+                                       'cat_tpl'               => 
$this->get_cat_tpl_list($cat->cat_tpl), 
                                        'sort_order'            => 
$cat->sort_order,
                                        'def_page'              => 
$def_page_list,
-                                       'parent_dropdown'       => 
$this->getParentOptions($cat->parent,$cat_id),
+                                       'parent_dropdown'       => 
$this->get_parent_options($cat->parent,$cat_id),
                                        'stateselect'           => 
$GLOBALS['Common_BO']->inputstateselect($cat->state),
                                        'old_parent'            => $cat->parent,
                                        'lang_basic'            => lang('Basic 
Settings'),
+                                       'lang_cat_tpl'          => 
lang('template for category'),
                                        'lang_catname'          => 
lang('Category Name'),
                                        'lang_catsort'          => lang('Sort 
Order'),
                                        'lang_catparent'        => 
lang('Parent'),
@@ -174,10 +216,10 @@
                                                $permission_id = 0;
                                        }
 
-                                       $this->t->set_var('groupname', 
$account_name);
+                                       $this->t->set_var('groupname', lang('%1 
group', $account_name));
                                        if ($permission_id & PHPGW_ACL_READ)  
                                        {
-                                               
$this->t->set_var('checkedgroupread','CHECKED');
+                                               
$this->t->set_var('checkedgroupread','checked="checked"');
                                        }
                                        else
                                        {
@@ -185,7 +227,7 @@
                                        }
                                        if ($permission_id & PHPGW_ACL_ADD)
                                        {
-                                               
$this->t->set_var('checkedgroupwrite','CHECKED');
+                                               
$this->t->set_var('checkedgroupwrite','checked="checked"');
                                        }
                                        else
                                        {
@@ -208,7 +250,7 @@
                        {
                                for($i = 0; $i < count($userlist); $i++ )
                                {
-                                       $user_name = 
$userlist[$i]['account_lid'];
+                                       $user_name = 
$userlist[$i]['account_firstname'] . ' ' . $userlist[$i]['account_lastname'] ;
                                        $user_id = $userlist[$i]['account_id'];
                                        if ($cat_id)
                                        {
@@ -223,7 +265,7 @@
                                        $this->t->set_var('username', 
$user_name);
                                        if ($user_permission_id & 
PHPGW_ACL_READ )
                                        {
-                                               
$this->t->set_var('checkeduserread','CHECKED');
+                                               
$this->t->set_var('checkeduserread','checked="checked"');
                                        }
                                        else
                                        {
@@ -231,7 +273,7 @@
                                        }
                                        if ($user_permission_id & PHPGW_ACL_ADD 
)
                                        {
-                                               
$this->t->set_var('checkeduserwrite','CHECKED');
+                                               
$this->t->set_var('checkeduserwrite','checked="checked"');
                                        }
                                        else
                                        {
@@ -249,19 +291,31 @@
 
                        $this->common_ui->DisplayFooter();
                }
+               
+               function get_cat_tpl_list($cat_tpl)
+               {
+                       $str = '<option value="">' . lang('site template') . 
"</option>\n";
+                       foreach 
($GLOBALS['Common_BO']->theme->getAvailableThemes() as $tpl )
+                       {
+                               $str .= "<option value=\"{$tpl['value']}\""
+                                               . ($tpl['value'] == $cat_tpl ? 
'selected="selected"' : '')
+                                               
.">{$tpl['display']}</option>\n";
+                       }
+                       return $str;
+               }
 
-               function getParentOptions($selected_id=0,$skip_id=0)
+               function get_parent_options($selected_id=0,$skip_id=0)
                {
                        $option_list=$this->cat_bo->getCategoryOptionList();
                        if (!$selected_id)
                        {
-                               $selected=' SELECTED';
+                               $selected=' selected="selected"';
                        }
                        if (!$skip_id)
                        {
                                $skip_id = -1;
                        }
-                       $retval="\n".'<SELECT NAME="inputparent">'."\n";
+                       $retval="\n".'<select name="inputparent" 
id="inputparent">'."\n";
                        foreach($option_list as $option)
                        {
                                if ($option['value']!=$skip_id)
@@ -269,49 +323,14 @@
                                        $selected='';
                                        if ($option['value']==$selected_id)
                                        {
-                                               $selected=' SELECTED';
+                                               $selected=' 
selected="selected"';
                                        }
-                                       $retval.='<OPTION 
VALUE="'.$option['value'].'"'.$selected.'>'.
-                                               
$option['display'].'</OPTION>'."\n";
+                                       $retval.='<option 
value="'.$option['value'].'"'.$selected.'>'.
+                                               
$option['display'].'</option>'."\n";
                                }
                        }
-                       $retval.='</SELECT>';
+                       $retval.='</select>';
                        return $retval;
                }
-
-               function delete()
-               {
-                       if (!$this->isadmin)
-                       {
-                               
$GLOBALS['phpgw']->redirect($GLOBALS['phpgw']->link('/index.php','menuaction=sitemgr.Outline_UI.manage'));
-                               return;
-                       }
-
-                       
$GLOBALS['Common_BO']->globalize(array('btnDelete','btnCancel'));
-                       global $btnDelete,$btnCancel;
-                       $cat_id = $_GET['cat_id'];
-
-                       if ($btnDelete)
-                       {
-                               $this->cat_bo->removeCategory($cat_id);
-                               
$GLOBALS['phpgw']->redirect($GLOBALS['phpgw']->link('/index.php','menuaction=sitemgr.Outline_UI.manage'));
-                               return;
-                       }
-                       if ($btnCancel)
-                       {
-                               
$GLOBALS['phpgw']->redirect($GLOBALS['phpgw']->link('/index.php','menuaction=sitemgr.Outline_UI.manage'));
-                               return;
-                       }
-
-                       $this->common_ui->DisplayHeader();
-
-                       $cat = 
$this->cat_bo->getCategory($cat_id,$this->sitelanguages[0]);
-                       $this->t->set_file('ConfirmDelete','confirmdelete.tpl');
-                       $this->t->set_var('deleteheader',lang('Are you sure you 
want to delete the category %1 and all of its associated pages?  You cannot 
retrieve the deleted pages if you continue.',$cat->name));
-                       $this->t->set_var('cat_id',$cat_id);
-                       $this->t->set_var('lang_yes',lang('Yes, please delete 
it'));
-                       $this->t->set_var('lang_no',lang('Cancel the delete'));
-                       $this->t->pfp('out','ConfirmDelete');
-               }
        }
 ?>
Index: sitemgr/inc/class.Category_SO.inc.php
diff -u sitemgr/inc/class.Category_SO.inc.php:1.4.10.1 
sitemgr/inc/class.Category_SO.inc.php:1.4.10.2
--- sitemgr/inc/class.Category_SO.inc.php:1.4.10.1      Sat Nov 12 13:15:37 2005
+++ sitemgr/inc/class.Category_SO.inc.php       Mon Mar 27 13:13:24 2006
@@ -9,6 +9,7 @@
                var $depth;
                var $root;
                var $def_page;
+               var $cat_tpl;
 
                function Category_SO()
                {
Index: sitemgr/inc/class.Content_BO.inc.php
diff -u /dev/null sitemgr/inc/class.Content_BO.inc.php:1.2.2.1.4.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/inc/class.Content_BO.inc.php        Mon Mar 27 13:13:24 2006
@@ -0,0 +1,339 @@
+<?php
+
+require_once(PHPGW_INCLUDE_ROOT . SEP . 'sitemgr' . SEP . 'inc' . SEP . 
'class.module.inc.php');
+
+define('SITEMGR_STATE_DRAFT',0);
+define('SITEMGR_STATE_PREPUBLISH',1);
+define('SITEMGR_STATE_PUBLISH',2);
+define('SITEMGR_STATE_PREUNPUBLISH',3);
+define('SITEMGR_STATE_ARCHIVE',4);
+
+define('SITEMGR_VIEWABLE_EVERBODY',0);
+define('SITEMGR_VIEWABLE_USER',1);
+define('SITEMGR_VIEWABLE_ADMIN',2);
+define('SITEMGR_VIEWABLE_ANONYMOUS',3);
+       class Content_BO
+       {
+               var $so;
+
+               function Content_BO()
+               {
+                       $this->so = CreateObject('sitemgr.Content_SO', true);
+               }
+
+               function getContentAreas()
+               {
+                       $theme = 
$GLOBALS['Common_BO']->sites->current_site['themesel'];
+                       
+                       if ( isset($_REQUEST['cat_id']) && $_REQUEST['cat_id'] )
+                       {       
+                               $cat = 
$GLOBALS['Common_BO']->cats->getCategory($_REQUEST['cat_id']);
+                               if ( isset($cat->cat_tpl) && $cat->cat_tpl )
+                               {
+                                       $theme = $cat->cat_tpl;
+                               }
+                       }
+                       elseif ( isset($_REQUEST['page_id']) && 
$_REQUEST['page_id'])
+                       {
+                               $page = 
$GLOBALS['Common_BO']->pages->getPage($_GET['page_id']);
+                               if ( isset($page->cat_id) && $page->cat_id )
+                               {
+                                       $cat = 
$GLOBALS['Common_BO']->cats->getCategory($page->cat_id);
+                                       if ( isset($cat->cat_tpl) && 
$cat->cat_tpl )
+                                       {
+                                               $theme = $cat->cat_tpl;
+                                       }
+                               }
+                       }
+                       
+                       $templatefile =  
"{$GLOBALS['Common_BO']->sites->current_site['site_dir']}/templates/{$theme}/main.tpl";
+
+                       if (file_exists($templatefile))
+                       {
+                               $str = implode('', @file($templatefile));
+                               if (preg_match_all("/\{contentarea:([^{ 
]+)\}/",$str,$matches))
+                               {
+                                       return $matches[1];
+                               }
+                               else
+                               {
+                                       return lang('No content areas found in 
selected template');
+                               }
+                       }
+                       else
+                       {
+                               return lang('No template file found.');
+                       }
+               }
+
+
+               function addblock($block)
+               {
+                       $permittedmoduleids = 
array_keys($GLOBALS['Common_BO']->modules->getcascadingmodulepermissions($block->area,$block->cat_id));
+                       $module = 
$GLOBALS['Common_BO']->modules->getmodule($block->module_id);
+
+                       if 
($GLOBALS['Common_BO']->acl->can_write_category($block->cat_id) &&
+                               in_array($block->module_id,$permittedmoduleids) 
&&
+                               
$GLOBALS['Common_BO']->modules->createmodule($module['module_name']))
+                       {
+                               return $this->so->addblock($block);
+                       }
+                       else
+                       {
+                               return false;
+                       }
+               }
+
+               function createversion($blockid)
+               {
+                       return $this->so->createversion($blockid);
+               }
+
+               function deleteversion($versionid,$force=False)
+               {
+                       if (!$force)
+                       {
+                               $blockid = 
$this->so->getblockidforversion($versionid);
+                               if (!$blockid)
+                               {
+                                       return false;
+                               }
+                               $block = $this->so->getblockdef($blockid);
+                               if (!($block && 
$GLOBALS['Common_BO']->acl->can_write_category($block->cat_id)))
+                               {
+                                       return false;
+                               }
+                       }
+                       return $this->so->deleteversion($versionid);
+               }
+
+               function removeBlocksInPageOrCat($cat_id,$page_id,$force=False)
+               {
+                       if (!($force || 
$GLOBALS['Common_BO']->acl->can_write_category($cat_id)))
+                       {
+                               return false;
+                       }
+                       $blocks = 
$this->so->getblocksforscope($cat_id,$page_id);
+                       while(list($blockid,) = each($blocks))
+                       {
+                               $this->removeblock($blockid,True);
+                       }
+               }
+
+               function removeblock($blockid,$force=False)
+               {
+                       if (!$force)
+                       {
+                               $block = $this->so->getblockdef($blockid);
+                               if (!($block && 
$GLOBALS['Common_BO']->acl->can_write_category($block->cat_id)))
+                               {
+                                       return false;
+                               }
+                       }
+                       if ($this->so->removeblock($blockid))
+                       {
+                               $versions = 
$this->so->getversionidsforblock($blockid);
+                               while(list(,$versionid) = @each($versions))
+                               {
+                                       //since we already did the ACL we force
+                                       $this->deleteversion($versionid,True);
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
+               //the next two functions retrieves all blocks for a certain 
area, if (cat_id = $site_id and page_id = 0), only site-wide blocks are 
retrieved.
+               //if (cat_id != $site_id and page_id is 0), site-wide blocks 
and all blocks for the category and all its ancestor categories are retrieved.
+               //if page_id is non zero, cat_id should be the page's category. 
Page blocks + category blocks + site blocks are retrieved.
+               //there is no ACL, since these functions are called in a 
context where getcategory and getpage have been called before and would have 
intercepted a breach
+               function 
getvisibleblockdefsforarea($area,$cat_id,$page_id,$isadmin,$isuser)
+               {
+                       $cat_ancestorlist = ($cat_id != CURRENT_SITE_ID) ? 
+                               
$GLOBALS['Common_BO']->cats->getCategoryancestorids($cat_id,True) : 
+                               False;
+                       return 
$this->so->getvisibleblockdefsforarea($area,$cat_ancestorlist,$page_id,$isadmin,$isuser);
+               }
+
+               function getallblocksforarea($area,$cat_id,$page_id,$lang)
+               {
+                       $cat_ancestorlist = ($cat_id != CURRENT_SITE_ID) ? 
+                               
$GLOBALS['Common_BO']->cats->getCategoryancestorids($cat_id,True) : 
+                               False;
+                       return 
$this->so->getallblocksforarea($area,$cat_ancestorlist,$page_id,$lang);
+               }
+
+               function getcommitableblocks()
+               {
+                       return 
$this->so->getallblocks($GLOBALS['Common_BO']->cats->getpermittedcatsWrite(),$GLOBALS['Common_BO']->getstates('Commit'));
+               }
+
+               function getarchivedblocks()
+               {
+                       return 
$this->so->getallblocks($GLOBALS['Common_BO']->cats->getpermittedcatsWrite(),$GLOBALS['Common_BO']->getstates('Archive'));
+               }
+               function getallversionsforblock($blockid,$lang)
+               {
+                       return 
$this->so->getallversionsforblock($blockid,$lang);
+               }
+
+               function getblock($id,$lang)
+               {
+                       //do we need ACL here, since we have ACL when getting 
the block lists, we could do without it here?
+                       return $this->so->getblock($id,$lang);
+               }
+
+               function getlangblocktitle($block_id,$lang=false)
+               {
+                               return 
$this->so->getlangblocktitle($block_id,$lang);
+               }
+
+               function getlangarrayforblocktitle($block_id)
+               {
+                       return $this->so->getlangarrayforblocktitle($block_id);
+               }
+
+               function getlangarrayforversion($version_id)
+               {
+                       return $this->so->getlangarrayforversion($version_id);
+               }
+
+               //this function retrieves blocks only for a certain scope 
(site-wide, specific to one category or specific to one page), 
+               //but for all areas.
+               function getblocksforscope($cat_id,$page_id)
+               {
+                       if ($cat_id && 
!$GLOBALS['Common_BO']->acl->can_read_category($cat_id))
+                       {
+                               return array();
+                       }
+                       else
+                       {
+                               return 
$this->so->getblocksforscope($cat_id,$page_id);
+                       }
+               }
+
+               function getversion($version_id,$lang=False)
+               {
+                       //TODO: add ACL ?
+                       return $this->so->getversion($version_id,$lang);
+               }
+
+               function saveblockdata($block,$data,$state,$lang)
+               {
+                       $oldblock = $this->so->getblockdef($block->id);
+                       if (!($oldblock && 
$GLOBALS['Common_BO']->acl->can_write_category($oldblock->cat_id)))
+                       {
+                               return lang("You are not entitled to edit block 
%1",$block->id);
+                       }
+                       $this->so->saveblockdata($block);
+                       
$this->so->saveblockdatalang($block->id,$block->title,$lang);
+                       if (!$this->saveversionstate($block->id,$state))
+                       {
+                               $validationerrors[] = lang('There can only be 
one version in (pre(un))published state, with the one exeption that one 
prepublished version can coexist with one preunpublished version');
+                       }
+                       $moduleobject = $this->getblockmodule($block->id);
+                       while (list($versionid,$versiondata) = @each($data))
+                       {
+                               if ($moduleobject->validate($versiondata))
+                               {
+                                       if 
($this->saveversiondatalang($block->id,$versionid,$versiondata['i18n'],$lang))
+                                       {
+                                               unset($versiondata['i18n']);
+                                               
$this->so->saveversiondata($block->id,$versionid,$versiondata);
+                                       }
+                               }
+                               if ($moduleobject->validation_error)
+                               {
+                                       $validationerrors[] = 
$moduleobject->validation_error;
+                               }
+                       }
+                       return $validationerrors ? $validationerrors : True;
+               }
+
+               function saveblockdatalang($block,$data,$lang)
+               {
+                       $oldblock = $this->so->getblockdef($block->id);
+                       if (!($oldblock && 
$GLOBALS['Common_BO']->acl->can_write_category($oldblock->cat_id)))
+                       {
+                               return lang("You are not entitled to edit block 
%1",$block->id);
+                       }
+                       
$this->so->saveblockdatalang($block->id,$block->title,$lang);
+                       $moduleobject = $this->getblockmodule($block->id);
+                       while (list($versionid,$versiondata) = @@each($data))
+                       //TODO: check if version really belongs to block
+                       {
+                               if ($moduleobject->validate($versiondata))
+                               {
+                                       
$this->saveversiondatalang($block->id,$versionid,$versiondata['i18n'],$lang);
+                               }
+                               else
+                               {
+                                       $validationerrors[] = 
$moduleobject->validation_error;
+                               }
+                       }
+                       return $validationerrors ? $validationerrors : True;
+               }
+
+               //takes the array (version_id => version_state) posted from the 
UI as argument
+               //and checks if there is only one in (pre(un))published state 
+               //(exeption one prepublished, and one preunpublished can 
coexsit)
+               function saveversionstate($block_id,$state)
+               {
+                       $count_array = array_count_values($state);
+                       $active_versions = 
$count_array[SITEMGR_STATE_PREPUBLISH] + 
+                               $count_array[SITEMGR_STATE_PUBLISH] + 
+                               $count_array[SITEMGR_STATE_PREUNPUBLISH];
+                       if (($active_versions < 2) || (($active_versions == 2) 
&& ($count_array[SITEMGR_STATE_PUBLISH] == 0)))
+                       {
+                               while (list($versionid,$versionstate) = 
each($state))
+                               {
+                                       
$this->so->saveversionstate($block_id,$versionid,$versionstate);
+                               }
+                               return true;
+                       }
+                       else
+                       {
+                               return false;
+                       }
+               }
+
+               function saveversiondatalang($block_id,$version_id,$data,$lang)
+               {
+                       return ($this->so->getblockidforversion($version_id) == 
$block_id) ?
+                               
$this->so->saveversiondatalang($version_id,$data,$lang) :
+                               false;
+               }
+
+               //this function can be called from a block's get_content 
function. It stores modification to the 
+               //blocks arguments in the database
+               function savepublicdata(&$block)
+               {
+                       //TODO: check if argument is public, disentangle 
session data from arguments
+                       
$this->so->saveversiondata($block->id,$block->version,$block->arguments);
+               }
+
+               function getblockmodule($blockid)
+               {
+                       $block = $this->so->getblockdef($blockid);
+                       return 
$GLOBALS['Common_BO']->modules->createmodule($block->module_name);
+               }
+
+               function commit($block_id)
+               {
+                       $block = $this->so->getblockdef($block_id);
+                       if 
($GLOBALS['Common_BO']->acl->can_write_category($block->cat_id))
+                       {
+                               $this->so->commit($block_id);
+                       }
+               }
+
+               function reactivate($block_id)
+               {
+                       $block = $this->so->getblockdef($block_id);
+                       if 
($GLOBALS['Common_BO']->acl->can_write_category($block->cat_id))
+                       {
+                               $this->so->reactivate($block_id);
+                       }
+               }
+       }
+?>
Index: sitemgr/inc/class.Content_UI.inc.php
diff -u sitemgr/inc/class.Content_UI.inc.php:1.3.2.4.2.2 
sitemgr/inc/class.Content_UI.inc.php:1.3.2.4.2.3
--- sitemgr/inc/class.Content_UI.inc.php:1.3.2.4.2.2    Fri Dec  9 00:40:38 2005
+++ sitemgr/inc/class.Content_UI.inc.php        Mon Mar 27 13:13:24 2006
@@ -72,7 +72,12 @@
                        {
                                $GLOBALS['phpgw']->js = 
createObject('phpgwapi.javascript');
                        }
-                       $GLOBALS['phpgw']->js->validate_file('fckeditor', 
'fckeditor', 'news_admin');
+
+                       if ( !isset($GLOBALS['phpgw']->richtext) || 
!is_object($GLOBALS['phpgw']->richtext) )
+                       {
+                               $GLOBALS['phpgw']->richtext =& 
createObject('phpgwapi.richtext');
+                       }
+                       
$GLOBALS['phpgw']->richtext->set_base_url($GLOBALS['Common_BO']->sites->current_site['site_url']);
                        
                        $GLOBALS['Common_BO']->globalize(array(
                                
'inputblockid','inputblocktitle','inputblocksort','inputblockview',
@@ -221,7 +226,6 @@
                                return;
                        }
 
-                       $this->common_ui->DisplayHeader();
 
                        $this->t->set_file('Managecontent', 
'manage_content.tpl');
                        $this->t->set_file('Blocks','edit_block.tpl');
@@ -237,7 +241,6 @@
                                'page_or_cat_name' => ($page_or_cat_name ? (' - 
' . $page_or_cat_name) : '')
                                ));
 
-
                        $contentareas = $this->bo->getContentAreas();
                        if (is_array($contentareas))
                        {
@@ -292,6 +295,8 @@
                        {
                                $this->t->set_var('CBlock',$contentareas);
                        }
+                       $GLOBALS['phpgw']->richtext->generate_script();
+                       $this->common_ui->DisplayHeader();
                        $this->t->pfp('out', 'Managecontent');
                        $this->common_ui->DisplayFooter();
                }
Index: sitemgr/inc/class.Sites_BO.inc.php
diff -u /dev/null sitemgr/inc/class.Sites_BO.inc.php:1.7.2.1.4.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/inc/class.Sites_BO.inc.php  Mon Mar 27 13:13:24 2006
@@ -0,0 +1,229 @@
+<?php
+  /**************************************************************************\
+  * phpGroupWare - phpgroupware SiteMgr                                      *
+  * http://www.phpgroupware.org                                              *
+  * --------------------------------------------                             *
+  *  This program 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 2 of the License, or (at your  *
+  *  option) any later version.                                              *
+  \**************************************************************************/
+
+  /* $Id: class.Sites_BO.inc.php,v 1.7.2.1.4.1 2006/03/27 13:13:24 skwashd Exp 
$ */
+
+       class Sites_BO
+       {
+
+               var $xml_functions  = array();
+               var $soap_functions = array();
+
+               var $debug = False;
+
+               var $so    = '';
+               var $start = 0;
+               var $query = '';
+               var $sort  = '';
+               var $order = '';
+               var $total = 0;
+
+               var $current_site;
+               var $number_of_sites;
+
+               var $use_session = False;
+
+               function Sites_BO($session=False)
+               {
+                       //Web site definitions are stored as top level 
categories
+                       $this->so = CreateObject('sitemgr.Sites_SO');
+
+                       if($session)
+                       {
+                               $this->read_sessiondata();
+                               $this->use_session = True;
+                       }
+
+                       foreach(array('start','query','sort','order') as $var)
+                       {
+                               if (isset($_REQUEST[$var]))
+                               {
+                                       $this->$var = $_REQUEST[$var];
+                               }
+                       }
+               }
+
+               function save_sessiondata($data)
+               {
+                       if ($this->use_session)
+                       {
+                               if($this->debug) { echo '<br>Save:'; 
_debug_array($data); }
+                               
$GLOBALS['phpgw']->session->appsession('session_data','sitemgr_sites',$data);
+                       }
+               }
+
+               function read_sessiondata()
+               {
+                       $data = 
$GLOBALS['phpgw']->session->appsession('session_data','sitemgr_sites');
+                       if($this->debug) { echo '<br>Read:'; 
_debug_array($data); }
+
+                       $this->start  = $data['start'];
+                       $this->query  = $data['query'];
+                       $this->sort   = $data['sort'];
+                       $this->order  = $data['order'];
+               }
+
+               function list_sites($limit=True)
+               {
+                       return 
$this->so->getWebsites($limit,$this->start,$this->sort,$this->order,$this->query,$this->total);
+               }
+
+               function getnumberofsites()
+               {
+                       return $this->so->getnumberofsites();
+               }
+
+               function read($id)
+               {
+                       $result = $this->so->read($id);
+                       if ($result)
+                       {
+                               $result['sitelanguages'] = 
$result['site_languages'] ? explode(',',$result['site_languages']) : 
array('en');;
+                               foreach($result['sitelanguages'] as $lang)
+                               {
+                                       $langinfo = 
$GLOBALS['Common_BO']->cats->getCategory($id,$lang,True);
+                                       $result['site_name_' . $lang] = 
$langinfo->name;
+                                       $result['site_desc_' . $lang] = 
$langinfo->description;
+                               }
+                               return $result;
+                       }
+                       else
+                       {
+                               return False;
+                       }
+               }
+
+               function get_adminlist($site_id)
+               {
+                       return 
$GLOBALS['Common_BO']->acl->get_permission_list($site_id);
+               }
+
+               function add($site)
+               {
+                       $site_id = $this->so->add($site);
+                       
//$GLOBALS['Common_BO']->cats->saveCategoryLang($site_id, 
$site['name'],$site['description'],$site['savelang']);
+                       
$GLOBALS['Common_BO']->acl->set_adminlist($site_id,$site['adminlist']);
+                       return $site_id;
+               }
+
+               function update($site_id,$site)
+               {
+                       $this->so->update($site_id,$site);
+
+                       
$GLOBALS['Common_BO']->acl->set_adminlist($site_id,$site['adminlist']);
+               }
+
+               function saveprefs($prefs)
+               {
+                       $this->so->saveprefs($prefs);
+                       $sitelanguages = $this->current_site['site_languages'] 
? 
+                               
explode(',',$this->current_site['site_languages']) :
+                               array('en');
+                       foreach ($sitelanguages as $lang)
+                       {
+                               $GLOBALS['Common_BO']->cats->saveCategoryLang(
+                                       CURRENT_SITE_ID,
+                                       $prefs['site_name_' . $lang],
+                                       $prefs['site_desc_' . $lang],
+                                       $lang
+                               );
+                       }
+                       $this->current_site = $this->read(CURRENT_SITE_ID);
+               }
+
+               function delete($id)
+               {
+                       if (!$GLOBALS['phpgw']->acl->check('run',1,'admin'))
+                       {
+                               return False;
+                       }
+                       
$GLOBALS['Common_BO']->cats->removeCategory($id,True,True);
+                       $this->so->delete($id);
+                       return True;
+               }
+
+               function urltoid($url)
+               {
+                       return $this->so->urltoid($url);
+               }
+
+
+               function set_currentsite($site_url,$mode)
+               {
+                       if ($site_url)
+                       {
+                               $this->current_site = 
$this->read($this->urltoid($site_url));
+                       }
+                       else
+                       {
+                               
$GLOBALS['phpgw']->preferences->read_repository();
+                               $siteswitch = get_var('siteswitch');
+                               if ($siteswitch)
+                               {
+                                       $this->current_site = 
$this->read($siteswitch);
+                                       
$GLOBALS['phpgw']->preferences->change('sitemgr','currentsite',$siteswitch);
+                                       
$GLOBALS['phpgw']->preferences->save_repository(True);
+                               }
+                               else
+                               {
+                                       $currentsite = 
$GLOBALS['phpgw_info']['user']['preferences']['sitemgr']['currentsite'];
+                                       if($currentsite)
+                                       {
+                                               $this->current_site = 
$this->read($currentsite);
+                                       }
+                               }
+                       }
+                       if (!$this->current_site)
+                       {
+                               $allsites = $this->so->list_siteids();
+                               if ($allsites)
+                               {
+                                       $this->current_site = 
$this->read($allsites[0]);
+                                       
$GLOBALS['phpgw']->preferences->change('sitemgr','currentsite',$allsites[0]);
+                                       
$GLOBALS['phpgw']->preferences->save_repository(True);
+                               }
+                               else
+                               {
+                                       return False;
+                               }
+                       }
+                       
+                       
define('CURRENT_SITE_ID',$this->current_site['site_id']);
+                       $this->setmode($mode);
+                       return True;
+               }
+
+               function setmode($mode)
+               {
+                       $this->current_site['mode'] = $mode;
+                       $GLOBALS['Common_BO']->setvisiblestates($mode);
+                       $GLOBALS['Common_BO']->cats->setcurrentcats();
+               }
+
+               //this function is here so that we can retrieve basic info from 
sitemgr-link without creating COMMON_BO
+               function get_currentsiteinfo()
+               {
+                       $GLOBALS['phpgw']->preferences->read_repository();
+                       $currentsite = 
$GLOBALS['phpgw_info']['user']['preferences']['sitemgr']['currentsite'];
+                       if($currentsite)
+                       {
+                               $info = $this->so->read2($currentsite);
+                       }
+                       if (!$info)
+                       {
+                               $allsites = $this->so->list_siteids();
+                               $info = $this->so->read2($allsites[0]);
+                               
$GLOBALS['phpgw']->preferences->change('sitemgr','currentsite',$allsites[0]);
+                               
$GLOBALS['phpgw']->preferences->save_repository(True);
+                       }
+                       return $info;
+               }
+       }
Index: sitemgr/inc/class.Sites_SO.inc.php
diff -u /dev/null sitemgr/inc/class.Sites_SO.inc.php:1.2.2.3.4.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/inc/class.Sites_SO.inc.php  Mon Mar 27 13:13:24 2006
@@ -0,0 +1,169 @@
+<?php
+       class Sites_SO
+       {
+               var $db;
+               
+               function Sites_SO()
+               {
+                       $this->db = $GLOBALS['phpgw']->db;
+               }
+
+               function list_siteids()
+               {
+                       $result = array();
+                       
+                       $this->db->query('SELECT site_id FROM 
phpgw_sitemgr_sites', __LINE__, __FILE__);
+                       while ($this->db->next_record())
+                       {
+                               $result[] = $this->db->f('site_id');
+                       }
+                       return $result;
+               }
+
+               function getWebsites($limit,$start,$sort,$order,$query,&$total)
+               {
+                       if ($limit)
+                       {
+                               if (!$sort)
+                               {
+                                       $sort = 'DESC';
+                               }
+                               if ($query)
+                               {
+                                       $query = 
$this->db->db_addslashes($query);
+                                       $whereclause = "WHERE site_name LIKE 
'%$query%'"
+                                               . "OR site_url LIKE '%$query%'"
+                                               . "OR site_dir LIKE '%$query%'";
+                               }
+                               if ($order)
+                               {
+                                       $orderclause = 'ORDER BY ' . 
$this->db->db_addslashes($order) 
+                                                       . ' ' . 
$this->db->db_addslashes($sort);
+                               }
+                               else
+                               {
+                                       $orderclause = 'ORDER BY site_name ASC';
+                               }
+                               $sql = "SELECT site_id,site_name,site_url from 
phpgw_sitemgr_sites $whereclause $orderclause";  
+                               $this->db->query($sql,__LINE__,__FILE__);
+                               $total = $this->db->num_rows();
+                               
$this->db->limit_query($sql,$start,__LINE__,__FILE__);
+                       }
+                       else
+                       {
+                               $this->db->query('SELECT 
site_id,site_name,site_url FROM phpgw_sitemgr_sites', __LINE__, __FILE__);
+                       }
+                       while ($this->db->next_record())
+                       {
+                               foreach(array('site_id', 'site_name', 
'site_url') as $col)
+                               {
+                                       $site[$col] = $this->db->f($col, true);
+                               }
+                               $result[$site['site_id']] = $site;
+                       }
+                       return $result;
+               }
+
+               function getnumberofsites()
+               {
+                       $this->db->query('SELECT COUNT(*) FROM 
phpgw_sitemgr_sites',__LINE__,__FILE__);
+                       $this->db->next_record();
+                       return $this->db->f(0);
+               }
+
+               function urltoid($url)
+               {
+                       $sql  = 'SELECT site_id FROM phpgw_sitemgr_sites ';
+                       $sql .= "WHERE site_url ='" . 
$this->db->db_addslashes($url) . "'";
+                       $this->db->query($sql,__LINE__,__FILE__);
+                       $this->db->next_record();
+                       return $this->db->f('site_id');
+               }
+
+               function read($id)
+               {
+                       $sql =  'SELECT * FROM phpgw_sitemgr_sites ';
+                       $sql .= 'WHERE site_id = ' . intval($id);
+                       $this->db->query($sql,__LINE__,__FILE__);
+                       if ($this->db->next_record())
+                       {
+                               foreach(
+                                       array(
+                                               'site_id', 'site_name', 
'site_url', 'site_dir', 'themesel', 
+                                               'site_languages', 
'home_page_id', 'anonymous_user','anonymous_passwd'
+                                       ) as $col
+                               )
+                               {
+                                       $site[$col] = $this->db->f($col);
+                               }
+                               return $site;
+                       }
+                       else
+                       {
+                               return false;
+                       }
+               }
+
+               function read2($id)
+               {
+                       $sql  = 'SELECT site_url,site_dir FROM 
phpgw_sitemgr_sites ';
+                       $sql .= 'WHERE site_id = ' . intval($id);
+                       $this->db->query($sql,__LINE__,__FILE__);
+                       if ($this->db->next_record())
+                       {
+                               foreach(
+                                       array(
+                                               'site_url', 'site_dir'
+                                       ) as $col
+                               )
+                               {
+                                       $site[$col] = $this->db->f($col);
+                               }
+                               return $site;
+                       }
+                       else
+                       {
+                               return false;
+                       }
+               }
+
+               function add($site)
+               {
+                       $cats = 
CreateObject('phpgwapi.categories',-1,'sitemgr');
+                               $data = array
+                       (
+                               'name'          => $site['name'],
+                               'descr'         => '',
+                               'access'        => 'public',
+                               'parent'        => 0,
+                               'old_parent' => 0
+                       );
+                       $site_id =  $cats->add($data);
+                       $sql = "INSERT INTO phpgw_sitemgr_sites 
(site_id,site_name,site_url,site_dir,anonymous_user,anonymous_passwd) VALUES 
($site_id,'" . 
+                               $site['name'] . "','" . $site['url'] . "','" . 
$site['dir'] . "','" . $site['anonuser'] . "','" . $site['anonpasswd'] .
+                               "')";
+                       $this->db->query($sql,__LINE__,__FILE__);
+                       return $site_id;
+               }
+
+               function update($id,$site)
+               {
+                       $sql = "UPDATE phpgw_sitemgr_sites SET site_name = '" . 
$site['name'] . "', site_url = '" . $site['url'] . "', site_dir = '" . 
+                               $site['dir'] . "', anonymous_user = '" . 
$site['anonuser'] . "', anonymous_passwd = '" . $site['anonpasswd'] . 
+                               "' WHERE site_id = $id";
+                        $this->db->query($sql,__LINE__,__FILE__);
+               }
+
+               function delete($id)
+               {
+                       $sql = "DELETE FROM phpgw_sitemgr_sites WHERE site_id = 
$id";
+                       $this->db->query($sql,__LINE__,__FILE__);
+               }
+
+               function saveprefs($prefs)
+               {
+                       $sql = "UPDATE phpgw_sitemgr_sites SET themesel = '" . 
$prefs['themesel'] . "', site_languages = '" . $prefs['site_languages'] .
+                               "', home_page_id = " . $prefs['home_page_id'] . 
" WHERE site_id = " . CURRENT_SITE_ID;
+                       $this->db->query($sql,__LINE__,__FILE__);
+               }
+       }
Index: sitemgr/inc/class.module.inc.php
diff -u sitemgr/inc/class.module.inc.php:1.8.2.2.4.1 
sitemgr/inc/class.module.inc.php:1.8.2.2.4.2
--- sitemgr/inc/class.module.inc.php:1.8.2.2.4.1        Sat Nov 12 14:11:58 2005
+++ sitemgr/inc/class.module.inc.php    Mon Mar 27 13:13:24 2006
@@ -174,6 +174,7 @@
                                while (isset($input[$i]))
                                {
                                        $element['label'] = $input[$i]['label'];
+                                       $element['label_for'] = 
'sitemgr_element_' . $this->block->version . $input[$i]['name'];
                                        $element['form'] = 
$this->build_input_element($input[$i],$this->block->arguments[$key][$i],$elementname.'[]');
                                        $interface[] = $element;
                                        $i++;
@@ -182,7 +183,7 @@
                        else
                        {
                                $element['label'] = $input['label'];
-                               $element['label_for'] = 'sitemgr_element_' . 
$this->block->version;
+                               $element['label_for'] = 
"sitemgr_element_{$this->block->version}_{$key}";
                                $element['form'] = 
$this->build_input_element($input,$this->block->arguments[$key],$elementname, 
$element['label_for']);
                                $interface[] = $element;
                        }
@@ -247,7 +248,8 @@
                return $this->build_input_element(
                        $this->post[$key],
                        ($default !== False) ? $default : 
$this->block->arguments[$key],
-                       ('block[' . $this->block->id  . '][' . $key . ']')
+                       ('block[' . $this->block->id  . '][' . $key . ']'),
+                       "block_{$this->block->id}_{$key}"
                );
        }
 
@@ -315,13 +317,8 @@
                                return '<input id="'.$element_id.'" 
type="image" ' . $inputdef .' src ="' . $input['src'] . '" />';
                        
                        case 'richtext':
-
-                               return "<textarea 
id=\"{$element_id}\"{$inputdef}>{$default}</textarea>\n"
-                                       . "<script>\n\nvar 
oFCKEditor_{$this->block->version} = new FCKeditor('{$elementname}');
-                                                
oFCKEditor_{$this->block->version}.BasePath = 
'{$GLOBALS['phpgw_info']['server']['webserver_url']}/news_admin/js/fckeditor/';
-                                                
oFCKEditor_{$this->block->version}.SpellChecker = '" . 
(extension_loaded('pspell') ? 'SpellerPages' : 'ieSpell') . "';
-                                                
oFCKEditor_{$this->block->version}.ReplaceTextarea();
-                                       \n</script>\n";
+                               
$GLOBALS['phpgw']->richtext->replace_element($element_id);
+                               return "<textarea id=\"{$element_id}\" 
{$inputdef}>{$default}</textarea>\n";
                }
        }
 
Index: sitemgr/js/columnlist/columnlist.css
diff -u /dev/null sitemgr/js/columnlist/columnlist.css:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/js/columnlist/columnlist.css        Mon Mar 27 13:13:24 2006
@@ -0,0 +1,113 @@
+.webfx-columnlist {
+       border: 1px solid;
+       border-color: threedshadow threedhighlight threedhighlight threedshadow;
+       display: block;
+       margin: 0px auto;
+       overflow: hidden;
+       width: 600px;
+       -moz-user-select: none;
+       -moz-user-focus: normal;
+       -moz-user-input: enabled;
+}
+
+.webfx-columnlist td {
+       font: menu;
+       padding: 1px;
+       white-space: nowrap;
+}
+
+.webfx-columnlist-head {
+       position: absolute;
+       background: threedface;
+       overflow: hidden;
+       -moz-user-select: none;
+}
+
+.webfx-columnlist-head table {
+       table-layout: fixed;
+}
+
+.webfx-columnlist-head td {
+       border: 1px solid;
+       border-color: threedhighlight threedshadow threedshadow threedhighlight;
+       overflow: hidden;
+       text-overflow: ellipsis;
+}
+
+.webfx-columnlist-head td img {
+       width:    8px;
+       height:   7px;
+       margin:   0px 5px 0px 5px;
+       display:  none;
+}
+
+.webfx-columnlist-body {
+       border: 1px solid;
+       border-color: threedhighlight threedface threedface threedhighlight;
+       background: window;
+       height: 300px;
+       overflow: auto;
+}
+
+.webfx-columnlist-body table {
+       table-layout: fixed;
+}
+
+.webfx-columnlist-body td {
+       border-bottom: solid white;
+       border-width:  0px 1px 1px 0px;
+       overflow:      hidden;
+       text-overflow: ellipsis;
+       white-space:   no-wrap;
+}
+
+.webfx-columnlist-body tr.selected td {
+       background:   #C0C0FF;
+}
+
+.webfx-columnlist-body tr.odd td {
+       background:   #FFFFC0;
+}
+
+.webfx-columnlist-body tr.even td {
+       background:   window;
+}
+
+.webfx-columnlist-move-header {
+       position: absolute;
+       background: threedshadow;
+       top: 0px;
+       font: menu;
+       padding: 2px;
+       height: 1em;
+       filter: Alpha(Opacity=50);
+       -moz-opacity: 0.5;
+       -moz-user-select: none;
+}
+
+.webfx-columnlist-active-header {
+       border-color: threedface !important;
+}
+
+.webfx-columnlist-separator-header {
+       position: absolute;
+       top: 0px;
+       left: 10px;
+       font: menu;
+       height: 1em;
+       width: 1px;
+       overflow: hidden;
+       background: blue;
+       padding: 3px 0px;
+}
+
+td
+{
+       width: 360px;
+}
+
+td.permscol, col.permscol
+{
+       text-align: center;
+       width: 120px;
+}
\ No newline at end of file
Index: sitemgr/js/columnlist/columnlist.js
diff -u /dev/null sitemgr/js/columnlist/columnlist.js:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/js/columnlist/columnlist.js Mon Mar 27 13:13:24 2006
@@ -0,0 +1,1258 @@
+/*----------------------------------------------------------------------------\
+|                           Column List Widget 1.03                           |
+|-----------------------------------------------------------------------------|
+|                           Created by Emil A Eklund                          |
+|                   (http://webfx.eae.net/contact.html#emil)                  |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| A DHTML column list widget. Can be generated from supplied data or attached |
+| to an existing html structure. Supports multiple selection, sorting, column |
+| resizing, column moving and keyboard navigation.                            |
+|-----------------------------------------------------------------------------|
+|                    Copyright (c) 2004, 205 Emil A Eklund                    |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including  but not limited  to the warranties of  merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or  copyright  holders be  liable for any claim,  damages or  other |
+| liability, whether  in an  action of  contract, tort  or otherwise, arising |
+| from,  out of  or in  connection with  the software or  the  use  or  other |
+| dealings in the software.                                                   |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This  software is  available under the  three different licenses  mentioned |
+| below.  To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License          http://webfx.eae.net/license.html |
+| Permits  anyone the right to use the  software in a  non-commercial context |
+| free of charge.                                                             |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license           http://webfx.eae.net/commercial.html |
+| Permits the  license holder the right to use  the software in a  commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of  implementations of the licensed software.                    |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License    http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper  credits are given  and the original  and modified source |
+| code are included. Requires  that the final product, software derivate from |
+| the original  source or any  software  utilizing a GPL  component, such  as |
+| this, is also licensed under the GPL license.                               |
+|-----------------------------------------------------------------------------|
+| Dependencies: columnlist.css      Column list style declarations            |
+|               sortabletable.js    Provides table sorting functionality      |
+|-----------------------------------------------------------------------------|
+| Browser compatibility: IE           Verified, 6.0+                          |
+|                        Mozilla      Verified, 1.7+ (Firefox 1.0+)           |
+|                        Opera        Not Verified                            |
+|                        Safari/KTML: Not Verified                            |
+|-----------------------------------------------------------------------------|
+| 2004-08-22 | Work started.                                                  |
+| 2004-10-24 | First version published.                                       |
+| 2004-11-01 | Added resizeColumns property,  allowing column  resizing to be |
+|            | enabled/disabled.  Fixed a bug in the  sort method that caused |
+|            | getSelectedRow to return an invalid index when called from the |
+|            | function triggered by onselect. Misc bugfixes for Mozilla.     |
+| 2004-11-23 | Fixed column resizing in mozilla.  It still can't make columns |
+|            | smaller than their content, but otherwise it seems to work.    |
+| 2005-05-22 | Fixed a bug in the removeRange method for index based removal, |
+|            | where the rows where deleted in the wrong order.  Also added a |
+|            | clear method, that removes all rows.                           |
+| 2005-11-30 | Fixed bug that caused rows to be colored even if colorEvenRows |
+|            | was false.  Added  rowSelection,  columnSorting,  moveColumns, |
+|            | sortAscImage and sortDescImage properties.  Implemented column |
+|            | moving and alignment. Updated column resizing implementation.  |
+| 2005-12-08 | Added support for making columns smaller than their content in |
+|            | Mozilla, bringing the Mozilla support up to pair with that for |
+|            | IE. Also added support for specifying column width on create.  |
+| 2005-12-20 | Fixed bug in setCellValue method.                              |
+|-----------------------------------------------------------------------------|
+| Created 2004-08-22 | All changes are in the log above. | Updated 2005-12-20 |
+\----------------------------------------------------------------------------*/
+
+var TYPE_STRING         = 0;
+var TYPE_NUMBER         = 1;
+var TYPE_DATE           = 2;
+var TYPE_STRING_NO_CASE = 3;
+
+var SORT_ASCENDING  = 0;
+var SORT_DESCENDING = 1;
+
+var ALIGN_AUTO   = 0;
+var ALIGN_LEFT   = 1;
+var ALIGN_CENTER = 2;
+var ALIGN_RIGHT  = 3;
+
+var COL_HEAD_NONE = 0;
+var COL_HEAD_EDGE = 1;
+var COL_HEAD_OVER = 2;
+var COL_HEAD_SIZE = 3;
+var COL_HEAD_DOWN = 4;
+var COL_HEAD_MOVE = 5;
+
+
+/*
+ * oColumnList = new WebFXColumnList()
+ * Default constructor
+ */
+function WebFXColumnList() {
+
+       /* public properties */
+       this.multiple       = true;                                             
      // Allow multiple selection (true or false)
+       this.colorEvenRows  = true;                                             
      // Mark even rows with different color (true or false)
+       this.resizeColumns  = true;                                             
      // Enable column resizing (true or false)
+       this.bodyColResize  = true;                                             
      // Resize body columns duing resize operation (true or false)
+       this.moveColumns    = true;                                             
      // Enable column moving (true or false)
+       this.rowSelection   = true;                                             
      // Enable row selection (true or false)
+       this.columnSorting  = true;                                             
      // Enable sorting (true or false)
+       this.columnAlign    = true;                                             
      // Enable column text alignment (true or false)
+       this.sortAscImage   = 'images/asc.png';                                 
      // Image used to indicate ascending sort order
+       this.sortDescImage  = 'images/desc.png';                                
      // Image used to indicate descending sort order
+
+       /* public read only properties */
+       this.sortCol        = -1;                                               
      // Column index currently sorted by, read only
+       this.sortDescending = 0;                                                
      // Column sort direction, read only (SORT_ASCENDING or SORT_DESCENDING)
+       this.error          = '';                                               
      // Error message set if an error code was returned, read only.
+       this.selectedRows   = [];                                               
      // Currently selected rows, read only.
+
+       /* events */
+       this.onresize       = null;
+       this.onsort         = null;
+       this.onselect       = null;
+
+       /* private properties */
+       this._eCont         = null;
+       this._eHead         = null;
+       this._eBody         = null;
+       this._eHeadTable    = null;
+       this._eBodyTable    = null;
+       this._eHeadCols     = null;
+       this._eBodyCols     = null;
+
+       this._aColumnTypes  = [];
+       this._aColumnAlign  = [];
+       this._rows          = 0;
+       this._cols          = 0;
+       this._headerOper    = COL_HEAD_NONE;
+       this._headerData    = null;
+}
+
+
+/*
+ * iError = create(eContainer, sColumn[])
+ * Transforms the supplied container into a column list.
+ * sColumn[]   - Array containing column headers
+ * sColumn[][] - Two dimensional array with column headers, widths and types
+*/
+WebFXColumnList.prototype.create = function(eContainer, aColumns) {
+       var eRow, eCell, eDiv, eImg, eTableBody, eColGroup, eCol, a, b;
+
+       for (var i = eContainer.childNodes.length - 1; i >= 0; i--) {
+               eContainer.removeChild(eContainer.childNodes[i]);
+       }
+
+       /* Create container, header and body */
+       this._eCont = eContainer;
+       this._eHead = document.createElement('div');
+       this._eBody = document.createElement('div');
+       this._eCont.className = 'webfx-columnlist';
+       this._eHead.className = 'webfx-columnlist-head';
+       this._eBody.className = 'webfx-columnlist-body';
+       this._eCont.appendChild(this._eHead);
+       this._eCont.appendChild(this._eBody);
+
+       /* Populate header */
+       this._eHeadTable = document.createElement('table');
+       this._eHeadTable.style.width = '100px';                                 
      // if a width is not set here the overflow: hidden rule will be ignored 
by mozilla
+       this._eHeadTable.cellSpacing = 0;
+       this._eHeadTable.cellPadding = 0;
+       this._eHead.appendChild(this._eHeadTable);
+       eTableBody = document.createElement('tbody');
+       this._eHeadTable.appendChild(eTableBody);
+       eRow = document.createElement('tr');
+       eTableBody.appendChild(eRow);
+       for (var i = 0; i < aColumns.length; i++) {
+               eCell = document.createElement('td');
+               eRow.appendChild(eCell);
+               eImg  = document.createElement('img');
+               if (typeof(aColumns[i]) == 'object') { 
eCell.appendChild(document.createTextNode(aColumns[i][0])); }
+               else { eCell.appendChild(document.createTextNode(aColumns[i])); 
}
+               eCell.appendChild(eImg);
+       }
+
+       /* Create main table, colgroup and col elements */
+       this._eBodyTable = document.createElement('table');
+       this._eBodyTable.cellSpacing = 0;
+       this._eBodyTable.cellPadding = 0;
+       this._eBody.appendChild(this._eBodyTable);
+       eTableBody = document.createElement('tbody');
+       this._eBodyTable.appendChild(eTableBody);
+       eColGroup = document.createElement('colgroup');
+       this._eBodyTable.appendChild(eColGroup);
+       for (var i = 0; i < aColumns.length; i++) {
+               eCol = document.createElement('col');
+               if ((typeof(aColumns[i]) == 'object') && (aColumns[i].length) 
&& (aColumns[i].length > 1)) { eCol.style.width = aColumns[i][1]; }
+               else { eCol.style.width = 'auto'; }
+               eColGroup.appendChild(eCol);
+       }
+
+       /* Init sortable table */
+       this._stl = new SortableTable(this._eBodyTable);
+
+       /* Set column data types */
+       a = new Array(); b = false;
+       for (var i = 0; i < aColumns.length; i++) {
+               if ((typeof(aColumns[i]) == 'object') && (aColumns[i].length) 
&& (aColumns[i].length > 2)) { a.push(aColumns[i][2]); b = true; }
+               else { a.push(TYPE_STRING); }
+       }
+
+       /* Only set explicitly if type was specified for at least one column */
+       if (b) { this.setColumnTypes(a); }
+
+       this._eHeadCols = eRow.cells;
+       this._eBodyCols = null;
+
+       this._cols = aColumns.length;
+       this._rows = 0;
+
+       this._init();
+
+       return 0;
+};
+
+
+/*
+ * iError = bind(eContainer, eHeader, eBody)
+ * Binds column list to an existing HTML structure. Use create
+ * to generate the strucutr automatically.
+*/
+WebFXColumnList.prototype.bind = function(eCont, eHead, eBody) {
+       try {
+               this._eCont      = eCont;
+               this._eHead      = eHead;
+               this._eBody      = eBody;
+               this._eHeadTable = this._eHead.getElementsByTagName('table')[0];
+               this._eBodyTable = this._eBody.getElementsByTagName('table')[0];
+               this._eHeadCols  = this._eHeadTable.tBodies[0].rows[0].cells;
+               this._eBodyCols  = this._eBodyTable.tBodies[0].rows[0].cells;
+       }
+       catch(oe) {
+               this.error = 'Unable to bind to elements: ' + oe.message;
+               return 1;
+       }
+       if (this._eHeadCols.length != this._eBodyCols.length) {
+               this.error = 'Unable to bind to elements: Number of columns in 
header and body does not match.';
+               return 2;
+       }
+
+       this._eHeadCols  = this._eHeadTable.tBodies[0].rows[0].cells;
+       this._eBodyCols  = this._eBodyTable.tBodies[0].rows[0].cells;
+
+       this._cols = this._eHeadCols.length;
+       this._rows = this._eBodyTable.tBodies[0].rows.length;
+
+       this._stl = new SortableTable(this._eBodyTable);
+
+       /* Set column class names (used for alignment in mozilla) */
+       if ((!document.all) && (this.columnAlign)) {
+               aRows = this._eBodyTable.tBodies[0].rows;
+               this._rows = aRows.length;
+               for (i = 0; i < this._rows; i++) {
+                       for (j = 0; j < this._cols; j++) {
+                               aRows[i].cells[j].className = 
'webfx-columnlist-col-' + j;
+       }       }       }
+
+       this._init();
+
+       return 0;
+};
+
+
+/*
+ * void _init(iWidth, iHeight)
+ * Initializes column list, called by create and bind
+*/
+WebFXColumnList.prototype._init = function(iWidth, iHeight) {
+       if (navigator.product == 'Gecko') {
+               /*
+                * Mozilla does not allow the scroll* properties of containers 
with the
+                * overflow property set to 'hidden' thus we'll have to set it 
to
+                * '-moz-scrollbars-none' which is basically the same as 
'hidden' in IE,
+                * the container has overflow type 'scroll' but no scrollbars 
are shown.
+               */
+               for (var n = 0; n < document.styleSheets.length; n++) {
+                       if 
(document.styleSheets[n].href.indexOf('columnlist.css') == -1) { continue; }
+                       var rules = document.styleSheets[n].cssRules;
+                       for (var i = 0; i < rules.length; i++) {
+                               if ((rules[i].type == CSSRule.STYLE_RULE) && 
(rules[i].selectorText == '.webfx-columnlist-head')) {
+                                       rules[i].style.overflow = 
'-moz-scrollbars-none';
+       }       }       }       }
+
+       /*
+        * Set tab index to allow element to be focused using keyboard, also 
allows
+        * keyboard events to be captured for Mozilla.
+        */
+       this._eCont.tabIndex = '0';
+
+       this.calcSize();
+       this._assignEventHandlers();
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+       if (this.columnAlign)   { this._setAlignment(); }
+}
+
+
+/*
+ * void _assignEventHandlers()
+ * Assigns event handlers to the grid elements, called by bind.
+*/
+WebFXColumnList.prototype._assignEventHandlers = function() {
+       var oThis = this;
+       this._eCont.onclick     = function(e) { oThis._click(e); }
+       if (this.resizeColumns) {
+               this._eCont.onmousedown = function(e) { oThis._mouseDown(e); }
+               this._eCont.onmousemove = function(e) { oThis._mouseMove(e); }
+       }
+       this._eCont.onmouseup   = function(e) { oThis._mouseUp(e); }
+       this._eCont.onselectstart = function(e) { return false; }
+       this._eBody.onscroll = function() {
+               oThis._eHead.scrollLeft = oThis._eBody.scrollLeft;
+       };
+       this._eCont.onkeydown = function(e) {
+               var el = (e)?e.target:window.event.srcElement;
+               var key = (e)?e.keyCode:window.event.keyCode;
+               if (oThis._handleRowKey(key)) { return; }
+               if (window.event) { window.event.cancelBubble = true; }
+               else { e.preventDefault(); e.stopPropagation() }
+               return false;
+       };
+};
+
+
+/*
+ * void calcSize()
+ * Used to calculate the desired size of the grid and size it accordingly.
+ */
+WebFXColumnList.prototype.calcSize = function() {
+       if (this._eCont.offsetWidth >= 4) {
+
+               /* Size body */
+               var h = this._eCont.clientHeight - this._eHead.offsetHeight - 2;
+               if (h >= 0) { this._eBody.style.height = h + 'px'; }
+               this._eBody.style.width = this._eCont.offsetWidth - 4 + 'px';
+               this._eBody.style.paddingTop = this._eHead.offsetHeight + 'px';
+               this._eBodyTable.style.width = this._eBody.clientWidth + 'px';
+
+               /* Size header */
+               var bNoScrollbar = ((this._eBody.offsetWidth - 
this._eBody.clientWidth) == 2);
+               this._eHeadTable.style.width = this._eHead.style.width = 
this._eBody.clientWidth + ((bNoScrollbar)?2:0) + 'px';
+
+               /* Size columns */
+               if (this._eBodyCols) {
+                       var length = this._eBodyCols.length;
+                       for (var i = 0; i < length; i++) {
+                               this._eHeadCols[i].style.width = 
(this._eBodyCols[i].offsetWidth - 4) + ((bNoScrollbar) && (i == length - 
1)?2:0) + 'px';
+       }       }       }
+
+       this._eHeadTable.style.width = 'auto';
+};
+
+
+/*
+ * iErrorCode = selectRow(iRowIndex, bMultiple)
+ * Selects the row identified by the sequence number supplied,
+ *
+ * If bMultiple is specified and multi-select is allowed the
+ * the previously selected row will not be deselected. If the
+ * specified row is already selected it will be deselected.
+ */
+WebFXColumnList.prototype.selectRow = function(iRowIndex, bMultiple) {
+       if (!this.rowSelection) { return; }
+
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to select row, index out of range.';
+               return 1;
+       }
+       var eRows = this._eBodyTable.tBodies[0].rows;
+       var bSelect = true;
+
+       /* Normal click */
+       if ((!bMultiple) || (!this.multiple)) {
+
+               /* Deselect previously selected rows */
+               while (this.selectedRows.length) {
+                       if (this.colorEvenRows) { 
eRows[this.selectedRows[0]].className = (this.selectedRows[0] & 
1)?'odd':'even'; }
+                       else { eRows[this.selectedRows[0]].className = ''; }
+                       this.selectedRows.splice(0, 1);
+       }       }
+
+       /* Control + Click */
+       else {
+               for (var i = 0; i < this.selectedRows.length; i++) {
+
+                       /* Deselect clicked row */
+                       if (this.selectedRows[i] == iRowIndex) {
+                               if (this.colorEvenRows) { 
eRows[this.selectedRows[i]].className = (i & 1)?'odd':'even'; }
+                               else { eRows[this.selectedRows[i]].className = 
''; }
+                               this.selectedRows.splice(i, 1);
+                               bSelect = false;
+                               break;
+       }       }       }
+
+       /* Select clicked row */
+       if (bSelect) {
+               this.selectedRows.push(iRowIndex);
+               eRows[iRowIndex].className = 'selected';
+       }
+
+       var a = (eRows[iRowIndex].offsetTop + this._eHead.offsetHeight) + 
eRows[iRowIndex].offsetHeight + 1;
+       var b = (this._eBody.clientHeight + this._eBody.scrollTop);
+       if (a > b) {
+               this._eBody.scrollTop = (a - this._eBody.clientHeight);
+       }
+       var c = eRows[iRowIndex].offsetTop;
+       var d = this._eBody.scrollTop;
+       if (c < d) {
+               this._eBody.scrollTop = c;
+       }
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = selectRange(iRowIndex[])
+ * iErrorCode = selectRange(iFromRowIndex, iToRowIndex)
+ * Selects all rows between iFromRowIndex and iToRowIndex.
+ */
+WebFXColumnList.prototype.selectRange = function(a, b) {
+       var aRowIndex;
+
+       if (!this.rowSelection) { return; }
+
+       if (typeof a == 'number') {
+               aRowIndex = new Array();
+               for (var i = a; i <= b; i++) { aRowIndex.push(i); }
+               for (var i = b; i <= a; i++) { aRowIndex.push(i); }
+       }
+       else { aRowIndex = a; }
+
+       for (var i = 0; i < aRowIndex.length; i++) {
+               if ((aRowIndex[i] < 0) || (aRowIndex[i] > this._rows - 1)) {
+                       this.error = 'Unable to select rows, index out of 
range.';
+                       return 1;
+       }       }
+
+       /* Deselect previously selected rows */
+       var eRows = this._eBodyTable.tBodies[0].rows;
+       while (this.selectedRows.length) {
+               if (this.colorEvenRows) { eRows[this.selectedRows[0]].className 
= (this.selectedRows[0] & 1)?'odd':'even'; }
+               else { eRows[this.selectedRows[0]].className = ''; }
+               this.selectedRows.splice(0, 1);
+       }
+
+       /* Select all rows indicated by range */
+       var eRows = this._eBodyTable.tBodies[0].rows;
+       var bMatch;
+       for (var i = 0; i < aRowIndex.length; i++) {
+               bMatch = false;
+               for (var j = 0; j < this.selectedRows.length; j++) {
+                       if (this.selectedRows[j] == aRowIndex[i]) { bMatch = 
true; break; }
+               }
+               if (!bMatch) {
+                       /* Select row */
+                       this.selectedRows.push(aRowIndex[i]);
+                       eRows[aRowIndex[i]].className = 'selected';
+       }       }
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * void resize(iWidth, iHeight)
+ * Resize the grid to the given dimensions, the outer (border) size is given, 
not the inner (content) size.
+ */
+WebFXColumnList.prototype.resize = function(w, h) {
+       this._eCont.style.width = w + 'px';
+       this._eCont.style.height = h + 'px';
+       this.calcSize();
+
+       /* Call onresize if defined */
+       if (this.onresize) { this.onresize(); }
+};
+
+
+/*
+ * void _colorEvenRows()
+ * Changes the color of even rows (usually to light yellow) to make it easier 
to read.
+ * Also updates the id column to a sequence counter rather than the row ids.
+ */
+WebFXColumnList.prototype._colorEvenRows = function() {
+       if (this._eBodyTable.tBodies.length) {
+               var nodes = this._eBodyTable.tBodies[0].rows;
+               var len = nodes.length;
+               for (var i = 0; i < len; i++) {
+                       if (nodes[i].className != 'selected') {
+                               nodes[i].className = (i & 1)?'odd':'even';
+       }       }       }
+};
+
+
+/*
+ * iErrorCode = addRow(aRowData)
+ * Appends supplied row to the column list.
+ */
+WebFXColumnList.prototype.addRow = function(aRowData) {
+       var rc = this._addRow(aRowData);
+       if (rc) { return rc; }
+       this.calcSize();
+       return 0;
+};
+
+
+/*
+ * iErrorCode = addRows(aData)
+ * Appends supplied rows to the column list.
+ */
+WebFXColumnList.prototype.addRows = function(aData) {
+       for (var i = 0; i < aData.length; i++) {
+               var rc = this._addRow(aData[i]);
+               if (rc) { return rc; }
+       }
+       this.calcSize();
+       return 0;
+};
+
+
+/*
+ * void _colorEvenRows()
+ * Changes the color of even rows (usually to light yellow) to make it easier 
to read.
+ * Also updates the id column to a sequence counter rather than the row ids.
+ */
+WebFXColumnList.prototype._colorEvenRows = function() {
+       if (this._eBodyTable.tBodies.length) {
+               var nodes = this._eBodyTable.tBodies[0].rows;
+               for (var i = 0; i < nodes.length; i++) {
+                       if (nodes[i].className != 'selected') {
+                               nodes[i].className = (i & 1)?'odd':'even';
+       }       }       }
+};
+
+
+/*
+ * iErrorCode = _addRow(aRowData)
+ */
+WebFXColumnList.prototype._addRow = function(aRowData) {
+       var eBody, eRow, eCell, i, len;
+
+       /* Validate column count */
+       if (aRowData.length != this._cols) { return 1; }
+
+       /* Construct Body Row */
+       eBody = this._eBodyTable.tBodies[0];
+       eRow  = document.createElement('tr');
+       if (this.colorEvenRows) {
+               eRow.className = (this._rows & 1)?'odd':'even';
+       }
+
+       for (i = 0; i < this._cols; i++) {
+               eCell = document.createElement('td');
+               eCell.className = 'webfx-columnlist-col-' + i;
+               eCell.appendChild(document.createTextNode(aRowData[i]));
+               eRow.appendChild(eCell);
+       }
+       eBody.appendChild(eRow);
+
+       /* Update row counter */
+       this._rows++;
+
+       if (this._eBodyCols == null) {
+               this._eBodyCols = this._eBodyTable.tBodies[0].rows[0].cells;
+       }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = removeRow(iRowIndex)
+ * Appends supplied row to the grid.
+ */
+WebFXColumnList.prototype.removeRow = function(iRowIndex) {
+       /* Remove row */
+       var rc = this._removeRow(iRowIndex);
+       if (rc) { return rc; }
+
+       /* Update row counter and select previous row, if any */
+       this._rows--;
+       this.selectRow((iRowIndex > 1)?iRowIndex-1:0);
+
+       /* Recolor rows, if needed */
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+       this.calcSize();
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = removeRange(iRowIndex[])
+ * iErrorCode = removeRange(iFirstRowIndex, iLastRowIndex)
+ * Appends supplied row to the grid.
+ */
+WebFXColumnList.prototype.removeRange = function(a, b) {
+       var aRowIndex = new Array();
+       if (typeof a == 'number') {
+               for (var i = a; i <= b; i++) { aRowIndex.push(i); }
+       }
+       else {
+               for (var i = 0; i < a.length; i++) {
+                       aRowIndex.push(a[i]);
+               }
+               aRowIndex.sort(compareNumericAsc);
+       }
+
+       while ((i = aRowIndex.pop()) >= 0) {
+               var rc = this._removeRow(i);
+               this._rows--;
+       }
+
+       /* Recolor rows, if needed */
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+       this.calcSize();
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = clear()
+ * Removes all rows from the column list.
+ */
+WebFXColumnList.prototype.clear = function() {
+       return this.removeRange(0, this._rows - 1);
+}
+
+/*
+ * iErrorCode = _removeRow(iRowIndex)
+ */
+WebFXColumnList.prototype._removeRow = function(iRowIndex) {
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to remove row, row index out of range.';
+               return 1;
+       }
+
+       /* Remove from selected */
+       for (var i = this.selectedRows.length - 1; i >= 0; i--) {
+               if (this.selectedRows[i] == iRowIndex) {
+                       this.selectedRows.splice(i, 1);
+       }       }
+
+       
this._eBodyTable.tBodies[0].removeChild(this._eBodyTable.tBodies[0].rows[iRowIndex]);
+       return 0;
+};
+
+
+/*
+ * iRowIndex getSelectedRow()
+ * Returns the index of the selected row or -1 if no row is selected.
+ */
+WebFXColumnList.prototype.getSelectedRow = function() {
+       return 
(this.selectedRows.length)?this.selectedRows[this.selectedRows.length-1]:-1;
+};
+
+
+/*
+ * iRowIndex[] getSelectedRange()
+ * Returns an array with the row index of all selecteds row or null if no row 
is selected.
+ */
+WebFXColumnList.prototype.getSelectedRange = function() {
+       return (this.selectedRows.length)?this.selectedRows:-1;
+};
+
+
+/*
+ * iRows getRowCount()
+ * Returns the nummer of rows.
+ */
+WebFXColumnList.prototype.getRowCount = function() {
+       return this._rows;
+};
+
+
+/*
+ * iRows getColumnCount()
+ * Returns the nummer of columns.
+ */
+WebFXColumnList.prototype.getColumnCount = function() {
+       return this._cols;
+};
+
+
+/*
+ * sValue = getCellValue(iRowIndex, iColumnIndex, bHTML)
+ * Returns the content of the specified cell.
+ */
+WebFXColumnList.prototype.getCellValue = function(iRowIndex, iColIndex) {
+       var el;
+
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to get cell value , row index out of 
range.';
+               return null;
+       }
+       if ((iColIndex < 0) || (iColIndex > this._cols - 1)) {
+               this.error = 'Unable to get cell value , row index out of 
range.';
+               return null;
+       }
+
+       el = this._eBodyTable.tBodies[0].rows[iRowIndex].cells[iColIndex];
+
+       return (bHTML)?el.innerHTML:getInnerText(el);
+};
+
+
+/*
+ * iError = setCellValue(iRowIndex, iColumnIndex, sValue, bHTML)
+ * Sets the content of the specified cell.
+ */
+WebFXColumnList.prototype.setCellValue = function(iRowIndex, iColIndex, 
sValue, bHTML) {
+       var el;
+
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to set cell value , row index out of 
range.';
+               return 1;
+       }
+       if ((iColIndex < 0) || (iColIndex > this._cols - 1)) {
+               this.error = 'Unable to set cell value , row index out of 
range.';
+               return 2;
+       }
+
+       el = this._eBodyTable.tBodies[0].rows[iRowIndex].cells[iColIndex];
+       if (bHTML) { el.innerHTML = sValue; }
+       else {
+               while (el.firstChild != el.lastChild) { 
el.removeChild(el.lastChild); }
+               if (el.firstChild) { el.firstChild.nodeValue = sValue; }
+               else { el.appendChild(document.createTextNode(sValue)); }
+       }
+
+       this.calcSize();
+
+       return 0;
+};
+
+
+/*
+ * void setSortTypes(sSortType[]) {
+ * Sets the column data types for sorting.
+ * Valid options: TYPE_STRING, TYPE_NUMBER, TYPE_DATE, TYPE_STRING_NO_CASE or
+ * custom string value that will be passed to sortable table. Can be registered
+ * with the SortableTable.prototype.addSortType method.
+ */
+WebFXColumnList.prototype.setSortTypes = function(aSortTypes) {
+       var i, a = new Array();
+
+       this._aColumnTypes = aSortTypes;
+       for (i = 0; i < this._cols; i++) {
+               switch (aSortTypes[i]) {
+                       case TYPE_STRING:         a.push('String');             
   break;
+                       case TYPE_NUMBER:         a.push('Number');             
   break;
+                       case TYPE_DATE:           a.push('Date');               
   break;
+                       case TYPE_STRING_NO_CASE: 
a.push('CaseInsensitiveString'); break;
+                       default:                  a.push('String');
+               };
+       }
+       this._stl.setSortTypes(a);
+};
+
+
+/*
+ * void setColumnTypes(aColumnTypes[]) {
+ * Sets the column data types for sorting, also affects the alignment for 
columns
+ * with alignment set to ALIGN_AUTO (which is the default), strings and dates
+ * are left aligned, numbers right aligned.
+ * Valid options: TYPE_STRING, TYPE_NUMBER, TYPE_DATE, TYPE_STRING_NO_CASE or
+ * custom string value that will be passed to sortable table. Can be registered
+ * with the SortableTable.prototype.addSortType method.
+ */
+WebFXColumnList.prototype.setColumnTypes = function(aColumnTypes) {
+       this.setSortTypes(aColumnTypes);
+};
+
+
+/*
+ * void setColumnAlignment(iAlignment[])
+ * Sets column text alignment, ALIGN_AUTO, ALIGN_LEFT, ALIGN_CENTER or 
ALIGN_RIGHT.
+ */
+WebFXColumnList.prototype.setColumnAlignment = function(aAlignment) {
+       _aColumnAlign = aAlignment;
+};
+
+
+/*
+ * void sort(iColumnIndex, [bDescending])
+ * Sorts the grid by the specified column (zero based index) and, optionally, 
in the specified direction.
+ */
+WebFXColumnList.prototype.sort = function(iCol, bDesc) {
+       if (!this.columnSorting) { return; }
+
+       /* Hide arrow from header for column currently sorted by */
+       if (this.sortCol != -1) {
+               var eImg = 
this._eHeadTable.tBodies[0].rows[0].cells[this.sortCol].getElementsByTagName('img')[0];
+               eImg.style.display = 'none';
+       }
+
+       /* Determine sort direction */
+       if (bDesc == null) {
+               bDesc = false;
+               if ((!this.sortDescending) && (iCol == this.sortCol)) { bDesc = 
true; }
+       }
+
+       /* Indicate sorting using arrow in header */
+       var eImg = 
this._eHeadTable.tBodies[0].rows[0].cells[iCol].getElementsByTagName('img')[0];
+       eImg.src = (bDesc)?this.sortDescImage:this.sortAscImage;
+       eImg.style.display = 'inline';
+
+       /* Perform sort operation */
+       this._stl.sort(iCol, bDesc);
+       this.sortCol = iCol;
+       this.sortDescending = bDesc;
+
+       /* Update row coloring */
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+
+       /* Update selection */
+       var nodes = this._eBodyTable.tBodies[0].rows;
+       var len = nodes.length;
+       var a = new Array();
+       for (var i = 0; i < len; i++) {
+               if (nodes[i].className == 'selected') { a.push(i); }
+       }
+       this.selectRange(a);
+
+       /* Call onsort if defined */
+       if (this.onsort) { this.onsort(this.sortCol, this.sortDescending); }
+
+};
+
+
+/*
+ * void _handleRowKey(iKeyCode)
+ * Key handler for events on row level.
+ */
+WebFXColumnList.prototype._handleRowKey = function(iKeyCode, bCtrl, bShift) {
+       var iActiveRow = -1;
+       if (this.selectedRows.length != 0) { iActiveRow = 
this.selectedRows[this.selectedRows.length-1]; }
+       if ((!bCtrl) && (!bShift)) {
+               if (iKeyCode == 38) {                                           
            // Up
+                       if (iActiveRow > 0) { this.selectRow(iActiveRow - 1); }
+               }
+               else if (iKeyCode == 40) {                                      
            // Down
+                       if (iActiveRow < this._rows - 1) { 
this.selectRow(iActiveRow + 1); }
+               }
+               else if (iKeyCode == 33) {                                      
            // Page Up
+                       if (iActiveRow > 10) { this.selectRow(iActiveRow - 10); 
}
+                       else { this.selectRow(0); }
+               }
+               else if (iKeyCode == 34) {                                      
            // Page Down
+                       if (iActiveRow < this._rows - 10) { 
this.selectRow(iActiveRow + 10); }
+                       else { this.selectRow(this._rows - 1); }
+               }
+               else if (iKeyCode == 36) { this.selectRow(0); }                 
            // Home
+               else if (iKeyCode == 35) { this.selectRow(this._rows - 1); }    
            // End
+               else { return true; }
+               return false;
+       }
+};
+
+
+/*
+ * Event Handlers
+ */
+WebFXColumnList.prototype._mouseMove = function(e) {
+       var el, x, w, tw, ox, rx, i, l;
+
+       el = (e)?e.target:window.event.srcElement;
+       x = (e)?e.pageX:window.event.x + this._eBody.scrollLeft;
+
+       /*
+        * Column move operation started, create elements required to indicate 
moving
+        * and set operation flag to COL_HEAD_MOVE.
+        */
+       if (this._headerOper == COL_HEAD_DOWN) {
+               this._headerOper = COL_HEAD_MOVE;
+               this._eCont.style.cursor = 'move';
+
+               w = this._headerData[2] + (x - this._headerData[1]);
+
+               if (!this._moveEl) {
+                       this._moveEl = document.createElement('div');
+                       
this._moveEl.appendChild(document.createTextNode(this._headerData[0].firstChild.nodeValue));
+                       this._moveEl.className = 'webfx-columnlist-move-header';
+                       this._eHead.appendChild(this._moveEl);
+
+                       if (this.columnAlign) {
+                               switch 
(this._aColumnAlign[this._headerData[0].cellIndex]) {
+                                       case ALIGN_LEFT:   
this._moveEl.style.textAlign = 'left';   break;
+                                       case ALIGN_CENTER: 
this._moveEl.style.textAlign = 'center'; break;
+                                       case ALIGN_RIGHT:  
this._moveEl.style.textAlign = 'right';  break;
+                                       case ALIGN_AUTO:
+                                       default:
+                                               
switch(this._aColumnTypes[this._headerData[0].cellIndex]) {
+                                                       case TYPE_NUMBER: 
this._moveEl.style.textAlign = 'right'; break;
+                                                       default:          
this._moveEl.style.textAlign = 'left';
+                                               };
+                               };
+                       }
+
+
+               }
+               else { this._moveEl.firstChild.nodeValue = 
this._headerData[0].firstChild.nodeValue; }
+               this._moveEl.style.width = this._headerData[0].clientWidth + 
'px';
+
+               if (!this._moveSepEl) {
+                       this._moveSepEl = document.createElement('div');
+                       this._moveSepEl.className = 
'webfx-columnlist-separator-header';
+                       this._eHead.appendChild(this._moveSepEl);
+       }       }
+
+       /*
+        * Column move operation, determine position of column and move place 
holder
+        * to that position. Also indicate in between which columns it will be 
placed.
+        */
+       if (this._headerOper == COL_HEAD_MOVE) {
+               ox = this._headerData[1] + (x - this._headerData[2]);
+               this._moveEl.style.left = ox + 'px';
+
+               ox = 0, rx = x - this._headerData[3];
+               for (i = 0; i < this._cols; i++) {
+                       ox += this._eHeadCols[i].offsetWidth;
+                       if (ox >= rx) { break; }
+               }
+               if (i == this._cols) { this._moveSepEl.style.left = 
(this._eHeadCols[this._cols-1].offsetLeft + 
this._eHeadCols[this._cols-1].offsetWidth - 1) + 'px'; }
+               else { this._moveSepEl.style.left = 
this._eHeadCols[i].offsetLeft + 'px'; }
+
+               this._headerData[4] = i;
+       }
+
+       /*
+        * Column resize operation, determine and set new size based on the 
original
+        * size and the difference between the current mouse position and the 
one that
+        * was recorded once the resize operation was started.
+        */
+       else if (this._headerOper == COL_HEAD_SIZE) {
+               w = this._headerData[1] + x - this._headerData[2];
+               tw = ((w - this._headerData[1]) + this._headerData[3]) + 1;
+               this._eHeadTable.style.width = tw + 'px';
+               if (w > 5) {
+                       this._headerData[0].style.width = w + 'px';
+                       if (this.bodyColResize) {
+                               this._eBodyTable.style.width = tw + 'px';
+                               
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col')[this._headerData[0].cellIndex].style.width
 = w + 'px';
+       }       }       }
+
+       else { this._checkHeaderOperation(el, x); }
+
+};
+
+
+WebFXColumnList.prototype._mouseDown = function(e) {
+       var el = (e)?e.target:window.event.srcElement;
+       var x = (e)?e.pageX:window.event.x + this._eBody.scrollLeft;
+
+       if ((el.tagName == 'TD') && 
(el.parentNode.parentNode.parentNode.parentNode.className == 
'webfx-columnlist-head')) {
+               this._checkHeaderOperation(el, x);
+
+               if (this._headerOper == COL_HEAD_EDGE) {
+                       if (this.bodyColResize) { 
this._sizeBodyAccordingToHeader(); }
+                       this._headerOper = COL_HEAD_SIZE;
+               }
+               else if (this._headerOper == COL_HEAD_OVER) {
+                       this._headerOper = COL_HEAD_DOWN;
+                       this._headerData[0].className = 
'webfx-columnlist-active-header';
+       }       }
+};
+
+
+WebFXColumnList.prototype._mouseUp = function(e) {
+       var el = (e)?e.target:window.event.srcElement;
+       var x = (e)?e.pageX:window.event.x + this._eBody.scrollLeft;
+
+       if (this._headerOper == COL_HEAD_SIZE) {
+
+       }
+       else if (this._headerOper == COL_HEAD_MOVE) {
+               if (this._moveEl)    { this._eHead.removeChild(this._moveEl);   
 this._moveEl    = null; }
+               if (this._moveSepEl) { 
this._eHead.removeChild(this._moveSepEl); this._moveSepEl = null; }
+               this._moveColumn(this._headerData[0].cellIndex, 
this._headerData[4]);
+       }
+       else if (this._headerOper == COL_HEAD_DOWN) {
+               this.sort(el.cellIndex);
+       }
+
+       if (this._headerOper != COL_HEAD_NONE) {
+               this._headerOper = COL_HEAD_NONE;
+               this._eCont.style.cursor = 'default';
+               this._headerData[0].className = '';
+               this._headerData = null;
+               this._sizeBodyAccordingToHeader();
+       }
+
+};
+
+
+WebFXColumnList.prototype._click = function(e) {
+       var el = (e)?e.target:window.event.srcElement;
+       if (el.tagName == 'IMG') { el = el.parentNode; }
+       if (el.tagName == 'DIV') { el = el.parentNode; }
+       if ((el.tagName == 'TD') && 
(el.parentNode.parentNode.parentNode.parentNode.className == 
'webfx-columnlist-body')) {
+               if (((e)?e.shiftKey:window.event.shiftKey) && 
(this.selectedRows.length) && (this.multiple)) {
+                       
this.selectRange(this.selectedRows[this.selectedRows.length-1], 
el.parentNode.rowIndex);
+               }
+               else { this.selectRow(el.parentNode.rowIndex, 
(e)?e.ctrlKey:window.event.ctrlKey); }
+}      };
+
+
+/*
+ * Event handler helpers
+ */
+
+WebFXColumnList.prototype._checkHeaderOperation = function(el, x) {
+       var prev, next, left, right, l, r;
+
+       /*
+        * Checks if the mouse cursor is near the edge of a header
+        * cell, in that case the cursor is set to 'e-resize' and
+        * the operation is set to COL_HEAD_EDGE, if it's over the
+        * header but not near the edge it's set to COL_HEAD_OVER
+        * and finnaly if it's not over the header it's set to
+        * COL_HEAD_NONE. The operation value is used to trigger
+        * column resize, move and sort commands.
+        */
+
+       if ((el.tagName == 'TD') && 
(el.parentNode.parentNode.parentNode.parentNode.className == 
'webfx-columnlist-head')) {
+               if (el.tagName == 'IMG') { el = el.parentNode; }
+
+               prev = el.previousSibling;
+               next = el.nextSibling;
+               left = getLeftPos(el);
+               right = left + el.offsetWidth;
+               l = (x - 5) - left;
+               r = right - x;
+
+               if ((l < 5) && (prev)) {
+                       this._eCont.style.cursor = 'e-resize';
+                       this._headerOper         = COL_HEAD_EDGE;
+                       this._headerData         = [prev, prev.offsetWidth - 5, 
x, this._eHeadTable.offsetWidth];
+               }
+               else if (r < 5) {
+                       this._eCont.style.cursor = 'e-resize';
+                       this._headerOper         = COL_HEAD_EDGE;
+                       this._headerData         = [el, el.offsetWidth - 5, x, 
this._eHeadTable.offsetWidth];
+               }
+               else {
+                       this._eCont.style.cursor = 'default';
+                       this._headerOper         = COL_HEAD_OVER;
+                       this._headerData         = [el, el.offsetLeft, x, 
getLeftPos(this._eHead), el.cellIndex];
+       }       }
+       else {
+               this._eCont.style.cursor = 'default';
+               this._headerOper         = COL_HEAD_NONE;
+               this._headerData         = null;
+}      };
+
+
+WebFXColumnList.prototype._sizeBodyAccordingToHeader = function() {
+       var aCols = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col');
+       var length = aCols.length;
+       var bNoScrollbar = ((this._eBody.offsetWidth - this._eBody.clientWidth) 
== 2);
+       this._eBodyTable.style.width = this._eHeadTable.offsetWidth - 
((bNoScrollbar)?2:0) + 'px';
+       for (var i = 0; i < length; i++) {
+               aCols[i].style.width = (this._eHeadCols[i].offsetWidth - 
((document.all)?2:0)) - (((bNoScrollbar && i) == (length - 1))?2:0) + 'px';
+}      };
+
+
+/*
+ * void moveColumn(iColumnIndex, iNewColumnIndex)
+ * Moves column from givin column index to new index.
+ */
+WebFXColumnList.prototype._moveColumn = function(iCol, iNew) {
+       var i, oParent, oCol, oBefore, aRows, a;
+
+       if (iCol == iNew) { return; }
+
+       /* Move header */
+       oCol    = this._eHeadCols[iCol];
+       oParent = oCol.parentNode;
+       if (iNew == this._cols) {
+               oParent.removeChild(oCol);
+               oParent.appendChild(oCol);
+       }
+       else {
+               oBefore = this._eHeadCols[iNew];
+               oParent.removeChild(oCol);
+               oParent.insertBefore(oCol, oBefore);
+       }
+
+       /* Move cols */
+       oCol    = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col')[iCol];
+       oParent = oCol.parentNode;
+       if (iNew == this._cols) {
+               oParent.removeChild(oCol);
+               oParent.appendChild(oCol);
+       }
+       else {
+               oBefore = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col')[iNew];
+               oParent.removeChild(oCol);
+               oParent.insertBefore(oCol, oBefore);
+       }
+
+       /* Move cells */
+       aRows = this._eBodyTable.tBodies[0].rows;
+       this._rows = aRows.length;
+       for (i = 0; i < this._rows; i++) {
+               oCol    = aRows[i].cells[iCol];
+               oParent = aRows[i];
+
+               if (iNew == this._cols) {
+                       oParent.removeChild(oCol);
+                       oParent.appendChild(oCol);
+               }
+               else {
+                       oBefore = aRows[i].cells[iNew];
+                       oParent.removeChild(oCol);
+                       oParent.insertBefore(oCol, oBefore);
+       }       }
+
+       /* Reorganize column type and sort data */
+       a = new Array();
+       oCol = this._aColumnTypes[iCol];
+       for (i = 0; i < this._aColumnTypes.length; i++) {
+               if (i == iCol) { continue; }
+               if (i == iNew) { a.push(oCol); }
+               a.push(this._aColumnTypes[i]);
+       }
+       if (iNew == this._aColumnTypes.length - 1) { a.push(oCol); }
+       this._aColumnTypes = a;
+       this.setSortTypes(a);
+
+       /* If sorted by column, update sortCol property */
+       if (iCol == this.sortCol) { this.sortCol = iNew; }
+};
+
+
+/*
+ * void _setAlignment()
+ * Sets column alignment
+ */
+WebFXColumnList.prototype._setAlignment = function() {
+       var i, aRows, aAlign, j;
+
+       aAlign = new Array();
+       for (i = 0; i < this._cols; i++) {
+               switch (this._aColumnAlign[i]) {
+                       case ALIGN_LEFT:   align = 'left';   break;
+                       case ALIGN_CENTER: align = 'center'; break;
+                       case ALIGN_RIGHT:  align = 'right';  break;
+                       case ALIGN_AUTO:
+                       default:
+                               switch(this._aColumnTypes[i]) {
+                                       case TYPE_NUMBER: align = 'right'; 
break;
+                                       default:          align = 'left';
+                               };
+               };
+               aAlign.push(align);
+       }
+
+       /* Set alignment for headers */
+       for (i = 0; i < this._cols; i++) {
+               this._eHeadCols[i].style.textAlign = aAlign[i];
+       }
+
+       /*
+        * Set alignment for rows.
+        * IE supports the align property on cols in colgorups. As thats the, 
by far,
+        * fastest way of setting it, that what we'll use.
+        */
+       var aCols = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col');
+       var length = aCols.length;
+       if (document.all) {
+               for (var i = 0; i < length; i++) {
+                       aCols[i].align = aAlign[i];
+       }       }
+
+       /*
+        * Mozilla does not support the align property, so we'll update the 
style
+        * sheet rule for each column instead. Still a lot faster than setting 
the
+        * style text-alignment property for all cells.
+        */
+       else {
+               var ss = null, rules = null;
+               for (var n = 0; n < document.styleSheets.length; n++) {
+                       if 
(document.styleSheets[n].href.indexOf('columnlist.css') == -1) { continue; }
+                       ss    = document.styleSheets[n];
+                       rules = ss.cssRules;
+               }
+               if (!rules) { return; }
+
+               if (!this._aColRules) { this._aColRules = new Array(); }
+               for (var j = 0; j < length; j++) {
+                       if (!this._aColRules[j]) {
+                               for (var i = 0; i < rules.length; i++) {
+                                       if ((rules[i].type == 
CSSRule.STYLE_RULE) && (rules[i].selectorText == '.webfx-columnlist-col-' + j)) 
{
+                                               this._aColRules[j] = rules[i];
+                                               break;
+                       }       }       }
+                       if (this._aColRules[j]) {
+                               this._aColRules[j].style.textAlign = aAlign[j];
+                       }
+                       else { this._aColRules[j] = 
ss.insertRule('.webfx-columnlist-col-' + j + ' { text-align: ' + aAlign[j] + 
'};', 0); }
+}      }       };
+
+
+/*
+ * Helper functions
+ */
+
+function getLeftPos(_el) {
+       var x = 0;
+       for (var el = _el; el; el = el.offsetParent) {
+               x += el.offsetLeft;
+       }
+       return x;
+}
+
+
+function compareNumericAsc(n1, n2) {
+       if (Number(n1) < Number(n2)) { return -1; }
+       if (Number(n1) > Number(n2)) { return 1; }
+       return 0;
+}
+
+
+function getInnerText(el) {
+       if (document.all) { return el.innerText; }
+       var str = '';
+       var cs = el.childNodes;
+       var l = cs.length;
+       for (var i = 0; i < l; i++) {
+               switch (cs[i].nodeType) {
+                       case 1: //ELEMENT_NODE
+                               str += getInnerText(cs[i]);
+                               break;
+                       case 3: //TEXT_NODE
+                               str += cs[i].nodeValue;
+                               break;
+       }       }
+       return str;
+}
Index: sitemgr/js/columnlist/original/api.html
diff -u /dev/null sitemgr/js/columnlist/original/api.html:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:24 2006
+++ sitemgr/js/columnlist/original/api.html     Mon Mar 27 13:13:24 2006
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+       <head>
+               <title>ColumnList Usage (WebFX)</title>
+               <meta http-equiv="Content-Type" content="text/html; 
charset=utf-8" />
+               <!-- WebFX Layout Include -->
+               <script type="text/javascript" 
src="local/webfxlayout.js"></script>
+               <script type="text/javascript" src="local/webfxapi.js"></script>
+               <!-- end WebFX Layout Includes -->
+               <link type="text/css" rel="stylesheet" href="columnlist.css" />
+               <script src="columnlist.js" type="text/javascript"></script>
+       </head>
+       <body>
+               <!-- WebFX Layout Include -->
+               <script type="text/javascript">
+                       //<![CDATA[
+                       var articleMenu= new WebFXMenu;
+                       articleMenu.left  = 384;
+                       articleMenu.top   = 86;
+                       articleMenu.width = 140;
+                       articleMenu.add(new WebFXMenuItem("Introduction", 
"columnlist.html"));
+                       articleMenu.add(new WebFXMenuItem("Implementation", 
"implementation.html"));
+                       articleMenu.add(new WebFXMenuItem("Usage", 
"usage.html"));
+                       articleMenu.add(new WebFXMenuItem("API", "api.html"));
+                       articleMenu.add(new WebFXMenuItem("Implementation", 
"implementation.html"));
+                       articleMenu.add(new WebFXMenuItem("Demo", "demo.html"));
+                       articleMenu.add(new WebFXMenuSeparator);
+                       articleMenu.add(new WebFXMenuItem("Download", 
"http://webfx.eae.net/download/collist103.zip";));
+                       webfxMenuBar.add(new WebFXMenuButton("Article Menu", 
null, null, articleMenu));
+
+                       webfxLayout.writeTitle("ColumnList API");
+                       webfxLayout.writeMenu();
+                       webfxLayout.writeDesignedByEdger();
+                       //]]>
+               </script>
+               <!-- End WebFX Layout Includes -->
+               <div class="webfx-main-body">
+                       <h2 id="ColumnList">ColumnList</h2><p>
+               The class that represents a column list.<br />
+               All indexes are zero based.
+       </p><h3>Syntax</h3><pre>new 
ColumnList();</pre><h3>Parameters</h3><h3>Static 
Methods</h3><table><thead><tr><td>Name</td><td>Description</td></tr></thead><tbody><tr><td
 colspan="2">None.</td></tr></tbody></table><h3>Static 
Fields</h3><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td
 
colspan="3">None.</td></tr></tbody></table><h3>Methods</h3><table><thead><tr><td>Name</td><td>Description</td></tr></thead><tbody><tr><td><a
 class="helpLink" href="javascript://" onclick="toggleMethodArguments( event, 
this ); return false;">addRow</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.addRow(<span 
class="methodArgument">aRowData</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>aRowData</code></td><td><code>String[]</code></td><td>Array
 containing data for the new row. Each element represents a 
cell.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Appends supplied 
row to the column list.</td></tr><tr><td><a class="helpLink" 
href="javascript://" onclick="toggleMethodArguments( event, this ); return 
false;">addRows</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.addRows(<span 
class="methodArgument">aData</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>aData</code></td><td><code>String[][]</code></td><td>Two
 dimensional array containing the data. The first dimension specifies the row 
and the second the column, thus each element represents a 
cell.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Appends supplied 
rows to the column list.</td></tr><tr><td><a class="helpLink" 
href="javascript://" onclick="toggleMethodArguments( event, this ); return 
false;">bind</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.bind(<span class="methodArgument">eCont</span>, 
<span class="methodArgument">eHead</span>, <span 
class="methodArgument">eBody</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>eCont</code></td><td><code>HTML
 Element</code></td><td>The outer 
container.</td></tr><tr><td><code>eHead</code></td><td><code>HTML 
Element</code></td><td>Container with the column list 
header.</td></tr><tr><td><code>eBody</code></td><td><code>HTML 
Element</code></td><td>Container with the column list 
body.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>MenuItem</code></p></div></div></td><td>Binds column list to 
an existing HTML structure. See the usage instructions for further 
information.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return false;">calcSize</a><div 
class="methodContainer"><div class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.calcSize()</code></p><h4>Arguments</h4><p>No 
Arguments.</p><h4>Return 
Type</h4><p><code>void</code></p></div></div></td><td>Recalculates the size of 
the column list widget. Should be called if the size of the outermost container 
is changed.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return false;">clear</a><div 
class="methodContainer"><div class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.clear()</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td></td></tr></tbody></table><h4>Return
 Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Removes all rows 
from column list.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return false;">create</a><div 
class="methodContainer"><div class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.create(<span 
class="methodArgument">eContent</span>, <span 
class="methodArgument">aColumns</span>, <span 
class="methodArgument">aColumns</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>eContent</code></td><td><code>HTML
 Element</code></td><td>The target container which the column list will be 
based 
upon.</td></tr><tr><td><code>aColumns</code></td><td><code>String[]</code></td><td>Array
 containing the desired column 
names.</td></tr><tr><td><code>aColumns</code></td><td><code>[][]</code></td><td>Optionallt
 a two dimensional array can be specified instead for the aColumns parameter. 
In that case the first child element is the column header, the second the width 
(number and unit, ex '30%') and the third the data type, see setColumnTypes for 
values.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Transforms the 
supplied container into an empty column list.</td></tr><tr><td><a 
class="helpLink" href="javascript://" onclick="toggleMethodArguments( event, 
this ); return false;">getCellValue</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.getCellValue(<span 
class="methodArgument">iRowIndex</span>, <span 
class="methodArgument">iColIndex</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iRowIndex</code></td><td><code>Number</code></td><td>Row
 
index.</td></tr><tr><td><code>iColIndex</code></td><td><code>Number</code></td><td>Column
 index.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>String</code></p></div></div></td><td>Returns the content of 
the specified cell.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return 
false;">getColumnCount</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.getColumnCount()</code></p><h4>Arguments</h4><p>No 
Arguments.</p><h4>Return 
Type</h4><p><code>Number</code></p></div></div></td><td>Returns the number of 
columns in the column list.</td></tr><tr><td><a class="helpLink" 
href="javascript://" onclick="toggleMethodArguments( event, this ); return 
false;">getRowCount</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.getRowCount()</code></p><h4>Arguments</h4><p>No 
Arguments.</p><h4>Return 
Type</h4><p><code>Number</code></p></div></div></td><td>Returns the number of 
rows in the column list.</td></tr><tr><td><a class="helpLink" 
href="javascript://" onclick="toggleMethodArguments( event, this ); return 
false;">getSelectedRange</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.getSelectedRange()</code></p><h4>Arguments</h4><p>No
 Arguments.</p><h4>Return 
Type</h4><p><code>Number[]</code></p></div></div></td><td>Returns an array 
containing the row indexes of all selected rows.</td></tr><tr><td><a 
class="helpLink" href="javascript://" onclick="toggleMethodArguments( event, 
this ); return false;">getSelectedRow</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.getSelectedRow()</code></p><h4>Arguments</h4><p>No 
Arguments.</p><h4>Return 
Type</h4><p><code>Number</code></p></div></div></td><td>Returns the row index 
of the selected row. If multiple rows are selected the first one is 
returned.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return 
false;">removeRange</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.removeRange(<span 
class="methodArgument">iFromRowIndex</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iFromRowIndex</code></td><td><code>Number</code></td><td>Index
 of the first row to remove.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Removes all rows in 
the range defined by the iFromRowIndex and iToRowIndex 
parameters.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return 
false;">removeRange</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.removeRange(<span 
class="methodArgument">iRowIndex</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iRowIndex</code></td><td><code>Number[]</code></td><td>Array
 containing the row indexes to remove.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Removes all rows 
specified in the iRowIndex parameter.</td></tr><tr><td><a class="helpLink" 
href="javascript://" onclick="toggleMethodArguments( event, this ); return 
false;">removeRow</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.removeRow(<span 
class="methodArgument">iRowIndex</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iRowIndex</code></td><td><code>Number</code></td><td>Index
 of the row to remove.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Removes the row 
identified by the sequence number supplied.</td></tr><tr><td><a 
class="helpLink" href="javascript://" onclick="toggleMethodArguments( event, 
this ); return false;">resize</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.resize(<span class="methodArgument">iWidth</span>, 
<span 
class="methodArgument">iHeight</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iWidth</code></td><td><code>Number</code></td><td>Desired
 width in 
pixels.</td></tr><tr><td><code>iHeight</code></td><td><code>Number</code></td><td>Desired
 height in pixels.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>void</code></p></div></div></td><td>Resize the grid to the 
given dimensions, the outer (border) size is given, not the inner (content) 
size.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return 
false;">selectRange</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.selectRange(<span 
class="methodArgument">iFromRowIndex</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iFromRowIndex</code></td><td><code>Number</code></td><td>Index
 of the first row to select.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Selects all rows in 
the range defined by the iFromRowIndex and iToRowIndex 
parameters.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return 
false;">selectRange</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.selectRange(<span 
class="methodArgument">iRowIndex</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iRowIndex</code></td><td><code>Number[]</code></td><td>Array
 containing the row indexes to select.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Selects all rows 
specified in the iRowIndex parameter.</td></tr><tr><td><a class="helpLink" 
href="javascript://" onclick="toggleMethodArguments( event, this ); return 
false;">selectRow</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.selectRow(<span 
class="methodArgument">iRowIndex</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iRowIndex</code></td><td><code>Number</code></td><td>Index
 of the row to select.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Selects the row 
identified by the sequence number supplied.</td></tr><tr><td><a 
class="helpLink" href="javascript://" onclick="toggleMethodArguments( event, 
this ); return false;">setCellValue</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.setCellValue(<span 
class="methodArgument">iRowIndex</span>, <span 
class="methodArgument">iColIndex</span>, <span 
class="methodArgument">sValue</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iRowIndex</code></td><td><code>Number</code></td><td>Row
 
index.</td></tr><tr><td><code>iColIndex</code></td><td><code>Number</code></td><td>Column
 
index.</td></tr><tr><td><code>sValue</code></td><td><code>String</code></td><td>Desired
 value.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>iErrorCode</code></p></div></div></td><td>Sets the content of 
the specified cell.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return 
false;">setColumnAlignment</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.setColumnAlignment(<span 
class="methodArgument">iAlignment</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iAlignment</code></td><td><code>Number[]</code></td><td>An
 array containing the alignment types. ALIGN_AUTO, ALIGN_LEFT, ALIGN_CENTER or 
ALIGN_RIGHT.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>void</code></p></div></div></td><td>Sets column text 
alignment.</td></tr><tr><td><a class="helpLink" href="javascript://" 
onclick="toggleMethodArguments( event, this ); return 
false;">setColumnTypes</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.setColumnTypes(<span 
class="methodArgument">iTypesTypes</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iTypesTypes</code></td><td><code>Number[]</code></td><td>An
 array containing the sort types. STRING, TYPE_NUMBER, TYPE_DATE, 
TYPE_STRING_NO_CASE or custom string value that will be passed to sortable 
table. Can be registered with the SortableTable.prototype.addSortType 
method.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>void</code></p></div></div></td><td>Sets the column data 
types. Used to determine alignment and sorting.</td></tr><tr><td><a 
class="helpLink" href="javascript://" onclick="toggleMethodArguments( event, 
this ); return false;">setSortTypes</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.setSortTypes(<span 
class="methodArgument">iTypesTypes</span>)</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iTypesTypes</code></td><td><code>Number[]</code></td><td>An
 array containing the sort types. STRING, TYPE_NUMBER, TYPE_DATE, 
TYPE_STRING_NO_CASE or custom string value that will be passed to sortable 
table. Can be registered with the SortableTable.prototype.addSortType 
method.</td></tr></tbody></table><h4>Return 
Type</h4><p><code>void</code></p></div></div></td><td>Sets the column data 
types. Used to determine alignment and sorting.</td></tr><tr><td><a 
class="helpLink" href="javascript://" onclick="toggleMethodArguments( event, 
this ); return false;">sort</a><div class="methodContainer"><div 
class="methodInfo"><h4>Syntax</h4><p><code><span 
class="object">object</span>.sort(<span 
class="methodArgument">iColumnIndex</span>&nbsp;[, <span 
class="methodArgument">bDescending</span>])</code></p><h4>Arguments</h4><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>iColumnIndex</code></td><td><code>Number</code></td><td>Index
 of column to sort 
by.</td></tr><tr><td><code>bDescending</code></td><td><code>Boolean</code></td><td><span
 class="optional">Optional.</span> Sort will be descending if true, ascending 
if false..<span class="defaultSentence">
+                                       The default value is <code>false</code>.
+                               </span></td></tr></tbody></table><h4>Return 
Type</h4><p><code>void</code></p></div></div></td><td>Sorts the column list by 
the specified 
column.</td></tr></tbody></table><h3>Fields</h3><table><thead><tr><td>Name</td><td>Type</td><td>Descripton</td></tr></thead><tbody><tr><td><code>bodyColResize</code></td><td><code>Boolean</code></td><td>If
 enabled the size of the body columns will be updated as the header column is 
resized, if not the size of the body columns won't update until resize 
operation has 
completed.</td></tr><tr><td><code>colorEvenRows</code></td><td><code>Boolean</code></td><td>If
 enabled odd and even rows will have different class names (odd and even) to 
allow their background color to be 
different.</td></tr><tr><td><code>columnAlign</code></td><td><code>Boolean</code></td><td>Enable
 column text alignment. If enabled the text alignment of columns can be set 
explicitly or determined implicit based on column data 
type.</td></tr><tr><td><code>columnSorting</code></td><td><code>Boolean</code></td><td>Enable
 column sorting. If enabled sort order can be set by clicking the column 
headers.</td></tr><tr><td><code>error</code></td><td><code>String</code></td><td><span
 class="readOnly">Read only.</span> If a method has returned an error code this 
property will contain an error 
message.</td></tr><tr><td><code>moveColumns</code></td><td><code>Boolean</code></td><td>Enable
 column moving. If enabled columns can be reorganized using drag and 
drop.</td></tr><tr><td><code>multiple</code></td><td><code>Boolean</code></td><td>If
 true multiple selection is allowed, if false it's 
not.</td></tr><tr><td><code>resizeColumns</code></td><td><code>Boolean</code></td><td>Enable
 column resizing. If enabled the columns may be resized by dragging the border 
between two column 
headers.</td></tr><tr><td><code>rowSelection</code></td><td><code>Boolean</code></td><td>Enable
 column selection. If enabled rows can be selected using either the mouse or 
keyboard.</td></tr><tr><td><code>selectedRows</code></td><td><code>Number[]</code></td><td><span
 class="readOnly">Read only.</span> An array containing the indexes of all 
selected 
rows.</td></tr><tr><td><code>sortAscImage</code></td><td><code>String</code></td><td>Image
 used to indicate ascending sort 
order</td></tr><tr><td><code>sortCol</code></td><td><code>Number</code></td><td><span
 class="readOnly">Read only.</span> Indicates which column the column list is 
sorted by or -1 if it is not 
sorted.</td></tr><tr><td><code>sortDescending</code></td><td><code>Boolean</code></td><td><span
 class="readOnly">Read only.</span> Indicates sort direction. False for 
ascending, true for 
descending.</td></tr><tr><td><code>sortDescImage</code></td><td><code>String</code></td><td>Image
 used to indicate descending sort 
order</td></tr></tbody></table><h3>Events</h3><table><thead><tr><td>Name</td><td>Descripton</td></tr></thead><tbody><tr><td><code>onresize</code></td><td>Reference
 to function that will be called when the widget has been 
resized.</td></tr><tr><td><code>onselect</code></td><td>Reference to function 
that will be called when a row has been 
selected.</td></tr><tr><td><code>onsort</code></td><td>Reference to function 
that will be called when a sort operation has been 
performed.</td></tr></tbody></table><h3>Remarks</h3><p>
+                       None.
+               </p>
+                       <p>
+                               <a href="columnlist.html">Introduction</a><br />
+                               <a 
href="implementation.html">Implementation</a><br />
+                               <a href="usage.html">Usage</a><br />
+                               API<br />
+                               <a href="demo.html">Demo</a><br />
+                               <a 
href="http://webfx.eae.net/download/collist103.zip";>Download</a>
+                       </p>
+                       <p class="author">Author: Emil A Eklund</p>
+                       <!-- end webfx-main-body -->
+               </div>
+       </body>
+</html>
Index: sitemgr/js/columnlist/original/api.xml
diff -u /dev/null sitemgr/js/columnlist/original/api.xml:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/api.xml      Mon Mar 27 13:13:24 2006
@@ -0,0 +1,198 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet type="text/xsl" href="api.xsl"?>
+
+<documentation>
+
+<class name="ColumnList">
+
+       <description>
+               The class that represents a column list.<br/>
+               All indexes are zero based.
+       </description>
+
+       <syntax>new ColumnList();</syntax>
+
+       <methods>
+               <method name="create">
+                       <description>Transforms the supplied container into an 
empty column list.</description>
+                       <arguments>
+                               <argument name="eContent" type="HTML Element" 
description="The target container which the column list will be based upon." />
+                               <argument name="aColumns" type="String[]" 
description="Array containing the desired column names." />
+                               <argument name="aColumns" type="[][]" 
description="Optionallt a two dimensional array can be specified instead for 
the aColumns parameter. In that case the first child element is the column 
header, the second the width (number and unit, ex '30%') and the third the data 
type, see setColumnTypes for values." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="bind">
+                       <description>Binds column list to an existing HTML 
structure. See the usage instructions for further information.</description>
+                       <arguments>
+                               <argument name="eCont"    type="HTML Element" 
description="The outer container." />
+                               <argument name="eHead"    type="HTML Element" 
description="Container with the column list header." />
+                               <argument name="eBody"    type="HTML Element" 
description="Container with the column list body." />
+                       </arguments>
+                       <returns type="MenuItem" />
+               </method>
+               <method name="calcSize">
+                       <description>Recalculates the size of the column list 
widget. Should be called if the size of the outermost container is 
changed.</description>
+                       <returns type="void" />
+               </method>
+               <method name="selectRow">
+                       <description>Selects the row identified by the sequence 
number supplied.</description>
+                       <arguments>
+                               <argument name="iRowIndex"  type="Number" 
description="Index of the row to select." />
+                               <arguments name="bMultiple"  type="Boolean" 
description="If set to true and multi-select is allowed the the previously 
selected row will not be deselected. If the specified row is already selected 
it will be deselected." optional="true" default="false" />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="selectRange">
+                       <description>Selects all rows in the range defined by 
the iFromRowIndex and iToRowIndex parameters.</description>
+                       <arguments>
+                               <argument name="iFromRowIndex" type="Number" 
description="Index of the first row to select." />
+                               <arguments name="iToRowIndex"  type="Number" 
description="Index of the last row to select." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="selectRange">
+                       <description>Selects all rows specified in the 
iRowIndex parameter.</description>
+                       <arguments>
+                               <argument name="iRowIndex" type="Number[]" 
description="Array containing the row indexes to select." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="resize">
+                       <description>Resize the grid to the given dimensions, 
the outer (border) size is given, not the inner (content) size.</description>
+                       <arguments>
+                               <argument name="iWidth"  type="Number" 
description="Desired width in pixels." />
+                               <argument name="iHeight" type="Number" 
description="Desired height in pixels." />
+                       </arguments>
+                       <returns type="void" />
+               </method>
+               <method name="addRow">
+                       <description>Appends supplied row to the column 
list.</description>
+                       <arguments>
+                               <argument name="aRowData" type="String[]" 
description="Array containing data for the new row. Each element represents a 
cell." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="addRows">
+                       <description>Appends supplied rows to the column 
list.</description>
+                       <arguments>
+                               <argument name="aData" type="String[][]" 
description="Two dimensional array containing the data. The first dimension 
specifies the row and the second the column, thus each element represents a 
cell." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="removeRow">
+                       <description>Removes the row identified by the sequence 
number supplied.</description>
+                       <arguments>
+                               <argument name="iRowIndex"  type="Number" 
description="Index of the row to remove." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="removeRange">
+                       <description>Removes all rows in the range defined by 
the iFromRowIndex and iToRowIndex parameters.</description>
+                       <arguments>
+                               <argument name="iFromRowIndex" type="Number" 
description="Index of the first row to remove." />
+                               <arguments name="iToRowIndex"  type="Number" 
description="Index of the last row to remove." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="removeRange">
+                       <description>Removes all rows specified in the 
iRowIndex parameter.</description>
+                       <arguments>
+                               <argument name="iRowIndex" type="Number[]" 
description="Array containing the row indexes to remove." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="clear">
+                       <description>Removes all rows from column 
list.</description>
+                       <arguments />
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="getSelectedRow">
+                       <description>Returns the row index of the selected row. 
If multiple rows are selected the first one is returned.</description>
+                       <returns type="Number" description="Index of selected 
row or -1 if no row is selected." />
+               </method>
+               <method name="getSelectedRange">
+                       <description>Returns an array containing the row 
indexes of all selected rows.</description>
+                       <returns type="Number[]" description="Indexes of 
selected rows or an empty array of no rows are selected." />
+               </method>
+               <method name="getRowCount">
+                       <description>Returns the number of rows in the column 
list.</description>
+                       <returns type="Number" description="Number of rows." />
+               </method>
+               <method name="getColumnCount">
+                       <description>Returns the number of columns in the 
column list.</description>
+                       <returns type="Number" description="Number of columns." 
/>
+               </method>
+               <method name="getCellValue">
+                       <description>Returns the content of the specified 
cell.</description>
+                       <arguments>
+                               <argument name="iRowIndex" type="Number" 
description="Row index." />
+                               <argument name="iColIndex" type="Number" 
description="Column index." />
+                       </arguments>
+                       <returns type="String" />
+               </method>
+               <method name="setCellValue">
+                       <description>Sets the content of the specified 
cell.</description>
+                       <arguments>
+                               <argument name="iRowIndex" type="Number" 
description="Row index." />
+                               <argument name="iColIndex" type="Number" 
description="Column index." />
+                               <argument name="sValue"    type="String" 
description="Desired value." />
+                       </arguments>
+                       <returns type="iErrorCode" description="Error code, a 
non-zero value indicates failure." />
+               </method>
+               <method name="setColumnAlignment">
+                       <description>Sets column text alignment.</description>
+                       <arguments>
+                               <argument name="iAlignment" type="Number[]" 
description="An array containing the alignment types. ALIGN_AUTO, ALIGN_LEFT, 
ALIGN_CENTER or ALIGN_RIGHT." />
+                       </arguments>
+                       <returns type="void" />
+               </method>
+               <method name="setColumnTypes">
+                       <description>Sets the column data types. Used to 
determine alignment and sorting.</description>
+                       <arguments>
+                               <argument name="iTypesTypes" type="Number[]" 
description="An array containing the sort types. STRING, TYPE_NUMBER, 
TYPE_DATE, TYPE_STRING_NO_CASE or custom string value that will be passed to 
sortable table. Can be registered with the SortableTable.prototype.addSortType 
method." />
+                       </arguments>
+                       <returns type="void" />
+               </method>
+               <method name="setSortTypes">
+                       <description>Sets the column data types. Used to 
determine alignment and sorting.</description>
+                       <arguments>
+                               <argument name="iTypesTypes" type="Number[]" 
description="An array containing the sort types. STRING, TYPE_NUMBER, 
TYPE_DATE, TYPE_STRING_NO_CASE or custom string value that will be passed to 
sortable table. Can be registered with the SortableTable.prototype.addSortType 
method." />
+                       </arguments>
+                       <returns type="void" />
+               </method>
+               <method name="sort">
+                       <description>Sorts the column list by the specified 
column.</description>
+                       <arguments>
+                               <argument name="iColumnIndex" type="Number" 
description="Index of column to sort by." />
+                               <argument name="bDescending" type="Boolean" 
optional="true" default="false" description="Sort will be descending if true, 
ascending if false.." />
+                       </arguments>
+                       <returns type="void" />
+               </method>
+       </methods>
+       <fields>
+               <field name="multiple" type="Boolean" default="true" 
description="If true multiple selection is allowed, if false it's not." />
+               <field name="colorEvenRows" type="Boolean" default="true" 
description="If enabled odd and even rows will have different class names (odd 
and even) to allow their background color to be different." />
+               <field name="resizeColumns" type="Boolean" default="true" 
description="Enable column resizing. If enabled the columns may be resized by 
dragging the border between two column headers." />
+               <field name="bodyColResize" type="Boolean" default="true" 
description="If enabled the size of the body columns will be updated as the 
header column is resized, if not the size of the body columns won't update 
until resize operation has completed." />              
+               <field name="moveColumns" type="Boolean" default="true" 
description="Enable column moving. If enabled columns can be reorganized using 
drag and drop." />
+               <field name="rowSelection" type="Boolean" default="true" 
description="Enable column selection. If enabled rows can be selected using 
either the mouse or keyboard." />
+               <field name="columnSorting" type="Boolean" default="true" 
description="Enable column sorting. If enabled sort order can be set by 
clicking the column headers." />
+               <field name="columnAlign" type="Boolean" default="true" 
description="Enable column text alignment. If enabled the text alignment of 
columns can be set explicitly or determined implicit based on column data 
type." />
+               <field name="sortAscImage" type="String" 
default="images/asc.png" description="Image used to indicate ascending sort 
order" />
+               <field name="sortDescImage" type="String" 
default="images/desc.png" description="Image used to indicate descending sort 
order" />
+               <field name="sortCol" type="Number" readOnly="true" 
description="Indicates which column the column list is sorted by or -1 if it is 
not sorted." />
+               <field name="sortDescending" type="Boolean" readOnly="true" 
description="Indicates sort direction. False for ascending, true for 
descending." />
+               <field name="error" type="String" readOnly="true" 
description="If a method has returned an error code this property will contain 
an error message." />
+               <field name="selectedRows" type="Number[]" readOnly="true" 
description="An array containing the indexes of all selected rows." />
+       </fields>
+       <events>
+               <event name="onresize" description="Reference to function that 
will be called when the widget has been resized." />
+               <event name="onsort" description="Reference to function that 
will be called when a sort operation has been performed." />
+               <event name="onselect" description="Reference to function that 
will be called when a row has been selected." />
+       </events>
+
+</class>
+
+</documentation>
\ No newline at end of file
Index: sitemgr/js/columnlist/original/article-images/ie.png
Index: sitemgr/js/columnlist/original/article-images/moz.png
Index: sitemgr/js/columnlist/original/columnlist.html
diff -u /dev/null sitemgr/js/columnlist/original/columnlist.html:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/columnlist.html      Mon Mar 27 13:13:24 2006
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+       <head>
+               <title>ColumnList (WebFX)</title>
+               <meta http-equiv="Content-Type" content="text/html; 
charset=utf-8" />
+               <script type="text/javascript" 
src="local/webfxlayout.js"></script>
+       </head>
+       <body>
+               <!-- WebFX Layout Include -->
+               <script type="text/javascript">
+                       //<![CDATA[
+                       var articleMenu= new WebFXMenu;
+                       articleMenu.left  = 384;
+                       articleMenu.top   = 86;
+                       articleMenu.width = 140;
+                       articleMenu.add(new WebFXMenuItem("Introduction", 
"columnlist.html"));
+                       articleMenu.add(new WebFXMenuItem("Implementation", 
"implementation.html"));
+                       articleMenu.add(new WebFXMenuItem("Usage", 
"usage.html"));
+                       articleMenu.add(new WebFXMenuItem("API", "api.html"));
+                       articleMenu.add(new WebFXMenuItem("Demo", "demo.html"));
+                       articleMenu.add(new WebFXMenuSeparator);
+                       articleMenu.add(new WebFXMenuItem("Download", 
"http://webfx.eae.net/download/collist103.zip";));
+                       webfxMenuBar.add(new WebFXMenuButton("Article Menu", 
null, null, articleMenu));
+
+                       webfxLayout.writeTitle("ColumnList");
+                       webfxLayout.writeMenu();
+                       webfxLayout.writeDesignedByEdger();
+                       //]]>
+               </script>
+               <!-- End WebFX Layout Includes -->
+               <div class="webfx-main-body">
+                       <p>
+                               <span class="date">2004-10-28</span>: First 
public version released.<br />
+                               <span class="date">2004-11-23</span>: Fixed 
column resizing in mozilla. It still can't make columns smaller than their 
content, but otherwise it seems to work.
+                               <span class="date">2005-05-22</span>: Fixed a 
bug in the removeRange method for index based removal, where the rows where 
deleted in the wrong order. Also added a clear method, that removes all 
rows.<br />
+                               <span class="date">2005-12-08</span>: Fixed bug 
that caused rows to be colored even if colorEvenRows was false.
+                                       Added rowSelection, columnSorting, 
moveColumns, sortAscImage and sortDescImage properties.
+                                       Implemented column moving and alignment.
+                                       Updated column resizing implementation.
+                                       Added support for making columns 
smaller than their content in Mozilla, bringing the Mozilla support up to pair 
with that for IE.
+                                       Added support for specifying column 
width on create.
+                       </p>
+                       <h2>Introduction</h2>
+                       <p>
+                               Since Erik wrote the <a 
href="../sortabletable/sortabletable.html">Sortable Table</a>
+                               article a year and a half ago we've received 
quite a few questions about
+                               how to combine it with the fixed header 
example, demonstrated in the
+                               <a 
href="../syncscroll/syncscroll.html">Synchronized Scroll</a> article, thus 
creating
+                               a sortable table with a fixed header. However 
it's not that easy to combine those and
+                               the result has often been a disappointment.
+                       </p>
+                       <p>
+                               This ColumnList widget tries to overcome this, 
it uses the Sortable Table script
+                               to perform the sorting and has a table with a 
fixed header. It also adds a few extras;
+                               such as a clean object oriented interface, 
column resizing and, row coloring,
+                               to name a few.
+                       </p>
+                       <h3>Attach or Generate</h3>
+                       <p>
+                               The widget can either attach to a set of 
existing html elements or create the
+                               necessary elements on-the-fly from a javascript 
data structure.
+                               Both methods has its advantages, it's more 
efficient to attach to an existing
+                               structure than to generate it, but on-the-fly 
creation allows for mor flexibility.
+                               Either way the content can be accessed and 
modified in the same way regardless
+                               of how the widget was created.
+                       </p>
+                       <h3>Multiple Selection</h3>
+                       <p>
+                               There's also an option to allow multiple 
selection which, if enabled, makes it
+                               possible to select more than one row using the 
control or shift keys.
+                               Other keyboard bindings, such as the up and 
down arrow keys, are supported as well.
+                       </p>
+                       <p>
+                               Introduction<br />
+                               <a 
href="implementation.html">Implementation</a><br />
+                               <a href="usage.html">Usage</a><br />
+                               <a href="api.html">API</a><br />
+                               <a href="demo.html">Demo</a><br />
+                               <a 
href="http://webfx.eae.net/download/collist103.zip";>Download</a>
+                       </p>
+                       <p class="author">Author: Emil A Eklund</p>
+                       <!-- end webfx-main-body -->
+               </div>
+       </body>
+</html>
Index: sitemgr/js/columnlist/original/demo.html
diff -u /dev/null sitemgr/js/columnlist/original/demo.html:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/demo.html    Mon Mar 27 13:13:24 2006
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+       <head>
+               <link type="text/css" rel="stylesheet" 
href="includes/columnlist.css" />
+               <script type="text/javascript" 
src="includes/sortabletable.js"></script>
+               <script type="text/javascript" 
src="includes/columnlist.js"></script>
+               <style type="text/css">
+                       body { background: threedface; }
+               </style>
+       </head>
+       <body>
+               <div id="container" class="webfx-columnlist" 
style="margin-left: 50px; width: 640px; height: 480px;">
+                       <div id="head" class="webfx-columnlist-head">
+                               <table cellspacing="0" cellpadding="0" 
style="width: 200px;">
+                                       <tr>
+                                               <td>Flavor<img 
src="images/asc.png"/></td><td>Color<img 
src="images/asc.png"/></td><td>Texture<img 
src="images/asc.png"/></td><td>Price<img src="images/asc.png"/></td>
+                                       </tr>
+                               </table>
+                       </div>
+                       <div id="body" class="webfx-columnlist-body">
+                               <table cellspacing="0" cellpadding="0" 
style="width: 200px;">
+                                       <colgroup span="4">
+                                               <col style="width: 30%;" />
+                                               <col style="width: 30%;" />
+                                               <col style="width: 30%;" />
+                                               <col style="width: 10%;" />
+                                       </colgroup>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                                       
<tr><td>Vanilla</td><td>White</td><td>Smooth</td><td>10</td></tr>
+                                       
<tr><td>Pear</td><td>Green</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Strawberry</td><td>Pink</td><td>Smooth</td><td>8</td></tr>
+                                       
<tr><td>Chocolate</td><td>Brown</td><td>Chunky</td><td>8</td></tr>
+                                       <tr><td>Pistachio</td><td>Light 
green</td><td>Chunky</td><td>9</td></tr>
+                               </table>
+                       </div>
+               </div>
+               <br/>
+               <button 
onclick="o.removeRow(o.getSelectedRow())">o.removeRow(o.getSelectedRow())</button>
+               <button 
onclick="o.removeRange(o.getSelectedRange())">o.removeRange(o.getSelectedRange())</button>
+               <button onclick="alert(o.getCellValue(o.getSelectedRow(), 
1))">alert(o.getCellValue(o.getSelectedRow(), 1))</button>
+               <button onclick="o.setCellValue(o.getSelectedRow(), 1, 
'test')">o.setCellValue(o.getSelectedRow(), 1, 'test')</button>
+       </body>
+       <script type="text/javascript">
+               var o = new WebFXColumnList();
+               var rc = o.bind(document.getElementById('container'), 
document.getElementById('head'), document.getElementById('body'));
+               o.setSortTypes([TYPE_STRING, TYPE_STRING, TYPE_STRING, 
TYPE_NUMBER]);
+               o._setAlignment();
+               //o.resize(640, 480);
+               //o.sort(0);
+       </script>
+</html>
Index: sitemgr/js/columnlist/original/demo2.html
diff -u /dev/null sitemgr/js/columnlist/original/demo2.html:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/demo2.html   Mon Mar 27 13:13:24 2006
@@ -0,0 +1,59 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+       <head>
+               <link type="text/css" rel="stylesheet" 
href="includes/columnlist.css" />
+               <script type="text/javascript" 
src="includes/sortabletable.js"></script>
+               <script type="text/javascript" 
src="includes/columnlist.js"></script>
+               <style type="text/css">
+                       html, body { margin: 0px; padding: 0px; overflow: 
hidden; border: none; }
+                       body { background: threedface;  }
+               </style>
+       </head>
+       <body>
+               <div id="container"></div>
+       </body>
+       <script type="text/javascript">
+               //<![CDATA[
+               var aColumns = [
+                       ['Rank',   '10%', TYPE_NUMBER],
+                       ['Flavor', '40%', TYPE_STRING],
+                       ['Color',  '40%', TYPE_STRING],
+                       ['Share',  '10%', TYPE_NUMBER]
+               ];
+
+               var aData = [
+                       ['1','Vanilla','White','29%'],
+                       ['2','Chocolate','Brown','8.9%'],
+                       ['3','Butter pecan','Light brown','5.3%'],
+                       ['4','Strawberry','Pink','5.3%'],
+                       ['5','Neapolitan','Greenish brown','4.2%'],
+                       ['6','Chocolate chip','Brown','3.9%'],
+                       ['7','French vanilla','Yellowish white','3.8%'],
+                       ['8','Cookies and cream','Light brown','3.6%'],
+                       ['9','Vanilla fudge ripple','White', '2.6%'],
+                       ['10','Praline pecan','Brown','1.7%'],
+                       ['11','Cherry','Red','1.6%'],
+                       ['12','Chocolate almond','Brown','1.6%'],
+                       ['13','Coffee','Dark brown', '1.6%'],
+                       ['14','Rocky road','brown', '1.5%'],
+                       ['15','Chocolate marshmallow','Light brown','1.3%']
+               ];
+
+               var el = document.getElementById('container');
+
+               var o = new WebFXColumnList();
+               o.create(el, aColumns);
+               o.addRows(aData);
+
+               function calcSize() {
+                       var dw = 
(window.innerWidth)?window.innerWidth:document.documentElement.clientWidth;
+                       var dh = 
(window.innerHeight)?window.innerHeight:document.documentElement.clientHeight;
+                       o.resize(dw-2, dh-2);
+               }
+               
+               calcSize();
+               
+               window.onresize = calcSize;
+               //]]>
+       </script>
+</html>
Index: sitemgr/js/columnlist/original/images/asc.png
Index: sitemgr/js/columnlist/original/images/desc.png
Index: sitemgr/js/columnlist/original/implementation.html
diff -u /dev/null sitemgr/js/columnlist/original/implementation.html:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/implementation.html  Mon Mar 27 13:13:24 2006
@@ -0,0 +1,133 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+       <head>
+               <title>ColumnList Usage (WebFX)</title>
+               <meta http-equiv="Content-Type" content="text/html; 
charset=utf-8" />
+               <script type="text/javascript" 
src="local/webfxlayout.js"></script>
+               <link type="text/css" rel="stylesheet" href="columnlist.css" />
+               <script src="columnlist.js" type="text/javascript"></script>
+       </head>
+       <body>
+               <!-- WebFX Layout Include -->
+               <script type="text/javascript">
+                       //<![CDATA[
+                       var articleMenu= new WebFXMenu;
+                       articleMenu.left  = 384;
+                       articleMenu.top   = 86;
+                       articleMenu.width = 140;
+                       articleMenu.add(new WebFXMenuItem("Introduction", 
"columnlist.html"));
+                       articleMenu.add(new WebFXMenuItem("Implementation", 
"implementation.html"));
+                       articleMenu.add(new WebFXMenuItem("Usage", 
"usage.html"));
+                       articleMenu.add(new WebFXMenuItem("API", "api.html"));
+                       articleMenu.add(new WebFXMenuItem("Demo", "demo.html"));
+                       articleMenu.add(new WebFXMenuSeparator);
+                       articleMenu.add(new WebFXMenuItem("Download", 
"http://webfx.eae.net/download/collist103.zip";));
+                       webfxMenuBar.add(new WebFXMenuButton("Article Menu", 
null, null, articleMenu));
+
+                       webfxLayout.writeTitle("ColumnList Implementation");
+                       webfxLayout.writeMenu();
+                       webfxLayout.writeDesignedByEdger();
+                       //]]>
+               </script>
+               <!-- End WebFX Layout Includes -->
+               <div class="webfx-main-body">
+                       <h2>Implementation</h2>
+                       <p>
+                               A ColumnList widget is basically a table where 
the header is fixed and the body
+                               scrollable. In HTML/XHTML terms that means a 
table divided into a thead and a tbody section.
+                               Where the <code>overflow</code> property of the 
tbody is set to <code>auto</code> (or <code>scroll</code>).
+                       </p>
+                       <p>
+                               The markup for such a table would look 
something like this, notice the style argument in red.
+                               The <code>overflow</code> property is pretty 
meaningless if the height is set to <code>auto</code>
+                               or if the height specified is greather than the 
height of the content. Thus to demonstrate the
+                               behavior it's set to slightly less than 
required for all rows to be visible.
+                       </p>
+                       <p>
+                               <pre>&lt;table cellspacing="0" 
cellpadding="0"&gt;
+       &lt;thead&gt;
+               
&lt;tr&gt;&lt;th&gt;Flavor&lt;/th&gt;&lt;th&gt;Color&lt;/th&gt;&lt;th&gt;Texture&lt;/th&gt;&lt;th&gt;Price&lt;/th&gt;&lt;/tr&gt;
+       &lt;/thead&gt;
+       &lt;tbody style="<span style="color: red;">height: 75px; overflow: 
auto</span>;"&gt;
+               
&lt;tr&gt;&lt;td&gt;Vanilla&lt;/td&gt;&lt;td&gt;White&lt;/td&gt;&lt;td&gt;Smooth&lt;/td&gt;&lt;td&gt;$
 10&lt;/td&gt;&lt;/tr&gt;
+               
&lt;tr&gt;&lt;td&gt;Pear&lt;/td&gt;&lt;td&gt;Green&lt;/td&gt;&lt;td&gt;Smooth&lt;/td&gt;&lt;td&gt;$
 8&lt;/td&gt;&lt;/tr&gt;
+               
&lt;tr&gt;&lt;td&gt;Strawberry&lt;/td&gt;&lt;td&gt;Pink&lt;/td&gt;&lt;td&gt;Smooth&lt;/td&gt;&lt;td&gt;$
 8&lt;/td&gt;&lt;/tr&gt;
+               
&lt;tr&gt;&lt;td&gt;Chocolate&lt;/td&gt;&lt;td&gt;Brown&lt;/td&gt;&lt;td&gt;Chunky&lt;/td&gt;&lt;td&gt;$
 8&lt;/td&gt;&lt;/tr&gt;
+               &lt;tr&gt;&lt;td&gt;Pistachio&lt;/td&gt;&lt;td&gt;Light 
green&lt;/td&gt;&lt;td&gt;Chunky&lt;/td&gt;&lt;td&gt;$ 9&lt;/td&gt;&lt;/tr&gt;
+       &lt;/tbody&gt;
+&lt;/table&gt;</pre>
+                       </p>
+                       <h2>The Problem</h2>
+                       <p>
+                               The screenshots below shows what the example 
code, together with a few css rules, looks like in Mozilla (Firefox 1.0 PR)
+                               and Internet Explorer (6.0).
+                       <p>
+                       <p style="font-weight: bold;">Result in  Mozilla</p>
+                       <p>
+                               <img src="article-images/moz.png" style="width: 
304px; height: 99px;" alt="Example as rendered in Mozilla." />
+                       </p>
+                       <p style="font-weight: bold;">Result in Internet 
Explorer</p>
+                       <p>
+                               <img src="article-images/ie.png" style="width: 
304px; height: 413px;" alt="Example as rendered in Internet Explorer" />
+                       </p>
+                       <p>
+                               In Mozilla the result is pretty much what would 
be expected. The horizontal scrollbar is clearly not desirable,
+                               but that's easy enough to resolve by setting 
the <code>overflow</code> property to the mozilla specifiec
+                               <code>-moz-scrollbars-vertical</code> value, or 
by setting the <code>overflow-x</code> property to <code>hidden</code>
+                               (<code>overflow-x</code>/<code>y</code> will be 
supported in Mozilla Firefox 1.1).
+                       </p>
+                       <p>
+                               In Internet Explorer on the other hand, the 
result is nothing like what one would expect. The <code>overflow</code>
+                               property on the tbody is completely ignored, 
and the height applies to all rows rather than the entire body section.
+                       </p>
+                       <h3>The Solution</h3>
+                       <p>
+                               Since Internet Explorer is still, by far, the 
most common browser this approach,
+                               no matter how conveniently, is not going to cut 
it. Instead we'll have to use two
+                               tables. One for the headers and the other for 
the body. Then by placing the table
+                               containing the body in a scrollable container 
(a block element, such as a
+                               <code>div</code>, with a fixed height and the 
<code>overflow</code> property set
+                               to <code>auto</code>) the body can be scrolled 
vertically without affecting the header.
+                       </p>
+                       <p>
+                               Of course, this approach results in a whole set 
of new issues;
+                               columns got different widths in the header and 
body and scrolling the body
+                               horizontally does not affect the header. Those 
issues, luckily, are quite
+                               easy to deal with. Each header column is simply 
resized according to the
+                               equivalent body column and the header's 
<code>scrollLeft</code> property is
+                               synchronized to that of the body.
+                       </p>
+                       <h3>Mozilla quirks</h3>
+                       <p>
+                               After overcoming all the Internet Explorer 
quirks it's time to deal with the
+                               Mozilla ones.
+                       <p>
+                               Since the horizontal scroll of the header is 
synchronized with that of the
+                               body the overflow property is set to hidden, as 
we don't want a horizontal
+                               scrollbar for header.
+                       </p>
+                       <p>
+                               However, mozilla does not allow the 
<code>scroll*</code> properties on elements
+                               with the <code>overflow</code> property set to 
<code>hidden</code> thus we'll
+                               have to set it to 
<code>-moz-scrollbars-none</code> which is basically the same
+                               as <code>hidden</code> in IE, the container has 
overflow type <code>scroll</code>
+                               but no scrollbars are shown.
+                       </p>
+                       <p>
+                               Recent versions of Mozilla handles 
<code>overflow: hidden</code> the same way Internet
+                               Explorer does, rendering this work around 
obsolete. However to remain compatible with
+                               older Mozilla versions this code is still used.
+                       </p>
+                       <p>
+                               <a href="columnlist.html">Introduction</a><br />
+                               Implementation<br />
+                               <a href="usage.html">Usage</a><br />
+                               <a href="api.html">API</a><br />
+                               <a href="demo.html">Demo</a><br />
+                               <a 
href="http://webfx.eae.net/download/collist103.zip";>Download</a>
+                       </p>
+                       <p class="author">Author: Emil A Eklund</p>
+                       <!-- end webfx-main-body -->
+               </div>
+       </body>
+</html>
Index: sitemgr/js/columnlist/original/includes/columnlist.css
diff -u /dev/null sitemgr/js/columnlist/original/includes/columnlist.css:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/includes/columnlist.css      Mon Mar 27 
13:13:24 2006
@@ -0,0 +1,99 @@
+.webfx-columnlist {
+       border: 1px solid;
+       border-color: threedshadow threedhighlight threedhighlight threedshadow;
+       overflow: hidden;
+       display: block;
+       -moz-user-select: none;
+       -moz-user-focus: normal;
+       -moz-user-input: enabled;
+}
+
+.webfx-columnlist td {
+       font: menu;
+       padding: 1px;
+       white-space: nowrap;
+}
+
+.webfx-columnlist-head {
+       position: absolute;
+       background: threedface;
+       overflow: hidden;
+       -moz-user-select: none;
+}
+
+.webfx-columnlist-head table {
+       table-layout: fixed;
+}
+
+.webfx-columnlist-head td {
+       border: 1px solid;
+       border-color: threedhighlight threedshadow threedshadow threedhighlight;
+       overflow: hidden;
+       text-overflow: ellipsis;
+}
+
+.webfx-columnlist-head td img {
+       width:    8px;
+       height:   7px;
+       margin:   0px 5px 0px 5px;
+       display:  none;
+}
+
+.webfx-columnlist-body {
+       border: 1px solid;
+       border-color: threedhighlight threedface threedface threedhighlight;
+       background: window;
+       overflow: auto;
+}
+
+.webfx-columnlist-body table {
+       table-layout: fixed;
+}
+
+.webfx-columnlist-body td {
+       border-bottom: solid white;
+       border-width:  0px 1px 1px 0px;
+       overflow:      hidden;
+       text-overflow: ellipsis;
+       white-space:   no-wrap;
+}
+
+.webfx-columnlist-body tr.selected td {
+       background:   #C0C0FF;
+}
+
+.webfx-columnlist-body tr.odd td {
+       background:   #FFFFC0;
+}
+
+.webfx-columnlist-body tr.even td {
+       background:   window;
+}
+
+.webfx-columnlist-move-header {
+       position: absolute;
+       background: threedshadow;
+       top: 0px;
+       font: menu;
+       padding: 2px;
+       height: 1em;
+       filter: Alpha(Opacity=50);
+       -moz-opacity: 0.5;
+       -moz-user-select: none;
+}
+
+.webfx-columnlist-active-header {
+       border-color: threedface !important;
+}
+
+.webfx-columnlist-separator-header {
+       position: absolute;
+       top: 0px;
+       left: 10px;
+       font: menu;
+       height: 1em;
+       width: 1px;
+       overflow: hidden;
+       background: blue;
+       padding: 3px 0px;
+}
Index: sitemgr/js/columnlist/original/includes/columnlist.js
diff -u /dev/null sitemgr/js/columnlist/original/includes/columnlist.js:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/includes/columnlist.js       Mon Mar 27 
13:13:24 2006
@@ -0,0 +1,1258 @@
+/*----------------------------------------------------------------------------\
+|                           Column List Widget 1.03                           |
+|-----------------------------------------------------------------------------|
+|                           Created by Emil A Eklund                          |
+|                   (http://webfx.eae.net/contact.html#emil)                  |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| A DHTML column list widget. Can be generated from supplied data or attached |
+| to an existing html structure. Supports multiple selection, sorting, column |
+| resizing, column moving and keyboard navigation.                            |
+|-----------------------------------------------------------------------------|
+|                    Copyright (c) 2004, 205 Emil A Eklund                    |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including  but not limited  to the warranties of  merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or  copyright  holders be  liable for any claim,  damages or  other |
+| liability, whether  in an  action of  contract, tort  or otherwise, arising |
+| from,  out of  or in  connection with  the software or  the  use  or  other |
+| dealings in the software.                                                   |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This  software is  available under the  three different licenses  mentioned |
+| below.  To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License          http://webfx.eae.net/license.html |
+| Permits  anyone the right to use the  software in a  non-commercial context |
+| free of charge.                                                             |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license           http://webfx.eae.net/commercial.html |
+| Permits the  license holder the right to use  the software in a  commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of  implementations of the licensed software.                    |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License    http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper  credits are given  and the original  and modified source |
+| code are included. Requires  that the final product, software derivate from |
+| the original  source or any  software  utilizing a GPL  component, such  as |
+| this, is also licensed under the GPL license.                               |
+|-----------------------------------------------------------------------------|
+| Dependencies: columnlist.css      Column list style declarations            |
+|               sortabletable.js    Provides table sorting functionality      |
+|-----------------------------------------------------------------------------|
+| Browser compatibility: IE           Verified, 6.0+                          |
+|                        Mozilla      Verified, 1.7+ (Firefox 1.0+)           |
+|                        Opera        Not Verified                            |
+|                        Safari/KTML: Not Verified                            |
+|-----------------------------------------------------------------------------|
+| 2004-08-22 | Work started.                                                  |
+| 2004-10-24 | First version published.                                       |
+| 2004-11-01 | Added resizeColumns property,  allowing column  resizing to be |
+|            | enabled/disabled.  Fixed a bug in the  sort method that caused |
+|            | getSelectedRow to return an invalid index when called from the |
+|            | function triggered by onselect. Misc bugfixes for Mozilla.     |
+| 2004-11-23 | Fixed column resizing in mozilla.  It still can't make columns |
+|            | smaller than their content, but otherwise it seems to work.    |
+| 2005-05-22 | Fixed a bug in the removeRange method for index based removal, |
+|            | where the rows where deleted in the wrong order.  Also added a |
+|            | clear method, that removes all rows.                           |
+| 2005-11-30 | Fixed bug that caused rows to be colored even if colorEvenRows |
+|            | was false.  Added  rowSelection,  columnSorting,  moveColumns, |
+|            | sortAscImage and sortDescImage properties.  Implemented column |
+|            | moving and alignment. Updated column resizing implementation.  |
+| 2005-12-08 | Added support for making columns smaller than their content in |
+|            | Mozilla, bringing the Mozilla support up to pair with that for |
+|            | IE. Also added support for specifying column width on create.  |
+| 2005-12-20 | Fixed bug in setCellValue method.                              |
+|-----------------------------------------------------------------------------|
+| Created 2004-08-22 | All changes are in the log above. | Updated 2005-12-20 |
+\----------------------------------------------------------------------------*/
+
+var TYPE_STRING         = 0;
+var TYPE_NUMBER         = 1;
+var TYPE_DATE           = 2;
+var TYPE_STRING_NO_CASE = 3;
+
+var SORT_ASCENDING  = 0;
+var SORT_DESCENDING = 1;
+
+var ALIGN_AUTO   = 0;
+var ALIGN_LEFT   = 1;
+var ALIGN_CENTER = 2;
+var ALIGN_RIGHT  = 3;
+
+var COL_HEAD_NONE = 0;
+var COL_HEAD_EDGE = 1;
+var COL_HEAD_OVER = 2;
+var COL_HEAD_SIZE = 3;
+var COL_HEAD_DOWN = 4;
+var COL_HEAD_MOVE = 5;
+
+
+/*
+ * oColumnList = new WebFXColumnList()
+ * Default constructor
+ */
+function WebFXColumnList() {
+
+       /* public properties */
+       this.multiple       = true;                                             
      // Allow multiple selection (true or false)
+       this.colorEvenRows  = true;                                             
      // Mark even rows with different color (true or false)
+       this.resizeColumns  = true;                                             
      // Enable column resizing (true or false)
+       this.bodyColResize  = true;                                             
      // Resize body columns duing resize operation (true or false)
+       this.moveColumns    = true;                                             
      // Enable column moving (true or false)
+       this.rowSelection   = true;                                             
      // Enable row selection (true or false)
+       this.columnSorting  = true;                                             
      // Enable sorting (true or false)
+       this.columnAlign    = true;                                             
      // Enable column text alignment (true or false)
+       this.sortAscImage   = 'images/asc.png';                                 
      // Image used to indicate ascending sort order
+       this.sortDescImage  = 'images/desc.png';                                
      // Image used to indicate descending sort order
+
+       /* public read only properties */
+       this.sortCol        = -1;                                               
      // Column index currently sorted by, read only
+       this.sortDescending = 0;                                                
      // Column sort direction, read only (SORT_ASCENDING or SORT_DESCENDING)
+       this.error          = '';                                               
      // Error message set if an error code was returned, read only.
+       this.selectedRows   = [];                                               
      // Currently selected rows, read only.
+
+       /* events */
+       this.onresize       = null;
+       this.onsort         = null;
+       this.onselect       = null;
+
+       /* private properties */
+       this._eCont         = null;
+       this._eHead         = null;
+       this._eBody         = null;
+       this._eHeadTable    = null;
+       this._eBodyTable    = null;
+       this._eHeadCols     = null;
+       this._eBodyCols     = null;
+
+       this._aColumnTypes  = [];
+       this._aColumnAlign  = [];
+       this._rows          = 0;
+       this._cols          = 0;
+       this._headerOper    = COL_HEAD_NONE;
+       this._headerData    = null;
+}
+
+
+/*
+ * iError = create(eContainer, sColumn[])
+ * Transforms the supplied container into a column list.
+ * sColumn[]   - Array containing column headers
+ * sColumn[][] - Two dimensional array with column headers, widths and types
+*/
+WebFXColumnList.prototype.create = function(eContainer, aColumns) {
+       var eRow, eCell, eDiv, eImg, eTableBody, eColGroup, eCol, a, b;
+
+       for (var i = eContainer.childNodes.length - 1; i >= 0; i--) {
+               eContainer.removeChild(eContainer.childNodes[i]);
+       }
+
+       /* Create container, header and body */
+       this._eCont = eContainer;
+       this._eHead = document.createElement('div');
+       this._eBody = document.createElement('div');
+       this._eCont.className = 'webfx-columnlist';
+       this._eHead.className = 'webfx-columnlist-head';
+       this._eBody.className = 'webfx-columnlist-body';
+       this._eCont.appendChild(this._eHead);
+       this._eCont.appendChild(this._eBody);
+
+       /* Populate header */
+       this._eHeadTable = document.createElement('table');
+       this._eHeadTable.style.width = '100px';                                 
      // if a width is not set here the overflow: hidden rule will be ignored 
by mozilla
+       this._eHeadTable.cellSpacing = 0;
+       this._eHeadTable.cellPadding = 0;
+       this._eHead.appendChild(this._eHeadTable);
+       eTableBody = document.createElement('tbody');
+       this._eHeadTable.appendChild(eTableBody);
+       eRow = document.createElement('tr');
+       eTableBody.appendChild(eRow);
+       for (var i = 0; i < aColumns.length; i++) {
+               eCell = document.createElement('td');
+               eRow.appendChild(eCell);
+               eImg  = document.createElement('img');
+               if (typeof(aColumns[i]) == 'object') { 
eCell.appendChild(document.createTextNode(aColumns[i][0])); }
+               else { eCell.appendChild(document.createTextNode(aColumns[i])); 
}
+               eCell.appendChild(eImg);
+       }
+
+       /* Create main table, colgroup and col elements */
+       this._eBodyTable = document.createElement('table');
+       this._eBodyTable.cellSpacing = 0;
+       this._eBodyTable.cellPadding = 0;
+       this._eBody.appendChild(this._eBodyTable);
+       eTableBody = document.createElement('tbody');
+       this._eBodyTable.appendChild(eTableBody);
+       eColGroup = document.createElement('colgroup');
+       this._eBodyTable.appendChild(eColGroup);
+       for (var i = 0; i < aColumns.length; i++) {
+               eCol = document.createElement('col');
+               if ((typeof(aColumns[i]) == 'object') && (aColumns[i].length) 
&& (aColumns[i].length > 1)) { eCol.style.width = aColumns[i][1]; }
+               else { eCol.style.width = 'auto'; }
+               eColGroup.appendChild(eCol);
+       }
+
+       /* Init sortable table */
+       this._stl = new SortableTable(this._eBodyTable);
+
+       /* Set column data types */
+       a = new Array(); b = false;
+       for (var i = 0; i < aColumns.length; i++) {
+               if ((typeof(aColumns[i]) == 'object') && (aColumns[i].length) 
&& (aColumns[i].length > 2)) { a.push(aColumns[i][2]); b = true; }
+               else { a.push(TYPE_STRING); }
+       }
+
+       /* Only set explicitly if type was specified for at least one column */
+       if (b) { this.setColumnTypes(a); }
+
+       this._eHeadCols = eRow.cells;
+       this._eBodyCols = null;
+
+       this._cols = aColumns.length;
+       this._rows = 0;
+
+       this._init();
+
+       return 0;
+};
+
+
+/*
+ * iError = bind(eContainer, eHeader, eBody)
+ * Binds column list to an existing HTML structure. Use create
+ * to generate the strucutr automatically.
+*/
+WebFXColumnList.prototype.bind = function(eCont, eHead, eBody) {
+       try {
+               this._eCont      = eCont;
+               this._eHead      = eHead;
+               this._eBody      = eBody;
+               this._eHeadTable = this._eHead.getElementsByTagName('table')[0];
+               this._eBodyTable = this._eBody.getElementsByTagName('table')[0];
+               this._eHeadCols  = this._eHeadTable.tBodies[0].rows[0].cells;
+               this._eBodyCols  = this._eBodyTable.tBodies[0].rows[0].cells;
+       }
+       catch(oe) {
+               this.error = 'Unable to bind to elements: ' + oe.message;
+               return 1;
+       }
+       if (this._eHeadCols.length != this._eBodyCols.length) {
+               this.error = 'Unable to bind to elements: Number of columns in 
header and body does not match.';
+               return 2;
+       }
+
+       this._eHeadCols  = this._eHeadTable.tBodies[0].rows[0].cells;
+       this._eBodyCols  = this._eBodyTable.tBodies[0].rows[0].cells;
+
+       this._cols = this._eHeadCols.length;
+       this._rows = this._eBodyTable.tBodies[0].rows.length;
+
+       this._stl = new SortableTable(this._eBodyTable);
+
+       /* Set column class names (used for alignment in mozilla) */
+       if ((!document.all) && (this.columnAlign)) {
+               aRows = this._eBodyTable.tBodies[0].rows;
+               this._rows = aRows.length;
+               for (i = 0; i < this._rows; i++) {
+                       for (j = 0; j < this._cols; j++) {
+                               aRows[i].cells[j].className = 
'webfx-columnlist-col-' + j;
+       }       }       }
+
+       this._init();
+
+       return 0;
+};
+
+
+/*
+ * void _init(iWidth, iHeight)
+ * Initializes column list, called by create and bind
+*/
+WebFXColumnList.prototype._init = function(iWidth, iHeight) {
+       if (navigator.product == 'Gecko') {
+               /*
+                * Mozilla does not allow the scroll* properties of containers 
with the
+                * overflow property set to 'hidden' thus we'll have to set it 
to
+                * '-moz-scrollbars-none' which is basically the same as 
'hidden' in IE,
+                * the container has overflow type 'scroll' but no scrollbars 
are shown.
+               */
+               for (var n = 0; n < document.styleSheets.length; n++) {
+                       if 
(document.styleSheets[n].href.indexOf('columnlist.css') == -1) { continue; }
+                       var rules = document.styleSheets[n].cssRules;
+                       for (var i = 0; i < rules.length; i++) {
+                               if ((rules[i].type == CSSRule.STYLE_RULE) && 
(rules[i].selectorText == '.webfx-columnlist-head')) {
+                                       rules[i].style.overflow = 
'-moz-scrollbars-none';
+       }       }       }       }
+
+       /*
+        * Set tab index to allow element to be focused using keyboard, also 
allows
+        * keyboard events to be captured for Mozilla.
+        */
+       this._eCont.tabIndex = '0';
+
+       this.calcSize();
+       this._assignEventHandlers();
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+       if (this.columnAlign)   { this._setAlignment(); }
+}
+
+
+/*
+ * void _assignEventHandlers()
+ * Assigns event handlers to the grid elements, called by bind.
+*/
+WebFXColumnList.prototype._assignEventHandlers = function() {
+       var oThis = this;
+       this._eCont.onclick     = function(e) { oThis._click(e); }
+       if (this.resizeColumns) {
+               this._eCont.onmousedown = function(e) { oThis._mouseDown(e); }
+               this._eCont.onmousemove = function(e) { oThis._mouseMove(e); }
+       }
+       this._eCont.onmouseup   = function(e) { oThis._mouseUp(e); }
+       this._eCont.onselectstart = function(e) { return false; }
+       this._eBody.onscroll = function() {
+               oThis._eHead.scrollLeft = oThis._eBody.scrollLeft;
+       };
+       this._eCont.onkeydown = function(e) {
+               var el = (e)?e.target:window.event.srcElement;
+               var key = (e)?e.keyCode:window.event.keyCode;
+               if (oThis._handleRowKey(key)) { return; }
+               if (window.event) { window.event.cancelBubble = true; }
+               else { e.preventDefault(); e.stopPropagation() }
+               return false;
+       };
+};
+
+
+/*
+ * void calcSize()
+ * Used to calculate the desired size of the grid and size it accordingly.
+ */
+WebFXColumnList.prototype.calcSize = function() {
+       if (this._eCont.offsetWidth >= 4) {
+
+               /* Size body */
+               var h = this._eCont.clientHeight - this._eHead.offsetHeight - 2;
+               if (h >= 0) { this._eBody.style.height = h + 'px'; }
+               this._eBody.style.width = this._eCont.offsetWidth - 4 + 'px';
+               this._eBody.style.paddingTop = this._eHead.offsetHeight + 'px';
+               this._eBodyTable.style.width = this._eBody.clientWidth + 'px';
+
+               /* Size header */
+               var bNoScrollbar = ((this._eBody.offsetWidth - 
this._eBody.clientWidth) == 2);
+               this._eHeadTable.style.width = this._eHead.style.width = 
this._eBody.clientWidth + ((bNoScrollbar)?2:0) + 'px';
+
+               /* Size columns */
+               if (this._eBodyCols) {
+                       var length = this._eBodyCols.length;
+                       for (var i = 0; i < length; i++) {
+                               this._eHeadCols[i].style.width = 
(this._eBodyCols[i].offsetWidth - 4) + ((bNoScrollbar) && (i == length - 
1)?2:0) + 'px';
+       }       }       }
+
+       this._eHeadTable.style.width = 'auto';
+};
+
+
+/*
+ * iErrorCode = selectRow(iRowIndex, bMultiple)
+ * Selects the row identified by the sequence number supplied,
+ *
+ * If bMultiple is specified and multi-select is allowed the
+ * the previously selected row will not be deselected. If the
+ * specified row is already selected it will be deselected.
+ */
+WebFXColumnList.prototype.selectRow = function(iRowIndex, bMultiple) {
+       if (!this.rowSelection) { return; }
+
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to select row, index out of range.';
+               return 1;
+       }
+       var eRows = this._eBodyTable.tBodies[0].rows;
+       var bSelect = true;
+
+       /* Normal click */
+       if ((!bMultiple) || (!this.multiple)) {
+
+               /* Deselect previously selected rows */
+               while (this.selectedRows.length) {
+                       if (this.colorEvenRows) { 
eRows[this.selectedRows[0]].className = (this.selectedRows[0] & 
1)?'odd':'even'; }
+                       else { eRows[this.selectedRows[0]].className = ''; }
+                       this.selectedRows.splice(0, 1);
+       }       }
+
+       /* Control + Click */
+       else {
+               for (var i = 0; i < this.selectedRows.length; i++) {
+
+                       /* Deselect clicked row */
+                       if (this.selectedRows[i] == iRowIndex) {
+                               if (this.colorEvenRows) { 
eRows[this.selectedRows[i]].className = (i & 1)?'odd':'even'; }
+                               else { eRows[this.selectedRows[i]].className = 
''; }
+                               this.selectedRows.splice(i, 1);
+                               bSelect = false;
+                               break;
+       }       }       }
+
+       /* Select clicked row */
+       if (bSelect) {
+               this.selectedRows.push(iRowIndex);
+               eRows[iRowIndex].className = 'selected';
+       }
+
+       var a = (eRows[iRowIndex].offsetTop + this._eHead.offsetHeight) + 
eRows[iRowIndex].offsetHeight + 1;
+       var b = (this._eBody.clientHeight + this._eBody.scrollTop);
+       if (a > b) {
+               this._eBody.scrollTop = (a - this._eBody.clientHeight);
+       }
+       var c = eRows[iRowIndex].offsetTop;
+       var d = this._eBody.scrollTop;
+       if (c < d) {
+               this._eBody.scrollTop = c;
+       }
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = selectRange(iRowIndex[])
+ * iErrorCode = selectRange(iFromRowIndex, iToRowIndex)
+ * Selects all rows between iFromRowIndex and iToRowIndex.
+ */
+WebFXColumnList.prototype.selectRange = function(a, b) {
+       var aRowIndex;
+
+       if (!this.rowSelection) { return; }
+
+       if (typeof a == 'number') {
+               aRowIndex = new Array();
+               for (var i = a; i <= b; i++) { aRowIndex.push(i); }
+               for (var i = b; i <= a; i++) { aRowIndex.push(i); }
+       }
+       else { aRowIndex = a; }
+
+       for (var i = 0; i < aRowIndex.length; i++) {
+               if ((aRowIndex[i] < 0) || (aRowIndex[i] > this._rows - 1)) {
+                       this.error = 'Unable to select rows, index out of 
range.';
+                       return 1;
+       }       }
+
+       /* Deselect previously selected rows */
+       var eRows = this._eBodyTable.tBodies[0].rows;
+       while (this.selectedRows.length) {
+               if (this.colorEvenRows) { eRows[this.selectedRows[0]].className 
= (this.selectedRows[0] & 1)?'odd':'even'; }
+               else { eRows[this.selectedRows[0]].className = ''; }
+               this.selectedRows.splice(0, 1);
+       }
+
+       /* Select all rows indicated by range */
+       var eRows = this._eBodyTable.tBodies[0].rows;
+       var bMatch;
+       for (var i = 0; i < aRowIndex.length; i++) {
+               bMatch = false;
+               for (var j = 0; j < this.selectedRows.length; j++) {
+                       if (this.selectedRows[j] == aRowIndex[i]) { bMatch = 
true; break; }
+               }
+               if (!bMatch) {
+                       /* Select row */
+                       this.selectedRows.push(aRowIndex[i]);
+                       eRows[aRowIndex[i]].className = 'selected';
+       }       }
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * void resize(iWidth, iHeight)
+ * Resize the grid to the given dimensions, the outer (border) size is given, 
not the inner (content) size.
+ */
+WebFXColumnList.prototype.resize = function(w, h) {
+       this._eCont.style.width = w + 'px';
+       this._eCont.style.height = h + 'px';
+       this.calcSize();
+
+       /* Call onresize if defined */
+       if (this.onresize) { this.onresize(); }
+};
+
+
+/*
+ * void _colorEvenRows()
+ * Changes the color of even rows (usually to light yellow) to make it easier 
to read.
+ * Also updates the id column to a sequence counter rather than the row ids.
+ */
+WebFXColumnList.prototype._colorEvenRows = function() {
+       if (this._eBodyTable.tBodies.length) {
+               var nodes = this._eBodyTable.tBodies[0].rows;
+               var len = nodes.length;
+               for (var i = 0; i < len; i++) {
+                       if (nodes[i].className != 'selected') {
+                               nodes[i].className = (i & 1)?'odd':'even';
+       }       }       }
+};
+
+
+/*
+ * iErrorCode = addRow(aRowData)
+ * Appends supplied row to the column list.
+ */
+WebFXColumnList.prototype.addRow = function(aRowData) {
+       var rc = this._addRow(aRowData);
+       if (rc) { return rc; }
+       this.calcSize();
+       return 0;
+};
+
+
+/*
+ * iErrorCode = addRows(aData)
+ * Appends supplied rows to the column list.
+ */
+WebFXColumnList.prototype.addRows = function(aData) {
+       for (var i = 0; i < aData.length; i++) {
+               var rc = this._addRow(aData[i]);
+               if (rc) { return rc; }
+       }
+       this.calcSize();
+       return 0;
+};
+
+
+/*
+ * void _colorEvenRows()
+ * Changes the color of even rows (usually to light yellow) to make it easier 
to read.
+ * Also updates the id column to a sequence counter rather than the row ids.
+ */
+WebFXColumnList.prototype._colorEvenRows = function() {
+       if (this._eBodyTable.tBodies.length) {
+               var nodes = this._eBodyTable.tBodies[0].rows;
+               for (var i = 0; i < nodes.length; i++) {
+                       if (nodes[i].className != 'selected') {
+                               nodes[i].className = (i & 1)?'odd':'even';
+       }       }       }
+};
+
+
+/*
+ * iErrorCode = _addRow(aRowData)
+ */
+WebFXColumnList.prototype._addRow = function(aRowData) {
+       var eBody, eRow, eCell, i, len;
+
+       /* Validate column count */
+       if (aRowData.length != this._cols) { return 1; }
+
+       /* Construct Body Row */
+       eBody = this._eBodyTable.tBodies[0];
+       eRow  = document.createElement('tr');
+       if (this.colorEvenRows) {
+               eRow.className = (this._rows & 1)?'odd':'even';
+       }
+
+       for (i = 0; i < this._cols; i++) {
+               eCell = document.createElement('td');
+               eCell.className = 'webfx-columnlist-col-' + i;
+               eCell.appendChild(document.createTextNode(aRowData[i]));
+               eRow.appendChild(eCell);
+       }
+       eBody.appendChild(eRow);
+
+       /* Update row counter */
+       this._rows++;
+
+       if (this._eBodyCols == null) {
+               this._eBodyCols = this._eBodyTable.tBodies[0].rows[0].cells;
+       }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = removeRow(iRowIndex)
+ * Appends supplied row to the grid.
+ */
+WebFXColumnList.prototype.removeRow = function(iRowIndex) {
+       /* Remove row */
+       var rc = this._removeRow(iRowIndex);
+       if (rc) { return rc; }
+
+       /* Update row counter and select previous row, if any */
+       this._rows--;
+       this.selectRow((iRowIndex > 1)?iRowIndex-1:0);
+
+       /* Recolor rows, if needed */
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+       this.calcSize();
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = removeRange(iRowIndex[])
+ * iErrorCode = removeRange(iFirstRowIndex, iLastRowIndex)
+ * Appends supplied row to the grid.
+ */
+WebFXColumnList.prototype.removeRange = function(a, b) {
+       var aRowIndex = new Array();
+       if (typeof a == 'number') {
+               for (var i = a; i <= b; i++) { aRowIndex.push(i); }
+       }
+       else {
+               for (var i = 0; i < a.length; i++) {
+                       aRowIndex.push(a[i]);
+               }
+               aRowIndex.sort(compareNumericAsc);
+       }
+
+       while ((i = aRowIndex.pop()) >= 0) {
+               var rc = this._removeRow(i);
+               this._rows--;
+       }
+
+       /* Recolor rows, if needed */
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+       this.calcSize();
+
+       /* Call onselect if defined */
+       if (this.onselect) { this.onselect(this.selectedRows); }
+
+       return 0;
+};
+
+
+/*
+ * iErrorCode = clear()
+ * Removes all rows from the column list.
+ */
+WebFXColumnList.prototype.clear = function() {
+       return this.removeRange(0, this._rows - 1);
+}
+
+/*
+ * iErrorCode = _removeRow(iRowIndex)
+ */
+WebFXColumnList.prototype._removeRow = function(iRowIndex) {
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to remove row, row index out of range.';
+               return 1;
+       }
+
+       /* Remove from selected */
+       for (var i = this.selectedRows.length - 1; i >= 0; i--) {
+               if (this.selectedRows[i] == iRowIndex) {
+                       this.selectedRows.splice(i, 1);
+       }       }
+
+       
this._eBodyTable.tBodies[0].removeChild(this._eBodyTable.tBodies[0].rows[iRowIndex]);
+       return 0;
+};
+
+
+/*
+ * iRowIndex getSelectedRow()
+ * Returns the index of the selected row or -1 if no row is selected.
+ */
+WebFXColumnList.prototype.getSelectedRow = function() {
+       return 
(this.selectedRows.length)?this.selectedRows[this.selectedRows.length-1]:-1;
+};
+
+
+/*
+ * iRowIndex[] getSelectedRange()
+ * Returns an array with the row index of all selecteds row or null if no row 
is selected.
+ */
+WebFXColumnList.prototype.getSelectedRange = function() {
+       return (this.selectedRows.length)?this.selectedRows:-1;
+};
+
+
+/*
+ * iRows getRowCount()
+ * Returns the nummer of rows.
+ */
+WebFXColumnList.prototype.getRowCount = function() {
+       return this._rows;
+};
+
+
+/*
+ * iRows getColumnCount()
+ * Returns the nummer of columns.
+ */
+WebFXColumnList.prototype.getColumnCount = function() {
+       return this._cols;
+};
+
+
+/*
+ * sValue = getCellValue(iRowIndex, iColumnIndex, bHTML)
+ * Returns the content of the specified cell.
+ */
+WebFXColumnList.prototype.getCellValue = function(iRowIndex, iColIndex) {
+       var el;
+
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to get cell value , row index out of 
range.';
+               return null;
+       }
+       if ((iColIndex < 0) || (iColIndex > this._cols - 1)) {
+               this.error = 'Unable to get cell value , row index out of 
range.';
+               return null;
+       }
+
+       el = this._eBodyTable.tBodies[0].rows[iRowIndex].cells[iColIndex];
+
+       return (bHTML)?el.innerHTML:getInnerText(el);
+};
+
+
+/*
+ * iError = setCellValue(iRowIndex, iColumnIndex, sValue, bHTML)
+ * Sets the content of the specified cell.
+ */
+WebFXColumnList.prototype.setCellValue = function(iRowIndex, iColIndex, 
sValue, bHTML) {
+       var el;
+
+       if ((iRowIndex < 0) || (iRowIndex > this._rows - 1)) {
+               this.error = 'Unable to set cell value , row index out of 
range.';
+               return 1;
+       }
+       if ((iColIndex < 0) || (iColIndex > this._cols - 1)) {
+               this.error = 'Unable to set cell value , row index out of 
range.';
+               return 2;
+       }
+
+       el = this._eBodyTable.tBodies[0].rows[iRowIndex].cells[iColIndex];
+       if (bHTML) { el.innerHTML = sValue; }
+       else {
+               while (el.firstChild != el.lastChild) { 
el.removeChild(el.lastChild); }
+               if (el.firstChild) { el.firstChild.nodeValue = sValue; }
+               else { el.appendChild(document.createTextNode(sValue)); }
+       }
+
+       this.calcSize();
+
+       return 0;
+};
+
+
+/*
+ * void setSortTypes(sSortType[]) {
+ * Sets the column data types for sorting.
+ * Valid options: TYPE_STRING, TYPE_NUMBER, TYPE_DATE, TYPE_STRING_NO_CASE or
+ * custom string value that will be passed to sortable table. Can be registered
+ * with the SortableTable.prototype.addSortType method.
+ */
+WebFXColumnList.prototype.setSortTypes = function(aSortTypes) {
+       var i, a = new Array();
+
+       this._aColumnTypes = aSortTypes;
+       for (i = 0; i < this._cols; i++) {
+               switch (aSortTypes[i]) {
+                       case TYPE_STRING:         a.push('String');             
   break;
+                       case TYPE_NUMBER:         a.push('Number');             
   break;
+                       case TYPE_DATE:           a.push('Date');               
   break;
+                       case TYPE_STRING_NO_CASE: 
a.push('CaseInsensitiveString'); break;
+                       default:                  a.push('String');
+               };
+       }
+       this._stl.setSortTypes(a);
+};
+
+
+/*
+ * void setColumnTypes(aColumnTypes[]) {
+ * Sets the column data types for sorting, also affects the alignment for 
columns
+ * with alignment set to ALIGN_AUTO (which is the default), strings and dates
+ * are left aligned, numbers right aligned.
+ * Valid options: TYPE_STRING, TYPE_NUMBER, TYPE_DATE, TYPE_STRING_NO_CASE or
+ * custom string value that will be passed to sortable table. Can be registered
+ * with the SortableTable.prototype.addSortType method.
+ */
+WebFXColumnList.prototype.setColumnTypes = function(aColumnTypes) {
+       this.setSortTypes(aColumnTypes);
+};
+
+
+/*
+ * void setColumnAlignment(iAlignment[])
+ * Sets column text alignment, ALIGN_AUTO, ALIGN_LEFT, ALIGN_CENTER or 
ALIGN_RIGHT.
+ */
+WebFXColumnList.prototype.setColumnAlignment = function(aAlignment) {
+       _aColumnAlign = aAlignment;
+};
+
+
+/*
+ * void sort(iColumnIndex, [bDescending])
+ * Sorts the grid by the specified column (zero based index) and, optionally, 
in the specified direction.
+ */
+WebFXColumnList.prototype.sort = function(iCol, bDesc) {
+       if (!this.columnSorting) { return; }
+
+       /* Hide arrow from header for column currently sorted by */
+       if (this.sortCol != -1) {
+               var eImg = 
this._eHeadTable.tBodies[0].rows[0].cells[this.sortCol].getElementsByTagName('img')[0];
+               eImg.style.display = 'none';
+       }
+
+       /* Determine sort direction */
+       if (bDesc == null) {
+               bDesc = false;
+               if ((!this.sortDescending) && (iCol == this.sortCol)) { bDesc = 
true; }
+       }
+
+       /* Indicate sorting using arrow in header */
+       var eImg = 
this._eHeadTable.tBodies[0].rows[0].cells[iCol].getElementsByTagName('img')[0];
+       eImg.src = (bDesc)?this.sortDescImage:this.sortAscImage;
+       eImg.style.display = 'inline';
+
+       /* Perform sort operation */
+       this._stl.sort(iCol, bDesc);
+       this.sortCol = iCol;
+       this.sortDescending = bDesc;
+
+       /* Update row coloring */
+       if (this.colorEvenRows) { this._colorEvenRows(); }
+
+       /* Update selection */
+       var nodes = this._eBodyTable.tBodies[0].rows;
+       var len = nodes.length;
+       var a = new Array();
+       for (var i = 0; i < len; i++) {
+               if (nodes[i].className == 'selected') { a.push(i); }
+       }
+       this.selectRange(a);
+
+       /* Call onsort if defined */
+       if (this.onsort) { this.onsort(this.sortCol, this.sortDescending); }
+
+};
+
+
+/*
+ * void _handleRowKey(iKeyCode)
+ * Key handler for events on row level.
+ */
+WebFXColumnList.prototype._handleRowKey = function(iKeyCode, bCtrl, bShift) {
+       var iActiveRow = -1;
+       if (this.selectedRows.length != 0) { iActiveRow = 
this.selectedRows[this.selectedRows.length-1]; }
+       if ((!bCtrl) && (!bShift)) {
+               if (iKeyCode == 38) {                                           
            // Up
+                       if (iActiveRow > 0) { this.selectRow(iActiveRow - 1); }
+               }
+               else if (iKeyCode == 40) {                                      
            // Down
+                       if (iActiveRow < this._rows - 1) { 
this.selectRow(iActiveRow + 1); }
+               }
+               else if (iKeyCode == 33) {                                      
            // Page Up
+                       if (iActiveRow > 10) { this.selectRow(iActiveRow - 10); 
}
+                       else { this.selectRow(0); }
+               }
+               else if (iKeyCode == 34) {                                      
            // Page Down
+                       if (iActiveRow < this._rows - 10) { 
this.selectRow(iActiveRow + 10); }
+                       else { this.selectRow(this._rows - 1); }
+               }
+               else if (iKeyCode == 36) { this.selectRow(0); }                 
            // Home
+               else if (iKeyCode == 35) { this.selectRow(this._rows - 1); }    
            // End
+               else { return true; }
+               return false;
+       }
+};
+
+
+/*
+ * Event Handlers
+ */
+WebFXColumnList.prototype._mouseMove = function(e) {
+       var el, x, w, tw, ox, rx, i, l;
+
+       el = (e)?e.target:window.event.srcElement;
+       x = (e)?e.pageX:window.event.x + this._eBody.scrollLeft;
+
+       /*
+        * Column move operation started, create elements required to indicate 
moving
+        * and set operation flag to COL_HEAD_MOVE.
+        */
+       if (this._headerOper == COL_HEAD_DOWN) {
+               this._headerOper = COL_HEAD_MOVE;
+               this._eCont.style.cursor = 'move';
+
+               w = this._headerData[2] + (x - this._headerData[1]);
+
+               if (!this._moveEl) {
+                       this._moveEl = document.createElement('div');
+                       
this._moveEl.appendChild(document.createTextNode(this._headerData[0].firstChild.nodeValue));
+                       this._moveEl.className = 'webfx-columnlist-move-header';
+                       this._eHead.appendChild(this._moveEl);
+
+                       if (this.columnAlign) {
+                               switch 
(this._aColumnAlign[this._headerData[0].cellIndex]) {
+                                       case ALIGN_LEFT:   
this._moveEl.style.textAlign = 'left';   break;
+                                       case ALIGN_CENTER: 
this._moveEl.style.textAlign = 'center'; break;
+                                       case ALIGN_RIGHT:  
this._moveEl.style.textAlign = 'right';  break;
+                                       case ALIGN_AUTO:
+                                       default:
+                                               
switch(this._aColumnTypes[this._headerData[0].cellIndex]) {
+                                                       case TYPE_NUMBER: 
this._moveEl.style.textAlign = 'right'; break;
+                                                       default:          
this._moveEl.style.textAlign = 'left';
+                                               };
+                               };
+                       }
+
+
+               }
+               else { this._moveEl.firstChild.nodeValue = 
this._headerData[0].firstChild.nodeValue; }
+               this._moveEl.style.width = this._headerData[0].clientWidth + 
'px';
+
+               if (!this._moveSepEl) {
+                       this._moveSepEl = document.createElement('div');
+                       this._moveSepEl.className = 
'webfx-columnlist-separator-header';
+                       this._eHead.appendChild(this._moveSepEl);
+       }       }
+
+       /*
+        * Column move operation, determine position of column and move place 
holder
+        * to that position. Also indicate in between which columns it will be 
placed.
+        */
+       if (this._headerOper == COL_HEAD_MOVE) {
+               ox = this._headerData[1] + (x - this._headerData[2]);
+               this._moveEl.style.left = ox + 'px';
+
+               ox = 0, rx = x - this._headerData[3];
+               for (i = 0; i < this._cols; i++) {
+                       ox += this._eHeadCols[i].offsetWidth;
+                       if (ox >= rx) { break; }
+               }
+               if (i == this._cols) { this._moveSepEl.style.left = 
(this._eHeadCols[this._cols-1].offsetLeft + 
this._eHeadCols[this._cols-1].offsetWidth - 1) + 'px'; }
+               else { this._moveSepEl.style.left = 
this._eHeadCols[i].offsetLeft + 'px'; }
+
+               this._headerData[4] = i;
+       }
+
+       /*
+        * Column resize operation, determine and set new size based on the 
original
+        * size and the difference between the current mouse position and the 
one that
+        * was recorded once the resize operation was started.
+        */
+       else if (this._headerOper == COL_HEAD_SIZE) {
+               w = this._headerData[1] + x - this._headerData[2];
+               tw = ((w - this._headerData[1]) + this._headerData[3]) + 1;
+               this._eHeadTable.style.width = tw + 'px';
+               if (w > 5) {
+                       this._headerData[0].style.width = w + 'px';
+                       if (this.bodyColResize) {
+                               this._eBodyTable.style.width = tw + 'px';
+                               
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col')[this._headerData[0].cellIndex].style.width
 = w + 'px';
+       }       }       }
+
+       else { this._checkHeaderOperation(el, x); }
+
+};
+
+
+WebFXColumnList.prototype._mouseDown = function(e) {
+       var el = (e)?e.target:window.event.srcElement;
+       var x = (e)?e.pageX:window.event.x + this._eBody.scrollLeft;
+
+       if ((el.tagName == 'TD') && 
(el.parentNode.parentNode.parentNode.parentNode.className == 
'webfx-columnlist-head')) {
+               this._checkHeaderOperation(el, x);
+
+               if (this._headerOper == COL_HEAD_EDGE) {
+                       if (this.bodyColResize) { 
this._sizeBodyAccordingToHeader(); }
+                       this._headerOper = COL_HEAD_SIZE;
+               }
+               else if (this._headerOper == COL_HEAD_OVER) {
+                       this._headerOper = COL_HEAD_DOWN;
+                       this._headerData[0].className = 
'webfx-columnlist-active-header';
+       }       }
+};
+
+
+WebFXColumnList.prototype._mouseUp = function(e) {
+       var el = (e)?e.target:window.event.srcElement;
+       var x = (e)?e.pageX:window.event.x + this._eBody.scrollLeft;
+
+       if (this._headerOper == COL_HEAD_SIZE) {
+
+       }
+       else if (this._headerOper == COL_HEAD_MOVE) {
+               if (this._moveEl)    { this._eHead.removeChild(this._moveEl);   
 this._moveEl    = null; }
+               if (this._moveSepEl) { 
this._eHead.removeChild(this._moveSepEl); this._moveSepEl = null; }
+               this._moveColumn(this._headerData[0].cellIndex, 
this._headerData[4]);
+       }
+       else if (this._headerOper == COL_HEAD_DOWN) {
+               this.sort(el.cellIndex);
+       }
+
+       if (this._headerOper != COL_HEAD_NONE) {
+               this._headerOper = COL_HEAD_NONE;
+               this._eCont.style.cursor = 'default';
+               this._headerData[0].className = '';
+               this._headerData = null;
+               this._sizeBodyAccordingToHeader();
+       }
+
+};
+
+
+WebFXColumnList.prototype._click = function(e) {
+       var el = (e)?e.target:window.event.srcElement;
+       if (el.tagName == 'IMG') { el = el.parentNode; }
+       if (el.tagName == 'DIV') { el = el.parentNode; }
+       if ((el.tagName == 'TD') && 
(el.parentNode.parentNode.parentNode.parentNode.className == 
'webfx-columnlist-body')) {
+               if (((e)?e.shiftKey:window.event.shiftKey) && 
(this.selectedRows.length) && (this.multiple)) {
+                       
this.selectRange(this.selectedRows[this.selectedRows.length-1], 
el.parentNode.rowIndex);
+               }
+               else { this.selectRow(el.parentNode.rowIndex, 
(e)?e.ctrlKey:window.event.ctrlKey); }
+}      };
+
+
+/*
+ * Event handler helpers
+ */
+
+WebFXColumnList.prototype._checkHeaderOperation = function(el, x) {
+       var prev, next, left, right, l, r;
+
+       /*
+        * Checks if the mouse cursor is near the edge of a header
+        * cell, in that case the cursor is set to 'e-resize' and
+        * the operation is set to COL_HEAD_EDGE, if it's over the
+        * header but not near the edge it's set to COL_HEAD_OVER
+        * and finnaly if it's not over the header it's set to
+        * COL_HEAD_NONE. The operation value is used to trigger
+        * column resize, move and sort commands.
+        */
+
+       if ((el.tagName == 'TD') && 
(el.parentNode.parentNode.parentNode.parentNode.className == 
'webfx-columnlist-head')) {
+               if (el.tagName == 'IMG') { el = el.parentNode; }
+
+               prev = el.previousSibling;
+               next = el.nextSibling;
+               left = getLeftPos(el);
+               right = left + el.offsetWidth;
+               l = (x - 5) - left;
+               r = right - x;
+
+               if ((l < 5) && (prev)) {
+                       this._eCont.style.cursor = 'e-resize';
+                       this._headerOper         = COL_HEAD_EDGE;
+                       this._headerData         = [prev, prev.offsetWidth - 5, 
x, this._eHeadTable.offsetWidth];
+               }
+               else if (r < 5) {
+                       this._eCont.style.cursor = 'e-resize';
+                       this._headerOper         = COL_HEAD_EDGE;
+                       this._headerData         = [el, el.offsetWidth - 5, x, 
this._eHeadTable.offsetWidth];
+               }
+               else {
+                       this._eCont.style.cursor = 'default';
+                       this._headerOper         = COL_HEAD_OVER;
+                       this._headerData         = [el, el.offsetLeft, x, 
getLeftPos(this._eHead), el.cellIndex];
+       }       }
+       else {
+               this._eCont.style.cursor = 'default';
+               this._headerOper         = COL_HEAD_NONE;
+               this._headerData         = null;
+}      };
+
+
+WebFXColumnList.prototype._sizeBodyAccordingToHeader = function() {
+       var aCols = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col');
+       var length = aCols.length;
+       var bNoScrollbar = ((this._eBody.offsetWidth - this._eBody.clientWidth) 
== 2);
+       this._eBodyTable.style.width = this._eHeadTable.offsetWidth - 
((bNoScrollbar)?2:0) + 'px';
+       for (var i = 0; i < length; i++) {
+               aCols[i].style.width = (this._eHeadCols[i].offsetWidth - 
((document.all)?2:0)) - (((bNoScrollbar && i) == (length - 1))?2:0) + 'px';
+}      };
+
+
+/*
+ * void moveColumn(iColumnIndex, iNewColumnIndex)
+ * Moves column from givin column index to new index.
+ */
+WebFXColumnList.prototype._moveColumn = function(iCol, iNew) {
+       var i, oParent, oCol, oBefore, aRows, a;
+
+       if (iCol == iNew) { return; }
+
+       /* Move header */
+       oCol    = this._eHeadCols[iCol];
+       oParent = oCol.parentNode;
+       if (iNew == this._cols) {
+               oParent.removeChild(oCol);
+               oParent.appendChild(oCol);
+       }
+       else {
+               oBefore = this._eHeadCols[iNew];
+               oParent.removeChild(oCol);
+               oParent.insertBefore(oCol, oBefore);
+       }
+
+       /* Move cols */
+       oCol    = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col')[iCol];
+       oParent = oCol.parentNode;
+       if (iNew == this._cols) {
+               oParent.removeChild(oCol);
+               oParent.appendChild(oCol);
+       }
+       else {
+               oBefore = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col')[iNew];
+               oParent.removeChild(oCol);
+               oParent.insertBefore(oCol, oBefore);
+       }
+
+       /* Move cells */
+       aRows = this._eBodyTable.tBodies[0].rows;
+       this._rows = aRows.length;
+       for (i = 0; i < this._rows; i++) {
+               oCol    = aRows[i].cells[iCol];
+               oParent = aRows[i];
+
+               if (iNew == this._cols) {
+                       oParent.removeChild(oCol);
+                       oParent.appendChild(oCol);
+               }
+               else {
+                       oBefore = aRows[i].cells[iNew];
+                       oParent.removeChild(oCol);
+                       oParent.insertBefore(oCol, oBefore);
+       }       }
+
+       /* Reorganize column type and sort data */
+       a = new Array();
+       oCol = this._aColumnTypes[iCol];
+       for (i = 0; i < this._aColumnTypes.length; i++) {
+               if (i == iCol) { continue; }
+               if (i == iNew) { a.push(oCol); }
+               a.push(this._aColumnTypes[i]);
+       }
+       if (iNew == this._aColumnTypes.length - 1) { a.push(oCol); }
+       this._aColumnTypes = a;
+       this.setSortTypes(a);
+
+       /* If sorted by column, update sortCol property */
+       if (iCol == this.sortCol) { this.sortCol = iNew; }
+};
+
+
+/*
+ * void _setAlignment()
+ * Sets column alignment
+ */
+WebFXColumnList.prototype._setAlignment = function() {
+       var i, aRows, aAlign, j;
+
+       aAlign = new Array();
+       for (i = 0; i < this._cols; i++) {
+               switch (this._aColumnAlign[i]) {
+                       case ALIGN_LEFT:   align = 'left';   break;
+                       case ALIGN_CENTER: align = 'center'; break;
+                       case ALIGN_RIGHT:  align = 'right';  break;
+                       case ALIGN_AUTO:
+                       default:
+                               switch(this._aColumnTypes[i]) {
+                                       case TYPE_NUMBER: align = 'right'; 
break;
+                                       default:          align = 'left';
+                               };
+               };
+               aAlign.push(align);
+       }
+
+       /* Set alignment for headers */
+       for (i = 0; i < this._cols; i++) {
+               this._eHeadCols[i].style.textAlign = aAlign[i];
+       }
+
+       /*
+        * Set alignment for rows.
+        * IE supports the align property on cols in colgorups. As thats the, 
by far,
+        * fastest way of setting it, that what we'll use.
+        */
+       var aCols = 
this._eBodyTable.getElementsByTagName('colgroup')[0].getElementsByTagName('col');
+       var length = aCols.length;
+       if (document.all) {
+               for (var i = 0; i < length; i++) {
+                       aCols[i].align = aAlign[i];
+       }       }
+
+       /*
+        * Mozilla does not support the align property, so we'll update the 
style
+        * sheet rule for each column instead. Still a lot faster than setting 
the
+        * style text-alignment property for all cells.
+        */
+       else {
+               var ss = null, rules = null;
+               for (var n = 0; n < document.styleSheets.length; n++) {
+                       if 
(document.styleSheets[n].href.indexOf('columnlist.css') == -1) { continue; }
+                       ss    = document.styleSheets[n];
+                       rules = ss.cssRules;
+               }
+               if (!rules) { return; }
+
+               if (!this._aColRules) { this._aColRules = new Array(); }
+               for (var j = 0; j < length; j++) {
+                       if (!this._aColRules[j]) {
+                               for (var i = 0; i < rules.length; i++) {
+                                       if ((rules[i].type == 
CSSRule.STYLE_RULE) && (rules[i].selectorText == '.webfx-columnlist-col-' + j)) 
{
+                                               this._aColRules[j] = rules[i];
+                                               break;
+                       }       }       }
+                       if (this._aColRules[j]) {
+                               this._aColRules[j].style.textAlign = aAlign[j];
+                       }
+                       else { this._aColRules[j] = 
ss.insertRule('.webfx-columnlist-col-' + j + ' { text-align: ' + aAlign[j] + 
'};', 0); }
+}      }       };
+
+
+/*
+ * Helper functions
+ */
+
+function getLeftPos(_el) {
+       var x = 0;
+       for (var el = _el; el; el = el.offsetParent) {
+               x += el.offsetLeft;
+       }
+       return x;
+}
+
+
+function compareNumericAsc(n1, n2) {
+       if (Number(n1) < Number(n2)) { return -1; }
+       if (Number(n1) > Number(n2)) { return 1; }
+       return 0;
+}
+
+
+function getInnerText(el) {
+       if (document.all) { return el.innerText; }
+       var str = '';
+       var cs = el.childNodes;
+       var l = cs.length;
+       for (var i = 0; i < l; i++) {
+               switch (cs[i].nodeType) {
+                       case 1: //ELEMENT_NODE
+                               str += getInnerText(cs[i]);
+                               break;
+                       case 3: //TEXT_NODE
+                               str += cs[i].nodeValue;
+                               break;
+       }       }
+       return str;
+}
Index: sitemgr/js/columnlist/original/includes/sortabletable.js
diff -u /dev/null 
sitemgr/js/columnlist/original/includes/sortabletable.js:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/includes/sortabletable.js    Mon Mar 27 
13:13:24 2006
@@ -0,0 +1,455 @@
+
+/*----------------------------------------------------------------------------\
+|                            Sortable Table 1.12                              |
+|-----------------------------------------------------------------------------|
+|                         Created by Erik Arvidsson                           |
+|                  (http://webfx.eae.net/contact.html#erik)                   |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| A DOM 1 based script that allows an ordinary HTML table to be sortable.     |
+|-----------------------------------------------------------------------------|
+|                  Copyright (c) 1998 - 2004 Erik Arvidsson                   |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including  but not limited  to the warranties of  merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or  copyright  holders be  liable for any claim,  damages or  other |
+| liability, whether  in an  action of  contract, tort  or otherwise, arising |
+| from,  out of  or in  connection with  the software or  the  use  or  other |
+| dealings in the software.                                                   |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This  software is  available under the  three different licenses  mentioned |
+| below.  To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License          http://webfx.eae.net/license.html |
+| Permits  anyone the right to use the  software in a  non-commercial context |
+| free of charge.                                                             |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license           http://webfx.eae.net/commercial.html |
+| Permits the  license holder the right to use  the software in a  commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of  implementations of the licensed software.                    |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License    http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper  credits are given  and the original  and modified source |
+| code are included. Requires  that the final product, software derivate from |
+| the original  source or any  software  utilizing a GPL  component, such  as |
+| this, is also licensed under the GPL license.                               |
+|-----------------------------------------------------------------------------|
+| 2003-01-10 | First version                                                  |
+| 2003-01-19 | Minor changes to the date parsing                              |
+| 2003-01-28 | JScript 5.0 fixes (no support for 'in' operator)               |
+| 2003-02-01 | Sloppy typo like error fixed in getInnerText                   |
+| 2003-07-04 | Added workaround for IE cellIndex bug.                         |
+| 2003-11-09 | The bDescending argument to sort was not correctly working     |
+|            | Using onclick DOM0 event if no support for addEventListener    |
+|            | or attachEvent                                                 |
+| 2004-01-13 | Adding addSortType and removeSortType which makes it a lot     |
+|            | easier to add new, custom sort types.                          |
+| 2004-01-27 | Switch to use descending = false as the default sort order.    |
+|            | Change defaultDescending to suit your needs.                   |
+| 2004-03-14 | Improved sort type None look and feel a bit                    |
+| 2004-08-26 | Made the handling of tBody and tHead more flexible. Now you    |
+|            | can use another tHead or no tHead, and you can chose some      |
+|            | other tBody.                                                   |
+|-----------------------------------------------------------------------------|
+| Created 2003-01-10 | All changes are in the log above. | Updated 2004-08-26 |
+\----------------------------------------------------------------------------*/
+
+
+function SortableTable(oTable, oSortTypes) {
+
+       this._sortTypes = oSortTypes || [];
+
+       this.sortColumn = null;
+       this.descending = null;
+
+       var oThis = this;
+       this._headerOnclick = function (e) {
+               oThis.headerOnclick(e);
+       };
+
+       if (oTable) {
+               this.setTable( oTable );
+               this.document = oTable.ownerDocument || oTable.document;
+       }
+       else {
+               this.document = document;
+       }
+
+
+       // only IE needs this
+       var win = this.document.defaultView || this.document.parentWindow;
+       this._onunload = function () {
+               oThis.destroy();
+       };
+       if (win && typeof win.attachEvent != "undefined") {
+               win.attachEvent("onunload", this._onunload);
+       }
+}
+
+SortableTable.gecko = navigator.product == "Gecko";
+SortableTable.msie = /msie/i.test(navigator.userAgent);
+// Mozilla is faster when doing the DOM manipulations on
+// an orphaned element. MSIE is not
+SortableTable.removeBeforeSort = SortableTable.gecko;
+
+SortableTable.prototype.onsort = function () {};
+
+// default sort order. true -> descending, false -> ascending
+SortableTable.prototype.defaultDescending = false;
+
+// shared between all instances. This is intentional to allow external files
+// to modify the prototype
+SortableTable.prototype._sortTypeInfo = {};
+
+SortableTable.prototype.setTable = function (oTable) {
+       if ( this.tHead )
+               this.uninitHeader();
+       this.element = oTable;
+       this.setTHead( oTable.tHead );
+       this.setTBody( oTable.tBodies[0] );
+};
+
+SortableTable.prototype.setTHead = function (oTHead) {
+       if (this.tHead && this.tHead != oTHead )
+               this.uninitHeader();
+       this.tHead = oTHead;
+       this.initHeader( this._sortTypes );
+};
+
+SortableTable.prototype.setTBody = function (oTBody) {
+       this.tBody = oTBody;
+};
+
+SortableTable.prototype.setSortTypes = function ( oSortTypes ) {
+       if ( this.tHead )
+               this.uninitHeader();
+       this._sortTypes = oSortTypes || [];
+       if ( this.tHead )
+               this.initHeader( this._sortTypes );
+};
+
+// adds arrow containers and events
+// also binds sort type to the header cells so that reordering columns does
+// not break the sort types
+SortableTable.prototype.initHeader = function (oSortTypes) {
+       if (!this.tHead) return;
+       var cells = this.tHead.rows[0].cells;
+       var doc = this.tHead.ownerDocument || this.tHead.document;
+       this._sortTypes = oSortTypes || [];
+       var l = cells.length;
+       var img, c;
+       for (var i = 0; i < l; i++) {
+               c = cells[i];
+               if (this._sortTypes[i] != null && this._sortTypes[i] != "None") 
{
+                       img = doc.createElement("IMG");
+                       img.src = "images/blank.png";
+                       c.appendChild(img);
+                       if (this._sortTypes[i] != null)
+                               c._sortType = this._sortTypes[i];
+                       if (typeof c.addEventListener != "undefined")
+                               c.addEventListener("click", 
this._headerOnclick, false);
+                       else if (typeof c.attachEvent != "undefined")
+                               c.attachEvent("onclick", this._headerOnclick);
+                       else
+                               c.onclick = this._headerOnclick;
+               }
+               else
+               {
+                       c.setAttribute( "_sortType", oSortTypes[i] );
+                       c._sortType = "None";
+               }
+       }
+       this.updateHeaderArrows();
+};
+
+// remove arrows and events
+SortableTable.prototype.uninitHeader = function () {
+       if (!this.tHead) return;
+       var cells = this.tHead.rows[0].cells;
+       var l = cells.length;
+       var c;
+       for (var i = 0; i < l; i++) {
+               c = cells[i];
+               if (c._sortType != null && c._sortType != "None") {
+                       c.removeChild(c.lastChild);
+                       if (typeof c.removeEventListener != "undefined")
+                               c.removeEventListener("click", 
this._headerOnclick, false);
+                       else if (typeof c.detachEvent != "undefined")
+                               c.detachEvent("onclick", this._headerOnclick);
+                       c._sortType = null;
+                       c.removeAttribute( "_sortType" );
+               }
+       }
+};
+
+SortableTable.prototype.updateHeaderArrows = function () {
+       if (!this.tHead) return;
+       var cells = this.tHead.rows[0].cells;
+       var l = cells.length;
+       var img;
+       for (var i = 0; i < l; i++) {
+               if (cells[i]._sortType != null && cells[i]._sortType != "None") 
{
+                       img = cells[i].lastChild;
+                       if (i == this.sortColumn)
+                               img.className = "sort-arrow " + 
(this.descending ? "descending" : "ascending");
+                       else
+                               img.className = "sort-arrow";
+               }
+       }
+};
+
+SortableTable.prototype.headerOnclick = function (e) {
+       // find TD element
+       var el = e.target || e.srcElement;
+       while (el.tagName != "TD")
+               el = el.parentNode;
+
+       this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : 
el.cellIndex);
+};
+
+// IE returns wrong cellIndex when columns are hidden
+SortableTable.getCellIndex = function (oTd) {
+       var cells = oTd.parentNode.childNodes
+       var l = cells.length;
+       var i;
+       for (i = 0; cells[i] != oTd && i < l; i++)
+               ;
+       return i;
+};
+
+SortableTable.prototype.getSortType = function (nColumn) {
+       return this._sortTypes[nColumn] || "String";
+};
+
+// only nColumn is required
+// if bDescending is left out the old value is taken into account
+// if sSortType is left out the sort type is found from the sortTypes array
+
+SortableTable.prototype.sort = function (nColumn, bDescending, sSortType) {
+       if (!this.tBody) return;
+       if (sSortType == null)
+               sSortType = this.getSortType(nColumn);
+
+       // exit if None
+       if (sSortType == "None")
+               return;
+
+       if (bDescending == null) {
+               if (this.sortColumn != nColumn)
+                       this.descending = this.defaultDescending;
+               else
+                       this.descending = !this.descending;
+       }
+       else
+               this.descending = bDescending;
+
+       this.sortColumn = nColumn;
+
+       if (typeof this.onbeforesort == "function")
+               this.onbeforesort();
+
+       var f = this.getSortFunction(sSortType, nColumn);
+       var a = this.getCache(sSortType, nColumn);
+       var tBody = this.tBody;
+
+       a.sort(f);
+
+       if (this.descending)
+               a.reverse();
+
+       if (SortableTable.removeBeforeSort) {
+               // remove from doc
+               var nextSibling = tBody.nextSibling;
+               var p = tBody.parentNode;
+               p.removeChild(tBody);
+       }
+
+       // insert in the new order
+       var l = a.length;
+       for (var i = 0; i < l; i++)
+               tBody.appendChild(a[i].element);
+
+       if (SortableTable.removeBeforeSort) {
+               // insert into doc
+               p.insertBefore(tBody, nextSibling);
+       }
+
+       this.updateHeaderArrows();
+
+       this.destroyCache(a);
+
+       if (typeof this.onsort == "function")
+               this.onsort();
+};
+
+SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) 
{
+       var oThis = this;
+       this._asyncsort = function () {
+               oThis.sort(nColumn, bDescending, sSortType);
+       };
+       window.setTimeout(this._asyncsort, 1);
+};
+
+SortableTable.prototype.getCache = function (sType, nColumn) {
+       if (!this.tBody) return [];
+       var rows = this.tBody.rows;
+       var l = rows.length;
+       var a = new Array(l);
+       var r;
+       for (var i = 0; i < l; i++) {
+               r = rows[i];
+               a[i] = {
+                       value:          this.getRowValue(r, sType, nColumn),
+                       element:        r
+               };
+       };
+       return a;
+};
+
+SortableTable.prototype.destroyCache = function (oArray) {
+       var l = oArray.length;
+       for (var i = 0; i < l; i++) {
+               oArray[i].value = null;
+               oArray[i].element = null;
+               oArray[i] = null;
+       }
+};
+
+SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
+       // if we have defined a custom getRowValue use that
+       if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
+               return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);
+
+       var s;
+       var c = oRow.cells[nColumn];
+       if (typeof c.innerText != "undefined")
+               s = c.innerText;
+       else
+               s = SortableTable.getInnerText(c);
+       return this.getValueFromString(s, sType);
+};
+
+SortableTable.getInnerText = function (oNode) {
+       var s = "";
+       var cs = oNode.childNodes;
+       var l = cs.length;
+       for (var i = 0; i < l; i++) {
+               switch (cs[i].nodeType) {
+                       case 1: //ELEMENT_NODE
+                               s += SortableTable.getInnerText(cs[i]);
+                               break;
+                       case 3: //TEXT_NODE
+                               s += cs[i].nodeValue;
+                               break;
+               }
+       }
+       return s;
+};
+
+SortableTable.prototype.getValueFromString = function (sText, sType) {
+       if (this._sortTypeInfo[sType])
+               return this._sortTypeInfo[sType].getValueFromString( sText );
+       return sText;
+       /*
+       switch (sType) {
+               case "Number":
+                       return Number(sText);
+               case "CaseInsensitiveString":
+                       return sText.toUpperCase();
+               case "Date":
+                       var parts = sText.split("-");
+                       var d = new Date(0);
+                       d.setFullYear(parts[0]);
+                       d.setDate(parts[2]);
+                       d.setMonth(parts[1] - 1);
+                       return d.valueOf();
+       }
+       return sText;
+       */
+       };
+
+SortableTable.prototype.getSortFunction = function (sType, nColumn) {
+       if (this._sortTypeInfo[sType])
+               return this._sortTypeInfo[sType].compare;
+       return SortableTable.basicCompare;
+};
+
+SortableTable.prototype.destroy = function () {
+       this.uninitHeader();
+       var win = this.document.parentWindow;
+       if (win && typeof win.detachEvent != "undefined") {     // only IE 
needs this
+               win.detachEvent("onunload", this._onunload);
+       }
+       this._onunload = null;
+       this.element = null;
+       this.tHead = null;
+       this.tBody = null;
+       this.document = null;
+       this._headerOnclick = null;
+       this.sortTypes = null;
+       this._asyncsort = null;
+       this.onsort = null;
+};
+
+// Adds a sort type to all instance of SortableTable
+// sType : String - the identifier of the sort type
+// fGetValueFromString : function ( s : string ) : T - A function that takes a
+//    string and casts it to a desired format. If left out the string is just
+//    returned
+// fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort
+//    compare function. Takes two values and compares them. If left out less 
than,
+//    <, compare is used
+// fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A 
function
+//    that takes the row and the column index and returns the value used to 
compare.
+//    If left out then the innerText is first taken for the cell and then the
+//    fGetValueFromString is used to convert that string the desired value and 
type
+
+SortableTable.prototype.addSortType = function (sType, fGetValueFromString, 
fCompareFunction, fGetRowValue) {
+       this._sortTypeInfo[sType] = {
+               type:                           sType,
+               getValueFromString:     fGetValueFromString || 
SortableTable.idFunction,
+               compare:                        fCompareFunction || 
SortableTable.basicCompare,
+               getRowValue:            fGetRowValue
+       };
+};
+
+// this removes the sort type from all instances of SortableTable
+SortableTable.prototype.removeSortType = function (sType) {
+       delete this._sortTypeInfo[sType];
+};
+
+SortableTable.basicCompare = function compare(n1, n2) {
+       if (n1.value < n2.value)
+               return -1;
+       if (n2.value < n1.value)
+               return 1;
+       return 0;
+};
+
+SortableTable.idFunction = function (x) {
+       return x;
+};
+
+SortableTable.toUpperCase = function (s) {
+       return s.toUpperCase();
+};
+
+SortableTable.toDate = function (s) {
+       var parts = s.split("-");
+       var d = new Date(0);
+       d.setFullYear(parts[0]);
+       d.setDate(parts[2]);
+       d.setMonth(parts[1] - 1);
+       return d.valueOf();
+};
+
+
+// add sort types
+SortableTable.prototype.addSortType("Number", Number);
+SortableTable.prototype.addSortType("CaseInsensitiveString", 
SortableTable.toUpperCase);
+SortableTable.prototype.addSortType("Date", SortableTable.toDate);
+SortableTable.prototype.addSortType("String");
+// None is a special case
Index: sitemgr/js/columnlist/original/local/helptip.css
diff -u /dev/null sitemgr/js/columnlist/original/local/helptip.css:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/local/helptip.css    Mon Mar 27 13:13:24 2006
@@ -0,0 +1,36 @@
+/*
+       Notice that IE has a display problem if the help link is on
+       the last line of a container with no padding. If this is the
+       case increase the padding bottom to at least 1px
+*/
+
+a.helpLink {
+       color:                          Green;
+       text-decoration:        none;
+       border-bottom:          1px dashed Green;
+}
+
+a.helpLink:hover {
+       color:                          Red;
+       text-decoration:        none;
+       border-bottom:          1px dashed Red;
+}
+
+.help-tooltip {
+       position:       absolute;
+       width:          250px;
+       border:         1px Solid WindowFrame;
+       background:     Infobackground;
+       color:          InfoText;
+       font:           StatusBar;
+       font:           Status-Bar;
+       padding:        3px;
+       filter:         
progid:DXImageTransform.Microsoft.Shadow(color="#777777", Direction=135, 
Strength=3);
        z-index:        10000;
+}
+
+
+.help-tooltip a,
+.help-tooltip a:hover {
+       color:          blue !important;
+       background:     none;
+}
Index: sitemgr/js/columnlist/original/local/helptip.js
diff -u /dev/null sitemgr/js/columnlist/original/local/helptip.js:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/local/helptip.js     Mon Mar 27 13:13:24 2006
@@ -0,0 +1,91 @@
+/*
+ * This script was created by Erik Arvidsson (erik(at)eae.net)
+ * for WebFX (http://webfx.eae.net)
+ * Copyright 2001
+ * 
+ * For usage see license at http://webfx.eae.net/license.html  
+ *
+ * Version: 1.0
+ * Created: 2001-09-27
 * Updated: 2001-11-25  Added a resize to the tooltip if the document width is 
too small
+ *
+ * Dependencies: helptip.css (To set up the CSS of the help-tooltip class)
+ *
+ *     Usage:
+ *
+ *    <script type="text/javascript" src="helptip.js"></script>
+ *    <link type="text/css" rel="StyleSheet" href="helptip.css" />
+ *
+ *    <a class="helpLink" href="?" onclick="showHelp(event, 'String to show'); 
return false">Help</a>
+ *
+ */
+
+function showHelpTip(e, s) {
+       // find anchor element
+       var el = e.target ? e.target : e.srcElement;
+       while (el.tagName != "A")
+               el = el.parentNode;
+       
+       // is there already a tooltip? If so, remove it
+       if (el._helpTip) {
+               document.body.removeChild(el._helpTip);
+               el._helpTip = null;
+               el.onblur = null;
+               return;
+       }
+
+       // create element and insert last into the body
+       var d = document.createElement("DIV");
+       d.className = "help-tooltip";
+       document.body.appendChild(d);
+       d.innerHTML = s;
+       
+       // Allow clicks on A elements inside tooltip
+       d.onmousedown = function (e) {
+               if (!e) e = event;
+               var t = e.target ? e.target : e.srcElement;
+               while (t.tagName != "A" && t != d)
+                       t = t.parentNode;
+               if (t == d) return;
+               
+               el._onblur = el.onblur;
+               el.onblur = null;
+       };
+       d.onmouseup = function () {
+               el.onblur = el._onblur;
+               el.focus();
+       };
+       
+       // position tooltip
+       var dw = document.width ? document.width : 
document.documentElement.offsetWidth - 25;
        
+       if (d.offsetWidth >= dw)
+               d.style.width = dw - 10 + "px";
        else
+               d.style.width = "";
        
+       var scroll = getScroll();
+       if (e.clientX > dw - d.offsetWidth)
+               d.style.left = dw - d.offsetWidth + scroll.x + "px";
+       else
+               d.style.left = e.clientX - 2 + scroll.x + "px";
+       d.style.top = e.clientY + 18 + scroll.y + "px";
+
+       // add a listener to the blur event. When blurred remove tooltip and 
restore anchor
+       el.onblur = function () {
+               document.body.removeChild(d);
+               el.onblur = null;
+               el._helpTip = null;
+       };
+       
+       // store a reference to the tooltip div
+       el._helpTip = d;
+}
+
+// returns the scroll left and top for the browser viewport.
+function getScroll() {
+       if (document.all && document.body.scrollTop != undefined) {     // IE 
model
+               var ieBox = document.compatMode != "CSS1Compat";
+               var cont = ieBox ? document.body : document.documentElement;
+               return {x : cont.scrollLeft, y : cont.scrollTop};
+       }
+       else {
+               return {x : window.pageXOffset, y : window.pageYOffset};
+       }
+}
\ No newline at end of file
Index: sitemgr/js/columnlist/original/local/title-background.png
Index: sitemgr/js/columnlist/original/local/webfxapi.css
diff -u /dev/null sitemgr/js/columnlist/original/local/webfxapi.css:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/local/webfxapi.css   Mon Mar 27 13:13:24 2006
@@ -0,0 +1,47 @@
+/* This style sheet is used for WebFX Api pages */

a.helpLink,
+a.helpLink:hover {
+       color:                          rgb(0,66,174);
+       border-bottom-color:rgb(0,66,174);
+}
+
+.help-tooltip {
+       width:  auto;
+}
+
+.help-tooltip h4,
+.help-tooltip table,
+.help-tooltip p {
+       width:  auto;
+}
+
+.methodContainer {
+       display:        none;
+}
+
+.methodInfo h4,
+.methodInfo thead td {
+       font-size:              13px;
+       background:             none;
+       border-bottom:  0;
+}
+
+.methodInfo h4,
+.methodInfo p, 
+.methodInfo table {
+       margin:         5px;
+       padding:        0;
+}
+
+td {
+       vertical-align: top;
+}
+
+td code {
+       white-space:    nowrap;
+}
+
+code a:visited,
+code a:hover {
+       color:          rgb(0,66,174);
+       background:     transparent;    
+}
\ No newline at end of file
Index: sitemgr/js/columnlist/original/local/webfxapi.js
diff -u /dev/null sitemgr/js/columnlist/original/local/webfxapi.js:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/local/webfxapi.js    Mon Mar 27 13:13:24 2006
@@ -0,0 +1,20 @@
+/*
+ *     This script is used for WebFX Api pages
+ *
+ *     It defines one funtion and includes helptip.js, helptip.css and 
webfxapi.css
+ */
+
+document.write( "<script type='text/javascript' 
src='local/helptip.js'><\/script>" );
+document.write( "<link type='text/css' rel='stylesheet' 
href='local/helptip.css' />" );
+document.write( "<link type='text/css' rel='stylesheet' 
href='local/webfxapi.css' />" );
+
+function toggleMethodArguments( e, a ) {
+       if ( a && a.nextSibling &&
+               typeof a.nextSibling.innerHTML != "undefined" &&
+               typeof showHelpTip != "undefined" ) {
+       
+               showHelpTip( e, a.nextSibling.innerHTML );
+               
+       }
+}
+  
\ No newline at end of file
Index: sitemgr/js/columnlist/original/local/webfxlayout.css
diff -u /dev/null sitemgr/js/columnlist/original/local/webfxlayout.css:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/local/webfxlayout.css        Mon Mar 27 
13:13:24 2006
@@ -0,0 +1,297 @@
+
+/*
+
+bright: rgb(234,242,255);
+normal: rgb(120,172,255);
+dark:  rgb(0,66,174);
+
+*/
+
+/* import menu css */
+/*
@import "dhtml/xmenu/xmenu.css";
*/
+
+#webfx-about {
+       position:               absolute;
+       background:             white;
+       top:                    102px;
+       right:                  10px;
+       width:                  20px;
+       writing-mode:   tb-rl;
+       filter:                 flipH() flipV() alpha(opacity=50);
+}
+
+/* headers css */
+
+#webfx-title {
+       position:               absolute;
+       left:                   90px;
+       top:                    -5px;
+       color:                  black;
+       background:             transparent;
+       border:                 0;
+       padding:                0;
+       margin:                 0;
+       font-family:    Arial Black, Verdana, Helvetica, Sans-Serif;
+       font-weight:    bold;
+       font-style:             italic;
+       font-size:              45px;
+       letter-spacing: -5px;
+}
+
+#webfx-title-background {
+       width:                                  100%;
+       height:                                 67px;
+       background:                             white 
no-repeat;/*rgb(100,100,100) no-repeat;*/
+       background-image:               url("images/title-background.png");
+       background-position:    0 0;
+}
+
+#webfx-sub-title {
+       position:               absolute;
+       left:                   96px;
+       top:                    45px;
+       color:                  black;
+       background:             transparent;
+       padding:                0;
+       margin:                 0;
+       border:                 0;
+       font-family:    Verdana, Helvetica, Sans-Serif;
+       font-size:              11px;
+}
+
+#webfx-menu-bar-1,
+#webfx-menu-bar-2,
+#webfx-menu-bar-3,
+#webfx-menu-bar-4,
+#webfx-menu-bar-5 {
+       height:                 2px;
+       font-size:              0;
+       overflow:               hidden;
+       background:             rgb(120,172,255);/*#ff8800;*/
+       padding:                0;
+}
+
+#webfx-menu-bar-1 {
+       background:             
rgb(0,66,174);/*rgb(120,172,255);/*black;/*rgb(234,242,255);*/
+       height:                 1px;
+}
+
+#webfx-menu-bar-2 {
+       background:             rgb(120,172,255);/*#ff8800;*/
+       height:                 1px;
+}
+
+#webfx-menu-bar-3 {
+       background:             rgb(120,172,255);/*#ff8800;*/
+       height:                 1px;
+}
+
+#webfx-menu-bar-4 {
+       background:             rgb(0,66,174);
+       height:                 1px;
+}
+
+#webfx-menu-bar-5 {
+       background:             #dddddd;
+       height:                 3px;
+}
+
+/* headers css end */
+
+
+html, body {
+       height:         100%;
+       margin:         0;
+       padding:        0;
+       background:     url("images/background-shadow.gif") repeat-y white;
+       color:          black;
+       
+       font-size:      13px;
+       font-family:    "Verdana", "Tahoma", "Helvetica", "Sans-Serif";
+}
+
+.webfx-main-body {
+       margin-left:    100px;
        width:                  500px;
        border-left:    1px solid rgb(120,172,255);
+}
+
+/* h1 only used in header */                   
+h2,h3,h4,h5,h6 {
        margin-top:             10px;
+       margin-left:    10px;
+       margin-right:   10px;
+       padding:                2px 10px 2px 10px;
+       background:             rgb(234,242,255);
+       border-bottom:  1px solid rgb(120,172,255);
+}
+
+h1,h2 {
+       font-weight:    normal;
+}
+
+h3,h4,h5,h6 {
+       font-weight:    bold;
+}
+
+h1 {
+       font-size:              50px;
+}
+
+h2 {
+       font-size:              20px;
+}
+
+h3 {
+       font-size:              15px;
+}
+
h4 {
+       font-size:              12px;
+}
+

+p {
+       margin:                 10px;
+       font-size:              13px;
        color:                  black;
        text-align:             justify;
+}
+
+td {
+       font-size:              13px;
+       font-family:    "Verdana", "Tahoma", "Helvetica", "Sans-Serif";
+}
+
+pre {
        margin:                 20px;
        margin-right:   10px;
+       background:             #eeeeee;
+       padding:                10px;
+       border:                 1px solid #dddddd;
+       color:                  black;
+}
+
+code {
+       background:             #eeeeee;
+       border:                 1px solid #dddddd;
+       color:                  black;
+}
+
+a {
+       text-decoration:underline;
+       color:                  rgb(0,66,174);
+}
+
+a:hover {/*rgb(0,66,174)*/
+       color:                  rgb(0,66,174);
+       background:             rgb(234,242,255);
+}
+
+a:visited {
+       color:                  rgb(120,172,255);
+}
+
+a:visited:hover {
+       color:                  rgb(0,66,174);
+}
+
+hr {
+       margin-left:            10px;
+       margin-right:           10px;
+       padding:                        0;
+       text-align:                     left;
+       height:                         1px;
+       color:                          rgb(120,172,255);
+       background-color:       rgb(120,172,255);
+       border-bottom:          1px solid rgb(120,172,255);
+       border:                         0;
+}
+
+h2 a, h3 a {
+       display:                        block;
+       text-decoration:        none;
+       width:                          expression("100%");
+}
+
+table {
+       margin:                 10px;
+       font-size:              13px;
+       color:                  black;
+}
+
+thead td {
+       background:             rgb(234,242,255);
+       border-bottom:  1px solid rgb(120,172,255);
+       font-weight:    bold;
+}
+
+.author {
+       margin-top:             50px;
+       font-style:             italic;
+}
+
+.date {
+       color:                  rgb(0,66,174);
+}
+
+.warning,
+.warning a {
+       color:                  red;
+}
+
+
+.warning a:visited,
+.warning a:hover {
+       color:  red;
+}
+
+.warning a:hover {
+       background:     rgb(255,230,230);
+}
+
+
+
+
+/* copied from xmenu.css */
+
+.webfx-menu-bar {
+       background:             rgb(120,172,255);/*rgb(255,128,0);*/
+
+       padding:                2px;
+       
+       font-family:    Verdana, Helvetica, Sans-Serif;
+       font-size:              11px;
+       
+}
+
+.webfx-menu-bar a,
+.webfx-menu-bar a:visited {
+       color:                          black;
+       border:                         1px solid 
rgb(120,172,255);/*rgb(255,128,0);*/
+       
+       text-decoration:        none;
+       padding:                        1px;
+       padding-left:           5px;
+       padding-right:          5px;
+}
+
+.webfx-menu-bar a:hover {
+       color:                  black;
+       background:             rgb(120,172,255);
+       border-left:    1px solid rgb(234,242,255);/*#ffcc88;*/
+       border-right:   1px solid rgb(0,66,174);/*#884400;*/
+       border-top:             1px solid rgb(234,242,255);/*#ffcc88;*/
+       border-bottom:  1px solid rgb(0,66,174);/*#884400;*/
+}
+
+.webfx-menu-bar a .arrow {
+       border:                 0;
+       float:                  none;
+/*
+       float:                  right;
+       width:                  6px;
+       height:                 16px;
+
+       margin-right:   2px;
+       background: red;
+*/
+}
+
+.webfx-menu-bar a:active, .webfx-menu-bar a:focus {
+       -moz-outline:   none;
+       outline:                none;
+}
+
+/* end xmenu.css copy */
\ No newline at end of file
Index: sitemgr/js/columnlist/original/local/webfxlayout.js
diff -u /dev/null sitemgr/js/columnlist/original/local/webfxlayout.js:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/local/webfxlayout.js Mon Mar 27 13:13:24 2006
@@ -0,0 +1,111 @@
+/* this is a dummy webfxlayout file to be used in download zip files */
+
+
+/* Do includes */
+
+if (window.pathToRoot == null)
+       pathToRoot = "./";
+
+document.write('<link type="text/css" rel="stylesheet" 
href="local/webfxlayout.css">');
+webfxMenuDefaultImagePath = pathToRoot + "images/";
+
+/* end includes */
+
+/* set up browser checks and add a simple emulation for IE4 */
+
+// check browsers
+var op = /opera 5|opera\/5/i.test(navigator.userAgent);
+var ie = !op && /msie/i.test(navigator.userAgent);     // preventing opera to 
be identified as ie
+var mz = !op && /mozilla\/5/i.test(navigator.userAgent);       // preventing 
opera to be identified as mz
+
+if (ie && document.getElementById == null) {   // ie4
+       document.getElementById = function(sId) {
+               return document.all[sId];
+       };
+}
+
+/* end browser checks */
+
+webfxLayout = {
+       writeTitle              :       function (s, s2) {
+               document.write("<div id='webfx-title-background'></div>");
+               if (op) {
+                       document.write("<h1 id='webfx-title' style='top:9px;'>" 
+ s + "</h1>");
+               }
+               else {
+                       document.write("<h1 id='webfx-title'>" + s + "</h1>");
+               }
+
+               if (s2 == null)
+                       s2 = "WebFX - What you never thought possible!";
+               
+               if (op) {
+                       document.write("<span id='webfx-sub-title' 
style='top:46px;'>" + s2 + "</span>");
+               }
+               else {
+                       document.write("<span id='webfx-sub-title'>" + s2 + 
"</span>");
+               }
+       },
+       writeMainTitle  :       function () {
+               this.writeTitle("WebFX", "What you never thought possible!");   
+       },
+       writeTopMenuBar         :       function () {
+               document.write("<div id='webfx-menu-bar-1'></div>");
+               if (op) {
+                       document.write("<style>.webfx-menu-bar a 
{padding-top:3px;}</style>");
+                       document.write("<div id='webfx-menu-bar-2' 
style='height:2px;'></div>");
+               }
+               else
+                       document.write("<div id='webfx-menu-bar-2'></div>");
+               document.write("<div id='webfx-menu-bar'>");// div is closed in 
writeBottomMenuBar
+       },
+       writeBottomMenuBar      :       function () {
+               document.write("</div>");
+               if (op)
+                       document.write("<div id='webfx-menu-bar-3' 
style='height:0px;'></div>");
+               else
+                       document.write("<div id='webfx-menu-bar-3'></div>");
+               document.write("<div id='webfx-menu-bar-4'></div>");
+               document.write("<div id='webfx-menu-bar-5'></div>");
+       },
+       writeMenu                       :       function () {
+               this.writeTopMenuBar();
+               //document.write(webfxMenuBar);
+               document.write("<div class='webfx-menu-bar'><a 
href='http://webfx.eae.net'>WebFX Home</a></div>");
+               this.writeBottomMenuBar();
+       },
+       writeDesignedByEdger    :       function () {
+               if (ie && document.body.currentStyle.writingMode != null)
+                       document.write("<div id='webfx-about'>Page designed and 
maintained by " +
+                                       "<a href='mailto:address@hidden'>Erik 
Arvidsson</a> &amp; " +
+                                       "<a href='mailto:address@hidden'>Emil A 
Eklund</a>.</div>");
+       }
+};
+
+if (ie && window.attachEvent) {
+       window.attachEvent("onload", function () {
+               var scrollBorderColor   =       "rgb(120,172,255)";
+               var scrollFaceColor             =       "rgb(234,242,255)";
+               with (document.body.style) {
+                       scrollbarDarkShadowColor        =       
scrollBorderColor;
+                       scrollbar3dLightColor           =       
scrollBorderColor;
+                       scrollbarArrowColor                     =       "black";
+                       scrollbarBaseColor                      =       
scrollFaceColor;
+                       scrollbarFaceColor                      =       
scrollFaceColor;
+                       scrollbarHighlightColor         =       scrollFaceColor;
+                       scrollbarShadowColor            =       scrollFaceColor;
+                       scrollbarTrackColor                     =       "white";
+               }
+       });
+}
+
+/* we also need some dummy constructors */
+webfxMenuBar = {
+       add : function () {}
+};
+function WebFXMenu() {
+       this.add = function () {};
+}
+function WebFXMenuItem() {}
+function WebFXMenuSeparator() {}
+function WebFXMenuButton() {}
\ No newline at end of file
Index: sitemgr/js/columnlist/original/usage.html
diff -u /dev/null sitemgr/js/columnlist/original/usage.html:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/original/usage.html   Mon Mar 27 13:13:24 2006
@@ -0,0 +1,173 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+       <head>
+               <title>ColumnList Usage (WebFX)</title>
+               <meta http-equiv="Content-Type" content="text/html; 
charset=utf-8" />
+               <script type="text/javascript" 
src="local/webfxlayout.js"></script>
+               <link type="text/css" rel="stylesheet" href="columnlist.css" />
+               <script src="columnlist.js" type="text/javascript"></script>
+       </head>
+       <body>
+               <!-- WebFX Layout Include -->
+               <script type="text/javascript">
+                       //<![CDATA[
+                       var articleMenu= new WebFXMenu;
+                       articleMenu.left  = 384;
+                       articleMenu.top   = 86;
+                       articleMenu.width = 140;
+                       articleMenu.add(new WebFXMenuItem("Introduction", 
"columnlist.html"));
+                       articleMenu.add(new WebFXMenuItem("Implementation", 
"implementation.html"));
+                       articleMenu.add(new WebFXMenuItem("Usage", 
"usage.html"));
+                       articleMenu.add(new WebFXMenuItem("API", "api.html"));
+                       articleMenu.add(new WebFXMenuItem("Demo", "demo.html"));
+                       articleMenu.add(new WebFXMenuSeparator);
+                       articleMenu.add(new WebFXMenuItem("Download", 
"http://webfx.eae.net/download/collist103.zip";));
+                       webfxMenuBar.add(new WebFXMenuButton("Article Menu", 
null, null, articleMenu));
+
+                       webfxLayout.writeTitle("ColumnList Usage");
+                       webfxLayout.writeMenu();
+                       webfxLayout.writeDesignedByEdger();
+                       //]]>
+               </script>
+               <!-- End WebFX Layout Includes -->
+               <div class="webfx-main-body">
+                       <h2>Usage</h2>
+                       <p>
+                               To use the ColumnList widget the 
<i>columnlist.js</i>, <i>sortabletable.js</i>
+                               and <i>columnlist.css</i> files needs to be 
included and two images used to
+                               indicate sorting direction <i>asc.png</i> and 
<i>desc.png</i> should be
+                               placed in a the same directory (if their 
located elsewhere change the
+                               <code>IMG_DESC</code> and <code>IMG_ASC</code> 
settings at the top of
+                               the <i>columnlist.js</i> file).
+                               <pre>&lt;link type="text/css" rel="stylesheet" 
href="columnlist.css" /&gt;
+&lt;script type="text/javascript" src="sortabletable.js"&gt;&lt;/script&gt;
+&lt;script type="text/javascript" src="columnlist.js"&gt;&lt;/script&gt;</pre>
+                       </p>
+                       <p>
+                               As mentioned in the introduction the columnlist 
can be created in two different
+                               ways, either by attaching to an existing 
structure or by generating it. Let's
+                               begin with the later of the two.
+                       </p>
+                       <h3>Generating a new structure</h3>
+                       <p>
+                               The first step is to create an instance of the 
WebFXColumnList class using
+                               the default constructor <code>o = new 
WebFXColumnList()</code>. Then the
+                               <code>create</code> method is called, with the 
target element and an array
+                               with column labels as the arguments. This will 
create a new, emtpy, column
+                               list widget out of the container element. Once 
it's created rows can be added
+                               using the <code>addRow</code> method (or 
<code>addRows</code> to add multiple
+                               rows at once).
+                       </p>
+                       <h3>HTML</h3>
+                       <p>
+                               The base of the column list is the container 
element and it has to be an
+                               existing element. The size of this element 
controls the size of the widget.
+                               <pre>&lt;div id="container" style="width: 
320px; height: 240px;"&gt;</pre>
+                       </p>
+                       <h3>JavaScript</h3>
+                       <p>
+                               The following JavaScript code will create a 
ColumnList widget with the 15
+                               most popular kinds of ice cream (according to 
the International Ice Cream Association).
+                               <pre>var aColumns = [
+       'Rank',
+       'Flavor',
+       'Color',
+       'Share'
+];
+
+var aData = [
+       ['1','Vanilla','White','29%'],
+       ['2','Chocolate','Brown','8.9%'],
+       ['3','Butter pecan','Light brown','5.3%'],
+       ['4','Strawberry','Pink','5.3%'],
+       ['5','Neapolitan','Greenish brown','4.2%'],
+       ['6','Chocolate chip','Brown','3.9%'],
+       ['7','French vanilla','Yellowish white','3.8%'],
+       ['8','Cookies and cream','Light brown','3.6%'],
+       ['9','Vanilla fudge ripple','White', '2.6%'],
+       ['10','Praline pecan','Brown','1.7%'],
+       ['11','Cherry','Red','1.6%'],
+       ['12','Chocolate almond','Brown','1.6%'],
+       ['13','Coffee','Dark brown', '1.6%'],
+       ['14','Rocky road','brown', '1.5%'],
+       ['15','Chocolate marshmallow','Light brown','1.3%']
+];
+
+var el = document.getElementById('container');
+
+var o = new WebFXColumnList();
+o.create(el, aColumns);
+o.addRows(aData);</pre>
+                       </p>
+                       <h3>Result</h3>
+                       <p>
+                               <iframe src="demo2.html" style="width: 500px; 
height: 240px;" onkeydown="if (window.event) { window.event.cancelBubble = 
true; } else { preventDefault(); } return false;"></iframe>
+                       </p>
+                       <h3>Attaching to existing structure</h3>
+                       <p>
+                               The other method that can be used to create a 
column list widget
+                               is to attach it to an existing structure. This 
method is preferred
+                               if the content is being generated by a server 
side script of some
+                               sort as it's quite a lot faster for larger 
amounts of date. The major
+                               drawbacks are that it's not as convenient and 
requires more markup.
+                       </p>
+                       <p>
+                               The idea here is to manually create the 
structure that would be generated
+                               by the create method (described above) and then 
simply attach the widget
+                               to it.
+                       </p>
+                       <p>
+                               The main difference here is that the content 
(header columns and data)
+                               is defined using HTML rather than JavaScript. 
Thus there's a lot of HTML
+                               markup but very little JavaScript, quite the 
opposite of the create method.
+                       <h3>HTML</h3>
+                       <pre>&lt;div id="container" class="webfx-columnlist" 
style="margin-left: 50px; width: 640px; height: 480px;"&gt;
+&lt;div id="head" class="webfx-columnlist-head"&gt;
+       &lt;table cellspacing="0" cellpadding="0"&gt;
+               &lt;tr&gt;
+                       &lt;td&gt;Flavor&lt;img 
src="images/asc.png"/&gt;&lt;/td&gt;
+                       &lt;td&gt;Color&lt;img 
src="images/asc.png"/&gt;&lt;/td&gt;
+                       &lt;td&gt;Texture&lt;img 
src="images/asc.png"/&gt;&lt;/td&gt;
+                       &lt;td&gt;Price&lt;img 
src="images/asc.png"/&gt;&lt;/td&gt;
+               &lt;/tr&gt;
+       &lt;/table&gt;
+&lt;/div&gt;
+&lt;div id="body" class="webfx-columnlist-body"&gt;
+       &lt;table cellspacing="0" cellpadding="0"&gt;
+               &lt;colgroup span="4"&gt;
+                       &lt;col style="width: auto;" /&gt;
+                       &lt;col style="width: auto;" /&gt;
+                       &lt;col style="width: auto;" /&gt;
+                       &lt;col style="width: auto;" /&gt;
+               &lt;/colgroup&gt;
+               
&lt;tr&gt;&lt;td&gt;Vanilla&lt;/td&gt;&lt;td&gt;White&lt;/td&gt;&lt;td&gt;Smooth&lt;/td&gt;&lt;td&gt;$
 10&lt;/td&gt;&lt;/tr&gt;
+               
&lt;tr&gt;&lt;td&gt;Pear&lt;/td&gt;&lt;td&gt;Green&lt;/td&gt;&lt;td&gt;Smooth&lt;/td&gt;&lt;td&gt;$
 8&lt;/td&gt;&lt;/tr&gt;
+               
&lt;tr&gt;&lt;td&gt;Strawberry&lt;/td&gt;&lt;td&gt;Pink&lt;/td&gt;&lt;td&gt;Smooth&lt;/td&gt;&lt;td&gt;$
 8&lt;/td&gt;&lt;/tr&gt;
+               
&lt;tr&gt;&lt;td&gt;Chocolate&lt;/td&gt;&lt;td&gt;Brown&lt;/td&gt;&lt;td&gt;Chunky&lt;/td&gt;&lt;td&gt;$
 8&lt;/td&gt;&lt;/tr&gt;
+               &lt;tr&gt;&lt;td&gt;Pistachio&lt;/td&gt;&lt;td&gt;Light 
green&lt;/td&gt;&lt;td&gt;Chunky&lt;/td&gt;&lt;td&gt;$ 9&lt;/td&gt;&lt;/tr&gt;
+       &lt;/table&gt;
+&lt;/div&gt;</pre>
+                       </p>
+                       <h3>JavaScript</h3>
+                       <p>
+                               <pre>var o = new WebFXColumnList();
+var rc = o.bind(document.getElementById('container'), 
document.getElementById('head'), document.getElementById('body'));</pre>
+                       </p>
+                       <h3>Result</h3>
+                       <p>
+                               The example code above is actually a shortened 
version of the demo linked below.
+                               Please see that demo for the full source and 
the result.
+                       </p>
+                       <p>
+                               <a href="columnlist.html">Introduction</a><br />
+                               <a 
href="implementation.html">Implementation</a><br />
+                               Usage<br />
+                               <a href="api.html">API</a><br />
+                               <a href="demo.html">Demo</a><br />
+                               <a 
href="http://webfx.eae.net/download/collist103.zip";>Download</a>
+                       </p>
+                       <p class="author">Author: Emil A Eklund</p>
+                       <!-- end webfx-main-body -->
+               </div>
+       </body>
+</html>
Index: sitemgr/js/columnlist/sortabletable.js
diff -u /dev/null sitemgr/js/columnlist/sortabletable.js:1.1.2.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/js/columnlist/sortabletable.js      Mon Mar 27 13:13:24 2006
@@ -0,0 +1,455 @@
+
+/*----------------------------------------------------------------------------\
+|                            Sortable Table 1.12                              |
+|-----------------------------------------------------------------------------|
+|                         Created by Erik Arvidsson                           |
+|                  (http://webfx.eae.net/contact.html#erik)                   |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| A DOM 1 based script that allows an ordinary HTML table to be sortable.     |
+|-----------------------------------------------------------------------------|
+|                  Copyright (c) 1998 - 2004 Erik Arvidsson                   |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including  but not limited  to the warranties of  merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or  copyright  holders be  liable for any claim,  damages or  other |
+| liability, whether  in an  action of  contract, tort  or otherwise, arising |
+| from,  out of  or in  connection with  the software or  the  use  or  other |
+| dealings in the software.                                                   |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This  software is  available under the  three different licenses  mentioned |
+| below.  To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License          http://webfx.eae.net/license.html |
+| Permits  anyone the right to use the  software in a  non-commercial context |
+| free of charge.                                                             |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license           http://webfx.eae.net/commercial.html |
+| Permits the  license holder the right to use  the software in a  commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of  implementations of the licensed software.                    |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License    http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper  credits are given  and the original  and modified source |
+| code are included. Requires  that the final product, software derivate from |
+| the original  source or any  software  utilizing a GPL  component, such  as |
+| this, is also licensed under the GPL license.                               |
+|-----------------------------------------------------------------------------|
+| 2003-01-10 | First version                                                  |
+| 2003-01-19 | Minor changes to the date parsing                              |
+| 2003-01-28 | JScript 5.0 fixes (no support for 'in' operator)               |
+| 2003-02-01 | Sloppy typo like error fixed in getInnerText                   |
+| 2003-07-04 | Added workaround for IE cellIndex bug.                         |
+| 2003-11-09 | The bDescending argument to sort was not correctly working     |
+|            | Using onclick DOM0 event if no support for addEventListener    |
+|            | or attachEvent                                                 |
+| 2004-01-13 | Adding addSortType and removeSortType which makes it a lot     |
+|            | easier to add new, custom sort types.                          |
+| 2004-01-27 | Switch to use descending = false as the default sort order.    |
+|            | Change defaultDescending to suit your needs.                   |
+| 2004-03-14 | Improved sort type None look and feel a bit                    |
+| 2004-08-26 | Made the handling of tBody and tHead more flexible. Now you    |
+|            | can use another tHead or no tHead, and you can chose some      |
+|            | other tBody.                                                   |
+|-----------------------------------------------------------------------------|
+| Created 2003-01-10 | All changes are in the log above. | Updated 2004-08-26 |
+\----------------------------------------------------------------------------*/
+
+
+function SortableTable(oTable, oSortTypes) {
+
+       this._sortTypes = oSortTypes || [];
+
+       this.sortColumn = null;
+       this.descending = null;
+
+       var oThis = this;
+       this._headerOnclick = function (e) {
+               oThis.headerOnclick(e);
+       };
+
+       if (oTable) {
+               this.setTable( oTable );
+               this.document = oTable.ownerDocument || oTable.document;
+       }
+       else {
+               this.document = document;
+       }
+
+
+       // only IE needs this
+       var win = this.document.defaultView || this.document.parentWindow;
+       this._onunload = function () {
+               oThis.destroy();
+       };
+       if (win && typeof win.attachEvent != "undefined") {
+               win.attachEvent("onunload", this._onunload);
+       }
+}
+
+SortableTable.gecko = navigator.product == "Gecko";
+SortableTable.msie = /msie/i.test(navigator.userAgent);
+// Mozilla is faster when doing the DOM manipulations on
+// an orphaned element. MSIE is not
+SortableTable.removeBeforeSort = SortableTable.gecko;
+
+SortableTable.prototype.onsort = function () {};
+
+// default sort order. true -> descending, false -> ascending
+SortableTable.prototype.defaultDescending = false;
+
+// shared between all instances. This is intentional to allow external files
+// to modify the prototype
+SortableTable.prototype._sortTypeInfo = {};
+
+SortableTable.prototype.setTable = function (oTable) {
+       if ( this.tHead )
+               this.uninitHeader();
+       this.element = oTable;
+       this.setTHead( oTable.tHead );
+       this.setTBody( oTable.tBodies[0] );
+};
+
+SortableTable.prototype.setTHead = function (oTHead) {
+       if (this.tHead && this.tHead != oTHead )
+               this.uninitHeader();
+       this.tHead = oTHead;
+       this.initHeader( this._sortTypes );
+};
+
+SortableTable.prototype.setTBody = function (oTBody) {
+       this.tBody = oTBody;
+};
+
+SortableTable.prototype.setSortTypes = function ( oSortTypes ) {
+       if ( this.tHead )
+               this.uninitHeader();
+       this._sortTypes = oSortTypes || [];
+       if ( this.tHead )
+               this.initHeader( this._sortTypes );
+};
+
+// adds arrow containers and events
+// also binds sort type to the header cells so that reordering columns does
+// not break the sort types
+SortableTable.prototype.initHeader = function (oSortTypes) {
+       if (!this.tHead) return;
+       var cells = this.tHead.rows[0].cells;
+       var doc = this.tHead.ownerDocument || this.tHead.document;
+       this._sortTypes = oSortTypes || [];
+       var l = cells.length;
+       var img, c;
+       for (var i = 0; i < l; i++) {
+               c = cells[i];
+               if (this._sortTypes[i] != null && this._sortTypes[i] != "None") 
{
+                       img = doc.createElement("IMG");
+                       img.src = "images/blank.png";
+                       c.appendChild(img);
+                       if (this._sortTypes[i] != null)
+                               c._sortType = this._sortTypes[i];
+                       if (typeof c.addEventListener != "undefined")
+                               c.addEventListener("click", 
this._headerOnclick, false);
+                       else if (typeof c.attachEvent != "undefined")
+                               c.attachEvent("onclick", this._headerOnclick);
+                       else
+                               c.onclick = this._headerOnclick;
+               }
+               else
+               {
+                       c.setAttribute( "_sortType", oSortTypes[i] );
+                       c._sortType = "None";
+               }
+       }
+       this.updateHeaderArrows();
+};
+
+// remove arrows and events
+SortableTable.prototype.uninitHeader = function () {
+       if (!this.tHead) return;
+       var cells = this.tHead.rows[0].cells;
+       var l = cells.length;
+       var c;
+       for (var i = 0; i < l; i++) {
+               c = cells[i];
+               if (c._sortType != null && c._sortType != "None") {
+                       c.removeChild(c.lastChild);
+                       if (typeof c.removeEventListener != "undefined")
+                               c.removeEventListener("click", 
this._headerOnclick, false);
+                       else if (typeof c.detachEvent != "undefined")
+                               c.detachEvent("onclick", this._headerOnclick);
+                       c._sortType = null;
+                       c.removeAttribute( "_sortType" );
+               }
+       }
+};
+
+SortableTable.prototype.updateHeaderArrows = function () {
+       if (!this.tHead) return;
+       var cells = this.tHead.rows[0].cells;
+       var l = cells.length;
+       var img;
+       for (var i = 0; i < l; i++) {
+               if (cells[i]._sortType != null && cells[i]._sortType != "None") 
{
+                       img = cells[i].lastChild;
+                       if (i == this.sortColumn)
+                               img.className = "sort-arrow " + 
(this.descending ? "descending" : "ascending");
+                       else
+                               img.className = "sort-arrow";
+               }
+       }
+};
+
+SortableTable.prototype.headerOnclick = function (e) {
+       // find TD element
+       var el = e.target || e.srcElement;
+       while (el.tagName != "TD")
+               el = el.parentNode;
+
+       this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : 
el.cellIndex);
+};
+
+// IE returns wrong cellIndex when columns are hidden
+SortableTable.getCellIndex = function (oTd) {
+       var cells = oTd.parentNode.childNodes
+       var l = cells.length;
+       var i;
+       for (i = 0; cells[i] != oTd && i < l; i++)
+               ;
+       return i;
+};
+
+SortableTable.prototype.getSortType = function (nColumn) {
+       return this._sortTypes[nColumn] || "String";
+};
+
+// only nColumn is required
+// if bDescending is left out the old value is taken into account
+// if sSortType is left out the sort type is found from the sortTypes array
+
+SortableTable.prototype.sort = function (nColumn, bDescending, sSortType) {
+       if (!this.tBody) return;
+       if (sSortType == null)
+               sSortType = this.getSortType(nColumn);
+
+       // exit if None
+       if (sSortType == "None")
+               return;
+
+       if (bDescending == null) {
+               if (this.sortColumn != nColumn)
+                       this.descending = this.defaultDescending;
+               else
+                       this.descending = !this.descending;
+       }
+       else
+               this.descending = bDescending;
+
+       this.sortColumn = nColumn;
+
+       if (typeof this.onbeforesort == "function")
+               this.onbeforesort();
+
+       var f = this.getSortFunction(sSortType, nColumn);
+       var a = this.getCache(sSortType, nColumn);
+       var tBody = this.tBody;
+
+       a.sort(f);
+
+       if (this.descending)
+               a.reverse();
+
+       if (SortableTable.removeBeforeSort) {
+               // remove from doc
+               var nextSibling = tBody.nextSibling;
+               var p = tBody.parentNode;
+               p.removeChild(tBody);
+       }
+
+       // insert in the new order
+       var l = a.length;
+       for (var i = 0; i < l; i++)
+               tBody.appendChild(a[i].element);
+
+       if (SortableTable.removeBeforeSort) {
+               // insert into doc
+               p.insertBefore(tBody, nextSibling);
+       }
+
+       this.updateHeaderArrows();
+
+       this.destroyCache(a);
+
+       if (typeof this.onsort == "function")
+               this.onsort();
+};
+
+SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) 
{
+       var oThis = this;
+       this._asyncsort = function () {
+               oThis.sort(nColumn, bDescending, sSortType);
+       };
+       window.setTimeout(this._asyncsort, 1);
+};
+
+SortableTable.prototype.getCache = function (sType, nColumn) {
+       if (!this.tBody) return [];
+       var rows = this.tBody.rows;
+       var l = rows.length;
+       var a = new Array(l);
+       var r;
+       for (var i = 0; i < l; i++) {
+               r = rows[i];
+               a[i] = {
+                       value:          this.getRowValue(r, sType, nColumn),
+                       element:        r
+               };
+       };
+       return a;
+};
+
+SortableTable.prototype.destroyCache = function (oArray) {
+       var l = oArray.length;
+       for (var i = 0; i < l; i++) {
+               oArray[i].value = null;
+               oArray[i].element = null;
+               oArray[i] = null;
+       }
+};
+
+SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
+       // if we have defined a custom getRowValue use that
+       if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
+               return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);
+
+       var s;
+       var c = oRow.cells[nColumn];
+       if (typeof c.innerText != "undefined")
+               s = c.innerText;
+       else
+               s = SortableTable.getInnerText(c);
+       return this.getValueFromString(s, sType);
+};
+
+SortableTable.getInnerText = function (oNode) {
+       var s = "";
+       var cs = oNode.childNodes;
+       var l = cs.length;
+       for (var i = 0; i < l; i++) {
+               switch (cs[i].nodeType) {
+                       case 1: //ELEMENT_NODE
+                               s += SortableTable.getInnerText(cs[i]);
+                               break;
+                       case 3: //TEXT_NODE
+                               s += cs[i].nodeValue;
+                               break;
+               }
+       }
+       return s;
+};
+
+SortableTable.prototype.getValueFromString = function (sText, sType) {
+       if (this._sortTypeInfo[sType])
+               return this._sortTypeInfo[sType].getValueFromString( sText );
+       return sText;
+       /*
+       switch (sType) {
+               case "Number":
+                       return Number(sText);
+               case "CaseInsensitiveString":
+                       return sText.toUpperCase();
+               case "Date":
+                       var parts = sText.split("-");
+                       var d = new Date(0);
+                       d.setFullYear(parts[0]);
+                       d.setDate(parts[2]);
+                       d.setMonth(parts[1] - 1);
+                       return d.valueOf();
+       }
+       return sText;
+       */
+       };
+
+SortableTable.prototype.getSortFunction = function (sType, nColumn) {
+       if (this._sortTypeInfo[sType])
+               return this._sortTypeInfo[sType].compare;
+       return SortableTable.basicCompare;
+};
+
+SortableTable.prototype.destroy = function () {
+       this.uninitHeader();
+       var win = this.document.parentWindow;
+       if (win && typeof win.detachEvent != "undefined") {     // only IE 
needs this
+               win.detachEvent("onunload", this._onunload);
+       }
+       this._onunload = null;
+       this.element = null;
+       this.tHead = null;
+       this.tBody = null;
+       this.document = null;
+       this._headerOnclick = null;
+       this.sortTypes = null;
+       this._asyncsort = null;
+       this.onsort = null;
+};
+
+// Adds a sort type to all instance of SortableTable
+// sType : String - the identifier of the sort type
+// fGetValueFromString : function ( s : string ) : T - A function that takes a
+//    string and casts it to a desired format. If left out the string is just
+//    returned
+// fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort
+//    compare function. Takes two values and compares them. If left out less 
than,
+//    <, compare is used
+// fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A 
function
+//    that takes the row and the column index and returns the value used to 
compare.
+//    If left out then the innerText is first taken for the cell and then the
+//    fGetValueFromString is used to convert that string the desired value and 
type
+
+SortableTable.prototype.addSortType = function (sType, fGetValueFromString, 
fCompareFunction, fGetRowValue) {
+       this._sortTypeInfo[sType] = {
+               type:                           sType,
+               getValueFromString:     fGetValueFromString || 
SortableTable.idFunction,
+               compare:                        fCompareFunction || 
SortableTable.basicCompare,
+               getRowValue:            fGetRowValue
+       };
+};
+
+// this removes the sort type from all instances of SortableTable
+SortableTable.prototype.removeSortType = function (sType) {
+       delete this._sortTypeInfo[sType];
+};
+
+SortableTable.basicCompare = function compare(n1, n2) {
+       if (n1.value < n2.value)
+               return -1;
+       if (n2.value < n1.value)
+               return 1;
+       return 0;
+};
+
+SortableTable.idFunction = function (x) {
+       return x;
+};
+
+SortableTable.toUpperCase = function (s) {
+       return s.toUpperCase();
+};
+
+SortableTable.toDate = function (s) {
+       var parts = s.split("-");
+       var d = new Date(0);
+       d.setFullYear(parts[0]);
+       d.setDate(parts[2]);
+       d.setMonth(parts[1] - 1);
+       return d.valueOf();
+};
+
+
+// add sort types
+SortableTable.prototype.addSortType("Number", Number);
+SortableTable.prototype.addSortType("CaseInsensitiveString", 
SortableTable.toUpperCase);
+SortableTable.prototype.addSortType("Date", SortableTable.toDate);
+SortableTable.prototype.addSortType("String");
+// None is a special case
Index: sitemgr/modules/class.module_html.inc.php
diff -u sitemgr/modules/class.module_html.inc.php:1.1.2.2.4.1 
sitemgr/modules/class.module_html.inc.php:1.1.2.2.4.2
--- sitemgr/modules/class.module_html.inc.php:1.1.2.2.4.1       Sat Nov 12 
14:11:58 2005
+++ sitemgr/modules/class.module_html.inc.php   Mon Mar 27 13:13:24 2006
@@ -10,7 +10,7 @@
                                        'type' => 'richtext', //'textarea', 
                                        'label' => lang('Enter the block 
content here'), 
                                        'i18n' => True,
-                                       'params' => array('width' => 650, 
'height' => 250)
+                                       'params' => array('cols' => 80, 'rows' 
=> 20)
                                )
                        );
                        $this->properties = array('striphtml' => array('type' 
=> 'checkbox', 'label' => lang('Strip HTML from block content?')));
Index: sitemgr/setup/setup.inc.php
diff -u sitemgr/setup/setup.inc.php:1.12.2.2.4.2 
sitemgr/setup/setup.inc.php:1.12.2.2.4.3
--- sitemgr/setup/setup.inc.php:1.12.2.2.4.2    Sat Nov 12 14:11:58 2005
+++ sitemgr/setup/setup.inc.php Mon Mar 27 13:13:24 2006
@@ -9,11 +9,11 @@
        *  option) any later version.                                           
   *
        
\**************************************************************************/
 
-       /* $Id: setup.inc.php,v 1.12.2.2.4.2 2005/11/12 14:11:58 skwashd Exp $ 
*/
+       /* $Id: setup.inc.php,v 1.12.2.2.4.3 2006/03/27 13:13:24 skwashd Exp $ 
*/
 
        $setup_info['sitemgr']['name']      = 'sitemgr';
        $setup_info['sitemgr']['title']     = 'SiteMgr Web Content Manager';
-       $setup_info['sitemgr']['version']   = '0.9.16.000';
+       $setup_info['sitemgr']['version']   = '0.9.16.001';
        $setup_info['sitemgr']['app_order'] = 8;
        $setup_info['sitemgr']['tables']    = 
array('phpgw_sitemgr_pages','phpgw_sitemgr_pages_lang','phpgw_sitemgr_categories_state','phpgw_sitemgr_categories_lang','phpgw_sitemgr_modules','phpgw_sitemgr_blocks','phpgw_sitemgr_blocks_lang','phpgw_sitemgr_content','phpgw_sitemgr_content_lang','phpgw_sitemgr_active_modules','phpgw_sitemgr_properties','phpgw_sitemgr_sites');
        $setup_info['sitemgr']['enable']    = 1;
@@ -38,4 +38,4 @@
                                                        'appname'       => 
'news_admin',
                                                        'versions'      => 
array('0.9.17')
                                                );
-?>
+
Index: sitemgr/setup/tables_current.inc.php
diff -u sitemgr/setup/tables_current.inc.php:1.11.2.1.4.1 
sitemgr/setup/tables_current.inc.php:1.11.2.1.4.2
--- sitemgr/setup/tables_current.inc.php:1.11.2.1.4.1   Sat Nov 12 13:15:38 2005
+++ sitemgr/setup/tables_current.inc.php        Mon Mar 27 13:13:24 2006
@@ -9,7 +9,7 @@
        *  option) any later version.                                           
   *
        
\**************************************************************************/
 
-       /* $Id: tables_current.inc.php,v 1.11.2.1.4.1 2005/11/12 13:15:38 
skwashd Exp $ */
+       /* $Id: tables_current.inc.php,v 1.11.2.1.4.2 2006/03/27 13:13:24 
skwashd Exp $ */
 
        $phpgw_baseline = array(
                'phpgw_sitemgr_pages' => array(
@@ -42,7 +42,8 @@
                        'fd' => array(
                                'cat_id' => array('type' => 'int','precision' 
=> '4','nullable' => False),
                                'state' => array('type' => 'int','precision' => 
'2','nullable' => False),
-                               'def_page' => array('type' => 'int','precision' 
=> '4','nullable' => False,'default' => '0')
+                               'def_page' => array('type' => 'int','precision' 
=> '4','nullable' => False,'default' => '0'),
+                               'template_set' => array('type' => 
'varchar','precision' => '50','nullable' => True)
                        ),
                        'pk' => array('cat_id'),
                        'fk' => array(),
Index: sitemgr/setup/tables_update.inc.php
diff -u sitemgr/setup/tables_update.inc.php:1.11.2.4.4.1 
sitemgr/setup/tables_update.inc.php:1.11.2.4.4.2
--- sitemgr/setup/tables_update.inc.php:1.11.2.4.4.1    Sat Nov 12 13:15:38 2005
+++ sitemgr/setup/tables_update.inc.php Mon Mar 27 13:13:24 2006
@@ -9,7 +9,7 @@
        *  option) any later version.                                           
   *
        
\**************************************************************************/
 
-       /* $Id: tables_update.inc.php,v 1.11.2.4.4.1 2005/11/12 13:15:38 
skwashd Exp $ */
+       /* $Id: tables_update.inc.php,v 1.11.2.4.4.2 2006/03/27 13:13:24 
skwashd Exp $ */
 
        $test[] = '0.9.13.001';
        function sitemgr_upgrade0_9_13_001()
@@ -655,4 +655,19 @@
                $GLOBALS['setup_info']['sitemgr']['currentver'] = '0.9.16.000';
                return $GLOBALS['setup_info']['sitemgr']['currentver'];
        }
+
+
+       $test[] = '0.9.16.000';
+       function sitemgr_upgrade0_9_16_000()
+       {
+               
$GLOBALS['phpgw_setup']->oProc->AddColumn('phpgw_sitemgr_categories_state','template_set',array(
+                       'type' => 'varchar',
+                       'precision' => '50',
+                       'nullable' => True
+               ));
+
+
+               $GLOBALS['setup_info']['sitemgr']['currentver'] = '0.9.16.001';
+               return $GLOBALS['setup_info']['sitemgr']['currentver'];
+       }
 ?>
Index: sitemgr/sitemgr-site/inc/class.sitebo.inc.php
diff -u /dev/null sitemgr/sitemgr-site/inc/class.sitebo.inc.php:1.1.2.3.4.1
--- /dev/null   Mon Mar 27 13:13:25 2006
+++ sitemgr/sitemgr-site/inc/class.sitebo.inc.php       Mon Mar 27 13:13:24 2006
@@ -0,0 +1,359 @@
+<?php
+       
/*************************************************************************\
+       * phpGroupWare - Web Content Manager                                    
  *
+       * http://www.phpgroupware.org                                           
  *
+       * -------------------------------------------------                     
  *
+       * This program 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 2 of the License, or (at 
your  *
+       * option) any later version.                                            
  *
+       
\*************************************************************************/
+       /* $Id: class.sitebo.inc.php,v 1.1.2.3.4.1 2006/03/27 13:13:24 skwashd 
Exp $ */
+
+       class sitebo
+       {
+               var $pages_bo;
+               var $catbo;
+               var $acl;
+
+               function sitebo()
+               {
+                       $this->catbo = &$GLOBALS['Common_BO']->cats;
+                       $this->pages_bo = &$GLOBALS['Common_BO']->pages;
+                       $this->acl = &$GLOBALS['Common_BO']->acl;
+                       $this->isadmin = $this->acl->is_admin;
+                       //$anonymous_user is globally set in config.inc.php
+                       $this->isuser = 
($GLOBALS['phpgw_info']['user']['account_lid'] != $GLOBALS['anonymous_user']);
+               }
+
+               function getcatwrapper($cat_id)
+               {
+                       $availablelangsforcat = 
$this->catbo->getlangarrayforcategory($cat_id);
+                       if 
(in_array($GLOBALS['sitemgr_info']['userlang'],$availablelangsforcat))
+                       {
+                               return 
$this->catbo->getCategory($cat_id,$GLOBALS['sitemgr_info']['userlang']);
+                       }
+                       else
+                       {
+                               foreach 
($GLOBALS['sitemgr_info']['sitelanguages'] as $lang)
+                               {
+                                       if 
(in_array($lang,$availablelangsforcat))
+                                       {
+                                               return 
$this->catbo->getCategory($cat_id,$lang);
+                                       }
+                               }
+                       }
+                       //fall back to a category in "default" lang
+                       return $this->catbo->getCategory($cat_id);
+               }
+
+               function getpagewrapper($page_id)
+               {
+                       $availablelangsforpage = 
$this->pages_bo->getlangarrayforpage($page_id);
+                       if 
(in_array($GLOBALS['sitemgr_info']['userlang'],$availablelangsforpage))
+                       {
+                               return 
$this->pages_bo->GetPage($page_id,$GLOBALS['sitemgr_info']['userlang']);
+                       }
+                       else
+                       {
+                               foreach 
($GLOBALS['sitemgr_info']['sitelanguages'] as $lang)
+                               {
+                                       if 
(in_array($lang,$availablelangsforpage))
+                                       {
+                                               return 
$this->pages_bo->GetPage($page_id,$lang);
+                                       }
+                               }
+                       }
+                       //fall back to a page in "default" lang
+                       return $this->pages_bo->GetPage($page_id);
+               }
+
+               function get_themesel()
+               {
+                       $theme = $sitemgr_info['themesel'];
+                       
+                       if ( isset($_GET['page_name']) && $_GET['page_name'] )
+                       {
+                               $page = 
$GLOBALS['Common_BO']->pages->getPage($GLOBALS['Common_BO']->pages->so->PageToID($_GET['page_name'])
 );
+                               if ( isset($page->cat_id) && $page->cat_id )
+                               {
+                                       $cat = 
$GLOBALS['Common_BO']->cats->getCategory($page->cat_id);
+                                       if ( isset($cat->cat_tpl) && 
$cat->cat_tpl )
+                                       {
+                                               return $cat->cat_tpl;
+                                       }
+                               }
+                       }
+                       elseif ( isset($_GET['category_id']) && 
$_GET['category_id'] )
+                       {       
+                               $cat = 
$GLOBALS['Common_BO']->cats->getCategory($_GET['category_id']);
+                               if ( isset($cat->cat_tpl) && $cat->cat_tpl )
+                               {
+                                       return $cat->cat_tpl;
+                               }
+                       }
+                       elseif ( isset($_GET['page_id']) && $_GET['page_id'])
+                       {
+                               $page = 
$GLOBALS['Common_BO']->pages->getPage($_GET['page_id']);
+                               if ( isset($page->cat_id) && $page->cat_id )
+                               {
+                                       $cat = 
$GLOBALS['Common_BO']->cats->getCategory($page->cat_id);
+                                       if ( isset($cat->cat_tpl) && 
$cat->cat_tpl )
+                                       {
+                                               return $cat->cat_tpl;
+                                       }
+                               }
+                       }
+                       elseif (isset($_GET['index']))
+                       {
+                               //do nothing
+                       }
+                       elseif (isset($_GET['toc']))
+                       {
+                               //do nothing
+                       }
+                       else 
+                       {
+                               if ($sitemgr_info['home_page_id'])
+                               {
+                                       $page = 
$GLOBALS['Common_BO']->pages->getPage($sitemgr_info['home_page_id']);
+                                       if ( isset($page->cat_id) && 
$page->cat_id )
+                                       {
+                                               $cat = 
$GLOBALS['Common_BO']->cats->getCategory($page->cat_id);
+                                               if ( isset($cat->cat_tpl) && 
$cat->cat_tpl )
+                                               {
+                                                       return $cat->cat_tpl;
+                                               }
+                                       }
+                               }
+                       }
+                       return $theme;
+               }
+
+               function loadPage($page_id)
+               {
+                       global $page;
+                       $page = $this->getpagewrapper($page_id);
+               }
+
+               function loadIndex()
+               {
+                       global $page;
+                       $page->title = lang('Site Index');
+                       $page->subtitle = '';
+                       $page->index = True;
+                       $page->block = CreateObject('sitemgr.Block_SO',True);
+                       $page->block->module_name = 'index';
+                       $page->block->module_id = 
$GLOBALS['Common_BO']->modules->getmoduleid('index');
+                       $page->block->view = SITEMGR_VIEWABLE_EVERBODY;
+                       $page->block->status = SITEMGR_STATE_PUBLISH;
+                       $page->cat_id = 
$GLOBALS['Common_BO']->current_site['site_id'];
+                       return true;
+               }
+
+               function getIndex($showhidden=true, $rootonly=false)
+               {
+                       $cats = $this->getCatLinks(0,!$rootonly);
+                       $index = array();
+
+                       if (count($cats)>0)
+                       {
+                               reset($cats);
+                               $content = "\n".'<ul>';
+                               while(list($cat_id,$cat) = each($cats))
+                               {
+                                       $pages = 
$this->getPageLinks($cat_id,$showhidden);
+                                       if (count($pages)>0)
+                                       {
+                                               foreach($pages as $link)
+                                               {
+                                                       $index[] = array(
+                                                               
'catname'=>$cat['name'],
+                                                               
'catdepth'=>$cat['depth'],
+                                                               
'catlink'=>$cat['link'],
+                                                               
'catdescrip'=>$cat['description'],
+                                                               
'pagename'=>$link['name'],
+                                                               
'pagelink'=>$link['link'],
+                                                               
'pagetitle'=>$link['title'],
+                                                               
'pagesubtitle'=>$link['subtitle']
+                                                       );
+                                               }
+                                       }
+                                       else
+                                       {
+                                               $index[] = array(
+                                                       'catname'=>$cat['name'],
+                                                       
'catdepth'=>$cat['depth'],
+                                                       
'catdescrip'=>$cat['description'],
+                                                       'catlink'=>$cat['link'],
+                                                       'pagelink'=>lang('No 
pages available')
+                                               );
+                                       }
+                               }
+                       }
+                       return $index;
+               }
+
+               function loadTOC($category_id=false)
+               {
+                       global $page;
+
+                       $page->title = lang('Table of Contents');
+                       $page->subtitle = '';
+                       $page->toc = True;
+                       $page->cat_id = $category_id ? $category_id : 
CURRENT_SITE_ID;
+                       $page->block = CreateObject('sitemgr.Block_SO',True);
+                       $page->block->module_name = 'toc';
+                       $page->block->arguments = array('category_id' => 
$category_id);
+                       $page->block->module_id = 
$GLOBALS['Common_BO']->modules->getmoduleid('toc');
+                       $page->block->view = SITEMGR_VIEWABLE_EVERBODY;
+                       $page->block->state = SITEMGR_STATE_PUBLISH;
+                       return true;
+               }
+
+               function getPageLinks($category_id, $showhidden=true)
+               {
+                       $pages=$this->pages_bo->getPageIDList($category_id);
+                       foreach($pages as $page_id)
+                       {
+                               $page=$this->getpagewrapper($page_id);
+                               if ($showhidden || !$page->hidden)
+                               {
+                                       $pglinks[$page_id] = array(
+                                               'name'=>$page->name,
+                                               'link'=>'<a 
href="'.sitemgr_link('page_name='.$page->name).'">'.$page->title.'</a>',
+                                               'title'=>$page->title,
+                                               'subtitle'=>$page->subtitle
+                                       );
+                               }
+                       }
+                       return $pglinks;
+               }
+
+               function getCatLinks($cat_id=0,$recurse=true)
+               {
+                       $catlinks = array();
+                       $cat_list = 
$this->catbo->getpermittedcatsRead($cat_id,$recurse);
+                       foreach($cat_list as $cat_id)
+                       {
+                               $category = $this->getcatwrapper($cat_id);
+                               $catlinks[$cat_id] = array(
+                                       'name'=>$category->name,
+                                       'link'=>'<a 
href="'.sitemgr_link('category_id='.$cat_id).'">'.$category->name.'</a>',
+                                       'description'=>$category->description,
+                                       'depth'=>$category->depth
+                               );
+                       }
+                       return $catlinks;
+               }
+
+               //like $GLOBALS['phpgw']->common->getPreferredLanguage,
+               //but compares languages accepted by the user 
+               //to the languages the website is configured for
+               //instead of the languages installed in phpgroupware
+               function setsitemgrPreferredLanguage()
+               {
+                       //since there are lang calls in the API, and the first 
lang call builds $GLOBAL['lang'], wet have to unset it, if
+                       //the change of 
$GLOBALS['phpgw_info']['user']['preferences']['common']['lang'] should have any 
effect.
+                       //is there a more efficient way to do the same thing?
+                       unset($GLOBALS['lang']);
+                       $supportedLanguages = 
$GLOBALS['sitemgr_info']['sitelanguages'] ? 
$GLOBALS['sitemgr_info']['sitelanguages'] : array('en');
+                       $postlang = trim($_GET['lang']);
+                       if ($postlang && 
in_array($postlang,$supportedLanguages))
+                       {
+                               
$GLOBALS['phpgw_info']['user']['preferences']['common']['lang'] = $postlang;
+                               $GLOBALS['sitemgr_info']['userlang'] = 
$postlang;
+                               
$GLOBALS['phpgw']->session->appsession('language','sitemgr-site',$postlang);
+                               return;
+                       }
+               
+                       $sessionlang = 
$GLOBALS['phpgw']->session->appsession('language','sitemgr-site');
+                       if ($sessionlang)
+                       {
+                               
$GLOBALS['phpgw_info']['user']['preferences']['common']['lang'] = $sessionlang;
+                               $GLOBALS['sitemgr_info']['userlang'] = 
$sessionlang;
+                               return;
+                       }
+
+                       $client_langs = split('[,;]', 
$_SERVER['HTTP_ACCEPT_LANGUAGE']);
+                       if(is_array($client_langs))
+                       {
+                               foreach($client_langs as $lang)
+                               {
+                                       if(strlen($lang) != 2)
+                                       {
+                                               list($lang) = explode('-', 
$lang);
+                                       }
+                                       if(in_array($lang, $supportedLanguages))
+                                       {
+                                               
$GLOBALS['phpgw_info']['user']['preferences']['common']['lang'] = $lang;
+                                               
$GLOBALS['sitemgr_info']['userlang'] = $lang;
+                                               
$GLOBALS['phpgw']->session->appsession('language','sitemgr-site',$lang);
+                                               return;
+                                       }
+                               }
+                       }
+                       
+                       if ($this->isuser)
+                       {
+                               $userlang = 
$GLOBALS['phpgw_info']['user']['preferences']['common']['lang'];
+                               if (in_array($userlang,$supportedLanguages))
+                               {
+                               //we do not touch 
$GLOBALS['phpgw_info']['user']['preferences']['common']['lang'] if
+                               //the user is registered and his lang 
preference is supported by the website,
+                               //but save it to the appsession for quicker 
retrieval
+                               
$GLOBALS['phpgw']->session->appsession('language','sitemgr-site',$userlang);
+                               $GLOBALS['sitemgr_info']['userlang'] = 
$userlang;
+                       return;
+                               }
+                       }
+                               
+                       // create a array of languages the user is accepting
+                       $userLanguages = 
explode(',',$GLOBALS['HTTP_ACCEPT_LANGUAGE']);
+               
+                       // find usersupported language
+                       while (list($key,$value) = each($userLanguages))
+                       {
+                               // remove everything behind '-' example: de-de
+                               $value = trim($value);
+                               $pieces = explode('-', $value);
+                               $value = $pieces[0];
+                               //print "current lang $value<br>";
+                               if (in_array($value,$supportedLanguages))
+                               {
+                                       $browserlang = $value;
+                                       break;
+                               }
+                       }
+
+                       // no usersupported language found -> return the first 
entry of sitelanguages
+                       if (empty($browserlang))
+                       {
+                               $browserlang = $supportedLanguages[0];
+                       }
+               
+                       
$GLOBALS['phpgw_info']['user']['preferences']['common']['lang'] = $browserlang;
+                       $GLOBALS['sitemgr_info']['userlang'] = $browserlang;
+                       
$GLOBALS['phpgw']->session->appsession('language','sitemgr-site',$browserlang);
+               }
+
+               function getmode()
+               {
+                       if ($this->isuser)
+                       {
+                               $postmode = $_GET['administration']['mode'];
+                               if ($postmode)
+                               {
+                                       
$GLOBALS['phpgw']->session->appsession('mode','sitemgr-site',$postmode);
+                                       return $postmode;
+                               }
+                               $sessionmode = 
$GLOBALS['phpgw']->session->appsession('mode','sitemgr-site');
+                               if($sessionmode)
+                               {
+                                       return $sessionmode;
+                               }
+                       }
+                       return 'Production';
+               }
+       }
+?>
Index: sitemgr/sitemgr-site/index.php
diff -u sitemgr/sitemgr-site/index.php:1.7.2.2.4.1 
sitemgr/sitemgr-site/index.php:1.7.2.2.4.2
--- sitemgr/sitemgr-site/index.php:1.7.2.2.4.1  Sat Nov 12 13:15:38 2005
+++ sitemgr/sitemgr-site/index.php      Mon Mar 27 13:13:24 2006
@@ -8,7 +8,7 @@
        *  Free Software Foundation; either version 2 of the License, or (at 
your  *
        *  option) any later version.                                           
   *
        
\**************************************************************************/
-       /* $Id: index.php,v 1.7.2.2.4.1 2005/11/12 13:15:38 skwashd Exp $ */
+       /* $Id: index.php,v 1.7.2.2.4.2 2006/03/27 13:13:24 skwashd Exp $ */
 
        $GLOBALS['phpgw_info']['flags'] = array
        (
@@ -43,6 +43,7 @@
        $sitemgr_info = 
array_merge($sitemgr_info,$Common_BO->sites->current_site);
        $sitemgr_info['sitelanguages'] = 
explode(',',$sitemgr_info['site_languages']);
        $objbo->setsitemgrPreferredLanguage();
+       $sitemgr_info['themesel'] = $objbo->get_themesel();
        $objui = new ui;
 
        $page = CreateObject('sitemgr.Page_SO');
@@ -52,7 +53,7 @@
                $objui->displayPageByName($_GET['page_name']);
        }
        elseif ( isset($_GET['category_id']) && $_GET['category_id'] )
-       {
+       {       
                $cat = $Common_BO->cats->getCategory($_GET['category_id']);
                if ( isset($cat->def_page) && $cat->def_page )
                {
@@ -89,6 +90,7 @@
                        $objui->displayIndex();
                }
        }
+
        if (DEBUG_TIMER)
        {
                $GLOBALS['debug_timer_stop'] = perfgetmicrotime();
Index: sitemgr/templates/default/edit_category.tpl
diff -u sitemgr/templates/default/edit_category.tpl:1.6.2.2.4.1 
sitemgr/templates/default/edit_category.tpl:1.6.2.2.4.2
--- sitemgr/templates/default/edit_category.tpl:1.6.2.2.4.1     Sat Nov 12 
13:15:38 2005
+++ sitemgr/templates/default/edit_category.tpl Mon Mar 27 13:13:24 2006
@@ -1,98 +1,158 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
 <html>
-<head></head>
-<body>
-<form method="post">
-<input type="hidden" name="inputcatid" value="{cat_id}" />
-<input type="hidden" name="inputparentold" value="{old_parent}" />
-<table align="center" border ="0" width="80%" cellpadding="5" cellspacing="0">
-       <tr>
-               <td align="center" colspan="2"><u><b>{add_edit}</b></u></td>
-       </tr>
-       <tr>
-               <td align="center" colspan="2"><font size="2" 
color="#FF0000"><b>&nbsp;{message}</b></font></td>
-       </tr>
-       <tr>
-               <td colspan="2"><b><u>{lang_basic}:</u></b></td>
-       </tr>
-       <tr>
-               <td>{lang_catname}:</td>
-               <td><input type="text" name="inputcatname" 
value="{catname}"></td>
-       </tr>
-       <tr>
-               <td>{lang_catsort}:</td>
-               <td><input type="text" name="inputsortorder" 
value="{sort_order}"></td>
-       </tr>
-       <tr>
-               <td>{lang_catparent}:</td>
-               <td>{parent_dropdown}</td>
-       </tr>
-       <tr>
-               <td>{lang_catdesc}:</td>
-               <td><textarea ROWS="3" COLS="50" 
name="inputcatdesc">{catdesc}</textarea></td>
-       </tr>   
-       <tr>
-               <td>{lang_state}:</td>
-               <td><select name="inputstate">{stateselect}</select></td>
-       </tr>
-       <tr>
-               <td>{lang_default_page}:</td>
-               <td><select name="def_page">{def_page}</select></td>
-       </tr>
-       <tr>
-               <td colspan="2"><input name="inputgetparentpermissions" 
type="checkbox">{lang_getparentpermissions}</td>
-       </tr>
-       <tr>
-               <td colspan="2"><input name="inputapplypermissionstosubs" 
type="checkbox">{lang_applypermissionstosubs}</td>
-       </tr>
-       <tr>
-               <td colspan="2"><b><u>{lang_groupaccess}</u></b></td>
-       </tr>
-       <tr>
-               <td colspan="2">
-                       <table align="center" border="0" width="80%" 
cellpadding="2" cellspacing="2">
-                               <tr>
-                                       <td align="center" 
width="33%"><u>{lang_groupname}</u></td>
-                                       <td align="center" 
width="33%"><u>{lang_readperm}</u></td>
-                                       <td align="center" 
width="33%"><u>{lang_writeperm}</u><br>({lang_implies})</td>
-                               </tr>
-                               <!-- BEGIN GroupBlock -->
-                               <tr>
-                                       <td align="center" bgcolor="dddddd" 
width="33%">{groupname}</td>
-                                       <td align="center" bgcolor="dddddd" 
width="33%"><input type="checkbox" {checkedgroupread} 
name="inputgroupaccessread[i{group_id}][read]" value="checked"></td>
-                                       <td align="center" bgcolor="dddddd" 
width="33%"><input type="checkbox" {checkedgroupwrite} 
name="inputgroupaccesswrite[i{group_id}][write]" value="checked"></td>
-                               </tr>
-                               <!-- END GroupBlock -->
-                       </table>
-               </td>
-       </tr>
-       <tr>
-               <td colspan="2"><b><u>{lang_useraccess}</u></b></td>
-       </tr>
-               <td colspan="2">
-                       <table align="center" border="0" width="80%" 
cellpadding="2" cellspacing="2">
-                               <tr>
-                                       <td align="center" 
width="33%"><u>{lang_username}</u></td>
-                                       <td align="center" 
width="33%"><u>{lang_readperm}</u></td>
-                                       <td align="center" 
width="33%"><u>{lang_writeperm}</u><br>({lang_implies})</td>
-                               </tr>
-                               <!-- BEGIN UserBlock -->
-                               <tr>
-                                       <td bgcolor="dddddd" 
align="center">{username}</td>
-                                       <td bgcolor="dddddd" 
align="center"><input type="checkbox" {checkeduserread} 
name="inputindividualaccessread[i{user_id}][read]" value="checked"></td>
-                                       <td bgcolor="dddddd" 
align="center"><input type="checkbox" {checkeduserwrite} 
name="inputindividualaccesswrite[i{user_id}][write]" value="checked"></td>
-                               </tr>
-                               <!-- END UserBlock -->
-                       </table>
-               </td>
-       </tr>
-       <tr>
-               <td colspan="2" align="center">
-                       <input type="reset" name="reset" value="{lang_reset}">
-                       <input type="submit" name="btnSave" 
value="{lang_save}"> {savelang}
-                       <input type="reset" 
onclick="opener.location.reload();self.close()" value="{lang_done}"  />
-               </td>
-       </tr>
-</table>
-</form>
-</body>
+       <head>
+               <title>{add_edit}</title>
+               <link type="text/css" rel="stylesheet" 
href="sitemgr/js/columnlist/columnlist.css" />
+               <script type="text/javascript" 
src="sitemgr/js/columnlist/sortabletable.js"></script>
+               <script type="text/javascript" 
src="sitemgr/js/columnlist/columnlist.js"></script>
+               <script type="text/javascript">
+
+                       var groupList, groupTbl, userList, userTbl;
+                       window.onload = function(e)
+                       {
+                               groupList = new WebFXColumnList();
+                               groupTbl = 
groupList.bind(document.getElementById('groupcontainer'), 
document.getElementById('grouphead'), document.getElementById('groupbody'));
+
+                               userList = new WebFXColumnList();
+                               userTbl = 
userList.bind(document.getElementById('usercontainer'), 
document.getElementById('userhead'), document.getElementById('userbody'));
+                       }
+               </script>
+               <style type="text/css">
+                       body, div, input, p, select, td, textarea
+                       {
+                               font-family: Arial, Helvetica, sans-serif;
+                               font-size: 12px;
+                       }
+                       
+                       br
+                       {
+                               clear: left;
+                       }
+                       
+                       fieldset input, fieldset label, fieldset select, 
fieldset textarea
+                       {
+                               display: block;
+                               float: left;
+                               margin-bottom: 10px;
+                               width: 250px;
+                       }
+                       
+                       fieldset label
+                       {
+                               display: block;
+                               font-weight: bold;
+                               width: 150px;
+                       }
+               </style>
+       </head>
+       <body>
+               <h1>{add_edit}</h1>
+               <p class="msg">{message}</p>
+                       <form method="post">
+                               
+                               <fieldset>
+                                       <legend>{lang_basic}</legend>
+                                       <label 
for="inputcatname">{lang_catname}:</label>
+                                       <input type="text" id="inputcatname" 
name="inputcatname" value="{catname}" /><br />
+       
+                                       <label 
for="inputsortorder">{lang_catsort}:</label>
+                                       <input type="text" id="inputsortorder" 
name="inputsortorder" value="{sort_order}" /><br />
+       
+                                       <label 
for="inputparent">{lang_catparent}:</label>
+                                       {parent_dropdown}<br />
+       
+                                       <label 
for="inputcatdesc">{lang_catdesc}:</label>
+                                       <textarea rows="3" cols="50" 
id="inputcatdesc" name="inputcatdesc">{catdesc}</textarea><br />
+       
+                                       <label 
for="inputstate">{lang_state}:</label>
+                                       <select id="inputstate" 
name="inputstate">{stateselect}</select><br />
+                                       
+                                       <label 
for="cat_tpl">{lang_cat_tpl}:</label>
+                                       <select id="cat_tpl" 
name="cat_tpl">{cat_tpl}</select><br />
+       
+                                       <label 
for="def_page">{lang_default_page}:</label>
+                                       <select name="def_page" 
id="def_page">{def_page}</select><br />
+                               </fieldset>     
+                               
+                               <h2>{lang_permissions}</h2>
+                               <div id="permission_options">
+                                       <span>{{lang_set_perms}</span>
+                                       <input name="permissions" 
id="permissionsparent" value="parent" type="radio" />
+                                       <label 
for="permissionsparent">{lang_getparentpermissions}</label>
+       
+                                       <input name="permissions" 
id="setpermissions" value="set" type="radio" />
+                                       <label 
for="setpermissions">{lang_applypermissionstosubs}</label><br />
+                               </div>
+
+                               <h3>{lang_groupaccess}</h3>
+                               <div id="groupcontainer" 
class="webfx-columnlist">
+                                       <div id="grouphead" 
class="webfx-columnlist-head">
+                                               <table>
+                                                       <tr>
+                                                               
<td>{lang_groupname}<img src="sitemgr/templates/default/images/asc.png"/></td>
+                                                               <td 
class="permscol">{lang_readperm}<img 
src="sitemgr/templates/default/images/asc.png"/></td>
+                                                               <td 
class="permscol">{lang_writeperm} [<span title="{lang_implies}">?</span>]<img 
src="sitemgr/templates/default/images/asc.png"/></td>
+                                                       </tr>
+                                               </table>
+                                       </div>
+                                       <div id="groupbody" 
class="webfx-columnlist-body">
+                                               <table>
+                                                       <colgroup span="3">
+                                                               <col/>
+                                                               <col/>
+                                                               <col/>
+                                                       </colgroup>
+                                                       <!-- BEGIN GroupBlock 
-->
+                                                       <tr class="row_class">
+                                                               
<td>{groupname}</td>
+                                                               <td 
class="permscol"><input type="checkbox" {checkedgroupread} 
name="inputgroupaccessread[i{group_id}][read]" value="checked" /></td>
+                                                               <td 
class="permscol"><input type="checkbox" {checkedgroupwrite} 
name="inputgroupaccesswrite[i{group_id}][write]" value="checked" /></td>
+                                                       </tr>
+                                                       <!-- END GroupBlock -->
+                                               </table>
+                                       </div>
+                               </div>
+
+                               <h3>{lang_useraccess}</h3>
+                               <div id="usercontainer" 
class="webfx-columnlist">
+                                       <div id="userhead" 
class="webfx-columnlist-head">
+                                               <table>
+                                                       <tr>
+                                                               
<td>{lang_username}<img src="sitemgr/templates/default/images/asc.png"/></td>
+                                                               <td 
class="permscol">{lang_readperm}<img 
src="sitemgr/templates/default/images/asc.png"/></td>
+                                                               <td 
class="permscol">{lang_writeperm} [<span title="{lang_implies}">?</span>]<img 
src="sitemgr/templates/default/images/asc.png"/></td>
+                                                       </tr>
+                                               </table>
+                                       </div>
+                                       <div id="userbody" 
class="webfx-columnlist-body">
+                                               <table>
+                                                       <colgroup span="3">
+                                                               <col/>
+                                                               <col 
class="permscol" />
+                                                               <col 
class="permscol" />
+                                                       </colgroup>
+                                                       <!-- BEGIN UserBlock -->
+                                                       <tr>
+                                                               
<td>{username}</td>
+                                                               <td 
class="permscol"><input type="checkbox" {checkeduserread} 
name="inputindividualaccessread[i{user_id}][read]" value="checked" /></td>
+                                                               <td 
class="permscol"><input type="checkbox" {checkeduserwrite} 
name="inputindividualaccesswrite[i{user_id}][write]" value="checked" /></td>
+                                                       </tr>
+                                                       <!-- END UserBlock -->
+                                               </table>
+                                       </div>
+                               </div>
+                               <div>
+                                       <input type="checkbox" 
name="permissionstosubs" id="permissionstosubs" value="1" />
+                                       <label 
for="permissionstosubs">{lang_applypermissionstosubs}</label><br />
+       
+                                       <input type="hidden" name="inputcatid" 
value="{cat_id}" />
+                                       <input type="hidden" 
name="inputparentold" value="{old_parent}" />
+       
+                                       <input type="reset" name="reset" 
value="{lang_reset}" />
+                                       <input type="submit" name="btnSave" 
value="{lang_save}" /> {savelang}
+                                       <input type="reset" 
onclick="opener.location.reload();self.close()" value="{lang_done}"  />
+                               </div>
+               </form>
+       </body>
 </html>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]