Index: /enpraxis.leftskin/tags/1.1.0/trunk/MANIFEST.in
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/MANIFEST.in	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/MANIFEST.in	(revision 429)
@@ -0,0 +1,2 @@
+recursive-include enpraxis *
+global-exclude *.pyc
Index: /enpraxis.leftskin/tags/1.1.0/trunk/README.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/README.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/README.txt	(revision 429)
@@ -0,0 +1,4 @@
+Introduction
+============
+
+Left Skin is a Plone skin that provides a prominent left column in a three column
Index: /enpraxis.leftskin/tags/1.1.0/trunk/docs/HISTORY.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/docs/HISTORY.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/docs/HISTORY.txt	(revision 429)
@@ -0,0 +1,10 @@
+Changelog
+=========
+
+1.1.0 - Unreleased
+----------------
+
+  * Updated the control panel to use jQuery Color Picker.
+  * Additional control panels to expose all base properties.
+  * Added theming logic to switch between themes.
+  * Back up old themes so that they can be restored. 
Index: /enpraxis.leftskin/tags/1.1.0/trunk/docs/INSTALL.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/docs/INSTALL.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/docs/INSTALL.txt	(revision 429)
@@ -0,0 +1,43 @@
+enpraxis.leftskin Installation
+==========================
+
+To install enpraxis.leftskin into the global Python environment (or a workingenv),
+using a traditional Zope 2 instance, you can do this:
+
+ * When you're reading this you have probably already run 
+   ``easy_install enpraxis.leftskin``. Find out how to install setuptools
+   (and EasyInstall) here:
+   http://peak.telecommunity.com/DevCenter/EasyInstall
+
+ * Create a file called ``enpraxis.leftskin-configure.zcml`` in the
+   ``/path/to/instance/etc/package-includes`` directory.  The file
+   should only contain this::
+
+       <include package="enpraxis.leftskin" />
+
+
+Alternatively, if you are using zc.buildout and the plone.recipe.zope2instance
+recipe to manage your project, you can do this:
+
+ * Add ``enpraxis.leftskin`` to the list of eggs to install, e.g.:
+ 
+    [buildout]
+    ...
+    eggs =
+        ...
+        enpraxis.leftskin
+        
+  * Tell the plone.recipe.zope2instance recipe to install a ZCML slug:
+  
+    [instance]
+    recipe = plone.recipe.zope2instance
+    ...
+    zcml =
+        enpraxis.leftskin
+        
+  * Re-run buildout, e.g. with:
+  
+    $ ./bin/buildout
+        
+You can skip the ZCML slug if you are going to explicitly include the package
+from another package's configure.zcml file.
Index: /enpraxis.leftskin/tags/1.1.0/trunk/docs/LICENSE.GPL
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/docs/LICENSE.GPL	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/docs/LICENSE.GPL	(revision 429)
@@ -0,0 +1,222 @@
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
Index: /enpraxis.leftskin/tags/1.1.0/trunk/docs/LICENSE.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/docs/LICENSE.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/docs/LICENSE.txt	(revision 429)
@@ -0,0 +1,16 @@
+  enpraxis.leftskin is copyright display. It allows the left column to be styled, and retains the ablilty to move
+
+  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.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+  MA 02111-1307 USA.
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/__init__.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/__init__.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/__init__.py	(revision 429)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/README.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/README.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/README.txt	(revision 429)
@@ -0,0 +1,6 @@
+Left Skin 3.0
+-------------
+
+  Left Skin is a Plone skin that provides a prominent left column in a three column
+  display. It allows the left column to be styled, and retains the ablilty to move
+  portlets into and out of it with no additional styling required.
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/__init__.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/__init__.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/__init__.py	(revision 429)
@@ -0,0 +1,31 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from zope.i18nmessageid import MessageFactory
+
+from config import GLOBALS
+from Products.CMFCore.DirectoryView import registerDirectory
+
+leftskinMessageFactory = MessageFactory('leftskin')
+
+registerDirectory('skins', GLOBALS)
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/__init__.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/__init__.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/__init__.py	(revision 429)
@@ -0,0 +1,1 @@
+# Make this directory a product
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/configure.zcml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/configure.zcml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/configure.zcml	(revision 429)
@@ -0,0 +1,96 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:browser="http://namespaces.zope.org/browser"
+   i18n_domain="leftskin">
+  
+  <interface
+     interface=".interfaces.ILeftSkinTheme"
+     type="zope.publisher.interfaces.browser.IBrowserSkinType"
+     name="Left Skin"
+     />
+
+  <browser:viewletManager
+     name="leftskin.contenttop"
+     provides=".interfaces.IContentTop"
+     permission="zope2.View"
+     class="plone.app.viewletmanager.manager.OrderedViewletManager"
+     />
+
+  <browser:viewlet
+     name="leftskin.personal_bar"
+     manager=".interfaces.IContentTop"
+     class=".viewlets.PersonalBarViewlet"
+     permission="zope2.View"
+     layer=".interfaces.ILeftSkinTheme"
+     />
+
+  <browser:viewlet
+     name="plone.app.i18n.locales.languageselector"
+     manager=".interfaces.IContentTop"
+     class="plone.app.i18n.locales.browser.selector.LanguageSelector"
+     permission="zope2.View"
+     layer=".interfaces.ILeftSkinTheme"
+     />
+
+  <browser:viewlet
+     name="plone.path_bar"
+     manager=".interfaces.IContentTop"
+     class="plone.app.layout.viewlets.common.PathBarViewlet"
+     permission="zope2.View"
+     layer=".interfaces.ILeftSkinTheme"
+     />
+
+  <utility
+     provides="zope.schema.interfaces.IVocabularyFactory"
+     component=".controlpaneladv.fontfamilies_vocab"
+     name="leftskin.fontfamilies_vocab"
+     />
+
+  <utility
+     provides="zope.schema.interfaces.IVocabularyFactory"
+     component=".controlpaneladv.borderstyles_vocab"
+     name="leftskin.borderstyles_vocab"
+     />
+
+  <utility
+     provides="zope.schema.interfaces.IVocabularyFactory"
+     component=".controlpaneladv.transforms_vocab"
+     name="leftskin.transforms_vocab"
+     />
+
+  <adapter factory=".controlpaneladv.BasePropertiesControlPanelAdapter" />
+
+  <adapter factory=".controlpanelcompl.LeftSkinComplControlPanelAdapter" />
+
+  <adapter factory=".controlpanel.LeftSkinControlPanelAdapter" />
+
+  <browser:page
+     name="leftskin-controlpanel"
+     for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+     class=".controlpanel.LeftSkinControlPanel"
+     permission="cmf.ManagePortal"
+     />
+
+  <browser:page
+     name="baseproperties-controlpanel"
+     for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+     class=".controlpaneladv.BasePropertiesControlPanel"
+     permission="cmf.ManagePortal"
+     />
+
+  <browser:page
+     name="leftskin-compl-controlpanel"
+     for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+     class=".controlpanelcompl.LeftSkinComplControlPanel"
+     permission="cmf.ManagePortal"
+     />
+
+  <browser:page
+     name="leftskin_view"
+     for="*"
+     class=".leftskinview.LeftSkinView"
+     permission="zope.Public"
+     allowed_interface=".leftskinview.ILeftSkinView"
+     />
+
+</configure>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpanel.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpanel.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpanel.py	(revision 429)
@@ -0,0 +1,540 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+
+from zope.interface import Interface, implements
+from zope.component import adapts, getUtility, getMultiAdapter
+from zope.schema import TextLine, Bool
+from schema import ImageLine
+from widgets import ImageWidget
+from zope.formlib import form
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+from Products.CMFCore.interfaces import ISkinsTool
+from Products.statusmessages.interfaces import IStatusMessage
+from plone.app.controlpanel.form import ControlPanelForm
+from plone.app.form.validators import null_validator
+from plone.fieldsets import FormFieldsets
+from enpraxis.leftskin import leftskinMessageFactory as _
+from Products.CMFPlone import PloneMessageFactory
+
+
+
+def uploadImage(context, filename, file):
+    """ Upload an image object. """
+    if filename in context.objectIds():
+        context.manage_delObjects([filename])
+    context.manage_addImage(id=filename, file=file.read())
+    
+
+class ILeftSkinGeneralSchema(Interface):
+
+    development_mode = Bool(title=_(u'Development Mode'),
+                            description=_(u'In development mode, stylesheets are not merged to composites, '
+                                          'and caching and compression of css is disabled. The registry also sends '
+                                          'http-headers to prevent browsers from caching the stylesheets. '
+                                          'Remember to turn it off as the developmentmode affects performance.'),
+                            required=True)
+
+    portal_logo = ImageLine(title=_(u'Portal Logo'),
+                            description=_(u'The clickable logo in the top banner. Select '
+                                          'the file to be added by clicking the \'Browse\' '
+                                          'button. This image should be 360px wide by 63px '
+                                          'high to fit within the default layout. The logo will '
+                                          'be rendered \'on top of\' the Portal Banner.'),
+                            required=False)
+                                         
+    portal_favicon = ImageLine(title=_(u'Portal Favicon'),
+                               description=_(u'The favicon for your portal. Save your image as favicon.ico.'),
+                               required=False)
+
+    fluid_fixed_width = Bool(title=_(u'Fluid Fixed Width'),
+                            description=_(u'If checked, the site will have a fixed width center column '
+                                            'of 960 pixels. Please set the Body Background Color and/or Body Backgound Image'
+                                            'as well.'),
+                            required=True)
+
+    fluid_fixed_repeat_y = Bool(title=_(u'Repeat Y-axis'),
+                            description=_(u'If checked, the Body Background Image will repeat on the x- and y- axis. If unchecked '
+                                            'the image will repeat only on the x-axis.'),
+                            required=True)
+                                                                                  
+    body_bkg_color = TextLine(title=_(u'Body Background Color'),
+                               description=_(u'The background color of the left and right columns, when the site is set to a floating fixed width.'),
+                               required=False)
+
+    body_bkg_img = ImageLine(title=_(u'Body Background Image'),
+                               description=_(u'The background image of the left and right columns, when the site is set to a floating fixed width.'),                             
+                               required=False)
+    
+                                         
+
+class ILeftSkinHeaderSchema(Interface):
+
+    portal_banner = ImageLine(title=_(u'Portal Banner'),
+                              description=_(u'The top banner of your eduCommons instance. '
+                                            'Select the file to be added by clicking the '
+                                            '\'Browse\' button. This image should be 2000px '
+                                            'wide by 65px high to fit within the default layout.'),
+                              required=False)
+    
+    header_bkg_color = TextLine(title=_(u'Background Color'),
+                                description=_(u'The background color of the header.'),
+                                required=False)
+
+    header_font_color = TextLine(title=_(u'Font Color'),
+                                 description=_(u'The font color of plain text in the header.'),
+                                 required=False)
+
+    header_link_color = TextLine(title=_(u'Link Color'),
+                                 description=_(u'The color of links in the header.'),
+                                 required=False)
+
+    header_active_color = TextLine(title=_(u'Active Link Color'),
+                                   description=_(u'The color of selected or highlighted links'),
+                                   required=False)
+
+class ILeftSkinTopNavSchema(Interface):
+
+    topnav_background = ImageLine(title=_(u'Background Image'),
+                                  description=_(u'You may customize the background of the top navigation '
+                                                'elements (home, courses, help, about OCW) by uploading a '
+                                                'background image. For non-tiling images, the size should '
+                                                'be 2000px wide by 28px high.'),
+                                  required=False)
+    
+    topnav_bkg_color = TextLine(title=_(u'Background Color'),
+                                description=_(u'The background color of the top navigation bar.'),
+                                required=False)
+
+    topnav_font_color = TextLine(title=_(u'Font Color'),
+                                 description=_(u'The font color for the top navigation bar.'),
+                                 required=False)
+
+    topnav_link_color = TextLine(title=_(u'Link Color'),
+                                 description=_(u'The color of links in the top navigation bar'),
+                                 required=False)
+
+    topnav_active_color = TextLine(title=_(u'Active Link Color'),
+                                   description=_(u'The color of selected or highlighted links.'),
+                                   required=False)
+
+class ILeftSkinLeftNavSchema(Interface):
+
+    leftnav_background = ImageLine(title=_(u'Background Image'),
+                                   description=_(u'The background image for the Left Hand Column. '
+                                                 'Select the file to be added by clicking the '
+                                                 '\'Browse\' button. This image should be 150px wide '
+                                                 'by 10px high to fit within the default layout.'),
+                                   required=False)
+    
+    leftnav_bkg_color = TextLine(title=_(u'Background Color'),
+                                 description=_(u'The background color of the left navigation section.'),
+                                 required=False)
+
+    leftnav_font_color = TextLine(title=_(u'Font Color'),
+                                  description=_(u'The font color for the left navigation section.'),
+                                  required=False)
+
+    leftnav_link_color = TextLine(title=_(u'Link Color'),
+                                  description=_(u'The color of links in the left navigation section.'),
+                                  required=False)
+
+    leftnav_active_color = TextLine(title=_(u'Active Link Color'),
+                                    description=_(u'The color of the selected or highlighted links.'),
+                                    required=False)
+
+class ILeftSkinContentSchema(Interface):
+    
+    content_bkg_color = TextLine(title=_(u'Background Color'),
+                                 description=_(u'The background color for this section.'),
+                                 required=False)
+
+    content_font_color = TextLine(title=_(u'Font Color'),
+                                  description=_(u'The link color for this section.'),
+                                  required=False)
+
+    content_link_color = TextLine(title=_(u'Link Color'),
+                                  description=_(u'The color of links in this section.'),
+                                  required=False)
+
+    content_active_color = TextLine(title=_(u'Active Link Color'),
+                                    description=_(u'The color of selected or highlighted links '
+                                                  'in this section.'),
+                                    required=False)
+
+class ILeftSkinSchema(ILeftSkinGeneralSchema,
+                      ILeftSkinHeaderSchema, 
+                      ILeftSkinTopNavSchema, 
+                      ILeftSkinLeftNavSchema,
+                      ILeftSkinContentSchema):
+    """ Combine schemas in tab form. """
+
+
+class LeftSkinControlPanelAdapter(SchemaAdapterBase):
+    
+    adapts(IPloneSiteRoot)
+    implements(ILeftSkinSchema)
+
+    def __init__(self, context):
+        super(LeftSkinControlPanelAdapter, self).__init__(context)
+        # look up the tool properly at some point, getUtility(ISkinsTool)
+        # fails for some reason, until then just access it directly
+        self.skins = context.portal_skins.custom
+        # check if exists; if not, find cur theme and customize it
+        self.props = context.portal_skins.custom.base_properties
+        self.ls_props = context.portal_properties.left_skin_properties
+        self.css = context.portal_css
+
+    # General settings
+
+    def get_development_mode(self):
+        return self.css.getDebugMode()
+
+    def set_development_mode(self, mode):
+        self.css.setDebugMode(mode)
+
+    development_mode = property(get_development_mode, set_development_mode)
+
+    def get_portal_logo(self):
+        return self.props.getProperty('logoName')
+
+    def set_portal_logo(self, file):
+        if file:
+            uploadImage(self.skins, 'logo.png', file)
+
+    portal_logo = property(get_portal_logo, set_portal_logo)
+
+    def get_portal_favicon(self):
+        return self.props.getProperty('faviconName')
+
+    def set_portal_favicon(self, file):
+        if file:
+            uploadImage(self.skins, 'favicon.ico', file)
+
+    portal_favicon = property(get_portal_favicon, set_portal_favicon)
+
+    def get_fluid_fixed_width(self):
+        return self.ls_props.getProperty('fluid_fixed_width')
+
+    def set_fluid_fixed_width(self, fixed):
+        self.ls_props.manage_changeProperties(fluid_fixed_width=fixed)
+
+    fluid_fixed_width = property(get_fluid_fixed_width, set_fluid_fixed_width)
+
+    def get_fluid_fixed_repeat_y(self):
+        return self.ls_props.getProperty('fluid_fixed_repeat_y')
+
+    def set_fluid_fixed_repeat_y(self, repeat):
+        self.ls_props.manage_changeProperties(fluid_fixed_repeat_y=repeat)
+
+    fluid_fixed_repeat_y = property(get_fluid_fixed_repeat_y, set_fluid_fixed_repeat_y)
+
+    def get_body_bkg_color(self):
+        return self.props.getProperty('bodyBackgroundColor')
+
+    def set_body_bkg_color(self, color):
+        self.props.manage_changeProperties(bodyBackgroundColor=color.encode('ascii'))
+
+    body_bkg_color = property(get_body_bkg_color, set_body_bkg_color)
+
+    def get_body_bkg_img(self):
+        return self.props.getProperty('bodyBackgroundImage')
+
+    def set_body_bkg_img(self, file):
+        if file:
+            uploadImage(self.skins, 'bodyBackground.gif', file)
+
+    body_bkg_img = property(get_body_bkg_img, set_body_bkg_img)
+
+    # Header settings
+
+    def get_portal_banner(self):
+        return self.props.getProperty('portalHeaderBackgroundImage')
+
+    def set_portal_banner(self, file):
+        if file:
+            uploadImage(self.skins, 'headerBackground.png', file)
+
+    portal_banner = property(get_portal_banner, set_portal_banner)
+        
+    def get_header_bkg_color(self):
+        return self.props.getProperty('portalHeaderBackgroundColor')
+
+    def set_header_bkg_color(self, color):
+        self.props.manage_changeProperties(portalHeaderBackgroundColor=color.encode('ascii'))
+
+    header_bkg_color = property(get_header_bkg_color, set_header_bkg_color)
+
+    def get_header_font_color(self):
+        return self.props.getProperty('portalHeaderFontColor')
+
+    def set_header_font_color(self, color):
+        self.props.manage_changeProperties(portalHeaderFontColor=color.encode('ascii'))
+
+    header_font_color = property(get_header_font_color, set_header_font_color)
+
+    def get_header_link_color(self):
+        return self.props.getProperty('portalHeaderLinkColor')
+
+    def set_header_link_color(self, color):
+        self.props.manage_changeProperties(portalHeaderLinkColor=color.encode('ascii'))
+
+    header_link_color = property(get_header_link_color, set_header_link_color)
+
+    def get_header_active_color(self):
+        return self.props.getProperty('portalHeaderActiveColor')
+
+    def set_header_active_color(self, color):
+        self.props.manage_changeProperties(portalHeaderActiveColor=color.encode('ascii'))
+
+    header_active_color = property(get_header_active_color, set_header_active_color)
+
+    # Top Navigation Bar settings
+
+    def get_topnav_background(self):
+        return self.props.getProperty('portalTopNavBackgroundImage')
+
+    def set_topnav_background(self, file):
+        if file:
+            uploadImage(self.skins, 'topNavBackground.png', file)
+
+    topnav_background = property(get_topnav_background, set_topnav_background)
+
+    def get_topnav_bkg_color(self):
+        return self.props.getProperty('portalTopNavBackgroundColor')
+
+    def set_topnav_bkg_color(self, color):
+        color = color.encode('ascii')
+        self.props.manage_changeProperties(portalTopNavBackgroundColor=color)
+        self.props.manage_changeProperties(globalBorderColor=color)
+
+    topnav_bkg_color = property(get_topnav_bkg_color, set_topnav_bkg_color)
+
+    def get_topnav_font_color(self):
+        return self.props.getProperty('portalTopNavFontColor')
+
+    def set_topnav_font_color(self, color):
+        self.props.manage_changeProperties(portalTopNavFontColor=color.encode('ascii'))
+
+    topnav_font_color = property(get_topnav_font_color, set_topnav_font_color)
+
+    def get_topnav_link_color(self):
+        return self.props.getProperty('portalTopNavLinkColor')
+
+    def set_topnav_link_color(self, color):
+        self.props.manage_changeProperties(portalTopNavLinkColor=color.encode('ascii'))
+
+    topnav_link_color = property(get_topnav_link_color, set_topnav_link_color)
+
+    def get_topnav_active_color(self):
+        return self.props.getProperty('portalTopNavActiveColor')
+
+    def set_topnav_active_color(self, color):
+        self.props.manage_changeProperties(portalTopNavActiveColor=color.encode('ascii'))
+
+    topnav_active_color = property(get_topnav_active_color, set_topnav_active_color)
+
+    # Left Navigation settings
+
+    def get_leftnav_background(self):
+        return self.props.getProperty('portalColumnOneBackgroundImage')
+
+    def set_leftnav_background(self, file):
+        if file:
+            uploadImage(self.skins, 'columnOneBackground.png', file)
+
+    leftnav_background = property(get_leftnav_background, set_leftnav_background)
+
+    def get_leftnav_bkg_color(self):
+        return self.props.getProperty('portalColumnOneBackgroundColor')
+
+    def set_leftnav_bkg_color(self, color):
+        self.props.manage_changeProperties(portalColumnOneBackgroundColor=color.encode('ascii'))
+
+    leftnav_bkg_color = property(get_leftnav_bkg_color, set_leftnav_bkg_color)
+
+    def get_leftnav_font_color(self):
+        return self.props.getProperty('portalColumnOneFontColor')
+
+    def set_leftnav_font_color(self, color):
+        self.props.manage_changeProperties(portalColumnOneFontColor=color.encode('ascii'))
+
+    leftnav_font_color = property(get_leftnav_font_color, set_leftnav_font_color)
+
+    def get_leftnav_link_color(self):
+        return self.props.getProperty('portalColumnOneLinkColor')
+
+    def set_leftnav_link_color(self, color):
+        self.props.manage_changeProperties(portalColumnOneLinkColor=color.encode('ascii'))
+
+    leftnav_link_color = property(get_leftnav_link_color, set_leftnav_link_color)
+
+    def get_leftnav_active_color(self):
+        return self.props.getProperty('portalColumnOneActiveColor')
+
+    def set_leftnav_active_color(self, color):
+        self.props.manage_changeProperties(portalColumnOneActiveColor=color.encode('ascii'))
+
+    leftnav_active_color = property(get_leftnav_active_color, set_leftnav_active_color)
+
+    # Content settings
+
+    def get_content_bkg_color(self):
+        return self.props.getProperty('backgroundColor')
+
+    def set_content_bkg_color(self, color):
+        self.props.manage_changeProperties(backgroundColor=color.encode('ascii'))
+
+    content_bkg_color = property(get_content_bkg_color, set_content_bkg_color)
+
+    def get_content_font_color(self):
+        return self.props.getProperty('fontColor')
+
+    def set_content_font_color(self, color):
+        self.props.manage_changeProperties(fontColor=color.encode('ascii'))
+
+    content_font_color = property(get_content_font_color, set_content_font_color)
+
+    def get_content_link_color(self):
+        return self.props.getProperty('linkColor')
+
+    def set_content_link_color(self, color):
+        self.props.manage_changeProperties(linkColor=color.encode('ascii'))
+
+    content_link_color = property(get_content_link_color, set_content_link_color)
+
+    def get_content_active_color(self):
+        return self.props.getProperty('linkActiveColor')
+
+    def set_content_active_color(self, color):
+        self.props.manage_changeProperties(linkActiveColor=color.encode('ascii'))
+
+    content_active_color = property(get_content_active_color, set_content_active_color)
+
+    def clearAllSettings(self):
+        """ Remove all customizations. """
+        objs = self.skins.objectIds()
+        custom = ['logo.png',
+                  'favicon.ico',
+                  'headerBackground.png', 
+                  'topNavBackground.png',
+                  'columnOneBackground.png',
+                  'bodyBackground.gif',
+                  'base_properties']
+        
+        self.skins.manage_delObjects(filter(lambda x:x in objs, custom))
+        self.ls_props.manage_changeProperties(fluid_fixed_width=False)
+        self.ls_props.manage_changeProperties(fluid_fixed_repeat_y=False)        
+        stool = self.context.portal_skins
+        stool.leftskin.base_properties.manage_doCustomize(folder_path='custom')
+        
+    def customizeBaseProperties(self):
+        """ Ensure a copy of the current theme's base_properties exists in the custom folder  """
+        self.custom = self.context.portal_skins.custom.aq_inner.aq_explicit
+
+        if not hasattr(self.custom, 'base_properties'):
+            base_props = self.context.base_properties
+            base_props.manage_doCustomize(folder_path='custom')
+
+
+generalset = FormFieldsets(ILeftSkinGeneralSchema)
+generalset['portal_logo'].custom_widget = ImageWidget
+generalset['portal_favicon'].custom_widget = ImageWidget
+generalset['body_bkg_img'].custom_widget = ImageWidget
+generalset.id = 'leftskinGeneralSchema'
+generalset.description = _(u'General settings for the Left Skin Theme.')
+generalset.label = _(u'General')
+
+headerset = FormFieldsets(ILeftSkinHeaderSchema)
+headerset['portal_banner'].custom_widget = ImageWidget
+headerset.id = 'leftSkinHeaderSchema'
+headerset.description = _(u'Skin settings for the portal header which appears '
+                          'at the top of the page.')
+headerset.label = _(u'Header')
+
+topnavset = FormFieldsets(ILeftSkinTopNavSchema)
+topnavset['topnav_background'].custom_widget = ImageWidget
+topnavset.id = 'leftSkinTopNavSchema'
+topnavset.description = _(u'Skin settings for the top navigation bar which '
+                          'appears below the portal header.')
+topnavset.label = _(u'Top Nav Bar')
+
+leftnavset = FormFieldsets(ILeftSkinLeftNavSchema)
+leftnavset['leftnav_background'].custom_widget = ImageWidget
+leftnavset.id = 'leftSkinleftNavSchema'
+leftnavset.description = _(u'Skin settings for the left navigation section.')
+leftnavset.label = _(u'Left Nav')
+
+contentset = FormFieldsets(ILeftSkinContentSchema)
+contentset.id = 'leftSkinContentSchema'
+contentset.description = _(u'Skin settings for the content section.')
+contentset.label = _(u'Content')
+
+
+class LeftSkinControlPanel(ControlPanelForm):
+    
+    form_fields = FormFieldsets(generalset, headerset, topnavset, leftnavset, contentset)
+
+    label = _(u'Left Skin Settings')
+    description = _(u'Settings that affect the left skin theme. '
+                    'Remember to clear you browser\'s cache in order '
+                    'to see the changes made in this control panel.')
+    form_name = _(u'Left Skin Settings')
+
+    @form.action(PloneMessageFactory(u'label_save', default=u'Save'), name=u'save')
+    def handle_edit_action(self, action, data):
+        if self.adapters.has_key('ILeftSkinGeneralSchema'):
+            self.adapters['ILeftSkinGeneralSchema'].customizeBaseProperties()
+
+        if form.applyChanges(self.context, self.form_fields, data,
+                             self.adapters):
+            self.status = PloneMessageFactory(u"Changes saved.")
+        else:
+            self.status = PloneMessageFactory(u"No changes made.")
+
+    @form.action(_(u'Reset to Default'),
+                 validator=null_validator,
+                 name=u'Reset to Default')
+    def handle_reset(self, action, data):
+        if self.adapters.has_key('ILeftSkinGeneralSchema'):
+            self.adapters['ILeftSkinGeneralSchema'].clearAllSettings()
+            self.status = PloneMessageFactory(u'Changes saved.')
+        else:
+            self.status = PloneMessageFactory(u'No changes made.')
+
+
+    @form.action(PloneMessageFactory(u'label_cancel', default=u'Cancel'),
+                 validator=null_validator,
+                 name=u'cancel')
+    def handle_cancel_action(self, action, data):
+        IStatusMessage(self.request).addStatusMessage(PloneMessageFactory(u"Changes canceled."),
+                                                      type="info")
+        url = getMultiAdapter((self.context, self.request),
+                              name='absolute_url')()
+        self.request.response.redirect(url + '/plone_control_panel')
+        return ''
+        
+
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpaneladv.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpaneladv.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpaneladv.py	(revision 429)
@@ -0,0 +1,591 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+
+from zope.interface import Interface, implements
+from zope.component import adapts, getUtility, getMultiAdapter
+from zope.schema import TextLine, Choice, Bool
+from zope.schema.vocabulary import SimpleVocabulary
+from schema import ImageLine
+from widgets import ImageWidget
+from zope.formlib import form
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+from Products.CMFPlone.utils import getToolByName
+from Products.CMFCore.interfaces import ISkinsTool
+from Products.statusmessages.interfaces import IStatusMessage
+from plone.app.controlpanel.form import ControlPanelForm
+from plone.app.form.validators import null_validator
+from plone.fieldsets import FormFieldsets
+from enpraxis.leftskin import leftskinMessageFactory as _
+from Products.CMFPlone import PloneMessageFactory
+
+
+
+def uploadImage(context, filename, file):
+    """ Upload an image object. """
+    if filename in context.objectIds():
+        context.manage_delObjects([filename])
+    context.manage_addImage(id=filename, file=file.read())
+    
+def borderstyles_vocab(context):
+    props = getToolByName(context, 'portal_properties')
+    border_styles = props.left_skin_properties.border_styles
+    return SimpleVocabulary.fromValues(border_styles)
+
+def fontfamilies_vocab(context):
+    props = getToolByName(context, 'portal_properties')
+    fonts = props.left_skin_properties.font_families
+    custom = context.custom
+    if hasattr(custom, 'base_properties'):
+        base_props = custom.base_properties
+        font_props = ['fontFamily', 'headingFontFamily']
+        for prop in font_props:
+            if getattr(base_props, prop) not in fonts:
+                base_fonts = list(fonts)
+                base_fonts.append(getattr(base_props,prop))
+                props.left_skin_properties.manage_changeProperties(font_families=base_fonts)
+                fonts = props.left_skin_properties.font_families                
+
+                
+    return SimpleVocabulary.fromValues(fonts)
+
+def transforms_vocab(context):
+    props = getToolByName(context, 'portal_properties')
+    transforms = props.left_skin_properties.text_transform
+    return SimpleVocabulary.fromValues(transforms)
+
+
+class IBasePropertiesDevSchema(Interface):
+
+    development_mode = Bool(title=_(u'Development Mode'),
+                            description=_(u'In development mode, stylesheets are not merged to composites, '
+                                          'and caching and compression of css is disabled. The registry also sends '
+                                          'http-headers to prevent browsers from caching the stylesheets. '
+                                          'Remember to turn it off as the developmentmode affects performance.'),
+                            required=True)
+
+
+
+class IBasePropertiesGeneralSchema(Interface):
+
+    portal_logo = ImageLine(title=_(u'Site Logo'),
+                            description=_(u'The clickable logo in the top banner. Select '
+                                          'the file to be added by clicking the \'Browse\' '
+                                          'button. This image should be 360px wide by 63px '
+                                          'high to fit within the default layout. The logo will '
+                                          'be rendered \'on top of\' the Portal Banner.'),
+                            required=False)
+
+    portal_favicon = ImageLine(title=_(u'Portal Favicon'),
+                               description=_(u'The favicon for your portal. Save your image as favicon.ico.'),
+                               required=False)
+
+    main_font = Choice(title=_(u'Main font'),
+                       description=_(u"The preferred font, and the fall-backs if the preferred font is not available in the user's browser"),
+                       required=True,
+                       vocabulary='leftskin.fontfamilies_vocab')
+
+    default_text_size  = TextLine(title=_('Default text size'),
+                                 description=_('You can specify this as a % value, or in em, or (not recommended) in pixels'),
+                                 required=False)
+
+    default_font_color = TextLine(title=_(u'Default text Color'),
+                                  description=_(u'The color for text in the content well of the page.  Colors can be specified as words of hex values'),
+                                  required=False)
+
+    small_text_size = TextLine(title=_('Small text size'),
+                               description=_('If you specify this as a % value, it is a % of the default text size (defined above)'),
+                               required=False)
+
+    page_bkg_color = TextLine(title=_(u'Page background color'),
+                                 description=_(u'Note: it is often hard to read text on a strong color'),
+                                 required=False)
+
+
+    unvisited_link_color = TextLine(title=_(u'Unvisited link color'),
+                                  description=_(u'Make sure this looks different from visited links, even to colorblind people'),
+                                  required=False)
+
+    active_link_color = TextLine(title=_(u'Active link color'),
+                                    description=_(u'When you click on a link in text, it will change color to whatever you specify here'),
+                                    required=False)
+
+    visited_link_color = TextLine(title=_(u'Visited link color'),
+                                  description=_('Make sure this looks different from unvisited links, even to colorblind people '),
+                                  required=False)
+
+    default_border_width = TextLine(title = _(u'Default border width'),
+                 description = _('You can specify this in pixels (e.g., 2px) or em (e.g., 0.25em) '),
+                 required = False)
+
+    default_border_style = Choice(title = _(u'Default border style'),
+                                  description = _('Choose a style, or choose "none" to have no borders at all '),
+                 required = True,
+                 vocabulary='leftskin.borderstyles_vocab')
+
+    annotation_border_style = Choice(title = _(u'Annotation border style'),
+                 description = _('For example, the border around comments made in response to a page '),
+                 required = True,
+                 vocabulary='leftskin.borderstyles_vocab')
+
+    default_border_color = TextLine(title = _(u'Default border color'),
+                 description = _(''),
+                 required = False)
+
+    secondary_bkg_color = TextLine(title = _(u'Secondary background color'),
+                 description = _('The background color for the footer, portlet headers and global navigation bar '),
+                 required = False)
+
+    secondary_text_color = TextLine(title = _(u'Secondary text color'),
+                 description = _('The color of the text in the footer, portlet headers and global navigation tabs '),
+                 required = False)
+
+    heading_font = Choice(title = _(u'Heading font'),
+                 description = _("The preferred font, and the fall-backs if the preferred font is not available in the user's browser "),
+                 required = True,
+                 vocabulary='leftskin.fontfamilies_vocab')
+
+    loggedin_tabs_border_color = TextLine(title = _(u'Logged-in tabs border color'),
+                 description = _('Applies to the tabs (view, edit, etc) that you may see when logged in '),
+                 required = False)
+
+    loggedin_tabs_bkg_color = TextLine(title = _(u'Logged-in tabs background color'),
+                 description = _('Applies to the tabs (view, edit, etc) that you may see when logged in '),
+                 required = False)
+
+    loggedin_tabs_text_color = TextLine(title = _(u'Logged-in tabs text color'),
+                 description = _('Applies to the tabs (view, edit, etc) that you may see when logged in '),
+                 required = False)
+
+    form_inputtext_color = TextLine(title = _(u'Color of input text on forms'),
+                 description = _('When someone types something into a form, the color of the text they enter '),
+                 required = False)
+
+    text_transform = Choice(title = _(u'Text transform'),
+                 description = _('Regardless of how text is entered, it can be transformed to all lower case, all capitals, etc. Applies to text in global navigation tabs among other things. '),
+                 required = True,
+                 vocabulary='leftskin.transforms_vocab')                 
+
+    evenrow_bkg_color = TextLine(title = _(u'Even row background color'),
+                 description = _('Even-numbered rows in certain kinds of tables or lists have this background color '),
+                 required = False)
+
+    oddrow_bkg_color = TextLine(title = _(u'Odd row background color'),
+                 description = _('Odd-numbered rows in certain kinds of tables or lists have this background color '),
+                 required = False)
+
+    notification_border_color = TextLine(title = _(u'Notification border color'),
+                 description = _('Applies to notification elements like the status message, the calendar focus '),
+                 required = False)
+
+    notification_bkg_color = TextLine(title = _(u'Notification background color'),
+                 description = _('Applies to notification elements like the status message, the calendar focus '),
+                 required = False)
+
+    discreet_text_color = TextLine(title = _(u'Discreet text color'),
+                 description = _('Applies to explanatory information in forms and other items given class "discreet" '),
+                 required = False)
+
+    info_popup_bkg_color = TextLine(title = _(u'Information pop-up background color'),
+                 description = _('Warning: this is not currently used by Plone, although it is available for you to use if you wish '),
+                 required = False)
+
+    site_min_width = TextLine(title = _(u'Site minimum width'),
+                 description = _('When you resize your browser window, how small can it get before a horizontal scroll bar appears? (Note: does not apply in Internet Explorer) '),
+                 required = False)
+
+    col_one_width = TextLine(title = _(u'Column One width'),
+                 description = _('How wide should the left column be? '),
+                 required = False)
+
+    col_two_width = TextLine(title = _(u'Column Two width'),
+                 description = _('How wide should the right column be? '),
+                 required = False)
+
+
+
+class IBasePropertiesSchema(IBasePropertiesDevSchema, IBasePropertiesGeneralSchema):
+    """ Combine schemas in tab form. """
+
+
+class BasePropertiesControlPanelAdapter(SchemaAdapterBase):
+    
+    adapts(IPloneSiteRoot)
+    implements(IBasePropertiesSchema)
+
+    def __init__(self, context):
+        super(BasePropertiesControlPanelAdapter, self).__init__(context)
+        # look up the tool properly at some point, getUtility(ISkinsTool)
+        # fails for some reason, until then just access it directly
+        self.customizeBaseProperties()
+        self.skins = context.portal_skins.custom
+        self.props = context.portal_skins.custom.base_properties
+        self.css = context.portal_css
+
+
+    # General settings
+
+    def get_development_mode(self):
+        return self.css.getDebugMode()
+
+    def set_development_mode(self, mode):
+        self.css.setDebugMode(mode)
+
+    development_mode = property(get_development_mode, set_development_mode)
+
+    def get_portal_logo(self):
+        return self.props.getProperty('logoName')
+
+    def set_portal_logo(self, file):
+        if file:
+            uploadImage(self.skins, 'logo.png', file)
+
+    portal_logo = property(get_portal_logo, set_portal_logo)
+
+    def get_portal_favicon(self):
+        return self.props.getProperty('faviconName')
+
+    def set_portal_favicon(self, file):
+        if file:
+            uploadImage(self.skins, 'favicon.ico', file)
+        
+        if hasattr(self.props, 'faviconName'):
+            self.props.manage_changeProperties(faviconName='favicon.ico')
+        else:
+            self.props.manage_addProperty('faviconName', 'favicon.ico', 'string')
+
+    portal_favicon = property(get_portal_favicon, set_portal_favicon)
+
+
+    def get_main_font(self):
+        return self.props.getProperty('fontFamily')
+
+    def set_main_font(self, family):
+        self.props.manage_changeProperties(fontFamily=family.encode('ascii'))
+
+    main_font = property(get_main_font, set_main_font)
+
+    def get_default_text_size(self):
+        return self.props.getProperty('fontBaseSize')
+
+    def set_default_text_size(self, size):
+        self.props.manage_changeProperties(fontBaseSize=size.encode('ascii'))
+
+    default_text_size = property(get_default_text_size, set_default_text_size)
+
+    def get_default_font_color(self):
+        return self.props.getProperty('fontColor')
+
+    def set_default_font_color(self, color):
+        self.props.manage_changeProperties(fontColor=color.encode('ascii'))
+
+    default_font_color = property(get_default_font_color, set_default_font_color)
+
+    def get_small_text_size(self):
+        return self.props.getProperty('fontSmallSize')
+
+    def set_small_text_size(self, size):
+        self.props.manage_changeProperties(fontSmallSize=size.encode('ascii'))
+
+    small_text_size = property(get_small_text_size, set_small_text_size)
+
+    def get_page_bkg_color(self):
+        return self.props.getProperty('backgroundColor')
+
+    def set_page_bkg_color(self, color):
+        self.props.manage_changeProperties(backgroundColor=color.encode('ascii'))
+
+    page_bkg_color = property(get_page_bkg_color, set_page_bkg_color)
+
+
+    def get_unvisited_link_color(self):
+        return self.props.getProperty('linkColor')
+
+    def set_unvisited_link_color(self, color):
+        self.props.manage_changeProperties(linkColor=color.encode('ascii'))
+
+    unvisited_link_color = property(get_unvisited_link_color, set_unvisited_link_color)
+
+    def get_active_link_color(self):
+        return self.props.getProperty('linkActiveColor')
+
+    def set_active_link_color(self, color):
+        self.props.manage_changeProperties(linkActiveColor=color.encode('ascii'))
+
+    active_link_color = property(get_active_link_color, set_active_link_color)
+
+    def get_visited_link_color(self):
+        return self.props.getProperty('linkVisitedColor')
+
+    def set_visited_link_color(self, color):
+        self.props.manage_changeProperties(linkVisitedColor=color.encode('ascii'))
+
+    visited_link_color = property(get_visited_link_color, set_visited_link_color)
+
+    def get_default_border_width(self):
+        return self.props.getProperty('borderWidth')
+
+    def set_default_border_width(self, width):
+        self.props.manage_changeProperties(borderWidth=width.encode('ascii'))
+
+    default_border_width = property(get_default_border_width, set_default_border_width)
+
+    def get_default_border_style(self):
+        return self.props.getProperty('borderStyle')
+
+    def set_default_border_style(self, style):
+        self.props.manage_changeProperties(borderStyle=style.encode('ascii'))
+
+    default_border_style = property(get_default_border_style, set_default_border_style)
+
+    def get_annotation_border_style(self):
+        return self.props.getProperty('borderStyleAnnotations')
+
+    def set_annotation_border_style(self, style):
+        self.props.manage_changeProperties(borderStyleAnnotations=style.encode('ascii'))
+
+    annotation_border_style = property(get_annotation_border_style, set_annotation_border_style)
+
+    def get_default_border_color(self):
+        return self.props.getProperty('globalBorderColor')
+
+    def set_default_border_color(self, color):
+        self.props.manage_changeProperties(globalBorderColor=color.encode('ascii'))
+
+    default_border_color = property(get_default_border_color, set_default_border_color)
+
+    def get_secondary_bkg_color(self):
+        return self.props.getProperty('globalBackgroundColor')
+
+    def set_secondary_bkg_color(self, color):
+        self.props.manage_changeProperties(globalBackgroundColor=color.encode('ascii'))
+
+    secondary_bkg_color = property(get_secondary_bkg_color, set_secondary_bkg_color)
+
+    def get_secondary_text_color(self):
+        return self.props.getProperty('globalFontColor')
+
+    def set_secondary_text_color(self, color):
+        self.props.manage_changeProperties(globalFontColor=color.encode('ascii'))
+
+    secondary_text_color = property(get_secondary_text_color, set_secondary_text_color)
+
+    def get_heading_font(self):
+        return self.props.getProperty('headingFontFamily')
+
+    def set_heading_font(self, family):
+        self.props.manage_changeProperties(headingFontFamily=family.encode('ascii'))
+
+    heading_font = property(get_heading_font, set_heading_font)
+
+    def get_loggedin_tabs_border_color(self):
+        return self.props.getProperty('contentViewBorderColor')
+
+    def set_loggedin_tabs_border_color(self, color):
+        self.props.manage_changeProperties(contentViewBorderColor=color.encode('ascii'))        
+
+    loggedin_tabs_border_color = property(get_loggedin_tabs_border_color, set_loggedin_tabs_border_color)
+
+    def get_loggedin_tabs_bkg_color(self):
+        return self.props.getProperty('contentViewBackgroundColor')
+
+    def set_loggedin_tabs_bkg_color(self, color):
+        self.props.manage_changeProperties(contentViewBackgroundColor=color.encode('ascii'))        
+
+    loggedin_tabs_bkg_color = property(get_loggedin_tabs_bkg_color, set_loggedin_tabs_bkg_color)
+
+    def get_loggedin_tabs_text_color(self):
+        return self.props.getProperty('contentViewFontColor')
+
+    def set_loggedin_tabs_text_color(self, color):
+        self.props.manage_changeProperties(contentViewFontColor=color.encode('ascii'))        
+
+    loggedin_tabs_text_color = property(get_loggedin_tabs_text_color, set_loggedin_tabs_text_color)
+
+    def get_form_inputtext_color(self):
+        return self.props.getProperty('inputFontColor')
+
+    def set_form_inputtext_color(self, color):
+        self.props.manage_changeProperties(inputFontColor=color.encode('ascii'))        
+
+    form_inputtext_color = property(get_form_inputtext_color, set_form_inputtext_color)
+
+    def get_text_transform(self):
+        return self.props.getProperty('textTransform')
+
+    def set_text_transform(self, xform):
+        self.props.manage_changeProperties(textTransform=xform.encode('ascii'))
+
+    text_transform = property(get_text_transform, set_text_transform)
+
+    def get_evenrow_bkg_color(self):
+        return self.props.getProperty('evenRowBackgroundColor')
+
+    def set_evenrow_bkg_color(self, color):
+        self.props.manage_changeProperties(evenRowBackgroundColor=color.encode('ascii'))
+
+    evenrow_bkg_color = property(get_evenrow_bkg_color, set_evenrow_bkg_color)                                     
+
+    def get_oddrow_bkg_color(self):
+        return self.props.getProperty('oddRowBackgroundColor')
+
+    def set_oddrow_bkg_color(self, color):
+        self.props.manage_changeProperties(oddRowBackgroundColor=color.encode('ascii'))
+
+    oddrow_bkg_color = property(get_oddrow_bkg_color, set_oddrow_bkg_color)                                     
+
+    def get_notification_border_color(self):
+        return self.props.getProperty('notifyBorderColor')
+
+    def set_notification_border_color(self, color):
+        self.props.manage_changeProperties(notifyBorder=color.encode('ascii'))
+
+    notification_border_color = property(get_notification_border_color, set_notification_border_color)                                     
+
+    def get_notification_bkg_color(self):
+        return self.props.getProperty('notifyBackgroundColor')
+
+    def set_notification_bkg_color(self, color):
+        self.props.manage_changeProperties(notifyBackgroundColor=color.encode('ascii'))
+
+    notification_bkg_color = property(get_notification_bkg_color, set_notification_bkg_color)                                     
+
+    def get_discreet_text_color(self):
+        return self.props.getProperty('discreetColor')
+
+    def set_discreet_text_color(self, color):
+        self.props.manage_changeProperties(discreetColor=color.encode('ascii'))
+
+    discreet_text_color = property(get_discreet_text_color, set_discreet_text_color)
+
+    def get_info_popup_bkg_color(self):
+        return self.props.getProperty('helpBackgroundColor')
+
+    def set_info_popup_bkg_color(self, color):
+        self.props.manage_changeProperties(helpBackgroundColor=color.encode('ascii'))
+
+    info_popup_bkg_color = property(get_info_popup_bkg_color, set_info_popup_bkg_color)                                     
+
+    def get_site_min_width(self):
+        return self.props.getProperty('portalMinWidth')
+
+    def set_site_min_width(self, width):
+        self.props.manage_changeProperties(portalMinWidth=width.encode('ascii'))
+
+    site_min_width = property(get_site_min_width, set_site_min_width)
+
+    def get_col_one_width(self):
+        return self.props.getProperty('columnOneWidth')
+
+    def set_col_one_width(self, width):
+        self.props.manage_changeProperties(columnOneWidth=width.encode('ascii'))
+
+    col_one_width = property(get_col_one_width, set_col_one_width)
+
+    def get_col_two_width(self):
+        return self.props.getProperty('columnTwoWidth')
+
+    def set_col_two_width(self, width):
+        self.props.manage_changeProperties(columnTwoWidth=width.encode('ascii'))
+
+    col_two_width = property(get_col_two_width, set_col_two_width)
+
+    def clearAllSettings(self):
+        """ Remove all customizations. """
+        objs = self.skins.objectIds()
+        custom = ['logo.png',
+                  'favicon.ico',
+                  'base_properties']
+        self.skins.manage_delObjects(filter(lambda x:x in objs, custom))
+
+        self.context.base_properties.manage_doCustomize(folder_path='custom')
+
+    def customizeBaseProperties(self):
+        """ Ensure a copy of the current theme's base_properties exists in the custom folder  """
+        self.custom = self.context.portal_skins.custom.aq_inner.aq_explicit
+
+        if not hasattr(self.custom, 'base_properties'):
+            base_props = self.context.base_properties
+            base_props.manage_doCustomize(folder_path='custom')
+
+
+devset = FormFieldsets(IBasePropertiesDevSchema)
+devset.id = 'basePropertiesDevSchema'
+devset.description = _(u"Development Mode Setting for the Theme.")
+devset.label = _(u"Development Mode")
+
+generalset = FormFieldsets(IBasePropertiesGeneralSchema)
+generalset['portal_logo'].custom_widget = ImageWidget
+generalset['portal_favicon'].custom_widget = ImageWidget
+generalset.id = 'basepropertiesGeneralSchema'
+generalset.description = _(u'Base Properties settings for the Theme.')
+generalset.label = _(u'Base Properties')
+
+
+class BasePropertiesControlPanel(ControlPanelForm):
+    
+    form_fields = FormFieldsets(devset, generalset)
+
+    label = _(u'Base Properties Settings')
+    description = _(u'Settings that affect the current theme. '
+                    'Remember to clear you browser\'s cache in order '
+                    'to see the changes made in this control panel.')
+    form_name = _(u'Base Properties Settings')
+
+    @form.action(PloneMessageFactory(u'label_save', default=u'Save'), name=u'save')
+    def handle_edit_action(self, action, data):
+        if form.applyChanges(self.context, self.form_fields, data,
+                             self.adapters):
+            self.status = PloneMessageFactory(u"Changes saved.")
+        else:
+            self.status = PloneMessageFactory(u"No changes made.")
+
+    @form.action(_(u'Reset to Default'),
+                 validator=null_validator,
+                 name=u'Reset to Default')
+
+    def handle_reset(self, action, data):
+
+        if self.adapters.has_key('IBasePropertiesGeneralSchema'):
+            self.adapters['IBasePropertiesGeneralSchema'].clearAllSettings()
+            self.status = PloneMessageFactory(u'Changes saved.')
+        else:
+            self.status = PloneMessageFactory(u'No changes made.')
+
+
+    @form.action(PloneMessageFactory(u'label_cancel', default=u'Cancel'),
+                 validator=null_validator,
+                 name=u'cancel')
+
+    def handle_cancel_action(self, action, data):
+        IStatusMessage(self.request).addStatusMessage(PloneMessageFactory(u"Changes canceled."),
+                                                      type="info")
+        url = getMultiAdapter((self.context, self.request),
+                              name='absolute_url')()
+        self.request.response.redirect(url + '/plone_control_panel')
+        return ''
+        
+
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpanelcompl.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpanelcompl.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/controlpanelcompl.py	(revision 429)
@@ -0,0 +1,682 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+
+from zope.interface import Interface, implements
+from zope.component import adapts, getUtility, getMultiAdapter
+from zope.schema import TextLine, Choice, Bool
+from zope.schema.vocabulary import SimpleVocabulary
+from schema import ImageLine
+from widgets import ImageWidget
+from zope.formlib import form
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+from Products.CMFPlone.utils import getToolByName
+from Products.CMFCore.interfaces import ISkinsTool
+from Products.statusmessages.interfaces import IStatusMessage
+from plone.app.controlpanel.form import ControlPanelForm
+from plone.app.form.validators import null_validator
+from plone.fieldsets import FormFieldsets
+from enpraxis.leftskin import leftskinMessageFactory as _
+from Products.CMFPlone import PloneMessageFactory
+
+
+def uploadImage(context, filename, file):
+    """ Upload an image object. """
+    if filename in context.objectIds():
+        context.manage_delObjects([filename])
+    context.manage_addImage(id=filename, file=file.read())
+    
+class ILeftSkinComplDevSchema(Interface):
+
+    development_mode = Bool(title=_(u'Development Mode'),
+                            description=_(u'In development mode, stylesheets are not merged to composites, '
+                                          'and caching and compression of css is disabled. The registry also sends '
+                                          'http-headers to prevent browsers from caching the stylesheets. '
+                                          'Remember to turn it off as the developmentmode affects performance.'),
+                            required=True)
+
+
+
+class ILeftSkinComplGeneralSchema(Interface):
+
+    portal_logo = ImageLine(title=_(u'Portal Logo'),
+                            description=_(u'The clickable logo in the top banner. Select '
+                                          'the file to be added by clicking the \'Browse\' '
+                                          'button. This image should be 360px wide by 63px '
+                                          'high to fit within the default layout. The logo will '
+                                          'be rendered \'on top of\' the Portal Banner.'),
+                            required=False)
+
+    portal_banner = ImageLine(title=_(u'Portal Banner'),
+                              description=_(u'The top banner of your eduCommons instance. '
+                                            'Select the file to be added by clicking the '
+                                            '\'Browse\' button. This image should be 2000px '
+                                            'wide by 65px high to fit within the default layout.'),
+                              required=False)
+
+    fluid_fixed_width = Bool(title=_(u'Fluid Fixed Width'),
+                          description=_(u'If checked, the site will have a fixed width center column '
+                                              'of 960 pixels. Please set the Body Background Color and/or Body Backgound Image'
+                                              'as well.'),
+                          required=True)
+
+    fluid_fixed_repeat_y = Bool(title=_(u'Repeat Y-axis'),
+                              description=_(u'If checked, the Body Background Image will repeat on the x- and y- axis. If unchecked '
+                                              'the image will repeat only on the x-axis.'),
+                              required=True)
+
+    body_bkg_color = TextLine(title=_(u'Body Background Color'),
+                                 description=_(u'The background color of the left and right columns, when the site is set to a floating fixed width.'),
+                                 required=False)
+
+    body_bkg_img = ImageLine(title=_(u'Body Background Image'),
+                                 description=_(u'The background image of the left and right columns, when the site is set to a floating fixed width.'),                             
+                                 required=False)
+
+
+    topnav_background = ImageLine(title=_(u'Top Navigation Background Image'),
+                                  description=_(u'You may customize the background of the top navigation '
+                                                'elements (home, courses, help, about OCW) by uploading a '
+                                                'background image. For non-tiling images, the size should '
+                                                'be 2000px wide by 28px high.'),
+                                  required=False)
+
+    leftnav_background = ImageLine(title=_(u'Left Navigation Background Image'),
+                                   description=_(u'The background image for the Left Hand Column. '
+                                                 'Select the file to be added by clicking the '
+                                                 '\'Browse\' button. This image should be 150px wide '
+                                                 'by 10px high to fit within the default layout.'),
+                                   required=False)
+                                         
+    portal_favicon = ImageLine(title=_(u'Portal Favicon'),
+                               description=_(u'The favicon for your portal. Save your image as favicon.ico.'),
+                               required=False)
+
+    main_font = Choice(title=_(u'Main font'),
+                       description=_(u"The preferred font, and the fall-backs if the preferred font is not available in the user's browser"),
+                       required=True,
+                       vocabulary='leftskin.fontfamilies_vocab')
+
+    default_text_size  = TextLine(title=_('Default text size'),
+                                 description=_('You can specify this as a % value, or in em, or (not recommended) in pixels'),
+                                 required=False)
+
+    default_font_color = TextLine(title=_(u'Default text Color'),
+                                  description=_(u'The color for text in the content well of the page.  Colors can be specified as words of hex values'),
+                                  required=False)
+
+    small_text_size = TextLine(title=_('Small text size'),
+                               description=_('If you specify this as a % value, it is a % of the default text size (defined above)'),
+                               required=False)
+
+    page_bkg_color = TextLine(title=_(u'Page background color'),
+                                 description=_(u'Note: it is often hard to read text on a strong color'),
+                                 required=False)
+
+
+    unvisited_link_color = TextLine(title=_(u'Unvisited link color'),
+                                  description=_(u'Make sure this looks different from visited links, even to colorblind people'),
+                                  required=False)
+
+    active_link_color = TextLine(title=_(u'Active link color'),
+                                    description=_(u'When you click on a link in text, it will change color to whatever you specify here'),
+                                    required=False)
+
+    visited_link_color = TextLine(title=_(u'Visited link color'),
+                                  description=_('Make sure this looks different from unvisited links, even to colorblind people '),
+                                  required=False)
+
+    default_border_width = TextLine(title = _(u'Default border width'),
+                 description = _('You can specify this in pixels (e.g., 2px) or em (e.g., 0.25em) '),
+                 required = False)
+
+    default_border_style = Choice(title = _(u'Default border style'),
+                                  description = _('Choose a style, or choose "none" to have no borders at all '),
+                 required = True,
+                 vocabulary='leftskin.borderstyles_vocab')
+
+    annotation_border_style = Choice(title = _(u'Annotation border style'),
+                 description = _('For example, the border around comments made in response to a page '),
+                 required = True,
+                 vocabulary='leftskin.borderstyles_vocab')
+
+    default_border_color = TextLine(title = _(u'Default border color'),
+                 description = _(''),
+                 required = False)
+
+    secondary_bkg_color = TextLine(title = _(u'Secondary background color'),
+                 description = _('The background color for the footer, portlet headers and global navigation bar '),
+                 required = False)
+
+    secondary_text_color = TextLine(title = _(u'Secondary text color'),
+                 description = _('The color of the text in the footer, portlet headers and global navigation tabs '),
+                 required = False)
+
+    heading_font = Choice(title = _(u'Heading font'),
+                 description = _("The preferred font, and the fall-backs if the preferred font is not available in the user's browser "),
+                 required = True,
+                 vocabulary='leftskin.fontfamilies_vocab')
+
+    loggedin_tabs_border_color = TextLine(title = _(u'Logged-in tabs border color'),
+                 description = _('Applies to the tabs (view, edit, etc) that you may see when logged in '),
+                 required = False)
+
+    loggedin_tabs_bkg_color = TextLine(title = _(u'Logged-in tabs background color'),
+                 description = _('Applies to the tabs (view, edit, etc) that you may see when logged in '),
+                 required = False)
+
+    loggedin_tabs_text_color = TextLine(title = _(u'Logged-in tabs text color'),
+                 description = _('Applies to the tabs (view, edit, etc) that you may see when logged in '),
+                 required = False)
+
+    form_inputtext_color = TextLine(title = _(u'Color of input text on forms'),
+                 description = _('When someone types something into a form, the color of the text they enter '),
+                 required = False)
+
+    text_transform = Choice(title = _(u'Text transform'),
+                 description = _('Regardless of how text is entered, it can be transformed to all lower case, all capitals, etc. Applies to text in global navigation tabs among other things. '),
+                 required = True,
+                 vocabulary='leftskin.transforms_vocab')                 
+
+    evenrow_bkg_color = TextLine(title = _(u'Even row background color'),
+                 description = _('Even-numbered rows in certain kinds of tables or lists have this background color '),
+                 required = False)
+
+    oddrow_bkg_color = TextLine(title = _(u'Odd row background color'),
+                 description = _('Odd-numbered rows in certain kinds of tables or lists have this background color '),
+                 required = False)
+
+    notification_border_color = TextLine(title = _(u'Notification border color'),
+                 description = _('Applies to notification elements like the status message, the calendar focus '),
+                 required = False)
+
+    notification_bkg_color = TextLine(title = _(u'Notification background color'),
+                 description = _('Applies to notification elements like the status message, the calendar focus '),
+                 required = False)
+
+    discreet_text_color = TextLine(title = _(u'Discreet text color'),
+                 description = _('Applies to explanatory information in forms and other items given class "discreet" '),
+                 required = False)
+
+    info_popup_bkg_color = TextLine(title = _(u'Information pop-up background color'),
+                 description = _('Warning: this is not currently used by Plone, although it is available for you to use if you wish '),
+                 required = False)
+
+    site_min_width = TextLine(title = _(u'Site minimum width'),
+                 description = _('When you resize your browser window, how small can it get before a horizontal scroll bar appears? (Note: does not apply in Internet Explorer) '),
+                 required = False)
+
+    col_one_width = TextLine(title = _(u'Column One width'),
+                 description = _('How wide should the left column be? '),
+                 required = False)
+
+    col_two_width = TextLine(title = _(u'Column Two width'),
+                 description = _('How wide should the right column be? '),
+                 required = False)
+
+
+
+class ILeftSkinComplSchema(ILeftSkinComplDevSchema, ILeftSkinComplGeneralSchema):
+    """ Combine schemas in tab form. """
+
+
+class LeftSkinComplControlPanelAdapter(SchemaAdapterBase):
+    
+    adapts(IPloneSiteRoot)
+    implements(ILeftSkinComplSchema)
+
+    def __init__(self, context):
+        super(LeftSkinComplControlPanelAdapter, self).__init__(context)
+        # look up the tool properly at some point, getUtility(ISkinsTool)
+        # fails for some reason, until then just access it directly
+        self.customizeBaseProperties()
+        self.skins = context.portal_skins.custom
+        self.props = context.portal_skins.custom.base_properties
+        self.ls_props = context.portal_properties.left_skin_properties        
+        self.css = context.portal_css
+
+    # Header settings
+
+    def get_portal_banner(self):
+        return self.props.getProperty('portalHeaderBackgroundImage')
+
+    def set_portal_banner(self, file):
+        if file:
+            uploadImage(self.skins, 'headerBackground.png', file)
+
+    portal_banner = property(get_portal_banner, set_portal_banner)
+
+    def get_fluid_fixed_width(self):
+        return self.ls_props.getProperty('fluid_fixed_width')
+
+    def set_fluid_fixed_width(self, fixed):
+        self.ls_props.manage_changeProperties(fluid_fixed_width=fixed)
+
+    fluid_fixed_width = property(get_fluid_fixed_width, set_fluid_fixed_width)
+
+    def get_fluid_fixed_repeat_y(self):
+        return self.ls_props.getProperty('fluid_fixed_repeat_y')
+
+    def set_fluid_fixed_repeat_y(self, repeat):
+        self.ls_props.manage_changeProperties(fluid_fixed_repeat_y=repeat)
+
+    fluid_fixed_repeat_y = property(get_fluid_fixed_repeat_y, set_fluid_fixed_repeat_y)
+
+    def get_body_bkg_color(self):
+        return self.props.getProperty('bodyBackgroundColor')
+
+    def set_body_bkg_color(self, color):
+        self.props.manage_changeProperties(bodyBackgroundColor=color.encode('ascii'))
+
+    body_bkg_color = property(get_body_bkg_color, set_body_bkg_color)
+
+    def get_body_bkg_img(self):
+        return self.props.getProperty('bodyBackgroundImage')
+
+    def set_body_bkg_img(self, file):
+        if file:
+            uploadImage(self.skins, 'bodyBackground.gif', file)
+
+    body_bkg_img = property(get_body_bkg_img, set_body_bkg_img)
+
+
+
+    # Top Navigation Bar settings
+
+    def get_topnav_background(self):
+        return self.props.getProperty('portalTopNavBackgroundImage')
+
+    def set_topnav_background(self, file):
+        if file:
+            uploadImage(self.skins, 'topNavBackground.png', file)
+
+    topnav_background = property(get_topnav_background, set_topnav_background)
+
+    # Left Navigation settings
+
+    def get_leftnav_background(self):
+        return self.props.getProperty('portalColumnOneBackgroundImage')
+
+    def set_leftnav_background(self, file):
+        if file:
+            uploadImage(self.skins, 'columnOneBackground.png', file)
+
+    leftnav_background = property(get_leftnav_background, set_leftnav_background)
+
+    # General settings
+
+    def get_development_mode(self):
+        return self.css.getDebugMode()
+
+    def set_development_mode(self, mode):
+        self.css.setDebugMode(mode)
+
+    development_mode = property(get_development_mode, set_development_mode)
+
+    def get_portal_logo(self):
+        return self.props.getProperty('logoName')
+
+    def set_portal_logo(self, file):
+        if file:
+            uploadImage(self.skins, 'logo.png', file)
+
+    portal_logo = property(get_portal_logo, set_portal_logo)
+
+    def get_portal_favicon(self):
+        return self.props.getProperty('faviconName')
+
+    def set_portal_favicon(self, file):
+        if file:
+            uploadImage(self.skins, 'favicon.ico', file)
+        
+        if hasattr(self.props, 'faviconName'):
+            self.props.manage_changeProperties(faviconName='favicon.ico')
+        else:
+            self.props.manage_addProperty('faviconName', 'favicon.ico', 'string')
+
+    portal_favicon = property(get_portal_favicon, set_portal_favicon)
+
+
+    def get_main_font(self):
+        return self.props.getProperty('fontFamily')
+
+    def set_main_font(self, family):
+        self.props.manage_changeProperties(fontFamily=family.encode('ascii'))
+
+    main_font = property(get_main_font, set_main_font)
+
+    def get_default_text_size(self):
+        return self.props.getProperty('fontBaseSize')
+
+    def set_default_text_size(self, size):
+        self.props.manage_changeProperties(fontBaseSize=size.encode('ascii'))
+
+    default_text_size = property(get_default_text_size, set_default_text_size)
+
+    def get_default_font_color(self):
+        return self.props.getProperty('fontColor')
+
+    def set_default_font_color(self, color):
+        self.props.manage_changeProperties(fontColor=color.encode('ascii'))
+
+    default_font_color = property(get_default_font_color, set_default_font_color)
+
+    def get_small_text_size(self):
+        return self.props.getProperty('fontSmallSize')
+
+    def set_small_text_size(self, size):
+        self.props.manage_changeProperties(fontSmallSize=size.encode('ascii'))
+
+    small_text_size = property(get_small_text_size, set_small_text_size)
+
+    def get_page_bkg_color(self):
+        return self.props.getProperty('backgroundColor')
+
+    def set_page_bkg_color(self, color):
+        self.props.manage_changeProperties(backgroundColor=color.encode('ascii'))
+
+    page_bkg_color = property(get_page_bkg_color, set_page_bkg_color)
+
+
+    def get_unvisited_link_color(self):
+        return self.props.getProperty('linkColor')
+
+    def set_unvisited_link_color(self, color):
+        self.props.manage_changeProperties(linkColor=color.encode('ascii'))
+
+    unvisited_link_color = property(get_unvisited_link_color, set_unvisited_link_color)
+
+    def get_active_link_color(self):
+        return self.props.getProperty('linkActiveColor')
+
+    def set_active_link_color(self, color):
+        self.props.manage_changeProperties(linkActiveColor=color.encode('ascii'))
+
+    active_link_color = property(get_active_link_color, set_active_link_color)
+
+    def get_visited_link_color(self):
+        return self.props.getProperty('linkVisitedColor')
+
+    def set_visited_link_color(self, color):
+        self.props.manage_changeProperties(linkVisitedColor=color.encode('ascii'))
+
+    visited_link_color = property(get_visited_link_color, set_visited_link_color)
+
+    def get_default_border_width(self):
+        return self.props.getProperty('borderWidth')
+
+    def set_default_border_width(self, width):
+        self.props.manage_changeProperties(borderWidth=width.encode('ascii'))
+
+    default_border_width = property(get_default_border_width, set_default_border_width)
+
+    def get_default_border_style(self):
+        return self.props.getProperty('borderStyle')
+
+    def set_default_border_style(self, style):
+        self.props.manage_changeProperties(borderStyle=style.encode('ascii'))
+
+    default_border_style = property(get_default_border_style, set_default_border_style)
+
+    def get_annotation_border_style(self):
+        return self.props.getProperty('borderStyleAnnotations')
+
+    def set_annotation_border_style(self, style):
+        self.props.manage_changeProperties(borderStyleAnnotations=style.encode('ascii'))
+
+    annotation_border_style = property(get_annotation_border_style, set_annotation_border_style)
+
+    def get_default_border_color(self):
+        return self.props.getProperty('globalBorderColor')
+
+    def set_default_border_color(self, color):
+        self.props.manage_changeProperties(globalBorderColor=color.encode('ascii'))
+
+    default_border_color = property(get_default_border_color, set_default_border_color)
+
+    def get_secondary_bkg_color(self):
+        return self.props.getProperty('globalBackgroundColor')
+
+    def set_secondary_bkg_color(self, color):
+        self.props.manage_changeProperties(globalBackgroundColor=color.encode('ascii'))
+
+    secondary_bkg_color = property(get_secondary_bkg_color, set_secondary_bkg_color)
+
+    def get_secondary_text_color(self):
+        return self.props.getProperty('globalFontColor')
+
+    def set_secondary_text_color(self, color):
+        self.props.manage_changeProperties(globalFontColor=color.encode('ascii'))
+
+    secondary_text_color = property(get_secondary_text_color, set_secondary_text_color)
+
+    def get_heading_font(self):
+        return self.props.getProperty('headingFontFamily')
+
+    def set_heading_font(self, family):
+        self.props.manage_changeProperties(headingFontFamily=family.encode('ascii'))
+
+    heading_font = property(get_heading_font, set_heading_font)
+
+    def get_loggedin_tabs_border_color(self):
+        return self.props.getProperty('contentViewBorderColor')
+
+    def set_loggedin_tabs_border_color(self, color):
+        self.props.manage_changeProperties(contentViewBorderColor=color.encode('ascii'))        
+
+    loggedin_tabs_border_color = property(get_loggedin_tabs_border_color, set_loggedin_tabs_border_color)
+
+    def get_loggedin_tabs_bkg_color(self):
+        return self.props.getProperty('contentViewBackgroundColor')
+
+    def set_loggedin_tabs_bkg_color(self, color):
+        self.props.manage_changeProperties(contentViewBackgroundColor=color.encode('ascii'))        
+
+    loggedin_tabs_bkg_color = property(get_loggedin_tabs_bkg_color, set_loggedin_tabs_bkg_color)
+
+    def get_loggedin_tabs_text_color(self):
+        return self.props.getProperty('contentViewFontColor')
+
+    def set_loggedin_tabs_text_color(self, color):
+        self.props.manage_changeProperties(contentViewFontColor=color.encode('ascii'))        
+
+    loggedin_tabs_text_color = property(get_loggedin_tabs_text_color, set_loggedin_tabs_text_color)
+
+    def get_form_inputtext_color(self):
+        return self.props.getProperty('inputFontColor')
+
+    def set_form_inputtext_color(self, color):
+        self.props.manage_changeProperties(inputFontColor=color.encode('ascii'))        
+
+    form_inputtext_color = property(get_form_inputtext_color, set_form_inputtext_color)
+
+    def get_text_transform(self):
+        return self.props.getProperty('textTransform')
+
+    def set_text_transform(self, xform):
+        self.props.manage_changeProperties(textTransform=xform.encode('ascii'))
+
+    text_transform = property(get_text_transform, set_text_transform)
+
+    def get_evenrow_bkg_color(self):
+        return self.props.getProperty('evenRowBackgroundColor')
+
+    def set_evenrow_bkg_color(self, color):
+        self.props.manage_changeProperties(evenRowBackgroundColor=color.encode('ascii'))
+
+    evenrow_bkg_color = property(get_evenrow_bkg_color, set_evenrow_bkg_color)                                     
+
+    def get_oddrow_bkg_color(self):
+        return self.props.getProperty('oddRowBackgroundColor')
+
+    def set_oddrow_bkg_color(self, color):
+        self.props.manage_changeProperties(oddRowBackgroundColor=color.encode('ascii'))
+
+    oddrow_bkg_color = property(get_oddrow_bkg_color, set_oddrow_bkg_color)                                     
+
+    def get_notification_border_color(self):
+        return self.props.getProperty('notifyBorderColor')
+
+    def set_notification_border_color(self, color):
+        self.props.manage_changeProperties(notifyBorder=color.encode('ascii'))
+
+    notification_border_color = property(get_notification_border_color, set_notification_border_color)                                     
+
+    def get_notification_bkg_color(self):
+        return self.props.getProperty('notifyBackgroundColor')
+
+    def set_notification_bkg_color(self, color):
+        self.props.manage_changeProperties(notifyBackgroundColor=color.encode('ascii'))
+
+    notification_bkg_color = property(get_notification_bkg_color, set_notification_bkg_color)                                     
+
+    def get_discreet_text_color(self):
+        return self.props.getProperty('discreetColor')
+
+    def set_discreet_text_color(self, color):
+        self.props.manage_changeProperties(discreetColor=color.encode('ascii'))
+
+    discreet_text_color = property(get_discreet_text_color, set_discreet_text_color)
+
+    def get_info_popup_bkg_color(self):
+        return self.props.getProperty('helpBackgroundColor')
+
+    def set_info_popup_bkg_color(self, color):
+        self.props.manage_changeProperties(helpBackgroundColor=color.encode('ascii'))
+
+    info_popup_bkg_color = property(get_info_popup_bkg_color, set_info_popup_bkg_color)                                     
+
+    def get_site_min_width(self):
+        return self.props.getProperty('portalMinWidth')
+
+    def set_site_min_width(self, width):
+        self.props.manage_changeProperties(portalMinWidth=width.encode('ascii'))
+
+    site_min_width = property(get_site_min_width, set_site_min_width)
+
+    def get_col_one_width(self):
+        return self.props.getProperty('columnOneWidth')
+
+    def set_col_one_width(self, width):
+        self.props.manage_changeProperties(columnOneWidth=width.encode('ascii'))
+
+    col_one_width = property(get_col_one_width, set_col_one_width)
+
+    def get_col_two_width(self):
+        return self.props.getProperty('columnTwoWidth')
+
+    def set_col_two_width(self, width):
+        self.props.manage_changeProperties(columnTwoWidth=width.encode('ascii'))
+
+    col_two_width = property(get_col_two_width, set_col_two_width)
+
+    def clearAllSettings(self):
+        """ Remove all customizations. """
+        objs = self.skins.objectIds()
+        custom = ['logo.png',
+                  'favicon.ico',
+                  'headerBackground.png', 
+                  'topNavBackground.png',
+                  'columnOneBackground.png',
+                  'bodyBackground.gif',
+                  'base_properties']
+        
+        self.skins.manage_delObjects(filter(lambda x:x in objs, custom))
+        self.ls_props.manage_changeProperties(fluid_fixed_width=False)
+        self.ls_props.manage_changeProperties(fluid_fixed_repeat_y=False)        
+        stool = self.context.portal_skins
+        stool.leftskin.base_properties.manage_doCustomize(folder_path='custom')
+
+    def customizeBaseProperties(self):
+        """ Ensure a copy of the current theme's base_properties exists in the custom folder  """
+        self.custom = self.context.portal_skins.custom.aq_inner.aq_explicit
+
+        if not hasattr(self.custom, 'base_properties'):
+            base_props = self.context.base_properties
+            base_props.manage_doCustomize(folder_path='custom')
+
+
+devset = FormFieldsets(ILeftSkinComplDevSchema)
+devset.id = 'basePropertiesDevSchema'
+devset.description = _(u"Development Mode Setting for the Theme.")
+devset.label = _(u"Development Mode")
+
+generalset = FormFieldsets(ILeftSkinComplGeneralSchema)
+generalset['portal_logo'].custom_widget = ImageWidget
+generalset['portal_favicon'].custom_widget = ImageWidget
+generalset['portal_banner'].custom_widget = ImageWidget
+generalset['body_bkg_img'].custom_widget = ImageWidget
+generalset['topnav_background'].custom_widget = ImageWidget
+generalset['leftnav_background'].custom_widget = ImageWidget
+generalset.id = 'basepropertiesGeneralSchema'
+generalset.description = _(u'Base Properties settings for the Theme.')
+generalset.label = _(u'Base Properties')
+
+
+class LeftSkinComplControlPanel(ControlPanelForm):
+    
+    form_fields = FormFieldsets(devset, generalset)
+
+    label = _(u'Base Properties Settings')
+    description = _(u'Settings that affect the current theme. '
+                    'Remember to clear you browser\'s cache in order '
+                    'to see the changes made in this control panel.')
+    form_name = _(u'Base Properties Settings')
+
+    @form.action(PloneMessageFactory(u'label_save', default=u'Save'), name=u'save')
+    def handle_edit_action(self, action, data):
+        if form.applyChanges(self.context, self.form_fields, data,
+                             self.adapters):
+            self.status = PloneMessageFactory(u"Changes saved.")
+        else:
+            self.status = PloneMessageFactory(u"No changes made.")
+
+    @form.action(_(u'Reset to Default'),
+                 validator=null_validator,
+                 name=u'Reset to Default')
+
+    def handle_reset(self, action, data):
+
+        if self.adapters.has_key('ILeftSkinComplGeneralSchema'):
+            self.adapters['ILeftSkinComplGeneralSchema'].clearAllSettings()
+            self.status = PloneMessageFactory(u'Changes saved.')
+        else:
+            self.status = PloneMessageFactory(u'No changes made.')
+
+
+    @form.action(PloneMessageFactory(u'label_cancel', default=u'Cancel'),
+                 validator=null_validator,
+                 name=u'cancel')
+
+    def handle_cancel_action(self, action, data):
+        IStatusMessage(self.request).addStatusMessage(PloneMessageFactory(u"Changes canceled."),
+                                                      type="info")
+        url = getMultiAdapter((self.context, self.request),
+                              name='absolute_url')()
+        self.request.response.redirect(url + '/plone_control_panel')
+        return ''
+        
+
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/interfaces.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/interfaces.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/interfaces.py	(revision 429)
@@ -0,0 +1,32 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from zope.viewlet.interfaces import IViewletManager
+from plone.theme.interfaces import IDefaultPloneLayer 
+
+class IContentTop(IViewletManager):
+    """ A viewlet manager that sits on top of the middle and right columns. """
+
+class ILeftSkinTheme(IDefaultPloneLayer):
+    """ Marker interface that defines a zope 3 layer for use witht the Left Skin Theme. """
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/leftskinview.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/leftskinview.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/leftskinview.py	(revision 429)
@@ -0,0 +1,48 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from zope.publisher.browser import BrowserView
+from zope.publisher.interfaces.browser import IBrowserPublisher
+
+
+class ILeftSkinView(IBrowserPublisher):
+    
+    def isLeftSkinControlPanel(request=None):
+        """ Determines whether the current page is a left skin control panel view """
+
+
+class LeftSkinView(BrowserView):
+    """ Left Skin views """
+
+    def isLeftSkinControlPanel(self, request=None):
+        """ Determines whether the current page is a left skin control panel view """
+        leftskinviews = ['@@leftskin-controlpanel', '@@leftskin-compl-controlpanel', '@@baseproperties-controlpanel']
+        if request.URL.split('/')[-1] in leftskinviews:
+            return True
+        else:
+            return False
+
+
+
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/personal_roles_bar.pt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/personal_roles_bar.pt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/personal_roles_bar.pt	(revision 429)
@@ -0,0 +1,39 @@
+<div id="portal-personaltools-wrapper"
+     i18n:domain="plone">
+
+<h5 class="hiddenStructure" i18n:translate="heading_personal_tools">Personal tools</h5>
+
+<ul id="portal-personaltools"
+    class="visualInline">
+   <tal:block condition="not: view/anonymous">
+       <li><a 
+           id="user-name"
+           tal:attributes="href view/homelink_url"
+          ><img src="" tal:replace="structure here/user.gif" />
+            <span class="visualCaseSensitive"
+                 tal:content="view/user_name">
+                John
+           </span
+       ></a>
+ 	 (<div tal:define="roles python:list(here.portal_membership.getAuthenticatedMember().getRoles())"
+ 	       tal:repeat="r python:[role for role in roles if role not in ['Authenticated', 'Member']]"
+ 	       tal:omit-tag=""><span tal:replace="r"/><span tal:condition="not: repeat/r/end">, </span></div>)
+       </li>
+   </tal:block>
+ 
+    <tal:actions tal:repeat="action view/user_actions">
+        <li tal:define="icon python:view.getIconFor(action['category'], action['id'], None);
+                        class_name string:visualIcon actionicon-${action/category}-${action/id};
+                        class_name python:icon is not None and class_name or nothing;"
+            tal:attributes="class class_name">
+            <a href=""
+               tal:attributes="href action/url;
+                               class python:icon is not None and 'visualIconPadding' or nothing;"
+            ><tal:actionname i18n:translate="" 
+                             tal:content="action/title">dummy</tal:actionname
+            ></a>
+        </li>
+    </tal:actions>
+
+</ul>
+</div>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/schema.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/schema.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/schema.py	(revision 429)
@@ -0,0 +1,42 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+
+from zope.schema import TextLine
+from zope.schema.interfaces import InvalidValue, WrongType
+
+
+class ImageLine(TextLine):
+    """ Override the File Widget and provide a working image upload. """
+
+    def _validate(self, value):
+        try:
+            ct = value.headers.getheader('content-type')
+        except AttributeError, e:
+            raise InvalidValue
+        else:
+            if value.filename == 'favicon.ico':
+                return
+            if 'image' not in ct:
+                raise WrongType(ct)
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/skins.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/skins.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/skins.py	(revision 429)
@@ -0,0 +1,185 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from zope.interface import Interface
+from zope.component import adapts
+from zope.formlib import form
+from zope.formlib.form import FormFields
+from zope.interface import implements
+from zope.schema import Bool
+from zope.schema import Choice
+
+from Products.CMFCore.utils import getToolByName
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+from Products.CMFPlone import PloneMessageFactory as _
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+
+from plone.app.controlpanel.form import ControlPanelForm
+from plone.app.controlpanel.widgets import DropdownChoiceWidget
+
+from zope.schema.vocabulary import SimpleTerm
+from zope.schema.vocabulary import SimpleVocabulary
+
+ICON_VISIBILITY_CHOICES = {
+    _(u"Only for users who are logged in"): 'authenticated',
+    _(u"Never show icons"): 'disabled',
+    _(u"Always show icons"): 'enabled',
+}
+
+ICON_VISIBILITY_VOCABULARY = SimpleVocabulary(
+    [SimpleTerm(v, v, k) for k, v in ICON_VISIBILITY_CHOICES.items()]
+    )
+
+
+class ISkinsSchema(Interface):
+
+    theme = Choice(title=_(u'Default theme'),
+                  description=_(u'''Select the default theme for the site.'''),
+                  required=True,
+                  missing_value=tuple(),
+                  vocabulary="plone.app.vocabularies.Skins")
+
+    mark_special_links = Bool(title=_(u'Mark external links'),
+                              description=_(u"If enabled all external links "
+                                             "will be marked with link type "
+                                             "specific icons. If disabled "
+                                             "the 'external links open in new "
+                                             "window' setting has no effect."),
+                              default=True)
+
+    ext_links_open_new_window = Bool(title=_(u"External links open in new "
+                                              "window"),
+                                     description=_(u"If enabled all external "
+                                                    "links in the content "
+                                                    "region open in a new "
+                                                    "window."),
+                                     default=False)
+
+    icon_visibility = Choice(title=_(u'Show content type icons'),
+                             description=_(u"If disabled the content icons "
+                                            "in folder listings and portlets "
+                                            "won't be visible."),
+                             vocabulary=ICON_VISIBILITY_VOCABULARY)
+
+
+class SkinsControlPanelAdapter(SchemaAdapterBase):
+    adapts(IPloneSiteRoot)
+    implements(ISkinsSchema)
+
+    def __init__(self, context):
+        super(SkinsControlPanelAdapter, self).__init__(context)
+        self.context = getToolByName(context, 'portal_skins')
+        self.jstool = getToolByName(context, 'portal_javascripts')
+        ptool = getToolByName(context, 'portal_properties')
+        self.props = ptool.site_properties
+
+    def get_theme(self):
+        return self.context.getDefaultSkin()
+
+    def set_theme(self, value):
+        self.context.default_skin = value
+
+    theme = property(get_theme, set_theme)
+
+    def get_mark_special_links(self):
+        return self.jstool.getResource('mark_special_links.js').getEnabled()
+
+    def set_mark_special_links(self, value):
+        if value:
+            self.jstool.getResource('mark_special_links.js').setEnabled(True)
+        else:
+            self.jstool.getResource('mark_special_links.js').setEnabled(False)
+        self.jstool.cookResources()
+
+    mark_special_links = property(get_mark_special_links,
+                                  set_mark_special_links)
+
+    def get_ext_links_open_new_window(self):
+        elonw = self.props.external_links_open_new_window
+        if elonw == 'true':
+            return True
+        return False
+
+    def set_ext_links_open_new_window(self, value):
+        if value:
+            self.props.manage_changeProperties(external_links_open_new_window='true')
+        else:
+            self.props.manage_changeProperties(external_links_open_new_window='false')
+        self.jstool.cookResources()
+
+    ext_links_open_new_window = property(get_ext_links_open_new_window,
+                                         set_ext_links_open_new_window)
+
+    def get_icon_visibility(self):
+        return self.props.icon_visibility
+
+    def set_icon_visibility(self, value):
+        self.props.manage_changeProperties(icon_visibility=value)
+
+    icon_visibility = property(get_icon_visibility,set_icon_visibility)
+
+
+class SkinsControlPanel(ControlPanelForm):
+
+    form_fields = FormFields(ISkinsSchema)
+    form_fields['theme'].custom_widget = DropdownChoiceWidget
+
+    label = _("Theme setting")
+    description = _("Settings that affect the site's look and feel.")
+    form_name = _("Theme settings")
+
+    @form.action(_(u'label_save', default=u'Save'), name=u'save')
+    def handle_edit_action(self, action, data):
+        #Define custom folder and base props
+        self.custom = self.context.portal_skins.custom.aq_inner.aq_explicit
+
+        if form.applyChanges(self.context, self.form_fields, data,
+                             self.adapters):
+            self.status = _(u"Changes saved.")
+
+            if hasattr(self.custom, 'base_properties'):
+                self.backup_base_properties(data)
+
+            self.restore_base_properties(self.custom, data)    
+
+        else:
+            self.status = _(u"No changes made.")
+
+    def backup_base_properties(self, data):
+        #backup base_properties on theme change
+        self.base_props = self.custom.base_properties
+        cur_theme_title = self.base_props.plone_skin
+
+        #If base_props plone_skin value != new theme name, back up base_props
+        if data['theme'] != cur_theme_title:
+            #backup self.base_props
+            self.custom.manage_renameObjects([self.base_props.id], [self.base_props.id + '.' + cur_theme_title.lower().replace(' ', '')])
+        
+    def restore_base_properties(self, custom, data):
+        #on theme change, restore backed up base_properties, if it exists
+        for id, obj in custom.items():
+            if 'base_properties' in id:
+                if obj.plone_skin == data['theme']:
+                    custom.manage_renameObjects([id], ['base_properties'])
+                    self.context.changeSkin(data['theme'], self.context.REQUEST)
+        
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/viewlets.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/viewlets.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/viewlets.py	(revision 429)
@@ -0,0 +1,30 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+
+from plone.app.layout.viewlets.common import PersonalBarViewlet as DefaultPersonalBarViewlet
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+
+class PersonalBarViewlet(DefaultPersonalBarViewlet):
+    render = ViewPageTemplateFile('personal_roles_bar.pt')
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/widgets.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/widgets.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/browser/widgets.py	(revision 429)
@@ -0,0 +1,49 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from zope.app.form.browser.textwidgets import FileWidget
+from zope.app.form.interfaces import ConversionError
+from enpraxis.leftskin import leftskinMessageFactory as _
+
+class ImageWidget(FileWidget):
+    """ A widget for an image object. """
+
+    def _toFieldValue(self, input):
+        """ Return file type object from form. """
+        if input is None or input == '':
+            return self.context.missing_value
+        try:
+            seek = input.seek
+            read = input.read
+        except AttributeError, e:
+            raise ConversionError(_(u'Form input is not an image object'), e)
+        else:
+            seek(0)
+            data = read(5)
+            seek(0)
+            if '' == data:
+                return self.context.missing_value
+            else:
+                return input
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/config.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/config.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/config.py	(revision 429)
@@ -0,0 +1,1 @@
+GLOBALS = globals()
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/configure.zcml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/configure.zcml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/configure.zcml	(revision 429)
@@ -0,0 +1,22 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+   xmlns:i18n="http://namespaces.zope.org/i18n"
+   xmlns:five="http://namespaces.zope.org/five"
+   i18n_domain="leftskin">
+
+  <genericsetup:registerProfile
+     name="default"
+     title="Left Skin"
+     directory="profiles/default"
+     description="Extension profile for Left Skin Product"
+     provides="Products.GenericSetup.interfaces.EXTENSION"
+     />
+
+  <five:registerPackage package="." />
+
+  <i18n:registerTranslations directory="locales" />
+
+  <include package=".browser" />
+
+</configure>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/en/LC_MESSAGES/leftskin.po
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/en/LC_MESSAGES/leftskin.po	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/en/LC_MESSAGES/leftskin.po	(revision 429)
@@ -0,0 +1,201 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2008-10-18 20:42+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"Language-Code: en\n"
+"Language-Name: English\n"
+"Preferred-Encodings: utf-8 latin1\n"
+"Domain: DOMAIN\n"
+
+#: ../browser/controlpanel.py:93
+msgid "Active Link Color"
+msgstr ""
+
+#: ../browser/controlpanel.py:81
+msgid "Background Color"
+msgstr ""
+
+#: ../browser/controlpanel.py:99
+msgid "Background Image"
+msgstr ""
+
+#: ../browser/controlpanel.py:425
+msgid "Content"
+msgstr ""
+
+#: ../browser/controlpanel.py:52
+msgid "Development Mode"
+msgstr ""
+
+#: ../browser/controlpanel.py:85
+msgid "Font Color"
+msgstr ""
+
+#: ../browser/widgets.py:39
+msgid "Form input is not an image object"
+msgstr ""
+
+#: ../browser/controlpanel.py:400
+msgid "General"
+msgstr ""
+
+#: ../browser/controlpanel.py:399
+msgid "General settings for the Left Skin Theme."
+msgstr ""
+
+#: ../browser/controlpanel.py:407
+msgid "Header"
+msgstr ""
+
+#: ../browser/controlpanel.py:53
+msgid "In development mode, stylesheets are not merged to composites, and caching and compression of css is disabled. The registry also sends http-headers to prevent browsers from caching the stylesheets. Remember to turn it off as the developmentmode affects performance."
+msgstr ""
+
+#: ../browser/controlpanel.py:420
+msgid "Left Nav"
+msgstr ""
+
+#. Default: "Left Skin"
+#: ../profiles/default/actionicons.xml
+msgid "Left Skin"
+msgstr ""
+
+#: ../browser/controlpanel.py:432
+msgid "Left Skin Settings"
+msgstr ""
+
+#: ../browser/controlpanel.py:89
+msgid "Link Color"
+msgstr ""
+
+#: ../browser/controlpanel.py:74
+msgid "Portal Banner"
+msgstr ""
+
+#: ../browser/controlpanel.py:67
+msgid "Portal Favicon"
+msgstr ""
+
+#: ../browser/controlpanel.py:59
+msgid "Portal Logo"
+msgstr ""
+
+#: ../browser/controlpanel.py:446
+msgid "Reset to Default"
+msgstr ""
+
+#: ../browser/controlpanel.py:433
+msgid "Settings that affect the left skin theme. Remember to clear you browser's cache in order to see the changes made in this control panel."
+msgstr ""
+
+#: ../browser/controlpanel.py:424
+msgid "Skin settings for the content section."
+msgstr ""
+
+#: ../browser/controlpanel.py:419
+msgid "Skin settings for the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:405
+msgid "Skin settings for the portal header which appears at the top of the page."
+msgstr ""
+
+#: ../browser/controlpanel.py:412
+msgid "Skin settings for the top navigation bar which appears below the portal header."
+msgstr ""
+
+#: ../browser/controlpanel.py:150
+msgid "The background color for this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:82
+msgid "The background color of the header."
+msgstr ""
+
+#: ../browser/controlpanel.py:132
+msgid "The background color of the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:107
+msgid "The background color of the top navigation bar."
+msgstr ""
+
+#: ../browser/controlpanel.py:125
+msgid "The background image for the Left Hand Column. Select the file to be added by clicking the 'Browse' button. This image should be 150px wide by 10px high to fit within the default layout."
+msgstr ""
+
+#: ../browser/controlpanel.py:60
+msgid "The clickable logo in the top banner. Select the file to be added by clicking the 'Browse' button. This image should be 360px wide by 63px high to fit within the default layout. The logo will be rendered 'on top of' the Portal Banner."
+msgstr ""
+
+#: ../browser/controlpanel.py:90
+msgid "The color of links in the header."
+msgstr ""
+
+#: ../browser/controlpanel.py:140
+msgid "The color of links in the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:115
+msgid "The color of links in the top navigation bar"
+msgstr ""
+
+#: ../browser/controlpanel.py:158
+msgid "The color of links in this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:94
+msgid "The color of selected or highlighted links"
+msgstr ""
+
+#: ../browser/controlpanel.py:162
+msgid "The color of selected or highlighted links in this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:119
+msgid "The color of selected or highlighted links."
+msgstr ""
+
+#: ../browser/controlpanel.py:144
+msgid "The color of the selected or highlighted links."
+msgstr ""
+
+#: ../browser/controlpanel.py:68
+msgid "The favicon for your portal. Save your image as favicon.ico."
+msgstr ""
+
+#: ../browser/controlpanel.py:136
+msgid "The font color for the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:111
+msgid "The font color for the top navigation bar."
+msgstr ""
+
+#: ../browser/controlpanel.py:86
+msgid "The font color of plain text in the header."
+msgstr ""
+
+#: ../browser/controlpanel.py:154
+msgid "The link color for this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:75
+msgid "The top banner of your eduCommons instance. Select the file to be added by clicking the 'Browse' button. This image should be 2000px wide by 65px high to fit within the default layout."
+msgstr ""
+
+#: ../browser/controlpanel.py:414
+msgid "Top Nav Bar"
+msgstr ""
+
+#: ../browser/controlpanel.py:100
+msgid "You may customize the background of the top navigation elements (home, courses, help, about OCW) by uploading a background image. For non-tiling images, the size should be 2000px wide by 28px high."
+msgstr ""
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/leftskin.pot
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/leftskin.pot	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/leftskin.pot	(revision 429)
@@ -0,0 +1,204 @@
+# --- PLEASE EDIT THE LINES BELOW CORRECTLY ---
+# SOME DESCRIPTIVE TITLE.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2008-10-18 20:42+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"Language-Code: en\n"
+"Language-Name: English\n"
+"Preferred-Encodings: utf-8 latin1\n"
+"Domain: leftskin\n"
+
+#: ../browser/controlpanel.py:93
+msgid "Active Link Color"
+msgstr ""
+
+#: ../browser/controlpanel.py:81
+msgid "Background Color"
+msgstr ""
+
+#: ../browser/controlpanel.py:99
+msgid "Background Image"
+msgstr ""
+
+#: ../browser/controlpanel.py:425
+msgid "Content"
+msgstr ""
+
+#: ../browser/controlpanel.py:52
+msgid "Development Mode"
+msgstr ""
+
+#: ../browser/controlpanel.py:85
+msgid "Font Color"
+msgstr ""
+
+#: ../browser/widgets.py:39
+msgid "Form input is not an image object"
+msgstr ""
+
+#: ../browser/controlpanel.py:400
+msgid "General"
+msgstr ""
+
+#: ../browser/controlpanel.py:399
+msgid "General settings for the Left Skin Theme."
+msgstr ""
+
+#: ../browser/controlpanel.py:407
+msgid "Header"
+msgstr ""
+
+#: ../browser/controlpanel.py:53
+msgid "In development mode, stylesheets are not merged to composites, and caching and compression of css is disabled. The registry also sends http-headers to prevent browsers from caching the stylesheets. Remember to turn it off as the developmentmode affects performance."
+msgstr ""
+
+#: ../browser/controlpanel.py:420
+msgid "Left Nav"
+msgstr ""
+
+#. Default: "Left Skin"
+#: ../profiles/default/actionicons.xml
+msgid "Left Skin"
+msgstr ""
+
+#: ../browser/controlpanel.py:432
+msgid "Left Skin Settings"
+msgstr ""
+
+#: ../browser/controlpanel.py:89
+msgid "Link Color"
+msgstr ""
+
+#: ../browser/controlpanel.py:74
+msgid "Portal Banner"
+msgstr ""
+
+#: ../browser/controlpanel.py:67
+msgid "Portal Favicon"
+msgstr ""
+
+#: ../browser/controlpanel.py:59
+msgid "Portal Logo"
+msgstr ""
+
+#: ../browser/controlpanel.py:446
+msgid "Reset to Default"
+msgstr ""
+
+#: ../browser/controlpanel.py:433
+msgid "Settings that affect the left skin theme. Remember to clear you browser's cache in order to see the changes made in this control panel."
+msgstr ""
+
+#: ../browser/controlpanel.py:424
+msgid "Skin settings for the content section."
+msgstr ""
+
+#: ../browser/controlpanel.py:419
+msgid "Skin settings for the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:405
+msgid "Skin settings for the portal header which appears at the top of the page."
+msgstr ""
+
+#: ../browser/controlpanel.py:412
+msgid "Skin settings for the top navigation bar which appears below the portal header."
+msgstr ""
+
+#: ../browser/controlpanel.py:150
+msgid "The background color for this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:82
+msgid "The background color of the header."
+msgstr ""
+
+#: ../browser/controlpanel.py:132
+msgid "The background color of the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:107
+msgid "The background color of the top navigation bar."
+msgstr ""
+
+#: ../browser/controlpanel.py:125
+msgid "The background image for the Left Hand Column. Select the file to be added by clicking the 'Browse' button. This image should be 150px wide by 10px high to fit within the default layout."
+msgstr ""
+
+#: ../browser/controlpanel.py:60
+msgid "The clickable logo in the top banner. Select the file to be added by clicking the 'Browse' button. This image should be 360px wide by 63px high to fit within the default layout. The logo will be rendered 'on top of' the Portal Banner."
+msgstr ""
+
+#: ../browser/controlpanel.py:90
+msgid "The color of links in the header."
+msgstr ""
+
+#: ../browser/controlpanel.py:140
+msgid "The color of links in the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:115
+msgid "The color of links in the top navigation bar"
+msgstr ""
+
+#: ../browser/controlpanel.py:158
+msgid "The color of links in this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:94
+msgid "The color of selected or highlighted links"
+msgstr ""
+
+#: ../browser/controlpanel.py:162
+msgid "The color of selected or highlighted links in this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:119
+msgid "The color of selected or highlighted links."
+msgstr ""
+
+#: ../browser/controlpanel.py:144
+msgid "The color of the selected or highlighted links."
+msgstr ""
+
+#: ../browser/controlpanel.py:68
+msgid "The favicon for your portal. Save your image as favicon.ico."
+msgstr ""
+
+#: ../browser/controlpanel.py:136
+msgid "The font color for the left navigation section."
+msgstr ""
+
+#: ../browser/controlpanel.py:111
+msgid "The font color for the top navigation bar."
+msgstr ""
+
+#: ../browser/controlpanel.py:86
+msgid "The font color of plain text in the header."
+msgstr ""
+
+#: ../browser/controlpanel.py:154
+msgid "The link color for this section."
+msgstr ""
+
+#: ../browser/controlpanel.py:75
+msgid "The top banner of your eduCommons instance. Select the file to be added by clicking the 'Browse' button. This image should be 2000px wide by 65px high to fit within the default layout."
+msgstr ""
+
+#: ../browser/controlpanel.py:414
+msgid "Top Nav Bar"
+msgstr ""
+
+#: ../browser/controlpanel.py:100
+msgid "You may customize the background of the top navigation elements (home, courses, help, about OCW) by uploading a background image. For non-tiling images, the size should be 2000px wide by 28px high."
+msgstr ""
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/tr/LC_MESSAGES/leftskin.po
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/tr/LC_MESSAGES/leftskin.po	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/locales/tr/LC_MESSAGES/leftskin.po	(revision 429)
@@ -0,0 +1,202 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2008-10-18 20:42+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"Language-Code: en\n"
+"Language-Name: English\n"
+"Preferred-Encodings: utf-8 latin1\n"
+"Domain: DOMAIN\n"
+
+#: ../browser/controlpanel.py:93
+msgid "Active Link Color"
+msgstr "Aktif Link Rengi"
+
+#: ../browser/controlpanel.py:81
+msgid "Background Color"
+msgstr "Arkaplan Rengi"
+
+#: ../browser/controlpanel.py:99
+msgid "Background Image"
+msgstr "Arkaplan Resmi"
+
+#: ../browser/controlpanel.py:425
+msgid "Content"
+msgstr "Ä°Ã§erik"
+
+#: ../browser/controlpanel.py:52
+msgid "Development Mode"
+msgstr "GeliÅim AÅamasÄ±"
+
+#: ../browser/controlpanel.py:85
+msgid "Font Color"
+msgstr "YazÄ± Tipi Rengi"
+
+#: ../browser/widgets.py:39
+msgid "Form input is not an image object"
+msgstr "Form Ä°Ã§eriÄi bir resim objesi deÄil"
+
+#: ../browser/controlpanel.py:400
+msgid "General"
+msgstr "Genel"
+
+#: ../browser/controlpanel.py:399
+msgid "General settings for the Left Skin Theme."
+msgstr "Sol KÄ±sÄ±m TemasÄ± iÃ§in Genel Ayarlar"
+
+#: ../browser/controlpanel.py:407
+msgid "Header"
+msgstr "BaÅlÄ±k"
+
+#: ../browser/controlpanel.py:53
+msgid "In development mode, stylesheets are not merged to composites, and caching and compression of css is disabled. The registry also sends http-headers to prevent browsers from caching the stylesheets. Remember to turn it off as the developmentmode affects performance."
+msgstr "GeliÅme aÅamasÄ±nda, stil ÅablonlarÄ± kompozitlere dahil deÄildir, Ã¶nbelleÄe alÄ±nÄ±rlar ve css'in sÄ±kÄ±ÅtÄ±rÄ±lmasÄ± geÃ§ersizdir. AyrÄ±ca kayÄ±t tarayÄ±cÄ±nÄ±n stil ÅablonlarÄ±nÄ± Ã¶nbelleÄe almasÄ±nÄ± engellemek iÃ§in http-baÅlÄ±klarÄ± gÃ¶nderir. GeliÅim aÅamasÄ±nÄ±n performansÄ±nÄ± etkilemesi iÃ§in onu kapatmayÄ± unutmayÄ±n."
+
+#: ../browser/controlpanel.py:420
+msgid "Left Nav"
+msgstr "Sol Gezinme BÃ¶lmesi"
+
+#. Default: "Left Skin"
+#: ../profiles/default/actionicons.xml
+msgid "Left Skin"
+msgstr "Sol KÄ±sÄ±m"
+
+#: ../browser/controlpanel.py:432
+msgid "Left Skin Settings"
+msgstr "Sol KÄ±sÄ±m AyarlarÄ±"
+
+#: ../browser/controlpanel.py:89
+msgid "Link Color"
+msgstr "Link Rengi"
+
+#: ../browser/controlpanel.py:74
+msgid "Portal Banner"
+msgstr "Portal Reklam BandÄ±"
+
+#: ../browser/controlpanel.py:67
+msgid "Portal Favicon"
+msgstr "Portal Simgesi"
+
+#: ../browser/controlpanel.py:59
+msgid "Portal Logo"
+msgstr "Portal Logosu"
+
+#. Default: "Reset to Default"
+#: ../browser/controlpanel.py:446
+msgid "Reset to Default"
+msgstr "VarsayÄ±lanÄ± sÄ±fÄ±rla"
+
+#: ../browser/controlpanel.py:433
+msgid "Settings that affect the left skin theme. Remember to clear you browser's cache in order to see the changes made in this control panel."
+msgstr "Sol kÄ±sÄ±m temasÄ±nÄ± etkileyen ayarlar. Kontrol Panelinde yaptÄ±ÄÄ±nÄ±z deÄiÅiklikleri gÃ¶rebilmeniz iÃ§in tarayÄ±cÄ±nÄ±zÄ±n Ã¶nbelliÄini temizlemeyi unutmayÄ±nÄ±z."
+
+#: ../browser/controlpanel.py:424
+msgid "Skin settings for the content section."
+msgstr "Ä°Ã§erik bÃ¶lÃŒmÃŒ ayarlarÄ±"
+
+#: ../browser/controlpanel.py:419
+msgid "Skin settings for the left navigation section."
+msgstr "Sol Gezinme alanÄ± ayarlarÄ±."
+
+#: ../browser/controlpanel.py:405
+msgid "Skin settings for the portal header which appears at the top of the page."
+msgstr "SayfanÄ±n ÃŒstÃŒndeki baÅlÄ±k kÄ±smÄ± ayarlarÄ±"
+
+#: ../browser/controlpanel.py:412
+msgid "Skin settings for the top navigation bar which appears below the portal header."
+msgstr "Portal baÅlÄ±ÄÄ± altÄ±nda bulunan gezinme bÃ¶lmesi ayarlarÄ±"
+
+#: ../browser/controlpanel.py:150
+msgid "The background color for this section."
+msgstr "Bu bÃ¶lÃŒm iÃ§in arkaplan ayarlarÄ±"
+
+#: ../browser/controlpanel.py:82
+msgid "The background color of the header."
+msgstr "BaÅlÄ±ÄÄ±n arkaplan rengi"
+
+#: ../browser/controlpanel.py:132
+msgid "The background color of the left navigation section."
+msgstr "Sol gezinme bÃ¶lÃŒmÃŒ arkaplan rengi"
+
+#: ../browser/controlpanel.py:107
+msgid "The background color of the top navigation bar."
+msgstr "Ãst gezinme bÃ¶lmesi arkaplan rengi"
+
+#: ../browser/controlpanel.py:125
+msgid "The background image for the Left Hand Column. Select the file to be added by clicking the 'Browse' button. This image should be 150px wide by 10px high to fit within the default layout."
+msgstr "Sol sÃŒtun arkaplan resmi. 'GÃ¶zat' dÃŒÄmesine basarak eklenecek dosyayÄ± seÃ§iniz. Resim varsayÄ±lan plana uymasÄ± iÃ§in 150 piksel geniÅliÄinde 10 piksel yÃŒksekliÄinde olmalÄ±dÄ±r."
+
+#: ../browser/controlpanel.py:60
+msgid "The clickable logo in the top banner. Select the file to be added by clicking the 'Browse' button. This image should be 360px wide by 63px high to fit within the default layout. The logo will be rendered 'on top of' the Portal Banner."
+msgstr "Ãst reklam bandÄ± tÄ±klanabilir logosu. 'GÃ¶zat' dÃŒÄmesine basarak eklenecek dosyayÄ± seÃ§iniz. Resim varsayÄ±lan plana uymasÄ± iÃ§in 360 piksel geniÅliÄinde 63 piksel yÃŒksekliÄinde olmalÄ±dÄ±r. Logo Portal Reklam bandÄ±nÄ±n ÃŒstÃŒne karÅÄ±lÄ±k gelecektir."
+
+#: ../browser/controlpanel.py:90
+msgid "The color of links in the header."
+msgstr "BaÅlÄ±ktaki linklerin rengi"
+
+#: ../browser/controlpanel.py:140
+msgid "The color of links in the left navigation section."
+msgstr "Sol gezinme bÃ¶lmesindeki linklerin rengi"
+
+#: ../browser/controlpanel.py:115
+msgid "The color of links in the top navigation bar"
+msgstr "Ãst gezinme bÃ¶lmesindeki linklerin rengi"
+
+#: ../browser/controlpanel.py:158
+msgid "The color of links in this section."
+msgstr "Bu bÃ¶lÃŒmdeki linklerin rengi"
+
+#: ../browser/controlpanel.py:94
+msgid "The color of selected or highlighted links"
+msgstr "SeÃ§ilmiÅ ya da vurgulanmÄ±Å linklerin rengi"
+
+#: ../browser/controlpanel.py:162
+msgid "The color of selected or highlighted links in this section."
+msgstr "Bu bÃ¶lÃŒmdeki seÃ§ilmiÅ ya da vurgulanmÄ±Å linklerin rengi"
+
+#: ../browser/controlpanel.py:119
+msgid "The color of selected or highlighted links."
+msgstr "SeÃ§ilmiÅ ya da vurgulanmÄ±Å linklerin rengi"
+
+#: ../browser/controlpanel.py:144
+msgid "The color of the selected or highlighted links."
+msgstr "SeÃ§ilmiÅ ya da vurgulanmÄ±Å linklerin rengi"
+
+#: ../browser/controlpanel.py:68
+msgid "The favicon for your portal. Save your image as favicon.ico."
+msgstr "Portal simgesi. Resminizi simge.ico olarak kaydedin."
+
+#: ../browser/controlpanel.py:136
+msgid "The font color for the left navigation section."
+msgstr "Sol gezinme bÃ¶lmesi yazÄ± tipi rengi."
+
+#: ../browser/controlpanel.py:111
+msgid "The font color for the top navigation bar."
+msgstr "Ãst Geznme bÃ¶lmesi yazÄ± tipi rengi."
+
+#: ../browser/controlpanel.py:86
+msgid "The font color of plain text in the header."
+msgstr "BaÅlÄ±ktaki dÃŒz metin yazÄ± tipi rengi."
+
+#: ../browser/controlpanel.py:154
+msgid "The link color for this section."
+msgstr "Bu bÃ¶lÃŒmÃŒn link rengi."
+
+#: ../browser/controlpanel.py:75
+msgid "The top banner of your eduCommons instance. Select the file to be added by clicking the 'Browse' button. This image should be 2000px wide by 65px high to fit within the default layout."
+msgstr "eduCommons Ã¶rneÄinizin ÃŒst reklam bandÄ±. 'GÃ¶zat' dÃŒÄmesine basarak eklenecek dosyayÄ± seÃ§iniz. Resim varsayÄ±lan plana uymasÄ± iÃ§in 2000 piksel geniÅliÄinde 65 piksel yÃŒksekliÄinde olmalÄ±dÄ±r."
+
+#: ../browser/controlpanel.py:414
+msgid "Top Nav Bar"
+msgstr "Ãst gezinme Ã§ubuÄu"
+
+#: ../browser/controlpanel.py:100
+msgid "You may customize the background of the top navigation elements (home, courses, help, about OCW) by uploading a background image. For non-tiling images, the size should be 2000px wide by 28px high."
+msgstr "Bir arkaplan resmi yÃŒkleyerek ÃŒst gezinme elemanlarÄ±nÄ±(anasayfa, dersler, yardÄ±m, hakkÄ±nda) dÃŒzenleyebilirsiniz. Resim boyutu 2000 piksel geniÅliÄinde 28 piksel yÃŒksekliÄinde olmalÄ±dÄ±r."
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/overrides.zcml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/overrides.zcml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/overrides.zcml	(revision 429)
@@ -0,0 +1,16 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser">
+
+
+  <adapter factory=".browser.skins.SkinsControlPanelAdapter" />
+
+  <browser:page
+      name="skins-controlpanel"
+      for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+      class=".browser.skins.SkinsControlPanel"
+      permission="cmf.ManagePortal"
+      />
+
+
+</configure>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/actionicons.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/actionicons.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/actionicons.xml	(revision 429)
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<action-icons xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+	      i18n:domain="leftskin">
+  <action-icon category="controlpanel"
+               action_id="LeftSkin_basic"
+               title="Left Skin"
+               priority="0" icon_expr="skin.gif"
+               i18n:attributes="title"/>
+  <action-icon category="controlpanel"
+               action_id="LeftSkin_adv"
+               title="Left Skin"
+               priority="0" icon_expr="skin.gif"
+               i18n:attributes="title"/>  
+  <action-icon category="controlpanel"
+               action_id="LeftSkin_compl"
+               title="Left Skin"
+               priority="0" icon_expr="skin.gif"
+               i18n:attributes="title"/>
+
+</action-icons>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/controlpanel.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/controlpanel.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/controlpanel.xml	(revision 429)
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<object name="portal_controlpanel" meta_type="Plone Control Panel Tool">
+  <configlet title="Left Skin CSS Settings"
+             action_id="LeftSkin_basic"
+             appId="LeftSkin"
+             category="Products"
+             condition_expr="python:here.portal_skins.getDefaultSkin() == 'Left Skin'"
+             url_expr="string:${portal_url}/@@leftskin-controlpanel"
+             visible="True">
+    <permission>Manage portal</permission>
+  </configlet>
+
+  <configlet title="CSS Helper"
+             action_id="LeftSkin_adv"
+             appId="LeftSkin"
+             category="Products"
+             condition_expr="python:here.portal_skins.getDefaultSkin() != 'Left Skin'"
+             url_expr="string:${portal_url}/@@baseproperties-controlpanel"
+             visible="True">
+    <permission>Manage portal</permission>
+  </configlet>
+
+  <configlet title="CSS Helper"
+             action_id="LeftSkin_compl"
+             appId="LeftSkin"
+             category="Products"
+             condition_expr="python:here.portal_skins.getDefaultSkin() == 'Left Skin'"
+             url_expr="string:${portal_url}/@@leftskin-compl-controlpanel"
+             visible="True">
+    <permission>Manage portal</permission>
+  </configlet>
+</object>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/cssregistry.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/cssregistry.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/cssregistry.xml	(revision 429)
@@ -0,0 +1,35 @@
+<object name="portal_css" meta_type="Stylesheets Registry">
+  <stylesheet title="" cacheable="True" compression="safe" cookable="True"
+	      enabled="1" expression="" id="leftskin.css" 
+	      media="screen" rel="stylesheet"
+	      rendering="import"/>
+
+  <stylesheet title="" cacheable="True" compression="safe" cookable="True"
+	      enabled="1" expression="python:portal.portal_properties.left_skin_properties.fluid_fixed_width == True" id="fixed_fluid.css" 
+	      media="screen" rel="stylesheet"
+	      rendering="import"/>
+
+  <stylesheet title="" cacheable="True" compression="safe" cookable="True"
+	      enabled="1" expression="python:portal.portal_properties.left_skin_properties.fluid_fixed_repeat_y == True" id="fixed_fluid_repeat_y.css" 
+	      media="screen" rel="stylesheet"
+	      rendering="import"/>
+
+
+  <stylesheet title="" cacheable="True" compression="safe" cookable="True"
+	      enabled="1" id="leftskinRTL.css" 
+	      media="screen" rel="stylesheet"
+              expression="python:portal.restrictedTraverse('@@plone_portal_state').is_rtl()"
+	      rendering="import"/>
+
+  <stylesheet title="" cacheable="True" compression="safe" cookable="True"
+	      enabled="1" id="css/colorpicker.css" 
+	      media="screen" rel="stylesheet"
+	      expression="python: here.restrictedTraverse('@@leftskin_view').isLeftSkinControlPanel(request=here.REQUEST)"
+	      rendering="import"/>
+
+  <stylesheet title="" cacheable="True" compression="safe" cookable="True"
+	      enabled="1" id="css/layout.css" 
+	      media="screen" rel="stylesheet"
+	      expression="python: here.restrictedTraverse('@@leftskin_view').isLeftSkinControlPanel(request=here.REQUEST)"
+	      rendering="import"/>
+</object>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/import_steps.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/import_steps.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/import_steps.xml	(revision 429)
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<import-steps>
+  <import-step id="leftskin-final" version="10070913-01"
+	       handler="enpraxis.leftskin.setupHandlers.importFinalSteps"
+	       title="Left Skin Final Steps Setup">
+    <dependency step="plone-final" />
+  </import-step>
+</import-steps>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/jsregistry.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/jsregistry.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/jsregistry.xml	(revision 429)
@@ -0,0 +1,23 @@
+<object name="portal_javascripts" meta_type="JavaScripts Registry">
+
+  <javascript cacheable="True" compression="none" cookable="False"
+              enabled="True" id="js/colorpicker.js"
+	      expression="python: here.restrictedTraverse('@@leftskin_view').isLeftSkinControlPanel(request=here.REQUEST)"
+	      inline="True"/>
+
+  <javascript cacheable="True" compression="none" cookable="False"
+              enabled="True" id="js/eye.js" 
+	      expression="python: here.restrictedTraverse('@@leftskin_view').isLeftSkinControlPanel(request=here.REQUEST)"
+	      inline="True"/>
+
+  <javascript cacheable="True" compression="none" cookable="False"
+              enabled="True" id="js/utils.js"
+	      expression="python: here.restrictedTraverse('@@leftskin_view').isLeftSkinControlPanel(request=here.REQUEST)"
+	      inline="True"/>
+
+  <javascript cacheable="True" compression="none" cookable="False"
+              enabled="True" id="js/layout.js"
+	      expression="python: here.restrictedTraverse('@@leftskin_view').isLeftSkinControlPanel(request=here.REQUEST)"
+	      inline="True"/>
+
+</object>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/propertiestool.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/propertiestool.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/propertiestool.xml	(revision 429)
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<object name="portal_properties" meta_type="Plone Properties Tool" xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+  <object name="left_skin_properties" meta_type="Plone Property Sheet">
+    <property name="title">CSS Helper properties</property>
+    <property name="fluid_fixed_width" type="boolean">False</property>
+    <property name="fluid_fixed_repeat_y" type="boolean">False</property>
+    <property name="border_styles" type="lines">
+      <element value="none" />
+      <element value="solid" />
+      <element value="dashed" />
+      <element value="dotted" />
+      <element value="double" />
+    </property>
+    <property name="font_families" type="lines">
+      <element value='"Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif' />
+      <element value='Arial, Helvetica, sans-serif' />
+      <element value='Verdana, Geneva, sans-serif' />
+      <element value='"Times New Roman", Times, serif' />
+      <element value='"Trebuchet MS", Helvetica, sans-serif' />
+    </property>
+    <property name="text_transform" type="lines">
+      <element value="none" />
+      <element value="capitalize" />
+      <element value="uppercase" />
+      <element value="lowercase" />
+    </property>
+  </object>
+</object>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/skins.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/skins.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/skins.xml	(revision 429)
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<object name="portal_skins" default_skin="Left Skin">
+ <object name="leftskin" meta_type="Filesystem Directory View"
+    directory="enpraxis.leftskin:skins/leftskin"/>
+ <skin-path name="Left Skin" based-on="Plone Default">
+  <layer name="leftskin" insert-before="LanguageTool"/>
+ </skin-path>
+
+ <object name="colorpicker" meta_type="Filesystem Directory View"
+    directory="enpraxis.leftskin:skins/colorpicker"/>
+ <skin-path name="*" based-on="Plone Default">
+  <layer name="colorpicker" insert-after="custom"/>
+ </skin-path>
+</object>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/viewlets.xml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/viewlets.xml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/profiles/default/viewlets.xml	(revision 429)
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<object>
+  <order manager="leftskin.contenttop" skinname="Left Skin">
+    <viewlet name="leftskin.personal_bar" />
+    <viewlet name="plone.app.i18n.locales.languageselector" />
+    <viewlet name="plone.path_bar" />
+  </order>
+  <hidden manager="plone.portaltop" skinname="Left Skin">
+    <viewlet name="plone.personal_bar" />
+    <viewlet name="plone.app.i18n.locales.languageselector" />
+    <viewlet name="plone.path_bar" />
+  </hidden>
+</object>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/setupHandlers.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/setupHandlers.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/setupHandlers.py	(revision 429)
@@ -0,0 +1,41 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+
+from zope.component import getUtility, getMultiAdapter
+from plone.portlets.interfaces import IPortletManager, IPortletAssignmentMapping
+from Products.CMFCore.interfaces import ISkinsTool
+
+def importFinalSteps(context):
+    site = context.getSite()
+
+    # Setup left navigation
+    leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=site)
+    left = getMultiAdapter((site, leftColumn), IPortletAssignmentMapping, context=site)
+    if u'navigation' in left:
+        left[u'navigation'].topLevel = 0
+
+    # Setup custom properties for skin
+    stool = site.portal_skins
+    if not stool.getSkinPath('custom/baseProperties'):
+        stool.leftskin.base_properties.manage_doCustomize(folder_path='custom')
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/css/colorpicker.css
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/css/colorpicker.css	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/css/colorpicker.css	(revision 429)
@@ -0,0 +1,173 @@
+.colorpicker {
+	width: 356px;
+	height: 176px;
+	overflow: hidden;
+	position: absolute;
+	background: url(../images/colorpicker_background.png);
+	font-family: Arial, Helvetica, sans-serif;
+	display: none;
+}
+.colorpicker_color {
+	width: 150px;
+	height: 150px;
+	left: 14px;
+	top: 13px;
+	position: absolute;
+	background: #f00;
+	overflow: hidden;
+	cursor: crosshair;
+}
+.colorpicker_color div {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 150px;
+	height: 150px;
+	background: url(../images/colorpicker_overlay.png);
+}
+.colorpicker_color div div {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 11px;
+	height: 11px;
+	overflow: hidden;
+	background: url(../images/colorpicker_select.gif);
+	margin: -5px 0 0 -5px;
+}
+.colorpicker_hue {
+	position: absolute;
+	top: 13px;
+	left: 171px;
+	width: 35px;
+	height: 150px;
+	cursor: n-resize;
+}
+.colorpicker_hue div {
+	position: absolute;
+	width: 35px;
+	height: 9px;
+	overflow: hidden;
+	background: url(../images/colorpicker_indic.gif) left top;
+	margin: -4px 0 0 0;
+	left: 0px;
+}
+.colorpicker_new_color {
+	position: absolute;
+	width: 60px;
+	height: 30px;
+	left: 213px;
+	top: 13px;
+	background: #f00;
+}
+.colorpicker_current_color {
+	position: absolute;
+	width: 60px;
+	height: 30px;
+	left: 283px;
+	top: 13px;
+	background: #f00;
+}
+.colorpicker input {
+	background-color: transparent;
+	border: 1px solid transparent;
+	position: absolute;
+	font-size: 10px;
+	font-family: Arial, Helvetica, sans-serif;
+	color: #898989;
+	top: 4px;
+	right: 11px;
+	text-align: right;
+	margin: 0;
+	padding: 0;
+	height: 11px;
+}
+.colorpicker_hex {
+	position: absolute;
+	width: 72px;
+	height: 22px;
+	background: url(../images/colorpicker_hex.png) top;
+	left: 212px;
+	top: 142px;
+}
+.colorpicker_hex input {
+	right: 6px;
+}
+.colorpicker_field {
+	height: 22px;
+	width: 62px;
+	background-position: top;
+	position: absolute;
+}
+.colorpicker_field span {
+	position: absolute;
+	width: 12px;
+	height: 22px;
+	overflow: hidden;
+	top: 0;
+	right: 0;
+	cursor: n-resize;
+}
+.colorpicker_rgb_r {
+	background-image: url(../images/colorpicker_rgb_r.png);
+	top: 52px;
+	left: 212px;
+}
+.colorpicker_rgb_g {
+	background-image: url(../images/colorpicker_rgb_g.png);
+	top: 82px;
+	left: 212px;
+}
+.colorpicker_rgb_b {
+	background-image: url(../images/colorpicker_rgb_b.png);
+	top: 112px;
+	left: 212px;
+}
+.colorpicker_hsb_h {
+	background-image: url(../images/colorpicker_hsb_h.png);
+	top: 52px;
+	left: 282px;
+}
+.colorpicker_hsb_s {
+	background-image: url(../images/colorpicker_hsb_s.png);
+	top: 82px;
+	left: 282px;
+}
+.colorpicker_hsb_b {
+	background-image: url(../images/colorpicker_hsb_b.png);
+	top: 112px;
+	left: 282px;
+}
+.colorpicker_submit {
+	position: absolute;
+	width: 22px;
+	height: 22px;
+	background: url(../images/colorpicker_submit.png) top;
+	left: 322px;
+	top: 142px;
+	overflow: hidden;
+}
+/*
+.colorpicker_submit {
+       position: absolute;
+       width: 40px;
+       height: 22px;
+       left: 304px;
+       top: 142px;
+       overflow: hidden;
+       color: white;
+       border: 1px solid: white;
+}
+*/
+.colorpicker_focus {
+	background-position: center;
+}
+.colorpicker_hex.colorpicker_focus {
+	background-position: bottom;
+}
+.colorpicker_submit.colorpicker_focus {
+	background-position: bottom;
+}
+.colorpicker_slider {
+	background-position: bottom;
+}
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/css/layout.css
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/css/layout.css	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/css/layout.css	(revision 429)
@@ -0,0 +1,82 @@
+
+#colorSelector {
+	position: relative;
+	width: 36px;
+	height: 36px;
+	background: url(../images/select.png);
+}
+#colorSelector div {
+	position: absolute;
+	top: 3px;
+	left: 3px;
+	width: 30px;
+	height: 30px;
+	background: url(../images/select.png) center;
+}
+#colorSelector2 {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 36px;
+	height: 36px;
+	background: url(../images/select2.png);
+}
+#colorSelector2 div {
+	position: absolute;
+	top: 4px;
+	left: 4px;
+	width: 28px;
+	height: 28px;
+	background: url(../images/select2.png) center;
+}
+#colorpickerHolder2 {
+	top: 32px;
+	left: 0;
+	width: 356px;
+	height: 0;
+	overflow: hidden;
+	position: absolute;
+}
+#colorpickerHolder2 .colorpicker {
+	background-image: url(../images/custom_background.png);
+	position: absolute;
+	bottom: 0;
+	left: 0;
+}
+#colorpickerHolder2 .colorpicker_hue div {
+	background-image: url(../images/custom_indic.gif);
+}
+#colorpickerHolder2 .colorpicker_hex {
+	background-image: url(../images/custom_hex.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_r {
+	background-image: url(../images/custom_rgb_r.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_g {
+	background-image: url(../images/custom_rgb_g.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_b {
+	background-image: url(../images/custom_rgb_b.png);
+}
+#colorpickerHolder2 .colorpicker_hsb_s {
+	background-image: url(../images/custom_hsb_s.png);
+	display: none;
+}
+#colorpickerHolder2 .colorpicker_hsb_h {
+	background-image: url(../images/custom_hsb_h.png);
+	display: none;
+}
+#colorpickerHolder2 .colorpicker_hsb_b {
+	background-image: url(../images/custom_hsb_b.png);
+	display: none;
+}
+#colorpickerHolder2 .colorpicker_submit {
+	background-image: url(../images/custom_submit.png);
+}
+#colorpickerHolder2 .colorpicker input {
+	color: #778398;
+}
+#customWidget {
+	position: relative;
+	height: 36px;
+}
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/colorpicker.js
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/colorpicker.js	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/colorpicker.js	(revision 429)
@@ -0,0 +1,450 @@
+/**
+ *
+ * Color picker
+ * Author: Stefan Petre www.eyecon.ro
+ * 
+ */
+(function ($) {
+	var ColorPicker = function () {
+		var
+			ids = {},
+			inAction,
+			charMin = 65,
+			visible,
+			tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>',
+			defaults = {
+				eventName: 'click',
+				onShow: function () {},
+				onBeforeShow: function(){},
+				onHide: function () {},
+				onChange: function () {},
+				onSubmit: function () {},
+				color: 'ff0000',
+				livePreview: true,
+				flat: false
+			},
+			fillRGBFields = function  (hsb, cal) {
+				var rgb = HSBToRGB(hsb);
+				$(cal).data('colorpicker').fields
+					.eq(1).val(rgb.r).end()
+					.eq(2).val(rgb.g).end()
+					.eq(3).val(rgb.b).end();
+			},
+			fillHSBFields = function  (hsb, cal) {
+				$(cal).data('colorpicker').fields
+					.eq(4).val(hsb.h).end()
+					.eq(5).val(hsb.s).end()
+					.eq(6).val(hsb.b).end();
+			},
+			fillHexFields = function (hsb, cal) {
+				$(cal).data('colorpicker').fields
+					.eq(0).val(HSBToHex(hsb)).end();
+			},
+			setSelector = function (hsb, cal) {
+				$(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100}));
+				$(cal).data('colorpicker').selectorIndic.css({
+					left: parseInt(150 * hsb.s/100, 10),
+					top: parseInt(150 * (100-hsb.b)/100, 10)
+				});
+			},
+			setHue = function (hsb, cal) {
+				$(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10));
+			},
+			setCurrentColor = function (hsb, cal) {
+				$(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));
+			},
+			setNewColor = function (hsb, cal) {
+				$(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));
+			},
+			keyDown = function (ev) {
+				var pressedKey = ev.charCode || ev.keyCode || -1;
+				if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) {
+					return false;
+				}
+				var cal = $(this).parent().parent();
+				if (cal.data('colorpicker').livePreview === true) {
+					change.apply(this);
+				}
+			},
+			change = function (ev) {
+				var cal = $(this).parent().parent(), col;
+				if (this.parentNode.className.indexOf('_hex') > 0) {
+					cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));
+				} else if (this.parentNode.className.indexOf('_hsb') > 0) {
+					cal.data('colorpicker').color = col = fixHSB({
+						h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),
+						s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),
+						b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)
+					});
+				} else {
+					cal.data('colorpicker').color = col = RGBToHSB(fixRGB({
+						r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),
+						g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),
+						b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)
+					}));
+				}
+				if (ev) {
+					fillRGBFields(col, cal.get(0));
+					fillHexFields(col, cal.get(0));
+					fillHSBFields(col, cal.get(0));
+				}
+				setSelector(col, cal.get(0));
+				setHue(col, cal.get(0));
+				setNewColor(col, cal.get(0));
+				cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);
+			},
+			blur = function (ev) {
+				var cal = $(this).parent().parent();
+				cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus')
+			},
+			focus = function () {
+				charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;
+				$(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');
+				$(this).parent().addClass('colorpicker_focus');
+			},
+			downIncrement = function (ev) {
+				var field = $(this).parent().find('input').focus();
+				var current = {
+					el: $(this).parent().addClass('colorpicker_slider'),
+					max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
+					y: ev.pageY,
+					field: field,
+					val: parseInt(field.val(), 10),
+					preview: $(this).parent().parent().data('colorpicker').livePreview					
+				};
+				$(document).bind('mouseup', current, upIncrement);
+				$(document).bind('mousemove', current, moveIncrement);
+			},
+			moveIncrement = function (ev) {
+				ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));
+				if (ev.data.preview) {
+					change.apply(ev.data.field.get(0), [true]);
+				}
+				return false;
+			},
+			upIncrement = function (ev) {
+				change.apply(ev.data.field.get(0), [true]);
+				ev.data.el.removeClass('colorpicker_slider').find('input').focus();
+				$(document).unbind('mouseup', upIncrement);
+				$(document).unbind('mousemove', moveIncrement);
+				return false;
+			},
+			downHue = function (ev) {
+				var current = {
+					cal: $(this).parent(),
+					y: $(this).offset().top
+				};
+				current.preview = current.cal.data('colorpicker').livePreview;
+				$(document).bind('mouseup', current, upHue);
+				$(document).bind('mousemove', current, moveHue);
+			},
+			moveHue = function (ev) {
+				change.apply(
+					ev.data.cal.data('colorpicker')
+						.fields
+						.eq(4)
+						.val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10))
+						.get(0),
+					[ev.data.preview]
+				);
+				return false;
+			},
+			upHue = function (ev) {
+				fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+				fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+				$(document).unbind('mouseup', upHue);
+				$(document).unbind('mousemove', moveHue);
+				return false;
+			},
+			downSelector = function (ev) {
+				var current = {
+					cal: $(this).parent(),
+					pos: $(this).offset()
+				};
+				current.preview = current.cal.data('colorpicker').livePreview;
+				$(document).bind('mouseup', current, upSelector);
+				$(document).bind('mousemove', current, moveSelector);
+			},
+			moveSelector = function (ev) {
+				change.apply(
+					ev.data.cal.data('colorpicker')
+						.fields
+						.eq(6)
+						.val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10))
+						.end()
+						.eq(5)
+						.val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10))
+						.get(0),
+					[ev.data.preview]
+				);
+				return false;
+			},
+			upSelector = function (ev) {
+				fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+				fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+				$(document).unbind('mouseup', upSelector);
+				$(document).unbind('mousemove', moveSelector);
+				return false;
+			},
+			enterSubmit = function (ev) {
+				$(this).addClass('colorpicker_focus');
+			},
+			leaveSubmit = function (ev) {
+				$(this).removeClass('colorpicker_focus');
+			},
+			clickSubmit = function (ev) {
+				var cal = $(this).parent();
+				var col = cal.data('colorpicker').color;
+				cal.data('colorpicker').origColor = col;
+				setCurrentColor(col, cal.get(0));
+				cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col));
+			},
+			show = function (ev) {
+				var cal = $('#' + $(this).data('colorpickerId'));
+				cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
+				var pos = $(this).offset();
+				var viewPort = getViewport();
+				var top = pos.top + this.offsetHeight;
+				var left = pos.left;
+				if (top + 176 > viewPort.t + viewPort.h) {
+					top -= this.offsetHeight + 176;
+				}
+				if (left + 356 > viewPort.l + viewPort.w) {
+					left -= 356;
+				}
+				cal.css({left: left + 'px', top: top + 'px'});
+				if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {
+					cal.show();
+				}
+				$(document).bind('mousedown', {cal: cal}, hide);
+				return false;
+			},
+			hide = function (ev) {
+				if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
+					if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
+						ev.data.cal.hide();
+					}
+					$(document).unbind('mousedown', hide);
+				}
+			},
+			isChildOf = function(parentEl, el, container) {
+				if (parentEl == el) {
+					return true;
+				}
+				if (parentEl.contains) {
+					return parentEl.contains(el);
+				}
+				if ( parentEl.compareDocumentPosition ) {
+					return !!(parentEl.compareDocumentPosition(el) & 16);
+				}
+				var prEl = el.parentNode;
+				while(prEl && prEl != container) {
+					if (prEl == parentEl)
+						return true;
+					prEl = prEl.parentNode;
+				}
+				return false;
+			},
+			getViewport = function () {
+				var m = document.compatMode == 'CSS1Compat';
+				return {
+					l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
+					t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
+					w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
+					h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
+				};
+			},
+			fixHSB = function (hsb) {
+				return {
+					h: Math.min(360, Math.max(0, hsb.h)),
+					s: Math.min(100, Math.max(0, hsb.s)),
+					b: Math.min(100, Math.max(0, hsb.b))
+				};
+			}, 
+			fixRGB = function (rgb) {
+				return {
+					r: Math.min(255, Math.max(0, rgb.r)),
+					g: Math.min(255, Math.max(0, rgb.g)),
+					b: Math.min(255, Math.max(0, rgb.b))
+				};
+			},
+			fixHex = function (hex) {
+				var len = 6 - hex.length;
+				if (len > 0) {
+					var o = [];
+					for (var i=0; i<len; i++) {
+						o.push('0');
+					}
+					o.push(hex);
+					hex = o.join('');
+				}
+				return hex;
+			}, 
+			HexToRGB = function (hex) {
+				var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
+				return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};
+			},
+			HexToHSB = function (hex) {
+				return RGBToHSB(HexToRGB(hex));
+			},
+			RGBToHSB = function (rgb) {
+				var hsb = {};
+				hsb.b = Math.max(Math.max(rgb.r,rgb.g),rgb.b);
+				hsb.s = (hsb.b <= 0) ? 0 : Math.round(100*(hsb.b - Math.min(Math.min(rgb.r,rgb.g),rgb.b))/hsb.b);
+				hsb.b = Math.round((hsb.b /255)*100);
+				if((rgb.r==rgb.g) && (rgb.g==rgb.b)) hsb.h = 0;
+				else if(rgb.r>=rgb.g && rgb.g>=rgb.b) hsb.h = 60*(rgb.g-rgb.b)/(rgb.r-rgb.b);
+				else if(rgb.g>=rgb.r && rgb.r>=rgb.b) hsb.h = 60  + 60*(rgb.g-rgb.r)/(rgb.g-rgb.b);
+				else if(rgb.g>=rgb.b && rgb.b>=rgb.r) hsb.h = 120 + 60*(rgb.b-rgb.r)/(rgb.g-rgb.r);
+				else if(rgb.b>=rgb.g && rgb.g>=rgb.r) hsb.h = 180 + 60*(rgb.b-rgb.g)/(rgb.b-rgb.r);
+				else if(rgb.b>=rgb.r && rgb.r>=rgb.g) hsb.h = 240 + 60*(rgb.r-rgb.g)/(rgb.b-rgb.g);
+				else if(rgb.r>=rgb.b && rgb.b>=rgb.g) hsb.h = 300 + 60*(rgb.r-rgb.b)/(rgb.r-rgb.g);
+				else hsb.h = 0;
+				hsb.h = Math.round(hsb.h);
+				return hsb;
+			},
+			HSBToRGB = function (hsb) {
+				var rgb = {};
+				var h = Math.round(hsb.h);
+				var s = Math.round(hsb.s*255/100);
+				var v = Math.round(hsb.b*255/100);
+				if(s == 0) {
+					rgb.r = rgb.g = rgb.b = v;
+				} else {
+					var t1 = v;
+					var t2 = (255-s)*v/255;
+					var t3 = (t1-t2)*(h%60)/60;
+					if(h==360) h = 0;
+					if(h<60) {rgb.r=t1;	rgb.b=t2; rgb.g=t2+t3}
+					else if(h<120) {rgb.g=t1; rgb.b=t2;	rgb.r=t1-t3}
+					else if(h<180) {rgb.g=t1; rgb.r=t2;	rgb.b=t2+t3}
+					else if(h<240) {rgb.b=t1; rgb.r=t2;	rgb.g=t1-t3}
+					else if(h<300) {rgb.b=t1; rgb.g=t2;	rgb.r=t2+t3}
+					else if(h<360) {rgb.r=t1; rgb.g=t2;	rgb.b=t1-t3}
+					else {rgb.r=0; rgb.g=0;	rgb.b=0}
+				}
+				return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
+			},
+			RGBToHex = function (rgb) {
+				var hex = [
+					rgb.r.toString(16),
+					rgb.g.toString(16),
+					rgb.b.toString(16)
+				];
+				$.each(hex, function (nr, val) {
+					if (val.length == 1) {
+						hex[nr] = '0' + val;
+					}
+				});
+				return hex.join('');
+			},
+			HSBToHex = function (hsb) {
+				return RGBToHex(HSBToRGB(hsb));
+			};
+		return {
+			init: function (options) {
+				options = $.extend({}, defaults, options||{});
+				if (typeof options.color == 'string') {
+					options.color = HexToHSB(options.color);
+				} else if (options.color.r != undefined && options.color.g != undefined && options.color.b != undefined) {
+					options.color = RGBToHSB(options.color);
+				} else if (options.color.h != undefined && options.color.s != undefined && options.color.b != undefined) {
+					options.color = fixHSB(options.color);
+				} else {
+					return this;
+				}
+				options.origColor = options.color;
+				return this.each(function () {
+					if (!$(this).data('colorpickerId')) {
+						var id = 'collorpicker_' + parseInt(Math.random() * 1000);
+						$(this).data('colorpickerId', id);
+						var cal = $(tpl).attr('id', id);
+						if (options.flat) {
+							cal.appendTo(this).show();
+						} else {
+							cal.appendTo(document.body);
+						}
+						options.fields = cal
+											.find('input')
+												.bind('keydown', keyDown)
+												.bind('change', change)
+												.bind('blur', blur)
+												.bind('focus', focus);
+						cal.find('span').bind('mousedown', downIncrement);
+						options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector);
+						options.selectorIndic = options.selector.find('div div');
+						options.hue = cal.find('div.colorpicker_hue div');
+						cal.find('div.colorpicker_hue').bind('mousedown', downHue);
+						options.newColor = cal.find('div.colorpicker_new_color');
+						options.currentColor = cal.find('div.colorpicker_current_color');
+						cal.data('colorpicker', options);
+						cal.find('div.colorpicker_submit')
+							.bind('mouseenter', enterSubmit)
+							.bind('mouseleave', leaveSubmit)
+							.bind('click', clickSubmit);
+						fillRGBFields(options.color, cal.get(0));
+						fillHSBFields(options.color, cal.get(0));
+						fillHexFields(options.color, cal.get(0));
+						setHue(options.color, cal.get(0));
+						setSelector(options.color, cal.get(0));
+						setCurrentColor(options.color, cal.get(0));
+						setNewColor(options.color, cal.get(0));
+						if (options.flat) {
+							cal.css({
+								position: 'relative',
+								display: 'block'
+							});
+						} else {
+							$(this).bind(options.eventName, show);
+						}
+					}
+				});
+			},
+			showPicker: function() {
+				return this.each( function () {
+					if ($(this).data('colorpickerId')) {
+						show.apply(this);
+					}
+				});
+			},
+			hidePicker: function() {
+				return this.each( function () {
+					if ($(this).data('colorpickerId')) {
+						$('#' + $(this).data('colorpickerId')).hide();
+					}
+				});
+			},
+			setColor: function(col) {
+				if (typeof col == 'string') {
+					col = HexToHSB(col);
+				} else if (col.r != undefined && col.g != undefined && col.b != undefined) {
+					col = RGBToHSB(col);
+				} else if (col.h != undefined && col.s != undefined && col.b != undefined) {
+					col = fixHSB(col);
+				} else {
+					return this;
+				}
+				return this.each(function(){
+					if ($(this).data('colorpickerId')) {
+						var cal = $('#' + $(this).data('colorpickerId'));
+						cal.data('colorpicker').color = col;
+						cal.data('colorpicker').origColor = col;
+						fillRGBFields(col, cal.get(0));
+						fillHSBFields(col, cal.get(0));
+						fillHexFields(col, cal.get(0));
+						setHue(col, cal.get(0));
+						setSelector(col, cal.get(0));
+						setCurrentColor(col, cal.get(0));
+						setNewColor(col, cal.get(0));
+					}
+				});
+			}
+		};
+	}();
+	$.fn.extend({
+		ColorPicker: ColorPicker.init,
+		ColorPickerHide: ColorPicker.hide,
+		ColorPickerShow: ColorPicker.show,
+		ColorPickerSetColor: ColorPicker.setColor
+	});
+})(jQuery)
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/eye.js
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/eye.js	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/eye.js	(revision 429)
@@ -0,0 +1,34 @@
+/**
+ *
+ * Zoomimage
+ * Author: Stefan Petre www.eyecon.ro
+ * 
+ */
+(function($){
+	var EYE = window.EYE = function() {
+		var _registered = {
+			init: []
+		};
+		return {
+			init: function() {
+				$.each(_registered.init, function(nr, fn){
+					fn.call();
+				});
+			},
+			extend: function(prop) {
+				for (var i in prop) {
+					if (prop[i] != undefined) {
+						this[i] = prop[i];
+					}
+				}
+			},
+			register: function(fn, type) {
+				if (!_registered[type]) {
+					_registered[type] = [];
+				}
+				_registered[type].push(fn);
+			}
+		};
+	}();
+	$(EYE.init);
+})(jQuery);
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/jquery.js
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/jquery.js	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/jquery.js	(revision 429)
@@ -0,0 +1,3549 @@
+(function(){
+/*
+ * jQuery 1.2.6 - New Wave Javascript
+ *
+ * Copyright (c) 2008 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $
+ * $Rev: 5685 $
+ */
+
+// Map over jQuery in case of overwrite
+var _jQuery = window.jQuery,
+// Map over the $ in case of overwrite
+	_$ = window.$;
+
+var jQuery = window.jQuery = window.$ = function( selector, context ) {
+	// The jQuery object is actually just the init constructor 'enhanced'
+	return new jQuery.fn.init( selector, context );
+};
+
+// A simple way to check for HTML strings or ID strings
+// (both of which we optimize for)
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
+
+// Is it a simple selector
+	isSimple = /^.[^:#\[\.]*$/,
+
+// Will speed up references to undefined, and allows munging its name.
+	undefined;
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		// Make sure that a selection was provided
+		selector = selector || document;
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this[0] = selector;
+			this.length = 1;
+			return this;
+		}
+		// Handle HTML strings
+		if ( typeof selector == "string" ) {
+			// Are we dealing with HTML string or an ID?
+			var match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] )
+					selector = jQuery.clean( [ match[1] ], context );
+
+				// HANDLE: $("#id")
+				else {
+					var elem = document.getElementById( match[3] );
+
+					// Make sure an element was located
+					if ( elem ){
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id != match[3] )
+							return jQuery().find( selector );
+
+						// Otherwise, we inject the element directly into the jQuery object
+						return jQuery( elem );
+					}
+					selector = [];
+				}
+
+			// HANDLE: $(expr, [context])
+			// (which is just equivalent to: $(content).find(expr)
+			} else
+				return jQuery( context ).find( selector );
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) )
+			return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
+
+		return this.setArray(jQuery.makeArray(selector));
+	},
+
+	// The current version of jQuery being used
+	jquery: "1.2.6",
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	// The number of elements contained in the matched element set
+	length: 0,
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == undefined ?
+
+			// Return a 'clean' array
+			jQuery.makeArray( this ) :
+
+			// Return just the object
+			this[ num ];
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery( elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Force the current matched set of elements to become
+	// the specified array of elements (destroying the stack in the process)
+	// You should use pushStack() in order to do this, but maintain the stack
+	setArray: function( elems ) {
+		// Resetting the length to 0, then using the native Array push
+		// is a super-fast way to populate an object with array-like properties
+		this.length = 0;
+		Array.prototype.push.apply( this, elems );
+
+		return this;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+		var ret = -1;
+
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem && elem.jquery ? elem[0] : elem
+		, this );
+	},
+
+	attr: function( name, value, type ) {
+		var options = name;
+
+		// Look for the case where we're accessing a style value
+		if ( name.constructor == String )
+			if ( value === undefined )
+				return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+			else {
+				options = {};
+				options[ name ] = value;
+			}
+
+		// Check to see if we're setting style values
+		return this.each(function(i){
+			// Set all the styles
+			for ( name in options )
+				jQuery.attr(
+					type ?
+						this.style :
+						this,
+					name, jQuery.prop( this, options[ name ], type, i, name )
+				);
+		});
+	},
+
+	css: function( key, value ) {
+		// ignore negative width and height values
+		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+			value = undefined;
+		return this.attr( key, value, "curCSS" );
+	},
+
+	text: function( text ) {
+		if ( typeof text != "object" && text != null )
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+		var ret = "";
+
+		jQuery.each( text || this, function(){
+			jQuery.each( this.childNodes, function(){
+				if ( this.nodeType != 8 )
+					ret += this.nodeType != 1 ?
+						this.nodeValue :
+						jQuery.fn.text( [ this ] );
+			});
+		});
+
+		return ret;
+	},
+
+	wrapAll: function( html ) {
+		if ( this[0] )
+			// The elements to wrap the target around
+			jQuery( html, this[0].ownerDocument )
+				.clone()
+				.insertBefore( this[0] )
+				.map(function(){
+					var elem = this;
+
+					while ( elem.firstChild )
+						elem = elem.firstChild;
+
+					return elem;
+				})
+				.append(this);
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		return this.each(function(){
+			jQuery( this ).contents().wrapAll( html );
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function(){
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, false, function(elem){
+			if (this.nodeType == 1)
+				this.appendChild( elem );
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, true, function(elem){
+			if (this.nodeType == 1)
+				this.insertBefore( elem, this.firstChild );
+		});
+	},
+
+	before: function() {
+		return this.domManip(arguments, false, false, function(elem){
+			this.parentNode.insertBefore( elem, this );
+		});
+	},
+
+	after: function() {
+		return this.domManip(arguments, false, true, function(elem){
+			this.parentNode.insertBefore( elem, this.nextSibling );
+		});
+	},
+
+	end: function() {
+		return this.prevObject || jQuery( [] );
+	},
+
+	find: function( selector ) {
+		var elems = jQuery.map(this, function(elem){
+			return jQuery.find( selector, elem );
+		});
+
+		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
+			jQuery.unique( elems ) :
+			elems );
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function(){
+			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to
+				// attributes in IE that are actually only stored
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var clone = this.cloneNode(true),
+					container = document.createElement("div");
+				container.appendChild(clone);
+				return jQuery.clean([container.innerHTML])[0];
+			} else
+				return this.cloneNode(true);
+		});
+
+		// Need to set the expando to null on the cloned set if it exists
+		// removeData doesn't work here, IE removes it from the original as well
+		// this is primarily for IE but the data expando shouldn't be copied over in any browser
+		var clone = ret.find("*").andSelf().each(function(){
+			if ( this[ expando ] != undefined )
+				this[ expando ] = null;
+		});
+
+		// Copy the events from the original to the clone
+		if ( events === true )
+			this.find("*").andSelf().each(function(i){
+				if (this.nodeType == 3)
+					return;
+				var events = jQuery.data( this, "events" );
+
+				for ( var type in events )
+					for ( var handler in events[ type ] )
+						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+			});
+
+		// Return the cloned set
+		return ret;
+	},
+
+	filter: function( selector ) {
+		return this.pushStack(
+			jQuery.isFunction( selector ) &&
+			jQuery.grep(this, function(elem, i){
+				return selector.call( elem, i );
+			}) ||
+
+			jQuery.multiFilter( selector, this ) );
+	},
+
+	not: function( selector ) {
+		if ( selector.constructor == String )
+			// test special case where just one selector is passed in
+			if ( isSimple.test( selector ) )
+				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
+			else
+				selector = jQuery.multiFilter( selector, this );
+
+		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+		return this.filter(function() {
+			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+		});
+	},
+
+	add: function( selector ) {
+		return this.pushStack( jQuery.unique( jQuery.merge(
+			this.get(),
+			typeof selector == 'string' ?
+				jQuery( selector ) :
+				jQuery.makeArray( selector )
+		)));
+	},
+
+	is: function( selector ) {
+		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+	},
+
+	hasClass: function( selector ) {
+		return this.is( "." + selector );
+	},
+
+	val: function( value ) {
+		if ( value == undefined ) {
+
+			if ( this.length ) {
+				var elem = this[0];
+
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type == "select-one";
+
+					// Nothing was selected
+					if ( index < 0 )
+						return null;
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						if ( option.selected ) {
+							// Get the specifc value for the option
+							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
+
+							// We don't need an array for one selects
+							if ( one )
+								return value;
+
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+
+					return values;
+
+				// Everything else, we just grab the value
+				} else
+					return (this[0].value || "").replace(/\r/g, "");
+
+			}
+
+			return undefined;
+		}
+
+		if( value.constructor == Number )
+			value += '';
+
+		return this.each(function(){
+			if ( this.nodeType != 1 )
+				return;
+
+			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
+				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+					jQuery.inArray(this.name, value) >= 0);
+
+			else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = jQuery.makeArray(value);
+
+				jQuery( "option", this ).each(function(){
+					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+						jQuery.inArray( this.text, values ) >= 0);
+				});
+
+				if ( !values.length )
+					this.selectedIndex = -1;
+
+			} else
+				this.value = value;
+		});
+	},
+
+	html: function( value ) {
+		return value == undefined ?
+			(this[0] ?
+				this[0].innerHTML :
+				null) :
+			this.empty().append( value );
+	},
+
+	replaceWith: function( value ) {
+		return this.after( value ).remove();
+	},
+
+	eq: function( i ) {
+		return this.slice( i, i + 1 );
+	},
+
+	slice: function() {
+		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function(elem, i){
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	},
+
+	data: function( key, value ){
+		var parts = key.split(".");
+		parts[1] = parts[1] ? "." + parts[1] : "";
+
+		if ( value === undefined ) {
+			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+			if ( data === undefined && this.length )
+				data = jQuery.data( this[0], key );
+
+			return data === undefined && parts[1] ?
+				this.data( parts[0] ) :
+				data;
+		} else
+			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+				jQuery.data( this, key, value );
+			});
+	},
+
+	removeData: function( key ){
+		return this.each(function(){
+			jQuery.removeData( this, key );
+		});
+	},
+
+	domManip: function( args, table, reverse, callback ) {
+		var clone = this.length > 1, elems;
+
+		return this.each(function(){
+			if ( !elems ) {
+				elems = jQuery.clean( args, this.ownerDocument );
+
+				if ( reverse )
+					elems.reverse();
+			}
+
+			var obj = this;
+
+			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
+				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
+
+			var scripts = jQuery( [] );
+
+			jQuery.each(elems, function(){
+				var elem = clone ?
+					jQuery( this ).clone( true )[0] :
+					this;
+
+				// execute all scripts after the elements have been injected
+				if ( jQuery.nodeName( elem, "script" ) )
+					scripts = scripts.add( elem );
+				else {
+					// Remove any inner scripts for later evaluation
+					if ( elem.nodeType == 1 )
+						scripts = scripts.add( jQuery( "script", elem ).remove() );
+
+					// Inject the elements into the document
+					callback.call( obj, elem );
+				}
+			});
+
+			scripts.each( evalScript );
+		});
+	}
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+	if ( elem.src )
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+
+	else
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+	if ( elem.parentNode )
+		elem.parentNode.removeChild( elem );
+}
+
+function now(){
+	return +new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+	// copy reference to target object
+	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+	// Handle a deep copy situation
+	if ( target.constructor == Boolean ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target != "object" && typeof target != "function" )
+		target = {};
+
+	// extend jQuery itself if only one argument is passed
+	if ( length == i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ )
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null )
+			// Extend the base object
+			for ( var name in options ) {
+				var src = target[ name ], copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy )
+					continue;
+
+				// Recurse if we're merging object values
+				if ( deep && copy && typeof copy == "object" && !copy.nodeType )
+					target[ name ] = jQuery.extend( deep, 
+						// Never move original objects, clone them
+						src || ( copy.length != null ? [ ] : { } )
+					, copy );
+
+				// Don't bring in undefined values
+				else if ( copy !== undefined )
+					target[ name ] = copy;
+
+			}
+
+	// Return the modified object
+	return target;
+};
+
+var expando = "jQuery" + now(), uuid = 0, windowData = {},
+	// exclude the following css properties to add px
+	exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+	// cache defaultView
+	defaultView = document.defaultView || {};
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep )
+			window.jQuery = _jQuery;
+
+		return jQuery;
+	},
+
+	// See test/unit/core.js for details concerning this function.
+	isFunction: function( fn ) {
+		return !!fn && typeof fn != "string" && !fn.nodeName &&
+			fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
+	},
+
+	// check if an element is in a (or is an) XML document
+	isXMLDoc: function( elem ) {
+		return elem.documentElement && !elem.body ||
+			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+	},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		data = jQuery.trim( data );
+
+		if ( data ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+			if ( jQuery.browser.msie )
+				script.text = data;
+			else
+				script.appendChild( document.createTextNode( data ) );
+
+			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+			// This arises when a base node is used (#2709).
+			head.insertBefore( script, head.firstChild );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+	},
+
+	cache: {},
+
+	data: function( elem, name, data ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// Compute a unique ID for the element
+		if ( !id )
+			id = elem[ expando ] = ++uuid;
+
+		// Only generate the data cache if we're
+		// trying to access or manipulate it
+		if ( name && !jQuery.cache[ id ] )
+			jQuery.cache[ id ] = {};
+
+		// Prevent overriding the named cache with undefined values
+		if ( data !== undefined )
+			jQuery.cache[ id ][ name ] = data;
+
+		// Return the named cache data, or the ID for the element
+		return name ?
+			jQuery.cache[ id ][ name ] :
+			id;
+	},
+
+	removeData: function( elem, name ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// If we want to remove a specific section of the element's data
+		if ( name ) {
+			if ( jQuery.cache[ id ] ) {
+				// Remove the section of cache data
+				delete jQuery.cache[ id ][ name ];
+
+				// If we've removed all the data, remove the element's cache
+				name = "";
+
+				for ( name in jQuery.cache[ id ] )
+					break;
+
+				if ( !name )
+					jQuery.removeData( elem );
+			}
+
+		// Otherwise, we want to remove all of the element's data
+		} else {
+			// Clean up the element expando
+			try {
+				delete elem[ expando ];
+			} catch(e){
+				// IE has trouble directly removing the expando
+				// but it's ok with using removeAttribute
+				if ( elem.removeAttribute )
+					elem.removeAttribute( expando );
+			}
+
+			// Completely remove the data cache
+			delete jQuery.cache[ id ];
+		}
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0, length = object.length;
+
+		if ( args ) {
+			if ( length == undefined ) {
+				for ( name in object )
+					if ( callback.apply( object[ name ], args ) === false )
+						break;
+			} else
+				for ( ; i < length; )
+					if ( callback.apply( object[ i++ ], args ) === false )
+						break;
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( length == undefined ) {
+				for ( name in object )
+					if ( callback.call( object[ name ], name, object[ name ] ) === false )
+						break;
+			} else
+				for ( var value = object[0];
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+		}
+
+		return object;
+	},
+
+	prop: function( elem, value, type, i, name ) {
+		// Handle executable functions
+		if ( jQuery.isFunction( value ) )
+			value = value.call( elem, i );
+
+		// Handle passing in a number to a CSS property
+		return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
+			value + "px" :
+			value;
+	},
+
+	className: {
+		// internal only, use addClass("class")
+		add: function( elem, classNames ) {
+			jQuery.each((classNames || "").split(/\s+/), function(i, className){
+				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+					elem.className += (elem.className ? " " : "") + className;
+			});
+		},
+
+		// internal only, use removeClass("class")
+		remove: function( elem, classNames ) {
+			if (elem.nodeType == 1)
+				elem.className = classNames != undefined ?
+					jQuery.grep(elem.className.split(/\s+/), function(className){
+						return !jQuery.className.has( classNames, className );
+					}).join(" ") :
+					"";
+		},
+
+		// internal only, use hasClass("class")
+		has: function( elem, className ) {
+			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( var name in options )
+			elem.style[ name ] = old[ name ];
+	},
+
+	css: function( elem, name, force ) {
+		if ( name == "width" || name == "height" ) {
+			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+			function getWH() {
+				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+				var padding = 0, border = 0;
+				jQuery.each( which, function() {
+					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+				});
+				val -= Math.round(padding + border);
+			}
+
+			if ( jQuery(elem).is(":visible") )
+				getWH();
+			else
+				jQuery.swap( elem, props, getWH );
+
+			return Math.max(0, val);
+		}
+
+		return jQuery.curCSS( elem, name, force );
+	},
+
+	curCSS: function( elem, name, force ) {
+		var ret, style = elem.style;
+
+		// A helper method for determining if an element's values are broken
+		function color( elem ) {
+			if ( !jQuery.browser.safari )
+				return false;
+
+			// defaultView is cached
+			var ret = defaultView.getComputedStyle( elem, null );
+			return !ret || ret.getPropertyValue("color") == "";
+		}
+
+		// We need to handle opacity special in IE
+		if ( name == "opacity" && jQuery.browser.msie ) {
+			ret = jQuery.attr( style, "opacity" );
+
+			return ret == "" ?
+				"1" :
+				ret;
+		}
+		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
+		if ( jQuery.browser.opera && name == "display" ) {
+			var save = style.outline;
+			style.outline = "0 solid black";
+			style.outline = save;
+		}
+
+		// Make sure we're using the right name for getting the float value
+		if ( name.match( /float/i ) )
+			name = styleFloat;
+
+		if ( !force && style && style[ name ] )
+			ret = style[ name ];
+
+		else if ( defaultView.getComputedStyle ) {
+
+			// Only "float" is needed here
+			if ( name.match( /float/i ) )
+				name = "float";
+
+			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+			var computedStyle = defaultView.getComputedStyle( elem, null );
+
+			if ( computedStyle && !color( elem ) )
+				ret = computedStyle.getPropertyValue( name );
+
+			// If the element isn't reporting its values properly in Safari
+			// then some display: none elements are involved
+			else {
+				var swap = [], stack = [], a = elem, i = 0;
+
+				// Locate all of the parent display: none elements
+				for ( ; a && color(a); a = a.parentNode )
+					stack.unshift(a);
+
+				// Go through and make them visible, but in reverse
+				// (It would be better if we knew the exact display type that they had)
+				for ( ; i < stack.length; i++ )
+					if ( color( stack[ i ] ) ) {
+						swap[ i ] = stack[ i ].style.display;
+						stack[ i ].style.display = "block";
+					}
+
+				// Since we flip the display style, we have to handle that
+				// one special, otherwise get the value
+				ret = name == "display" && swap[ stack.length - 1 ] != null ?
+					"none" :
+					( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
+
+				// Finally, revert the display styles back
+				for ( i = 0; i < swap.length; i++ )
+					if ( swap[ i ] != null )
+						stack[ i ].style.display = swap[ i ];
+			}
+
+			// We should always get a number back from opacity
+			if ( name == "opacity" && ret == "" )
+				ret = "1";
+
+		} else if ( elem.currentStyle ) {
+			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+			// From the awesome hack by Dean Edwards
+			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+			// If we're not dealing with a regular pixel number
+			// but a number that has a weird ending, we need to convert it to pixels
+			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+				// Remember the original values
+				var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+				// Put in the new values to get a computed value out
+				elem.runtimeStyle.left = elem.currentStyle.left;
+				style.left = ret || 0;
+				ret = style.pixelLeft + "px";
+
+				// Revert the changed values
+				style.left = left;
+				elem.runtimeStyle.left = rsLeft;
+			}
+		}
+
+		return ret;
+	},
+
+	clean: function( elems, context ) {
+		var ret = [];
+		context = context || document;
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if (typeof context.createElement == 'undefined')
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+		jQuery.each(elems, function(i, elem){
+			if ( !elem )
+				return;
+
+			if ( elem.constructor == Number )
+				elem += '';
+
+			// Convert html string into DOM nodes
+			if ( typeof elem == "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+						all :
+						front + "></" + tag + ">";
+				});
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
+
+				var wrap =
+					// option or optgroup
+					!tags.indexOf("<opt") &&
+					[ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+					!tags.indexOf("<leg") &&
+					[ 1, "<fieldset>", "</fieldset>" ] ||
+
+					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+					[ 1, "<table>", "</table>" ] ||
+
+					!tags.indexOf("<tr") &&
+					[ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+				 	// <thead> matched above
+					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+					!tags.indexOf("<col") &&
+					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+					// IE can't serialize <link> and <script> tags normally
+					jQuery.browser.msie &&
+					[ 1, "div<div>", "</div>" ] ||
+
+					[ 0, "", "" ];
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+
+				// Move to the right depth
+				while ( wrap[0]-- )
+					div = div.lastChild;
+
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( jQuery.browser.msie ) {
+
+					// String was a <table>, *may* have spurious <tbody>
+					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
+						div.firstChild && div.firstChild.childNodes :
+
+						// String was a bare <thead> or <tfoot>
+						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+							div.childNodes :
+							[];
+
+					for ( var j = tbody.length - 1; j >= 0 ; --j )
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
+					// IE completely kills leading whitespace when innerHTML is used
+					if ( /^\s/.test( elem ) )
+						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+
+				}
+
+				elem = jQuery.makeArray( div.childNodes );
+			}
+
+			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
+				return;
+
+			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
+				ret.push( elem );
+
+			else
+				ret = jQuery.merge( ret, elem );
+
+		});
+
+		return ret;
+	},
+
+	attr: function( elem, name, value ) {
+		// don't set attributes on text and comment nodes
+		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+			return undefined;
+
+		var notxml = !jQuery.isXMLDoc( elem ),
+			// Whether we are setting (or getting)
+			set = value !== undefined,
+			msie = jQuery.browser.msie;
+
+		// Try to normalize/fix the name
+		name = notxml && jQuery.props[ name ] || name;
+
+		// Only do all the following if this is a node (faster for style)
+		// IE elem.getAttribute passes even for style
+		if ( elem.tagName ) {
+
+			// These attributes require special treatment
+			var special = /href|src|style/.test( name );
+
+			// Safari mis-reports the default selected property of a hidden option
+			// Accessing the parent's selectedIndex property fixes it
+			if ( name == "selected" && jQuery.browser.safari )
+				elem.parentNode.selectedIndex;
+
+			// If applicable, access the attribute via the DOM 0 way
+			if ( name in elem && notxml && !special ) {
+				if ( set ){
+					// We can't allow the type property to be changed (since it causes problems in IE)
+					if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+						throw "type property can't be changed";
+
+					elem[ name ] = value;
+				}
+
+				// browsers index elements by id/name on forms, give priority to attributes.
+				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+					return elem.getAttributeNode( name ).nodeValue;
+
+				return elem[ name ];
+			}
+
+			if ( msie && notxml &&  name == "style" )
+				return jQuery.attr( elem.style, "cssText", value );
+
+			if ( set )
+				// convert the value to a string (all browsers do this but IE) see #1070
+				elem.setAttribute( name, "" + value );
+
+			var attr = msie && notxml && special
+					// Some attributes require a special call on IE
+					? elem.getAttribute( name, 2 )
+					: elem.getAttribute( name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return attr === null ? undefined : attr;
+		}
+
+		// elem is actually elem.style ... set the style
+
+		// IE uses filters for opacity
+		if ( msie && name == "opacity" ) {
+			if ( set ) {
+				// IE has trouble with opacity if it does not have layout
+				// Force it by setting the zoom level
+				elem.zoom = 1;
+
+				// Set the alpha filter to set the opacity
+				elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+			}
+
+			return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+				(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+				"";
+		}
+
+		name = name.replace(/-([a-z])/ig, function(all, letter){
+			return letter.toUpperCase();
+		});
+
+		if ( set )
+			elem[ name ] = value;
+
+		return elem[ name ];
+	},
+
+	trim: function( text ) {
+		return (text || "").replace( /^\s+|\s+$/g, "" );
+	},
+
+	makeArray: function( array ) {
+		var ret = [];
+
+		if( array != null ){
+			var i = array.length;
+			//the window, strings and functions also have 'length'
+			if( i == null || array.split || array.setInterval || array.call )
+				ret[0] = array;
+			else
+				while( i )
+					ret[--i] = array[i];
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		for ( var i = 0, length = array.length; i < length; i++ )
+		// Use === because on IE, window == document
+			if ( array[ i ] === elem )
+				return i;
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		// We have to loop this way because IE & Opera overwrite the length
+		// expando of getElementsByTagName
+		var i = 0, elem, pos = first.length;
+		// Also, we need to make sure that the correct elements are being returned
+		// (IE returns comment nodes in a '*' query)
+		if ( jQuery.browser.msie ) {
+			while ( elem = second[ i++ ] )
+				if ( elem.nodeType != 8 )
+					first[ pos++ ] = elem;
+
+		} else
+			while ( elem = second[ i++ ] )
+				first[ pos++ ] = elem;
+
+		return first;
+	},
+
+	unique: function( array ) {
+		var ret = [], done = {};
+
+		try {
+
+			for ( var i = 0, length = array.length; i < length; i++ ) {
+				var id = jQuery.data( array[ i ] );
+
+				if ( !done[ id ] ) {
+					done[ id ] = true;
+					ret.push( array[ i ] );
+				}
+			}
+
+		} catch( e ) {
+			ret = array;
+		}
+
+		return ret;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [];
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ )
+			if ( !inv != !callback( elems[ i ], i ) )
+				ret.push( elems[ i ] );
+
+		return ret;
+	},
+
+	map: function( elems, callback ) {
+		var ret = [];
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			var value = callback( elems[ i ], i );
+
+			if ( value != null )
+				ret[ ret.length ] = value;
+		}
+
+		return ret.concat.apply( [], ret );
+	}
+});
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
+	safari: /webkit/.test( userAgent ),
+	opera: /opera/.test( userAgent ),
+	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+var styleFloat = jQuery.browser.msie ?
+	"styleFloat" :
+	"cssFloat";
+
+jQuery.extend({
+	// Check to see if the W3C box model is being used
+	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
+
+	props: {
+		"for": "htmlFor",
+		"class": "className",
+		"float": styleFloat,
+		cssFloat: styleFloat,
+		styleFloat: styleFloat,
+		readonly: "readOnly",
+		maxlength: "maxLength",
+		cellspacing: "cellSpacing"
+	}
+});
+
+jQuery.each({
+	parent: function(elem){return elem.parentNode;},
+	parents: function(elem){return jQuery.dir(elem,"parentNode");},
+	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+	children: function(elem){return jQuery.sibling(elem.firstChild);},
+	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = jQuery.map( this, fn );
+
+		if ( selector && typeof selector == "string" )
+			ret = jQuery.multiFilter( selector, ret );
+
+		return this.pushStack( jQuery.unique( ret ) );
+	};
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function(name, original){
+	jQuery.fn[ name ] = function() {
+		var args = arguments;
+
+		return this.each(function(){
+			for ( var i = 0, length = args.length; i < length; i++ )
+				jQuery( args[ i ] )[ original ]( this );
+		});
+	};
+});
+
+jQuery.each({
+	removeAttr: function( name ) {
+		jQuery.attr( this, name, "" );
+		if (this.nodeType == 1)
+			this.removeAttribute( name );
+	},
+
+	addClass: function( classNames ) {
+		jQuery.className.add( this, classNames );
+	},
+
+	removeClass: function( classNames ) {
+		jQuery.className.remove( this, classNames );
+	},
+
+	toggleClass: function( classNames ) {
+		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
+	},
+
+	remove: function( selector ) {
+		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
+			// Prevent memory leaks
+			jQuery( "*", this ).add(this).each(function(){
+				jQuery.event.remove(this);
+				jQuery.removeData(this);
+			});
+			if (this.parentNode)
+				this.parentNode.removeChild( this );
+		}
+	},
+
+	empty: function() {
+		// Remove element nodes and prevent memory leaks
+		jQuery( ">*", this ).remove();
+
+		// Remove any remaining nodes
+		while ( this.firstChild )
+			this.removeChild( this.firstChild );
+	}
+}, function(name, fn){
+	jQuery.fn[ name ] = function(){
+		return this.each( fn, arguments );
+	};
+});
+
+jQuery.each([ "Height", "Width" ], function(i, name){
+	var type = name.toLowerCase();
+
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		return this[0] == window ?
+			// Opera reports document.body.client[Width/Height] properly in both quirks and standards
+			jQuery.browser.opera && document.body[ "client" + name ] ||
+
+			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
+			jQuery.browser.safari && window[ "inner" + name ] ||
+
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
+
+			// Get document width or height
+			this[0] == document ?
+				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+				Math.max(
+					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
+					Math.max(document.body["offset" + name], document.documentElement["offset" + name])
+				) :
+
+				// Get or set width or height on the element
+				size == undefined ?
+					// Get width or height on the element
+					(this.length ? jQuery.css( this[0], type ) : null) :
+
+					// Set the width or height on the element (default to pixels if value is unitless)
+					this.css( type, size.constructor == String ? size : size + "px" );
+	};
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+	return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
+		"(?:[\\w*_-]|\\\\.)" :
+		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
+	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
+	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
+	quickClass = new RegExp("^([#.]?)(" + chars + "*)");
+
+jQuery.extend({
+	expr: {
+		"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
+		"#": function(a,i,m){return a.getAttribute("id")==m[2];},
+		":": {
+			// Position Checks
+			lt: function(a,i,m){return i<m[3]-0;},
+			gt: function(a,i,m){return i>m[3]-0;},
+			nth: function(a,i,m){return m[3]-0==i;},
+			eq: function(a,i,m){return m[3]-0==i;},
+			first: function(a,i){return i==0;},
+			last: function(a,i,m,r){return i==r.length-1;},
+			even: function(a,i){return i%2==0;},
+			odd: function(a,i){return i%2;},
+
+			// Child Checks
+			"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
+			"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
+			"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
+
+			// Parent Checks
+			parent: function(a){return a.firstChild;},
+			empty: function(a){return !a.firstChild;},
+
+			// Text Check
+			contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
+
+			// Visibility
+			visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
+			hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
+
+			// Form attributes
+			enabled: function(a){return !a.disabled;},
+			disabled: function(a){return a.disabled;},
+			checked: function(a){return a.checked;},
+			selected: function(a){return a.selected||jQuery.attr(a,"selected");},
+
+			// Form elements
+			text: function(a){return "text"==a.type;},
+			radio: function(a){return "radio"==a.type;},
+			checkbox: function(a){return "checkbox"==a.type;},
+			file: function(a){return "file"==a.type;},
+			password: function(a){return "password"==a.type;},
+			submit: function(a){return "submit"==a.type;},
+			image: function(a){return "image"==a.type;},
+			reset: function(a){return "reset"==a.type;},
+			button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
+			input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
+
+			// :has()
+			has: function(a,i,m){return jQuery.find(m[3],a).length;},
+
+			// :header
+			header: function(a){return /h\d/i.test(a.nodeName);},
+
+			// :animated
+			animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
+		}
+	},
+
+	// The regular expressions that power the parsing engine
+	parse: [
+		// Match: [@value='test'], [@foo]
+		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
+
+		// Match: :contains('foo')
+		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
+
+		// Match: :even, :last-child, #id, .class
+		new RegExp("^([:.#]*)(" + chars + "+)")
+	],
+
+	multiFilter: function( expr, elems, not ) {
+		var old, cur = [];
+
+		while ( expr && expr != old ) {
+			old = expr;
+			var f = jQuery.filter( expr, elems, not );
+			expr = f.t.replace(/^\s*,\s*/, "" );
+			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
+		}
+
+		return cur;
+	},
+
+	find: function( t, context ) {
+		// Quickly handle non-string expressions
+		if ( typeof t != "string" )
+			return [ t ];
+
+		// check to make sure context is a DOM element or a document
+		if ( context && context.nodeType != 1 && context.nodeType != 9)
+			return [ ];
+
+		// Set the correct context (if none is provided)
+		context = context || document;
+
+		// Initialize the search
+		var ret = [context], done = [], last, nodeName;
+
+		// Continue while a selector expression exists, and while
+		// we're no longer looping upon ourselves
+		while ( t && last != t ) {
+			var r = [];
+			last = t;
+
+			t = jQuery.trim(t);
+
+			var foundToken = false,
+
+			// An attempt at speeding up child selectors that
+			// point to a specific element tag
+				re = quickChild,
+
+				m = re.exec(t);
+
+			if ( m ) {
+				nodeName = m[1].toUpperCase();
+
+				// Perform our own iteration and filter
+				for ( var i = 0; ret[i]; i++ )
+					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
+						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
+							r.push( c );
+
+				ret = r;
+				t = t.replace( re, "" );
+				if ( t.indexOf(" ") == 0 ) continue;
+				foundToken = true;
+			} else {
+				re = /^([>+~])\s*(\w*)/i;
+
+				if ( (m = re.exec(t)) != null ) {
+					r = [];
+
+					var merge = {};
+					nodeName = m[2].toUpperCase();
+					m = m[1];
+
+					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
+						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
+						for ( ; n; n = n.nextSibling )
+							if ( n.nodeType == 1 ) {
+								var id = jQuery.data(n);
+
+								if ( m == "~" && merge[id] ) break;
+
+								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
+									if ( m == "~" ) merge[id] = true;
+									r.push( n );
+								}
+
+								if ( m == "+" ) break;
+							}
+					}
+
+					ret = r;
+
+					// And remove the token
+					t = jQuery.trim( t.replace( re, "" ) );
+					foundToken = true;
+				}
+			}
+
+			// See if there's still an expression, and that we haven't already
+			// matched a token
+			if ( t && !foundToken ) {
+				// Handle multiple expressions
+				if ( !t.indexOf(",") ) {
+					// Clean the result set
+					if ( context == ret[0] ) ret.shift();
+
+					// Merge the result sets
+					done = jQuery.merge( done, ret );
+
+					// Reset the context
+					r = ret = [context];
+
+					// Touch up the selector string
+					t = " " + t.substr(1,t.length);
+
+				} else {
+					// Optimize for the case nodeName#idName
+					var re2 = quickID;
+					var m = re2.exec(t);
+
+					// Re-organize the results, so that they're consistent
+					if ( m ) {
+						m = [ 0, m[2], m[3], m[1] ];
+
+					} else {
+						// Otherwise, do a traditional filter check for
+						// ID, class, and element selectors
+						re2 = quickClass;
+						m = re2.exec(t);
+					}
+
+					m[2] = m[2].replace(/\\/g, "");
+
+					var elem = ret[ret.length-1];
+
+					// Try to do a global search by ID, where we can
+					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
+						// Optimization for HTML document case
+						var oid = elem.getElementById(m[2]);
+
+						// Do a quick check for the existence of the actual ID attribute
+						// to avoid selecting by the name attribute in IE
+						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
+						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
+							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
+
+						// Do a quick check for node name (where applicable) so
+						// that div#foo searches will be really fast
+						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
+					} else {
+						// We need to find all descendant elements
+						for ( var i = 0; ret[i]; i++ ) {
+							// Grab the tag name being searched for
+							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
+
+							// Handle IE7 being really dumb about <object>s
+							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
+								tag = "param";
+
+							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
+						}
+
+						// It's faster to filter by class and be done with it
+						if ( m[1] == "." )
+							r = jQuery.classFilter( r, m[2] );
+
+						// Same with ID filtering
+						if ( m[1] == "#" ) {
+							var tmp = [];
+
+							// Try to find the element with the ID
+							for ( var i = 0; r[i]; i++ )
+								if ( r[i].getAttribute("id") == m[2] ) {
+									tmp = [ r[i] ];
+									break;
+								}
+
+							r = tmp;
+						}
+
+						ret = r;
+					}
+
+					t = t.replace( re2, "" );
+				}
+
+			}
+
+			// If a selector string still exists
+			if ( t ) {
+				// Attempt to filter it
+				var val = jQuery.filter(t,r);
+				ret = r = val.r;
+				t = jQuery.trim(val.t);
+			}
+		}
+
+		// An error occurred with the selector;
+		// just return an empty set instead
+		if ( t )
+			ret = [];
+
+		// Remove the root context
+		if ( ret && context == ret[0] )
+			ret.shift();
+
+		// And combine the results
+		done = jQuery.merge( done, ret );
+
+		return done;
+	},
+
+	classFilter: function(r,m,not){
+		m = " " + m + " ";
+		var tmp = [];
+		for ( var i = 0; r[i]; i++ ) {
+			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
+			if ( !not && pass || not && !pass )
+				tmp.push( r[i] );
+		}
+		return tmp;
+	},
+
+	filter: function(t,r,not) {
+		var last;
+
+		// Look for common filter expressions
+		while ( t && t != last ) {
+			last = t;
+
+			var p = jQuery.parse, m;
+
+			for ( var i = 0; p[i]; i++ ) {
+				m = p[i].exec( t );
+
+				if ( m ) {
+					// Remove what we just matched
+					t = t.substring( m[0].length );
+
+					m[2] = m[2].replace(/\\/g, "");
+					break;
+				}
+			}
+
+			if ( !m )
+				break;
+
+			// :not() is a special case that can be optimized by
+			// keeping it out of the expression list
+			if ( m[1] == ":" && m[2] == "not" )
+				// optimize if only one selector found (most common case)
+				r = isSimple.test( m[3] ) ?
+					jQuery.filter(m[3], r, true).r :
+					jQuery( r ).not( m[3] );
+
+			// We can get a big speed boost by filtering by class here
+			else if ( m[1] == "." )
+				r = jQuery.classFilter(r, m[2], not);
+
+			else if ( m[1] == "[" ) {
+				var tmp = [], type = m[3];
+
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
+
+					if ( z == null || /href|src|selected/.test(m[2]) )
+						z = jQuery.attr(a,m[2]) || '';
+
+					if ( (type == "" && !!z ||
+						 type == "=" && z == m[5] ||
+						 type == "!=" && z != m[5] ||
+						 type == "^=" && z && !z.indexOf(m[5]) ||
+						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
+						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
+							tmp.push( a );
+				}
+
+				r = tmp;
+
+			// We can get a speed boost by handling nth-child here
+			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
+				var merge = {}, tmp = [],
+					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
+						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
+					// calculate the numbers (first)n+(last) including if they are negative
+					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
+
+				// loop through all the elements left in the jQuery object
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
+
+					if ( !merge[id] ) {
+						var c = 1;
+
+						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
+							if ( n.nodeType == 1 )
+								n.nodeIndex = c++;
+
+						merge[id] = true;
+					}
+
+					var add = false;
+
+					if ( first == 0 ) {
+						if ( node.nodeIndex == last )
+							add = true;
+					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
+						add = true;
+
+					if ( add ^ not )
+						tmp.push( node );
+				}
+
+				r = tmp;
+
+			// Otherwise, find the expression to execute
+			} else {
+				var fn = jQuery.expr[ m[1] ];
+				if ( typeof fn == "object" )
+					fn = fn[ m[2] ];
+
+				if ( typeof fn == "string" )
+					fn = eval("false||function(a,i){return " + fn + ";}");
+
+				// Execute it against the current filter
+				r = jQuery.grep( r, function(elem, i){
+					return fn(elem, i, m, r);
+				}, not );
+			}
+		}
+
+		// Return an array of filtered elements (r)
+		// and the modified expression string (t)
+		return { r: r, t: t };
+	},
+
+	dir: function( elem, dir ){
+		var matched = [],
+			cur = elem[dir];
+		while ( cur && cur != document ) {
+			if ( cur.nodeType == 1 )
+				matched.push( cur );
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	nth: function(cur,result,dir,elem){
+		result = result || 1;
+		var num = 0;
+
+		for ( ; cur; cur = cur[dir] )
+			if ( cur.nodeType == 1 && ++num == result )
+				break;
+
+		return cur;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType == 1 && n != elem )
+				r.push( n );
+		}
+
+		return r;
+	}
+});
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code orignated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function(elem, types, handler, data) {
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( jQuery.browser.msie && elem.setInterval )
+			elem = window;
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid )
+			handler.guid = this.guid++;
+
+		// if data is passed, bind to handler
+		if( data != undefined ) {
+			// Create temporary function pointer to original handler
+			var fn = handler;
+
+			// Create unique handler function, wrapped around original handler
+			handler = this.proxy( fn, function() {
+				// Pass arguments and context to original handler
+				return fn.apply(this, arguments);
+			});
+
+			// Store data in unique handler
+			handler.data = data;
+		}
+
+		// Init the element's event structure
+		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
+					return jQuery.event.handle.apply(arguments.callee.elem, arguments);
+			});
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native
+		// event in IE.
+		handle.elem = elem;
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		jQuery.each(types.split(/\s+/), function(index, type) {
+			// Namespaced event handlers
+			var parts = type.split(".");
+			type = parts[0];
+			handler.type = parts[1];
+
+			// Get the current list of functions bound to this event
+			var handlers = events[type];
+
+			// Init the event handler queue
+			if (!handlers) {
+				handlers = events[type] = {};
+
+				// Check for a special event handler
+				// Only use addEventListener/attachEvent if the special
+				// events handler returns false
+				if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
+					// Bind the global event handler to the element
+					if (elem.addEventListener)
+						elem.addEventListener(type, handle, false);
+					else if (elem.attachEvent)
+						elem.attachEvent("on" + type, handle);
+				}
+			}
+
+			// Add the function to the element's handler list
+			handlers[handler.guid] = handler;
+
+			// Keep track of which events have been used, for global triggering
+			jQuery.event.global[type] = true;
+		});
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	guid: 1,
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function(elem, types, handler) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		var events = jQuery.data(elem, "events"), ret, index;
+
+		if ( events ) {
+			// Unbind all events for the element
+			if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
+				for ( var type in events )
+					this.remove( elem, type + (types || "") );
+			else {
+				// types is actually an event object here
+				if ( types.type ) {
+					handler = types.handler;
+					types = types.type;
+				}
+
+				// Handle multiple events seperated by a space
+				// jQuery(...).unbind("mouseover mouseout", fn);
+				jQuery.each(types.split(/\s+/), function(index, type){
+					// Namespaced event handlers
+					var parts = type.split(".");
+					type = parts[0];
+
+					if ( events[type] ) {
+						// remove the given handler for the given type
+						if ( handler )
+							delete events[type][handler.guid];
+
+						// remove all handlers for the given type
+						else
+							for ( handler in events[type] )
+								// Handle the removal of namespaced events
+								if ( !parts[1] || events[type][handler].type == parts[1] )
+									delete events[type][handler];
+
+						// remove generic event handler if no more handlers exist
+						for ( ret in events[type] ) break;
+						if ( !ret ) {
+							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
+								if (elem.removeEventListener)
+									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+								else if (elem.detachEvent)
+									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+							}
+							ret = null;
+							delete events[type];
+						}
+					}
+				});
+			}
+
+			// Remove the expando if it's no longer used
+			for ( ret in events ) break;
+			if ( !ret ) {
+				var handle = jQuery.data( elem, "handle" );
+				if ( handle ) handle.elem = null;
+				jQuery.removeData( elem, "events" );
+				jQuery.removeData( elem, "handle" );
+			}
+		}
+	},
+
+	trigger: function(type, data, elem, donative, extra) {
+		// Clone the incoming data, if any
+		data = jQuery.makeArray(data);
+
+		if ( type.indexOf("!") >= 0 ) {
+			type = type.slice(0, -1);
+			var exclusive = true;
+		}
+
+		// Handle a global trigger
+		if ( !elem ) {
+			// Only trigger if we've ever bound an event for it
+			if ( this.global[type] )
+				jQuery("*").add([window, document]).trigger(type, data);
+
+		// Handle triggering a single element
+		} else {
+			// don't do events on text and comment nodes
+			if ( elem.nodeType == 3 || elem.nodeType == 8 )
+				return undefined;
+
+			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
+				// Check to see if we need to provide a fake event, or not
+				event = !data[0] || !data[0].preventDefault;
+
+			// Pass along a fake event
+			if ( event ) {
+				data.unshift({
+					type: type,
+					target: elem,
+					preventDefault: function(){},
+					stopPropagation: function(){},
+					timeStamp: now()
+				});
+				data[0][expando] = true; // no need to fix fake event
+			}
+
+			// Enforce the right trigger type
+			data[0].type = type;
+			if ( exclusive )
+				data[0].exclusive = true;
+
+			// Trigger the event, it is assumed that "handle" is a function
+			var handle = jQuery.data(elem, "handle");
+			if ( handle )
+				val = handle.apply( elem, data );
+
+			// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+			if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+				val = false;
+
+			// Extra functions don't get the custom event object
+			if ( event )
+				data.shift();
+
+			// Handle triggering of extra function
+			if ( extra && jQuery.isFunction( extra ) ) {
+				// call the extra function and tack the current return value on the end for possible inspection
+				ret = extra.apply( elem, val == null ? data : data.concat( val ) );
+				// if anything is returned, give it precedence and have it overwrite the previous value
+				if (ret !== undefined)
+					val = ret;
+			}
+
+			// Trigger the native events (except for clicks on links)
+			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+				this.triggered = true;
+				try {
+					elem[ type ]();
+				// prevent IE from throwing an error for some hidden elements
+				} catch (e) {}
+			}
+
+			this.triggered = false;
+		}
+
+		return val;
+	},
+
+	handle: function(event) {
+		// returned undefined or false
+		var val, ret, namespace, all, handlers;
+
+		event = arguments[0] = jQuery.event.fix( event || window.event );
+
+		// Namespaced event handlers
+		namespace = event.type.split(".");
+		event.type = namespace[0];
+		namespace = namespace[1];
+		// Cache this now, all = true means, any handler
+		all = !namespace && !event.exclusive;
+
+		handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+		for ( var j in handlers ) {
+			var handler = handlers[j];
+
+			// Filter the functions by class
+			if ( all || handler.type == namespace ) {
+				// Pass in a reference to the handler function itself
+				// So that we can later remove it
+				event.handler = handler;
+				event.data = handler.data;
+
+				ret = handler.apply( this, arguments );
+
+				if ( val !== false )
+					val = ret;
+
+				if ( ret === false ) {
+					event.preventDefault();
+					event.stopPropagation();
+				}
+			}
+		}
+
+		return val;
+	},
+
+	fix: function(event) {
+		if ( event[expando] == true )
+			return event;
+
+		// store a copy of the original event object
+		// and "clone" to set read-only properties
+		var originalEvent = event;
+		event = { originalEvent: originalEvent };
+		var props = "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");
+		for ( var i=props.length; i; i-- )
+			event[ props[i] ] = originalEvent[ props[i] ];
+
+		// Mark it as fixed
+		event[expando] = true;
+
+		// add preventDefault and stopPropagation since
+		// they will not work on the clone
+		event.preventDefault = function() {
+			// if preventDefault exists run it on the original event
+			if (originalEvent.preventDefault)
+				originalEvent.preventDefault();
+			// otherwise set the returnValue property of the original event to false (IE)
+			originalEvent.returnValue = false;
+		};
+		event.stopPropagation = function() {
+			// if stopPropagation exists run it on the original event
+			if (originalEvent.stopPropagation)
+				originalEvent.stopPropagation();
+			// otherwise set the cancelBubble property of the original event to true (IE)
+			originalEvent.cancelBubble = true;
+		};
+
+		// Fix timeStamp
+		event.timeStamp = event.timeStamp || now();
+
+		// Fix target property, if necessary
+		if ( !event.target )
+			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType == 3 )
+			event.target = event.target.parentNode;
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement )
+			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement, body = document.body;
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+		}
+
+		// Add which for key events
+		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+			event.which = event.charCode || event.keyCode;
+
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey )
+			event.metaKey = event.ctrlKey;
+
+		// Add which for click: 1 == left; 2 == middle; 3 == right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button )
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+		return event;
+	},
+
+	proxy: function( fn, proxy ){
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+		// So proxy can be declared as an argument
+		return proxy;
+	},
+
+	special: {
+		ready: {
+			setup: function() {
+				// Make sure the ready event is setup
+				bindReady();
+				return;
+			},
+
+			teardown: function() { return; }
+		},
+
+		mouseenter: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseenter
+				event.type = "mouseenter";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		},
+
+		mouseleave: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseleave
+				event.type = "mouseleave";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		}
+	}
+};
+
+jQuery.fn.extend({
+	bind: function( type, data, fn ) {
+		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+			jQuery.event.add( this, type, fn || data, fn && data );
+		});
+	},
+
+	one: function( type, data, fn ) {
+		var one = jQuery.event.proxy( fn || data, function(event) {
+			jQuery(this).unbind(event, one);
+			return (fn || data).apply( this, arguments );
+		});
+		return this.each(function(){
+			jQuery.event.add( this, type, one, fn && data);
+		});
+	},
+
+	unbind: function( type, fn ) {
+		return this.each(function(){
+			jQuery.event.remove( this, type, fn );
+		});
+	},
+
+	trigger: function( type, data, fn ) {
+		return this.each(function(){
+			jQuery.event.trigger( type, data, this, true, fn );
+		});
+	},
+
+	triggerHandler: function( type, data, fn ) {
+		return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
+	},
+
+	toggle: function( fn ) {
+		// Save reference to arguments for access in closure
+		var args = arguments, i = 1;
+
+		// link all the functions, so any of them can unbind this click handler
+		while( i < args.length )
+			jQuery.event.proxy( fn, args[i++] );
+
+		return this.click( jQuery.event.proxy( fn, function(event) {
+			// Figure out which function to execute
+			this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+			// Make sure that clicks stop
+			event.preventDefault();
+
+			// and execute the function
+			return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+		}));
+	},
+
+	hover: function(fnOver, fnOut) {
+		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
+	},
+
+	ready: function(fn) {
+		// Attach the listeners
+		bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady )
+			// Execute the function immediately
+			fn.call( document, jQuery );
+
+		// Otherwise, remember the function for later
+		else
+			// Add the function to the wait list
+			jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
+
+		return this;
+	}
+});
+
+jQuery.extend({
+	isReady: false,
+	readyList: [],
+	// Handle when the DOM is ready
+	ready: function() {
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.isReady ) {
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If there are functions bound, to execute
+			if ( jQuery.readyList ) {
+				// Execute all of them
+				jQuery.each( jQuery.readyList, function(){
+					this.call( document );
+				});
+
+				// Reset the list of functions
+				jQuery.readyList = null;
+			}
+
+			// Trigger any bound ready events
+			jQuery(document).triggerHandler("ready");
+		}
+	}
+});
+
+var readyBound = false;
+
+function bindReady(){
+	if ( readyBound ) return;
+	readyBound = true;
+
+	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
+	if ( document.addEventListener && !jQuery.browser.opera)
+		// Use the handy event callback
+		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
+
+	// If IE is used and is not in a frame
+	// Continually check to see if the document is ready
+	if ( jQuery.browser.msie && window == top ) (function(){
+		if (jQuery.isReady) return;
+		try {
+			// If IE is used, use the trick by Diego Perini
+			// http://javascript.nwbox.com/IEContentLoaded/
+			document.documentElement.doScroll("left");
+		} catch( error ) {
+			setTimeout( arguments.callee, 0 );
+			return;
+		}
+		// and execute any waiting functions
+		jQuery.ready();
+	})();
+
+	if ( jQuery.browser.opera )
+		document.addEventListener( "DOMContentLoaded", function () {
+			if (jQuery.isReady) return;
+			for (var i = 0; i < document.styleSheets.length; i++)
+				if (document.styleSheets[i].disabled) {
+					setTimeout( arguments.callee, 0 );
+					return;
+				}
+			// and execute any waiting functions
+			jQuery.ready();
+		}, false);
+
+	if ( jQuery.browser.safari ) {
+		var numStyles;
+		(function(){
+			if (jQuery.isReady) return;
+			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			if ( numStyles === undefined )
+				numStyles = jQuery("style, link[rel=stylesheet]").length;
+			if ( document.styleSheets.length != numStyles ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			// and execute any waiting functions
+			jQuery.ready();
+		})();
+	}
+
+	// A fallback to window.onload, that will always work
+	jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
+	"submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+	// Handle event binding
+	jQuery.fn[name] = function(fn){
+		return fn ? this.bind(name, fn) : this.trigger(name);
+	};
+});
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event, elem) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+	// Traverse up the tree
+	while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
+	// Return true if we actually just moused on to a sub-element
+	return parent == elem;
+};
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery(window).bind("unload", function() {
+	jQuery("*").add(document).unbind();
+});
+jQuery.fn.extend({
+	// Keep a copy of the old load
+	_load: jQuery.fn.load,
+
+	load: function( url, params, callback ) {
+		if ( typeof url != 'string' )
+			return this._load( url );
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		callback = callback || function(){};
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params )
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else {
+				params = jQuery.param( params );
+				type = "POST";
+			}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function(res, status){
+				// If successful, inject the HTML into all the matched elements
+				if ( status == "success" || status == "notmodified" )
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div/>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+
+				self.each( callback, [res.responseText, status, res] );
+			}
+		});
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+	serializeArray: function() {
+		return this.map(function(){
+			return jQuery.nodeName(this, "form") ?
+				jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled &&
+				(this.checked || /select|textarea/i.test(this.nodeName) ||
+					/text|hidden|password/i.test(this.type));
+		})
+		.map(function(i, elem){
+			var val = jQuery(this).val();
+			return val == null ? null :
+				val.constructor == Array ?
+					jQuery.map( val, function(val, i){
+						return {name: elem.name, value: val};
+					}) :
+					{name: elem.name, value: val};
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+	jQuery.fn[o] = function(f){
+		return this.bind(o, f);
+	};
+});
+
+var jsc = now();
+
+jQuery.extend({
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was ommited
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = null;
+		}
+
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		url: location.href,
+		global: true,
+		type: "GET",
+		timeout: 0,
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		data: null,
+		username: null,
+		password: null,
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			script: "text/javascript, application/javascript",
+			json: "application/json, text/javascript",
+			text: "text/plain",
+			_default: "*/*"
+		}
+	},
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+
+	ajax: function( s ) {
+		// Extend the settings, but re-extend 's' so that it can be
+		// checked again later (in the test suite, specifically)
+		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+		var jsonp, jsre = /=\?(&|$)/g, status, data,
+			type = s.type.toUpperCase();
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data != "string" )
+			s.data = jQuery.param(s.data);
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType == "jsonp" ) {
+			if ( type == "GET" ) {
+				if ( !s.url.match(jsre) )
+					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+			} else if ( !s.data || !s.data.match(jsre) )
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+			jsonp = "jsonp" + jsc++;
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data )
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			window[ jsonp ] = function(tmp){
+				data = tmp;
+				success();
+				complete();
+				// Garbage collect
+				window[ jsonp ] = undefined;
+				try{ delete window[ jsonp ]; } catch(e){}
+				if ( head )
+					head.removeChild( script );
+			};
+		}
+
+		if ( s.dataType == "script" && s.cache == null )
+			s.cache = false;
+
+		if ( s.cache === false && type == "GET" ) {
+			var ts = now();
+			// try replacing _= if it is there
+			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for get requests
+		if ( s.data && type == "GET" ) {
+			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+			// IE likes to send both get and post data, prevent this
+			s.data = null;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && ! jQuery.active++ )
+			jQuery.event.trigger( "ajaxStart" );
+
+		// Matches an absolute URL, and saves the domain
+		var remote = /^(?:\w+:)?\/\/([^\/?#]+)/;
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( s.dataType == "script" && type == "GET"
+				&& remote.test(s.url) && remote.exec(s.url)[1] != location.host ){
+			var head = document.getElementsByTagName("head")[0];
+			var script = document.createElement("script");
+			script.src = s.url;
+			if (s.scriptCharset)
+				script.charset = s.scriptCharset;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function(){
+					if ( !done && (!this.readyState ||
+							this.readyState == "loaded" || this.readyState == "complete") ) {
+						done = true;
+						success();
+						complete();
+						head.removeChild( script );
+					}
+				};
+			}
+
+			head.appendChild(script);
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object; Microsoft failed to properly
+		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+		var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+
+		// Open the socket
+		// Passing null username, generates a login popup on Opera (#2865)
+		if( s.username )
+			xhr.open(type, s.url, s.async, s.username, s.password);
+		else
+			xhr.open(type, s.url, s.async);
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set the correct header, if data is being sent
+			if ( s.data )
+				xhr.setRequestHeader("Content-Type", s.contentType);
+
+			// Set the If-Modified-Since header, if ifModified mode.
+			if ( s.ifModified )
+				xhr.setRequestHeader("If-Modified-Since",
+					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+			// Set the Accepts header for the server, depending on the dataType
+			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+				s.accepts[ s.dataType ] + ", */*" :
+				s.accepts._default );
+		} catch(e){}
+
+		// Allow custom headers/mimetypes
+		if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+			// cleanup active request counter
+			s.global && jQuery.active--;
+			// close opended socket
+			xhr.abort();
+			return false;
+		}
+
+		if ( s.global )
+			jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+		// Wait for a response to come back
+		var onreadystatechange = function(isTimeout){
+			// The transfer is complete and the data is available, or the request timed out
+			if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+				requestDone = true;
+
+				// clear poll interval
+				if (ival) {
+					clearInterval(ival);
+					ival = null;
+				}
+
+				status = isTimeout == "timeout" && "timeout" ||
+					!jQuery.httpSuccess( xhr ) && "error" ||
+					s.ifModified && jQuery.httpNotModified( xhr, s.url ) && "notmodified" ||
+					"success";
+
+				if ( status == "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xhr, s.dataType, s.dataFilter );
+					} catch(e) {
+						status = "parsererror";
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status == "success" ) {
+					// Cache Last-Modified header, if ifModified mode.
+					var modRes;
+					try {
+						modRes = xhr.getResponseHeader("Last-Modified");
+					} catch(e) {} // swallow exception thrown by FF if header is not available
+
+					if ( s.ifModified && modRes )
+						jQuery.lastModified[s.url] = modRes;
+
+					// JSONP handles its own success callback
+					if ( !jsonp )
+						success();
+				} else
+					jQuery.handleError(s, xhr, status);
+
+				// Fire the complete handlers
+				complete();
+
+				// Stop memory leaks
+				if ( s.async )
+					xhr = null;
+			}
+		};
+
+		if ( s.async ) {
+			// don't attach the handler to the request, just poll it instead
+			var ival = setInterval(onreadystatechange, 13);
+
+			// Timeout checker
+			if ( s.timeout > 0 )
+				setTimeout(function(){
+					// Check to see if the request is still happening
+					if ( xhr ) {
+						// Cancel the request
+						xhr.abort();
+
+						if( !requestDone )
+							onreadystatechange( "timeout" );
+					}
+				}, s.timeout);
+		}
+
+		// Send the data
+		try {
+			xhr.send(s.data);
+		} catch(e) {
+			jQuery.handleError(s, xhr, null, e);
+		}
+
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async )
+			onreadystatechange();
+
+		function success(){
+			// If a local callback was specified, fire it and pass it the data
+			if ( s.success )
+				s.success( data, status );
+
+			// Fire the global callback
+			if ( s.global )
+				jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+		}
+
+		function complete(){
+			// Process result
+			if ( s.complete )
+				s.complete(xhr, status);
+
+			// The request was completed
+			if ( s.global )
+				jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+		}
+
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xhr;
+	},
+
+	handleError: function( s, xhr, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) s.error( xhr, status, e );
+
+		// Fire the global callback
+		if ( s.global )
+			jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+	},
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( xhr ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !xhr.status && location.protocol == "file:" ||
+				( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
+				jQuery.browser.safari && xhr.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xhr, url ) {
+		try {
+			var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+			// Firefox always returns 200. check Last-Modified date
+			return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
+				jQuery.browser.safari && xhr.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	httpData: function( xhr, type, filter ) {
+		var ct = xhr.getResponseHeader("content-type"),
+			xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+			data = xml ? xhr.responseXML : xhr.responseText;
+
+		if ( xml && data.documentElement.tagName == "parsererror" )
+			throw "parsererror";
+			
+		// Allow a pre-filtering function to sanitize the response
+		if( filter )
+			data = filter( data, type );
+
+		// If the type is "script", eval it in global context
+		if ( type == "script" )
+			jQuery.globalEval( data );
+
+		// Get the JavaScript object, if JSON is used.
+		if ( type == "json" )
+			data = eval("(" + data + ")");
+
+		return data;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a ) {
+		var s = [];
+
+		// If an array was passed in, assume that it is an array
+		// of form elements
+		if ( a.constructor == Array || a.jquery )
+			// Serialize the form elements
+			jQuery.each( a, function(){
+				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
+			});
+
+		// Otherwise, assume that it's an object of key/value pairs
+		else
+			// Serialize the key/values
+			for ( var j in a )
+				// If the value is an array then the key names need to be repeated
+				if ( a[j] && a[j].constructor == Array )
+					jQuery.each( a[j], function(){
+						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
+					});
+				else
+					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( jQuery.isFunction(a[j]) ? a[j]() : a[j] ) );
+
+		// Return the resulting serialization
+		return s.join("&").replace(/%20/g, "+");
+	}
+
+});
+jQuery.fn.extend({
+	show: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "show", width: "show", opacity: "show"
+			}, speed, callback) :
+
+			this.filter(":hidden").each(function(){
+				this.style.display = this.oldblock || "";
+				if ( jQuery.css(this,"display") == "none" ) {
+					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
+					this.style.display = elem.css("display");
+					// handle an edge condition where css is - div { display:none; } or similar
+					if (this.style.display == "none")
+						this.style.display = "block";
+					elem.remove();
+				}
+			}).end();
+	},
+
+	hide: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "hide", width: "hide", opacity: "hide"
+			}, speed, callback) :
+
+			this.filter(":visible").each(function(){
+				this.oldblock = this.oldblock || jQuery.css(this,"display");
+				this.style.display = "none";
+			}).end();
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+
+	toggle: function( fn, fn2 ){
+		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+			this._toggle.apply( this, arguments ) :
+			fn ?
+				this.animate({
+					height: "toggle", width: "toggle", opacity: "toggle"
+				}, fn, fn2) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+				});
+	},
+
+	slideDown: function(speed,callback){
+		return this.animate({height: "show"}, speed, callback);
+	},
+
+	slideUp: function(speed,callback){
+		return this.animate({height: "hide"}, speed, callback);
+	},
+
+	slideToggle: function(speed, callback){
+		return this.animate({height: "toggle"}, speed, callback);
+	},
+
+	fadeIn: function(speed, callback){
+		return this.animate({opacity: "show"}, speed, callback);
+	},
+
+	fadeOut: function(speed, callback){
+		return this.animate({opacity: "hide"}, speed, callback);
+	},
+
+	fadeTo: function(speed,to,callback){
+		return this.animate({opacity: to}, speed, callback);
+	},
+
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		return this[ optall.queue === false ? "each" : "queue" ](function(){
+			if ( this.nodeType != 1)
+				return false;
+
+			var opt = jQuery.extend({}, optall), p,
+				hidden = jQuery(this).is(":hidden"), self = this;
+
+			for ( p in prop ) {
+				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+					return opt.complete.call(this);
+
+				if ( p == "height" || p == "width" ) {
+					// Store display property
+					opt.display = jQuery.css(this, "display");
+
+					// Make sure that nothing sneaks out
+					opt.overflow = this.style.overflow;
+				}
+			}
+
+			if ( opt.overflow != null )
+				this.style.overflow = "hidden";
+
+			opt.curAnim = jQuery.extend({}, prop);
+
+			jQuery.each( prop, function(name, val){
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( /toggle|show|hide/.test(val) )
+					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+				else {
+					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+						start = e.cur(true) || 0;
+
+					if ( parts ) {
+						var end = parseFloat(parts[2]),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit != "px" ) {
+							self.style[ name ] = (end || 1) + unit;
+							start = ((end || 1) / e.cur(true)) * start;
+							self.style[ name ] = start + unit;
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] )
+							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+						e.custom( start, end, unit );
+					} else
+						e.custom( start, val, "" );
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+
+	queue: function(type, fn){
+		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
+			fn = type;
+			type = "fx";
+		}
+
+		if ( !type || (typeof type == "string" && !fn) )
+			return queue( this[0], type );
+
+		return this.each(function(){
+			if ( fn.constructor == Array )
+				queue(this, type, fn);
+			else {
+				queue(this, type).push( fn );
+
+				if ( queue(this, type).length == 1 )
+					fn.call(this);
+			}
+		});
+	},
+
+	stop: function(clearQueue, gotoEnd){
+		var timers = jQuery.timers;
+
+		if (clearQueue)
+			this.queue([]);
+
+		this.each(function(){
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- )
+				if ( timers[i].elem == this ) {
+					if (gotoEnd)
+						// force the next step to be the last
+						timers[i](true);
+					timers.splice(i, 1);
+				}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if (!gotoEnd)
+			this.dequeue();
+
+		return this;
+	}
+
+});
+
+var queue = function( elem, type, array ) {
+	if ( elem ){
+
+		type = type || "fx";
+
+		var q = jQuery.data( elem, type + "queue" );
+
+		if ( !q || array )
+			q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
+
+	}
+	return q;
+};
+
+jQuery.fn.dequeue = function(type){
+	type = type || "fx";
+
+	return this.each(function(){
+		var q = queue(this, type);
+
+		q.shift();
+
+		if ( q.length )
+			q[0].call( this );
+	});
+};
+
+jQuery.extend({
+
+	speed: function(speed, easing, fn) {
+		var opt = speed && speed.constructor == Object ? speed : {
+			complete: fn || !fn && easing ||
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && easing.constructor != Function && easing
+		};
+
+		opt.duration = (opt.duration && opt.duration.constructor == Number ?
+			opt.duration :
+			jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def;
+
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function(){
+			if ( opt.queue !== false )
+				jQuery(this).dequeue();
+			if ( jQuery.isFunction( opt.old ) )
+				opt.old.call( this );
+		};
+
+		return opt;
+	},
+
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+
+	timers: [],
+	timerId: null,
+
+	fx: function( elem, options, prop ){
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig )
+			options.orig = {};
+	}
+
+});
+
+jQuery.fx.prototype = {
+
+	// Simple function for setting a style value
+	update: function(){
+		if ( this.options.step )
+			this.options.step.call( this.elem, this.now, this );
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+		// Set display property to block for height/width animations
+		if ( this.prop == "height" || this.prop == "width" )
+			this.elem.style.display = "block";
+	},
+
+	// Get the current size
+	cur: function(force){
+		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
+			return this.elem[ this.prop ];
+
+		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function(from, to, unit){
+		this.startTime = now();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+		this.update();
+
+		var self = this;
+		function t(gotoEnd){
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		jQuery.timers.push(t);
+
+		if ( jQuery.timerId == null ) {
+			jQuery.timerId = setInterval(function(){
+				var timers = jQuery.timers;
+
+				for ( var i = 0; i < timers.length; i++ )
+					if ( !timers[i]() )
+						timers.splice(i--, 1);
+
+				if ( !timers.length ) {
+					clearInterval( jQuery.timerId );
+					jQuery.timerId = null;
+				}
+			}, 13);
+		}
+	},
+
+	// Simple 'show' function
+	show: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		this.custom(0, this.cur());
+
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		if ( this.prop == "width" || this.prop == "height" )
+			this.elem.style[this.prop] = "1px";
+
+		// Start by showing the element
+		jQuery(this.elem).show();
+	},
+
+	// Simple 'hide' function
+	hide: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function(gotoEnd){
+		var t = now();
+
+		if ( gotoEnd || t > this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			var done = true;
+			for ( var i in this.options.curAnim )
+				if ( this.options.curAnim[i] !== true )
+					done = false;
+
+			if ( done ) {
+				if ( this.options.display != null ) {
+					// Reset the overflow
+					this.elem.style.overflow = this.options.overflow;
+
+					// Reset the display
+					this.elem.style.display = this.options.display;
+					if ( jQuery.css(this.elem, "display") == "none" )
+						this.elem.style.display = "block";
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide )
+					this.elem.style.display = "none";
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show )
+					for ( var p in this.options.curAnim )
+						jQuery.attr(this.elem.style, p, this.options.orig[p]);
+			}
+
+			if ( done )
+				// Execute the complete function
+				this.options.complete.call( this.elem );
+
+			return false;
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+
+};
+
+jQuery.extend( jQuery.fx, {
+	speeds:{
+		slow: 600,
+ 		fast: 200,
+ 		// Default speed
+ 		def: 400
+	},
+	step: {
+		scrollLeft: function(fx){
+			fx.elem.scrollLeft = fx.now;
+		},
+
+		scrollTop: function(fx){
+			fx.elem.scrollTop = fx.now;
+		},
+
+		opacity: function(fx){
+			jQuery.attr(fx.elem.style, "opacity", fx.now);
+		},
+
+		_default: function(fx){
+			fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+		}
+	}
+});
+// The Offset Method
+// Originally By Brandon Aaron, part of the Dimension Plugin
+// http://jquery.com/plugins/project/dimensions
+jQuery.fn.offset = function() {
+	var left = 0, top = 0, elem = this[0], results;
+
+	if ( elem ) with ( jQuery.browser ) {
+		var parent       = elem.parentNode,
+		    offsetChild  = elem,
+		    offsetParent = elem.offsetParent,
+		    doc          = elem.ownerDocument,
+		    safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
+		    css          = jQuery.curCSS,
+		    fixed        = css(elem, "position") == "fixed";
+
+		// Use getBoundingClientRect if available
+		if ( elem.getBoundingClientRect ) {
+			var box = elem.getBoundingClientRect();
+
+			// Add the document scroll offsets
+			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+
+			// IE adds the HTML element's border, by default it is medium which is 2px
+			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
+			// IE 7 standards mode, the border is always 2px
+			// This border/offset is typically represented by the clientLeft and clientTop properties
+			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
+			// Therefore this method will be off by 2px in IE while in quirksmode
+			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
+
+		// Otherwise loop through the offsetParents and parentNodes
+		} else {
+
+			// Initial element offsets
+			add( elem.offsetLeft, elem.offsetTop );
+
+			// Get parent offsets
+			while ( offsetParent ) {
+				// Add offsetParent offsets
+				add( offsetParent.offsetLeft, offsetParent.offsetTop );
+
+				// Mozilla and Safari > 2 does not include the border on offset parents
+				// However Mozilla adds the border for table or table cells
+				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
+					border( offsetParent );
+
+				// Add the document scroll offsets if position is fixed on any offsetParent
+				if ( !fixed && css(offsetParent, "position") == "fixed" )
+					fixed = true;
+
+				// Set offsetChild to previous offsetParent unless it is the body element
+				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
+				// Get next offsetParent
+				offsetParent = offsetParent.offsetParent;
+			}
+
+			// Get parent scroll offsets
+			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
+				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
+				if ( !/^inline|table.*$/i.test(css(parent, "display")) )
+					// Subtract parent scroll offsets
+					add( -parent.scrollLeft, -parent.scrollTop );
+
+				// Mozilla does not add the border for a parent that has overflow != visible
+				if ( mozilla && css(parent, "overflow") != "visible" )
+					border( parent );
+
+				// Get next parent
+				parent = parent.parentNode;
+			}
+
+			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
+			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
+			if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
+				(mozilla && css(offsetChild, "position") != "absolute") )
+					add( -doc.body.offsetLeft, -doc.body.offsetTop );
+
+			// Add the document scroll offsets if position is fixed
+			if ( fixed )
+				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+		}
+
+		// Return an object with top and left properties
+		results = { top: top, left: left };
+	}
+
+	function border(elem) {
+		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
+	}
+
+	function add(l, t) {
+		left += parseInt(l, 10) || 0;
+		top += parseInt(t, 10) || 0;
+	}
+
+	return results;
+};
+
+
+jQuery.fn.extend({
+	position: function() {
+		var left = 0, top = 0, results;
+
+		if ( this[0] ) {
+			// Get *real* offsetParent
+			var offsetParent = this.offsetParent(),
+
+			// Get correct offsets
+			offset       = this.offset(),
+			parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+			// Subtract element margins
+			// note: when an element has margin: auto the offsetLeft and marginLeft 
+			// are the same in Safari causing offset.left to incorrectly be 0
+			offset.top  -= num( this, 'marginTop' );
+			offset.left -= num( this, 'marginLeft' );
+
+			// Add offsetParent borders
+			parentOffset.top  += num( offsetParent, 'borderTopWidth' );
+			parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+			// Subtract the two offsets
+			results = {
+				top:  offset.top  - parentOffset.top,
+				left: offset.left - parentOffset.left
+			};
+		}
+
+		return results;
+	},
+
+	offsetParent: function() {
+		var offsetParent = this[0].offsetParent;
+		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+			offsetParent = offsetParent.offsetParent;
+		return jQuery(offsetParent);
+	}
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+	var method = 'scroll' + name;
+	
+	jQuery.fn[ method ] = function(val) {
+		if (!this[0]) return;
+
+		return val != undefined ?
+
+			// Set the scroll offset
+			this.each(function() {
+				this == window || this == document ?
+					window.scrollTo(
+						!i ? val : jQuery(window).scrollLeft(),
+						 i ? val : jQuery(window).scrollTop()
+					) :
+					this[ method ] = val;
+			}) :
+
+			// Return the scroll offset
+			this[0] == window || this[0] == document ?
+				self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+					jQuery.boxModel && document.documentElement[ method ] ||
+					document.body[ method ] :
+				this[0][ method ];
+	};
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+
+	var tl = i ? "Left"  : "Top",  // top or left
+		br = i ? "Right" : "Bottom"; // bottom or right
+
+	// innerHeight and innerWidth
+	jQuery.fn["inner" + name] = function(){
+		return this[ name.toLowerCase() ]() +
+			num(this, "padding" + tl) +
+			num(this, "padding" + br);
+	};
+
+	// outerHeight and outerWidth
+	jQuery.fn["outer" + name] = function(margin) {
+		return this["inner" + name]() +
+			num(this, "border" + tl + "Width") +
+			num(this, "border" + br + "Width") +
+			(margin ?
+				num(this, "margin" + tl) + num(this, "margin" + br) : 0);
+	};
+
+});})();
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/layout.js
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/layout.js	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/layout.js	(revision 429)
@@ -0,0 +1,449 @@
+(function($){
+
+	var initLayout = function() {
+
+		$('#form\\.body_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.body_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.header_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.header_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+
+		$('#form\\.header_font_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.header_font_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.header_link_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.header_link_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.header_active_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.header_active_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.topnav_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.topnav_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+
+		$('#form\\.topnav_font_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.topnav_font_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.topnav_link_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.topnav_link_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.topnav_active_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.topnav_active_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.leftnav_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.leftnav_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+
+		$('#form\\.leftnav_font_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.leftnav_font_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.leftnav_link_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.leftnav_link_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.leftnav_active_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.leftnav_active_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.content_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.content_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+
+		$('#form\\.content_font_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.content_font_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.content_link_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.content_link_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.content_active_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.content_active_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.default_font_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.default_font_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.page_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.page_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+
+		$('#form\\.unvisited_link_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.unvisited_link_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.active_link_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.active_link_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.visited_link_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.visited_link_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.default_border_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.default_border_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.secondary_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.secondary_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.secondary_text_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.secondary_text_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.loggedin_tabs_border_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.loggedin_tabs_border_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.loggedin_tabs_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.loggedin_tabs_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.loggedin_tabs_text_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.loggedin_tabs_text_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.form_inputtext_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.form_inputtext_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.evenrow_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.evenrow_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.oddrow_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.oddrow_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.notification_border_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.notification_border_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.notification_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.notification_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+		$('#form\\.discreet_text_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.discreet_text_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+		$('#form\\.info_popup_bkg_color').ColorPicker({
+			onSubmit: function(hsb, hex, rgb) {
+				$('#form\\.info_popup_bkg_color').val('#' + hex);
+			},
+			onBeforeShow: function () {
+				$(this).ColorPickerSetColor(this.value);
+			}
+		})
+		.bind('keyup', function(){
+			$(this).ColorPickerSetColor(this.value);
+		});
+
+
+
+
+	};
+		
+	EYE.register(initLayout, 'init');
+})(jQuery)
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/utils.js
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/utils.js	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/colorpicker/js/utils.js	(revision 429)
@@ -0,0 +1,252 @@
+/**
+ *
+ * Utilities
+ * Author: Stefan Petre www.eyecon.ro
+ * 
+ */
+(function($) {
+EYE.extend({
+	getPosition : function(e, forceIt)
+	{
+		var x = 0;
+		var y = 0;
+		var es = e.style;
+		var restoreStyles = false;
+		if (forceIt && jQuery.curCSS(e,'display') == 'none') {
+			var oldVisibility = es.visibility;
+			var oldPosition = es.position;
+			restoreStyles = true;
+			es.visibility = 'hidden';
+			es.display = 'block';
+			es.position = 'absolute';
+		}
+		var el = e;
+		if (el.getBoundingClientRect) { // IE
+			var box = el.getBoundingClientRect();
+			x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2;
+			y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2;
+		} else {
+			x = el.offsetLeft;
+			y = el.offsetTop;
+			el = el.offsetParent;
+			if (e != el) {
+				while (el) {
+					x += el.offsetLeft;
+					y += el.offsetTop;
+					el = el.offsetParent;
+				}
+			}
+			if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) {
+				x -= document.body.offsetLeft;
+				y -= document.body.offsetTop;
+			}
+			el = e.parentNode;
+			while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML') 
+			{
+				if (jQuery.curCSS(el, 'display') != 'inline') {
+					x -= el.scrollLeft;
+					y -= el.scrollTop;
+				}
+				el = el.parentNode;
+			}
+		}
+		if (restoreStyles == true) {
+			es.display = 'none';
+			es.position = oldPosition;
+			es.visibility = oldVisibility;
+		}
+		return {x:x, y:y};
+	},
+	getSize : function(e)
+	{
+		var w = parseInt(jQuery.curCSS(e,'width'), 10);
+		var h = parseInt(jQuery.curCSS(e,'height'), 10);
+		var wb = 0;
+		var hb = 0;
+		if (jQuery.curCSS(e, 'display') != 'none') {
+			wb = e.offsetWidth;
+			hb = e.offsetHeight;
+		} else {
+			var es = e.style;
+			var oldVisibility = es.visibility;
+			var oldPosition = es.position;
+			es.visibility = 'hidden';
+			es.display = 'block';
+			es.position = 'absolute';
+			wb = e.offsetWidth;
+			hb = e.offsetHeight;
+			es.display = 'none';
+			es.position = oldPosition;
+			es.visibility = oldVisibility;
+		}
+		return {w:w, h:h, wb:wb, hb:hb};
+	},
+	getClient : function(e)
+	{
+		var h, w;
+		if (e) {
+			w = e.clientWidth;
+			h = e.clientHeight;
+		} else {
+			var de = document.documentElement;
+			w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
+			h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
+		}
+		return {w:w,h:h};
+	},
+	getScroll : function (e)
+	{
+		var t=0, l=0, w=0, h=0, iw=0, ih=0;
+		if (e && e.nodeName.toLowerCase() != 'body') {
+			t = e.scrollTop;
+			l = e.scrollLeft;
+			w = e.scrollWidth;
+			h = e.scrollHeight;
+		} else  {
+			if (document.documentElement) {
+				t = document.documentElement.scrollTop;
+				l = document.documentElement.scrollLeft;
+				w = document.documentElement.scrollWidth;
+				h = document.documentElement.scrollHeight;
+			} else if (document.body) {
+				t = document.body.scrollTop;
+				l = document.body.scrollLeft;
+				w = document.body.scrollWidth;
+				h = document.body.scrollHeight;
+			}
+			if (typeof pageYOffset != 'undefined') {
+				t = pageYOffset;
+				l = pageXOffset;
+			}
+			iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
+			ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
+		}
+		return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };
+	},
+	getMargins : function(e, toInteger)
+	{
+		var t = jQuery.curCSS(e,'marginTop') || '';
+		var r = jQuery.curCSS(e,'marginRight') || '';
+		var b = jQuery.curCSS(e,'marginBottom') || '';
+		var l = jQuery.curCSS(e,'marginLeft') || '';
+		if (toInteger)
+			return {
+				t: parseInt(t, 10)||0,
+				r: parseInt(r, 10)||0,
+				b: parseInt(b, 10)||0,
+				l: parseInt(l, 10)
+			};
+		else
+			return {t: t, r: r,	b: b, l: l};
+	},
+	getPadding : function(e, toInteger)
+	{
+		var t = jQuery.curCSS(e,'paddingTop') || '';
+		var r = jQuery.curCSS(e,'paddingRight') || '';
+		var b = jQuery.curCSS(e,'paddingBottom') || '';
+		var l = jQuery.curCSS(e,'paddingLeft') || '';
+		if (toInteger)
+			return {
+				t: parseInt(t, 10)||0,
+				r: parseInt(r, 10)||0,
+				b: parseInt(b, 10)||0,
+				l: parseInt(l, 10)
+			};
+		else
+			return {t: t, r: r,	b: b, l: l};
+	},
+	getBorder : function(e, toInteger)
+	{
+		var t = jQuery.curCSS(e,'borderTopWidth') || '';
+		var r = jQuery.curCSS(e,'borderRightWidth') || '';
+		var b = jQuery.curCSS(e,'borderBottomWidth') || '';
+		var l = jQuery.curCSS(e,'borderLeftWidth') || '';
+		if (toInteger)
+			return {
+				t: parseInt(t, 10)||0,
+				r: parseInt(r, 10)||0,
+				b: parseInt(b, 10)||0,
+				l: parseInt(l, 10)||0
+			};
+		else
+			return {t: t, r: r,	b: b, l: l};
+	},
+	traverseDOM : function(nodeEl, func)
+	{
+		func(nodeEl);
+		nodeEl = nodeEl.firstChild;
+		while(nodeEl){
+			EYE.traverseDOM(nodeEl, func);
+			nodeEl = nodeEl.nextSibling;
+		}
+	},
+	getInnerWidth :  function(el, scroll) {
+		var offsetW = el.offsetWidth;
+		return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth;
+	},
+	getInnerHeight : function(el, scroll) {
+		var offsetH = el.offsetHeight;
+		return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight;
+	},
+	getExtraWidth : function(el) {
+		if($.boxModel)
+			return (parseInt($.curCSS(el, 'paddingLeft'))||0)
+				+ (parseInt($.curCSS(el, 'paddingRight'))||0)
+				+ (parseInt($.curCSS(el, 'borderLeftWidth'))||0)
+				+ (parseInt($.curCSS(el, 'borderRightWidth'))||0);
+		return 0;
+	},
+	getExtraHeight : function(el) {
+		if($.boxModel)
+			return (parseInt($.curCSS(el, 'paddingTop'))||0)
+				+ (parseInt($.curCSS(el, 'paddingBottom'))||0)
+				+ (parseInt($.curCSS(el, 'borderTopWidth'))||0)
+				+ (parseInt($.curCSS(el, 'borderBottomWidth'))||0);
+		return 0;
+	},
+	isChildOf: function(parentEl, el, container) {
+		if (parentEl == el) {
+			return true;
+		}
+		if (!el || !el.nodeType || el.nodeType != 1) {
+			return false;
+		}
+		if (parentEl.contains && !$.browser.safari) {
+			return parentEl.contains(el);
+		}
+		if ( parentEl.compareDocumentPosition ) {
+			return !!(parentEl.compareDocumentPosition(el) & 16);
+		}
+		var prEl = el.parentNode;
+		while(prEl && prEl != container) {
+			if (prEl == parentEl)
+				return true;
+			prEl = prEl.parentNode;
+		}
+		return false;
+	},
+	centerEl : function(el, axis)
+	{
+		var clientScroll = EYE.getScroll();
+		var size = EYE.getSize(el);
+		if (!axis || axis == 'vertically')
+			$(el).css(
+				{
+					top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px'
+				}
+			);
+		if (!axis || axis == 'horizontally')
+			$(el).css(
+				{
+					left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px'
+				}
+			);
+	}
+});
+if (!$.easing.easeout) {
+	$.easing.easeout = function(p, n, firstNum, delta, duration) {
+		return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum;
+	};
+}
+	
+})(jQuery);
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/base_properties.props
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/base_properties.props	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/base_properties.props	(revision 429)
@@ -0,0 +1,77 @@
+title:string=Plone's color, font, logo and border defaults
+
+plone_skin:string=Left Skin
+
+logoName:string=logo.png
+faviconName:string=favicon.ico
+
+fontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+fontBaseSize:string=72%
+fontColor:string=Black
+fontSmallSize:string=90%
+
+bodyBackgroundColor:string=#3c6477
+bodyBackgroundImage:string=bodyBackground.gif
+backgroundColor:string=White
+
+linkColor:string=#556670
+linkActiveColor:string=Red
+linkVisitedColor:string=Purple
+
+borderWidth:string=1px
+borderStyle:string=solid
+borderStyleAnnotations:string=solid
+
+globalBorderColor:string=#9a4e5a
+globalBackgroundColor:string=#cccccc
+globalFontColor:string=#436976
+
+portalHeaderBackgroundImage:string=headerBackground.png
+portalHeaderBackgroundColor:string=#4e819a
+portalHeaderFontColor:string=#f0f0f0
+portalHeaderLinkColor:string=#eeeeee
+portalHeaderActiveColor:string=white
+
+portalTopNavBackgroundImage:string=topNavBackground.png
+portalTopNavBackgroundColor:string=#9a4e5a
+portalTopNavFontColor:string=#C0C0C0
+portalTopNavLinkColor:string=#C0C0C0
+portalTopNavActiveColor:string=white
+
+portalColumnOneBackgroundImage:string=columnOneBackground.png
+portalColumnOneBackgroundColor:string=#37406d
+portalColumnOneFontColor:string=#f0f0f0
+portalColumnOneLinkColor:string=#cccccc
+portalColumnOneActiveColor:string=white
+
+
+
+headingFontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+
+contentViewBorderColor:string=#74ae0b
+contentViewBackgroundColor:string=#cde2a7
+contentViewFontColor:string=#578308
+
+inputFontColor:string=Black
+
+textTransform:string=none
+
+templateBackground:string=#606467
+
+testimonialtextcolor:string=#FFFFFF
+testimonial1:string=#555a5c
+testimonial2:string=#777b7c
+testimonial3:string=#999c9c
+
+evenRowBackgroundColor:string=#eeeeee
+oddRowBackgroundColor:string=transparent
+
+notifyBorderColor:string=#ffa500
+notifyBackgroundColor:string=#ffce7b
+
+discreetColor:string=#76797c
+helpBackgroundColor:string=#ffffe1
+
+portalMinWidth:string=70em
+columnOneWidth:string=16em
+columnTwoWidth:string=16em
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/fixed_fluid.css.dtml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/fixed_fluid.css.dtml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/fixed_fluid.css.dtml	(revision 429)
@@ -0,0 +1,20 @@
+/* <dtml-with base_properties> (do not remove this :) */
+/* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) */
+
+body {
+    background: <dtml-var bodyBackgroundColor missing="white"> url(<dtml-var bodyBackgroundImage missing="None">) repeat-x;
+}
+
+#visual-portal-wrapper {
+    position:relative;
+    margin-left:auto;
+    margin-right:auto;
+    width:960px;
+    background: white;
+} 
+
+#portal-colophon {
+	  margin: 0px;
+}
+
+/* </dtml-with> */
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/fixed_fluid_repeat_y.css.dtml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/fixed_fluid_repeat_y.css.dtml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/fixed_fluid_repeat_y.css.dtml	(revision 429)
@@ -0,0 +1,8 @@
+/* <dtml-with base_properties> (do not remove this :) */
+/* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) */
+
+body {
+    background: <dtml-var bodyBackgroundColor missing="white"> url(<dtml-var bodyBackgroundImage missing="None">) repeat;
+}
+
+/* </dtml-with> */
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/leftskin.css.dtml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/leftskin.css.dtml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/leftskin.css.dtml	(revision 429)
@@ -0,0 +1,307 @@
+/* <dtml-with base_properties> (do not remove this :) */
+/* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) */
+
+#portal-top { 
+}
+
+#portal-header {
+    background: &dtml-portalHeaderBackgroundColor; url(&dtml-portalHeaderBackgroundImage;) repeat-x;
+    color: &dtml-portalHeaderFontColor;;
+}
+
+#portal-header a:link,
+#portal-header a:visited { 
+    color: &dtml-portalHeaderLinkColor;;
+}
+
+#portal-header a:active,
+#portal-header a:hover { 
+    color: &dtml-portalHeaderActiveColor;;
+}
+
+
+#portal-searchbox {
+    margin-top: 0px;
+}
+
+.searchSection label {
+    color: &dtml-portalHeaderLinkColor;;
+}
+
+#portal-logo {
+    outline: none;
+}
+
+#portal-logo img { 
+    padding: 0 1em 0 1em;
+}
+
+#portal-siteactions { 
+}
+
+#portal-siteactions li a:link,
+#portal-siteactions li a:visited { 
+    border: none;
+    color: &dtml-portalHeaderLinkColor;
+}
+
+#portal-siteactions li a:hover,
+#portal-siteactions li a:active { 
+    background-color: transparent;
+    color: &dtml-portalHeaderActiveColor;;
+}
+
+
+
+#portal-globalnav {
+    background: &dtml-portalTopNavBackgroundColor; url(&dtml-portalTopNavBackgroundImage;) repeat-x;
+    color: &dtml-portalTopNavFontColor;;
+    padding: 3px 0em 3px 2em;
+    border-top: 1px white solid;
+    border-bottom: 1px white solid;
+    font-weight: bold;
+    font-size: 1em;
+}
+
+#portal-globalnav li a:link,
+#portal-globalnav li a:visited { 
+    color: &dtml-portalTopNavLinkColor;;
+    border: none;
+    border-style: none;
+    border-width: 0px;
+    text-transform: lowercase;
+}
+
+
+#portal-globalnav li a:hover,
+#portal-globalnav li a:active,
+#portal-globalnav li.selected a { 
+    background-color: transparent;
+    color: &dtml-portalTopNavActiveColor;;
+    border: none;
+    border-style: none;
+    border-width: 0px;
+}
+
+#portal-content-top { 
+    height: 2em;
+}
+
+
+#portal-personaltools { 
+    background-color: transparent;
+    border-top: none;
+    border-bottom: none;
+}
+
+#portal-breadcrumbs {
+    background-color: transparent;
+    border-bottom: none;
+}
+
+#portal-column-one { 
+    background: &dtml-portalColumnOneBackgroundColor;  url(&dtml-portalColumnOneBackgroundImage;);
+    color: &dtml-portalColumnOneFontColor;;
+}
+
+#portal-column-one a:link, 
+#portal-column-one a:visited { 
+    color: &dtml-portalColumnOneLinkColor;;
+}
+
+#portal-column-one dl.portlet a:active, 
+#portal-colunm-one dl.portlet a:hover {  
+    color: &dtml-portalColumnOneActiveColor;;
+}
+
+#portal-column-one .portletHeader { 
+}
+
+#portal-column-one .portletItemSelected a { 
+    color: &dtml-portalColumnOneActiveColor;;
+}
+
+#portal-column-one dd.portletItem a:hover { 
+    text-decoration: none;
+    color: &dtml-portalColumnOneActiveColor;;
+}
+
+#portal-column-content { 
+}
+
+#portal-column-two { 
+}
+
+#portal-column-two .portletHeader{
+   padding-left: 5px;
+     
+}
+
+#portal-column-content td { 
+    vertical-align: top;
+}
+
+#portal-footer { 
+    background-color: &dtml-portalHeaderBackgroundColor;;
+    color: &dtml-portalHeaderFontColor;;
+    border: 1px solid &dtml-portalHeaderBackgroundColor;;
+		border-top: 1px solid #FFF;
+    margin: 0 0 0 0;
+    padding: 0 0 0;
+}
+
+#portal-footer a:link,
+#portal-footer a:visited { 
+    color: &dtml-portalHeaderLinkColor;;
+}
+
+#portal-footer a:hover,
+#portal-footer a:active {  
+    text-decoration: none;
+    color: &dtml-portalHeaderActiveColor;;
+}
+
+#portal-colophon {
+    background-color: &dtml-portalHeaderBackgroundColor;;
+    color: &dtml-portalHeaderFontColor;;
+    margin: 0 0 0 0;
+}
+
+#portal-colophon ul {
+   margin:0;
+}
+
+#portal-colophon ul li a {
+   color: &dtml-portalHeaderFontColor;;
+   border-bottom: 0;
+}
+
+.portlet { 
+    background-color: transparent;
+    border-style: none;
+}
+
+.portletHeader { 
+    background-color: transparent;
+    border-style: none;
+    font-weight: bold;
+    font-size: 1.25em;
+    margin-left: -0.5em;
+    padding: 0.5em 0em;
+}
+
+.portletItem { 
+    border-left: none;
+    border-right: none;
+    padding: 0.25em;
+}
+
+.even { 
+    background-color: transparent;
+}
+
+.portletFooter { 
+    background-color: transparent;
+    border-style: none;
+}
+
+.portalFooter ul { 
+    list-style: none;
+    
+}
+
+.portletFooter ul li { 
+    display: inline;
+}
+
+.navTreeItem a,
+dd.portletItem .navTreeItem a { 
+    border-style: none;
+    background-color: transparent;
+    color: #333;
+}
+
+.navTreeItem a:hover,
+dd.portletItem .navTreeItem a:hover { 
+    border-style: none;
+    background-color: transparent;
+    color: #333;
+}
+
+.navTreeCurrentItem  { 
+    background-color: transparent;
+    color: #FF00FF;
+    border-style: none;
+    border: none !important;
+ }
+
+li.navTreeCurrentItem { 
+    background-color: transparent;
+    color: red;
+    border-style: none;
+}
+
+li.navTreeCurrentItem a,
+li.navTreeCurrentItem a:hover { 
+    border-style: none;
+    color: red;
+    background-color: transparent;
+}
+
+.image-inline {
+    border: 1px solid black;
+    padding: 1px;
+}
+
+.image-inline-left { 
+    border: 1px solid black;
+    padding: 1px;
+    float: left;
+    margin-right: 10px;
+}
+
+.image-inline-right { 
+    border: 1px solid black;
+    padding: 1px;
+    float: right;
+    margin-left: 10px;
+}
+
+
+#document-toc { 
+    border: 1px solid &dtml-globalBorderColor;;
+}
+
+#document-toc dt.portletHeader { 
+    background-color: &dtml-portalTopNavBackgroundColor;;
+    color: &dtml-portalTopNavFontColor;;
+    margin-left: 0em;
+    padding: 0em;
+}
+
+#document-toc dd.portletItem ol { 
+    list-style-type: none;                                  
+}
+
+#document-toc dd.portletItem ol ol { 
+    list-style-type: decimal;                                  
+}
+
+.portletCalendar dt { 
+    background-color: &dtml-backgroundColor;;
+}
+
+/* Live Search */
+.LSRow a:link, .LSRow a:visited, .LSRow a:hover, .LSRow a:active {
+    color: &dtml-portalHeaderBackgroundColor; !important;
+}
+
+.LSHighlight a:link, .LSHighlight a:visited, .LSHighlight a:hover, .LSHighlight a:active {
+    color: &dtml-portalHeaderBackgroundColor; !important;
+}
+
+
+/* </dtml-with> */
+
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/leftskinRTL.css
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/leftskinRTL.css	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/leftskinRTL.css	(revision 429)
@@ -0,0 +1,132 @@
+#portal-logo img {
+    padding: 0pt 1em;
+    margin: -1px 0em 0em -11px;
+    vertical-align: middle;
+}
+#portal-siteactions {
+    float: left;
+    padding: 3px 0 3px 2em;
+}
+#portal-searchbox {
+    margin-bottom: -5px;
+    padding: 0 0 0 2em;
+    float: left;
+    clear: left;
+}
+/* end goofy horizontal scroll problem */
+
+#portal-globalnav {
+    height: 1.5em;
+    margin-bottom: 1px;
+}
+/* #portal-globalnav li a {
+    float: right;
+    margin-left: 0.5em !important;
+    margin-bottom: -3px;
+} */
+/* html #portal-globalnav {
+    height: 0.1%;
+} */
+
+.visualClear{
+    margin: -1px -1px 0em 0pt;
+}
+
+.actionMenu .actionMenuContent li {
+    float:none;
+}
+.documentContent ul {
+    padding: 0em 12pt 0pt 0pt;
+}
+#opentext #opentext-a {
+    padding-left: 5px;
+    padding-right: 0px;
+}
+
+
+#portal-personaltools-wrapper{
+    /* settings from #portal-personaltools */
+    background-color: transparent;
+    border: none;
+}
+#portal-personaltools .portalUser {
+    background: transparent url(&dtml-portal_url;/user.gif) 100% 50% no-repeat;
+    margin: 0;
+    padding-right: 18px; /* fix for overlapping icon - smoothify */
+    padding-left: 1em; /* fix for overlapping icon - smoothify */
+    display: table-cell;
+}
+#portal-personaltools li {
+    background: transparent url(&dtml-portal_url;/rtl-linkOpaque.gif) 100% 50% no-repeat;
+    margin: 0;
+    padding-right: 10px; /* fix for overlapping icon - smoothify */
+    padding-left: 1em; /* fix for overlapping icon - smoothify */
+    display: table-cell;
+}
+
+.contentViews li a {
+    padding-bottom: 0.3em;
+}
+
+dl.collapsedInlineCollapsible {
+    float: right;
+    margin: 0.5em 1em 0em 0em;
+
+}
+
+dl.collapsedInlineCollapsible dt.collapsibleHeader {
+    background: transparent url(treeCollapsed.gif) scroll no-repeat 100% 50%;
+    padding: 0 15px 0px 0;
+    display: block;    
+}
+
+.contentActions {
+    clear: both;
+    text-align: left;
+    padding: 0 1em 0 0;
+}
+
+.contentActions ul,
+.contentActions li {
+    text-align: right !important;
+}
+
+
+.contentActions li {
+    float: left;
+    border-left: none;
+    border-right: &dtml-borderWidth; &dtml-borderStyle; &dtml-contentViewBorderColor;;
+}
+
+.contentActions .actionMenu {
+    left: -1px;
+} 
+.documentActions {
+    margin: 0.1em 0pt;
+}
+.documentActions a{
+    text-decoration: none !important;
+}
+.documentActions ul {
+    float: left;
+    clear: left;
+}
+* html .actionMenu .actionMenuHeader a {
+    float: left;
+}
+.actionMenu.activated .actionMenuHeader a,
+.actionMenu.deactivated .actionMenuHeader a {
+    padding: 0 0.5em;
+    cursor: pointer;
+}
+.hiddenStructure {
+    margin: -1px -1px 0 0;
+}
+#portal-column-one .visualPadding {
+    padding: 2em 2em 1em 0em;
+}
+/* Fix to big header which causes a horizontal scrollbar to appear */
+#portal-top {
+    margin-right: 1px;
+}
+/* </dtml-with> */
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/main_template.pt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/main_template.pt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/main_template.pt	(revision 429)
@@ -0,0 +1,206 @@
+<metal:page define-macro="master"><metal:doctype define-slot="doctype"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></metal:doctype>
+<metal:block define-slot="top_slot" />
+<metal:block use-macro="here/global_defines/macros/defines" />
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xml:lang="en"
+      lang="en"
+      tal:define="lang language"
+      tal:attributes="lang lang;
+                      xml:lang lang">
+
+  <tal:cache tal:define="charset site_properties/default_charset|string:utf-8">
+    <metal:cache use-macro="here/global_cache_settings/macros/cacheheaders">
+      Get the global cache headers located in global_cache_settings.
+    </metal:cache>
+  </tal:cache>
+
+  <head>
+
+    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"
+          tal:define="charset site_properties/default_charset|string:utf-8"
+          tal:attributes="content string:text/html;;charset=${charset}" />
+
+    <metal:baseslot define-slot="base">
+      <base tal:attributes="href here/renderBase" /><!--[if lt IE 7]></base><![endif]-->
+    </metal:baseslot>
+
+    <meta name="generator" content="Plone - http://plone.org" />
+
+    <div tal:replace="structure provider:plone.htmlhead" />
+
+    <meta tal:define="metatags python:putils.listMetaTags(here).items()"
+          tal:condition="metatags"
+          tal:repeat="keyval metatags"
+          tal:attributes="name python:keyval[0];
+                          content python:keyval[1];" />
+
+    <!-- Internet Explorer CSS Fixes -->
+    <tal:iefixstart replace="structure string:&lt;!--[if IE]&gt;" />
+        <style type="text/css" media="all" tal:condition="exists: portal/IEFixes.css"
+               tal:content="string:@import url($portal_url/IEFixes.css);">
+        </style>
+    <tal:iefixend replace="structure string:&lt;![endif]--&gt;" />
+
+    <link tal:replace="structure provider:plone.htmlhead.links" />
+
+    <link rel="alternate" href="" title="RSS 1.0" type="application/rss+xml"
+          tal:condition="python: syntool.isSyndicationAllowed(here)"
+          tal:attributes="href string:$here_url/RSS" />
+
+    <!-- Disable IE6 image toolbar -->
+    <meta http-equiv="imagetoolbar" content="no" />
+    
+    <tal:comment replace="nothing"> A slot where you can insert elements in the header from a template </tal:comment>
+    <metal:headslot define-slot="head_slot" />
+
+    <tal:comment replace="nothing"> A slot where you can insert CSS in the header from a template </tal:comment>
+    <metal:styleslot define-slot="style_slot" />
+
+    <tal:comment replace="nothing"> This is deprecated, please use style_slot instead. </tal:comment>
+    <metal:cssslot define-slot="css_slot" />
+
+    <tal:comment replace="nothing"> A slot where you can insert javascript in the header from a template </tal:comment>
+    <metal:javascriptslot define-slot="javascript_head_slot" />
+
+  </head>
+
+  <body tal:attributes="class string:${here/getSectionFromURL} template-${template/id};
+                        dir python:test(isRTL, 'rtl', 'ltr')">
+    <div id="visual-portal-wrapper">
+
+      <div id="portal-top" i18n:domain="plone">
+        <div tal:replace="structure provider:plone.portaltop" />
+      </div>
+
+      <div class="visualClear" id="clear-space-before-wrapper-table"><!-- --></div>
+
+      <table id="portal-columns">
+        <tbody>
+          <tr>
+            <tal:comment replace="nothing"> Start of the left column </tal:comment>
+            <td id="portal-column-one"
+                metal:define-slot="column_one_slot"
+                tal:condition="sl"
+		rowspan="2">
+              <div class="visualPadding">
+                <metal:portlets define-slot="portlets_one_slot">
+                  <tal:block replace="structure provider:plone.leftcolumn" />
+                </metal:portlets>
+                &nbsp;
+              </div>
+            </td>
+            <tal:comment replace="nothing"> End of the left column </tal:comment>
+
+	    <tal:comment replace="nothing"> Start of the content top </tal:comment>
+	    <td id="portal-content-top"
+		tal:define="cs python:test(sr, 2, 1)"
+		colspan="1"
+		tal:attributes="colspan cs">
+	      <div tal:replace="structure provider:leftskin.contenttop"/>
+	    </td>
+	    <tal:comment replace="nothing"> End of the content top </tal:comment>
+
+	  </tr>
+
+
+	  <tr>
+            <tal:comment replace="nothing"> Start of main content block </tal:comment>
+            <td id="portal-column-content" 
+                tal:define="tabindex python:Iterator(mainSlot=False)">
+
+              <metal:block define-slot="content">
+                <div metal:define-macro="content"
+                     tal:define="show_border context/@@plone/showEditableBorder"
+                     tal:attributes="class python:test(show_border,'documentEditable','')">
+
+                  <div tal:replace="structure provider:plone.contentviews" />
+
+                  <div id="region-content"
+                       class="documentContent">
+
+                    <span id="contentTopLeft"></span>
+                    <span id="contentTopRight"></span>
+                    
+                    <a name="documentContent"></a>
+
+                    <div metal:use-macro="here/global_statusmessage/macros/portal_message">
+                      Portal status message
+                    </div>
+                    
+                    <div id="viewlet-above-content" tal:content="structure provider:plone.abovecontent" />
+
+                    <metal:slot metal:define-slot="body">
+                    <tal:comment replace="nothing">
+                        The div with ID #content will only show up if we're actually on a content
+                        view, never on edit forms, control panels etc. It's meant to only wrap the
+                        actual content that gets rendered on a page, not the other UI elements.
+                    </tal:comment>
+                    <div id="content"
+                         tal:omit-tag="not:context/@@plone_context_state/is_view_template">
+                      <metal:header metal:define-slot="header" tal:content="nothing">
+                        Visual Header
+                      </metal:header>
+                      <metal:bodytext metal:define-slot="main" tal:content="nothing">
+                        Page body text
+                      </metal:bodytext>
+                    </div>
+                    </metal:slot>
+
+                    <metal:sub metal:define-slot="sub">
+                    
+                      <div tal:replace="structure provider:plone.belowcontent" />
+                    
+                    </metal:sub>
+
+                    <span id="contentBottomLeft"></span>
+                    <span id="contentBottomRight"></span>
+
+                  </div>
+
+                </div>
+
+              </metal:block>
+            </td>
+            <tal:comment replace="nothing"> End of main content block </tal:comment>
+
+            <tal:comment replace="nothing"> Start of right column </tal:comment>
+            <td id="portal-column-two"
+                metal:define-slot="column_two_slot"
+                tal:condition="sr">
+              <div class="visualPadding">
+                <metal:portlets define-slot="portlets_two_slot">
+                  <tal:block replace="structure provider:plone.rightcolumn" />
+                </metal:portlets>
+                &nbsp;
+              </div>
+            </td>
+            <tal:comment replace="nothing"> End of the right column </tal:comment>
+          </tr>
+        </tbody>
+      </table>
+      <tal:comment replace="nothing"> end column wrapper </tal:comment>
+
+      <div class="visualClear" id="clear-space-before-footer"><!-- --></div>
+      
+      <div tal:define="portlet_assignable context/@@plone_context_state/portlet_assignable"
+            tal:condition="python:not sl and not sr and portlet_assignable and checkPermission('Portlets: Manage portlets', context)">
+          <a class="managePortletsFallback"
+             tal:attributes="href string:${context/absolute_url}/@@manage-portlets"
+             i18n:translate="manage_portlets_fallback">
+             Manage portlets
+          </a>
+      </div>
+
+      <metal:block i18n:domain="plone">
+
+        <div tal:replace="structure provider:plone.portalfooter" />
+
+      </metal:block>
+
+      <div class="visualClear"></div>
+    </div>
+<div id="kss-spinner"><img tal:attributes="src string:${portal_url}/spinner.gif" alt="" /></div>
+</body>
+</html>
+</metal:page>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/portlet_prefs.pt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/portlet_prefs.pt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/portlet_prefs.pt	(revision 429)
@@ -0,0 +1,60 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+      xmlns:tal="http://xml.zope.org/namespaces/tal"
+      xmlns:metal="http://xml.zope.org/namespaces/metal"
+      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+      i18n:domain="plone">
+<body>
+<metal:portlet define-macro="portlet"
+   tal:define="controlPanel python:modules['Products.CMFCore.utils'].getToolByName(here, 'portal_controlpanel');
+               groups python:controlPanel.getGroups('site');
+               getIconFor nocall:putils/getIconFor">
+
+<td id="portal-column-one" rowspan="2">
+<div class="visualPadding">
+
+<dl class="portlet"
+    id="portlet-prefs">
+    <dt class="portletHeader">
+        <span class="portletTopLeft"></span>
+        <a href="" 
+           tal:attributes="href string:${portal_url}/plone_control_panel"
+           i18n:translate="heading_control_panel">Site Setup</a>
+        <span class="portletTopRight"></span>
+    </dt>
+
+    <dd class="portletItem"
+        tal:repeat="group groups">
+
+        <tal:block tal:define="configlets python:controlPanel.enumConfiglets(group=group['id'])"
+                   tal:condition="configlets">
+            <strong tal:content="group/title"
+                    i18n:translate="">Plone Configlet Group Title</strong>
+            <ul class="configlets">
+
+                <li tal:repeat="configlet configlets">
+                    <a href=""
+                       tal:attributes="href configlet/url"
+                       tal:condition="configlet/visible">
+                        <img src="" alt="" tal:attributes="src python:'%s/%s' % (portal_url, getIconFor('controlpanel',configlet['id']));
+                                             alt configlet/description"
+                             i18n:attributes="alt"
+                             tal:on-error="string:" />
+                    <tal:configletname tal:content="configlet/title"
+                                       i18n:translate=""></tal:configletname>
+                    </a>
+                </li>
+            </ul>
+        </tal:block>
+        <span class="portletBottomLeft"></span>
+        <span class="portletBottomRight"></span>
+    </dd>
+
+</dl>
+
+</div>
+</td>
+
+
+</metal:portlet>
+</body>
+</html>
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/s5_pretty.css.dtml
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/s5_pretty.css.dtml	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/skins/leftskin/s5_pretty.css.dtml	(revision 429)
@@ -0,0 +1,236 @@
+/* 
+*  S5 is a Simple Standards-based Slide Show System.
+*  Thanks to Eric Meyer for this excellent technique:
+*  http://meyerweb.com/eric/tools/s5/
+*/
+
+/* <dtml-with base_properties> (do not remove this :) */
+/* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) */
+
+/*
+** BASE STYLES
+*/
+
+body {
+    font-size: 2em;
+}
+html, body {margin: 0; padding: 0; line-height: 1.25em;}
+
+h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
+ul, pre {margin: 0;}
+ol {margin: 0 1.5em;}
+blockquote, q {font-style: italic;}
+blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}
+blockquote p {margin: 0;}
+blockquote i {font-style: normal;}
+blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}
+blockquote b i {font-style: italic;}
+
+kbd {font-weight: bold; font-size: 1em;}
+sup {font-size: smaller; line-height: 1px;}
+
+.slide code {padding: 2px 0.25em; font-weight: bold; color: &dtml-fontColor;;}
+.slide code.bad, code del {color: red;}
+.slide code.old {color: silver;}
+.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: &dtml-fontColor;; font-size: 90%;}
+.slide pre code {display: block;}
+.slide ul {margin-left: 5%; margin-right: 7%; list-style: square;}
+.slide li {margin-top: 0.75em; margin-right: 0;}
+.slide ul ul {line-height: 1;}
+.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}
+.slide img.leader {display: block; margin: 0 auto;}
+.slide a { text-decoration: none; border-bottom: 2px solid &dtml-linkColor;;}
+
+ul.urls {list-style: none; display: inline; margin: 0;}
+.urls li {display: inline; margin: 0;}
+.note,  .discreet {display: none;}
+.external {border-bottom: &dtml-borderWidth; dotted &dtml-contentViewBorderColor;;}
+html>body .external {border-bottom: none;}
+.external:after {content: " \274F"; font-size: smaller; color: #77B;}
+
+.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}
+img.incremental {visibility: hidden;}
+.slide .current {color: #B02;}
+
+div.long {
+    font-size: 0.75em;
+}
+h1 abbr {
+    font-variant: small-caps;
+}
+
+/*
+** TOP STYLES
+*/
+
+div#header {
+    color: &dtml-portalHeaderFontColor;;
+    line-height: 1px;
+    border-bottom: &dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;;
+    background-color: &dtml-portalHeaderBackgroundColor;;
+}
+.slide h1 {
+    position: absolute; 
+    top: 0; 
+    left: 0; 
+    z-index: 1;
+    margin: 0; 
+    padding: 0.3em 0 0 1em; 
+    white-space: nowrap;
+    font: bold 150%/1em Helvetica, sans-serif; 
+    color: &dtml-portalHeaderFontColor;; 
+    text-align: center;
+}
+
+/*
+** FOOTER STYLES
+*/
+
+div#footer {
+    background: &dtml-portalHeaderBackgroundColor; url('&dtml-portal_url;/&dtml-logoName;') 10px 10px no-repeat; 
+    border-top: &dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;;    
+    color: &dtml-portalHeaderFontColor;;
+    font-size: 0.5em; 
+    font-weight: bold; 
+    padding: 1em 0;    
+}
+#portal-logo img {
+    border: 0;
+    padding: 0;
+    margin: 0.5em;
+}
+#footer h1, 
+#footer h2 {
+    display: block; 
+    padding: 0 1em;
+}
+#footer h2 {
+    font-style: italic;
+}
+#currentSlide {
+    text-align: center; 
+    font-size: 0.5em; 
+    color: &dtml-portalHeaderFontColor;;
+}
+
+/* controls styles */
+#controls :focus {
+    outline: 1px dotted #227;
+}
+div#controls {
+    position: absolute; 
+    left: 50%; 
+    bottom: 0;
+    width: 50%;
+    text-align: right; 
+    font-weight: bold;
+    font-size: 0.9em;
+}
+html > body div#controls {
+    position: fixed; 
+    padding: 0 0 1em 0;
+    top: auto;
+}
+div#controls form {
+    position: absolute; 
+    bottom: 0; 
+    right: 0; 
+    width: 100%;
+    margin: 0; 
+    padding: 0;
+}
+#controls #navList {
+    height: 1em;
+}
+#controls #navList #jumplist {
+    position: absolute; 
+    bottom: 0; 
+    right: 0; 
+    background: &dtml-globalBackgroundColor;; 
+    color: &dtml-globalFontColor;;
+}
+#controls #navLinks a {
+    padding: 0; 
+    margin: 0 0.5em;
+    background: &dtml-portalHeaderBackgroundColor;; 
+    border: none; 
+    color: &dtml-portalHeaderLinkColor;; 
+    cursor: pointer;
+    text-decoration: none;
+}
+
+/*
+** SLIDE CONTENT'S STYLES
+*/
+
+.slide h3 {
+    font-size: 130%;
+}
+#slide0 {
+    padding-top: 2.5em; 
+    font-size: 90%;
+}
+
+#slide0 #header {
+    display: none;
+}
+
+#slide0 h1 {
+    position: static; 
+    margin: 1em 0 0; 
+    padding: 0;
+    font-weight: bold;
+    font-size: 2em; 
+    white-space: normal;
+    color: #000; 
+    background: transparent;
+    text-align: center;
+}
+#slide0 h2 {
+    font-weight: bold;
+    font-size: 1em;
+    margin: 0.25em;
+    text-align: center;
+}
+#slide0 h3 {
+    display: none;
+}
+#slide0 h4 {
+    margin-top: 0; 
+    font-size: 1em;
+}
+
+
+table.documentTable td { 
+    font-size: 0.6em;
+}
+
+table.documentTable {
+    border-top: 1px solid &dtml-portalHeaderBackgroundColor;; 
+    border-bottom: 1px solid &dtml-portalHeaderBackgroundColor;; 
+    border-left: 1px solid &dtml-portalHeaderBackgroundColor;; 
+
+}
+
+table.documentTable thead, .documentTable tfoot {
+    background: &dtml-portalHeaderBackgroundColor;; 
+    color: &dtml-portalHeaderFontColor;;
+}
+
+table.documentTable td {
+  border-right: 1px solid &dtml-portalHeaderBackgroundColor;; 
+  padding: 3px;
+}
+
+table.documentTable .odd {
+    background: &dtml-oddRowBackgroundColor;;
+}
+
+table.documentTable .even {
+    background: &dtml-evenRowBackgroundColor;;
+}
+
+
+ 
+
+/* </dtml-with> */ 
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/__init__.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/__init__.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/__init__.py	(revision 429)
@@ -0,0 +1,1 @@
+##I'm alive!
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/base.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/base.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/base.py	(revision 429)
@@ -0,0 +1,92 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from zope.testing import doctest
+from zope.testing.doctestunit import DocFileSuite
+from Testing import ZopeTestCase
+from Testing.ZopeTestCase import FunctionalDocFileSuite, ZopeDocFileSuite, Functional
+from Testing.ZopeTestCase import ZopeDocFileSuite
+from Products.PloneTestCase.PloneTestCase import PloneTestCase
+from Products.PloneTestCase.PloneTestCase import FunctionalTestCase, setupPloneSite, installProduct, installPackage
+from setuptools import find_packages
+
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+from Products.PloneTestCase.layer import onsetup
+from Testing import ZopeTestCase as ztc
+from Products.CMFPlone.tests import dummy
+
+
+packages=find_packages('src'),
+package_dir = {'': 'src'},
+
+@onsetup
+def setup_leftskin_project():
+    """Set up the additional products required for the borg.project tests.
+    
+    The @onsetup decorator causes the execution of this body to be deferred
+    until the setup of the Plone site testing layer.
+    """
+    
+    # Load the ZCML configuration for the enpraxis.leftskin package
+
+    fiveconfigure.debug_mode = True
+
+    import enpraxis.leftskin
+    zcml.load_config('configure.zcml', enpraxis.leftskin)
+    fiveconfigure.debug_mode = False
+    
+    # We need to tell the testing framework that these products
+    # should be available. This can't happen until after we have loaded
+    # the ZCML. Notice the extra package=True argument passed to 
+    # installProduct() - this tells it that these packages are *not* in the
+    # Products namespace.
+    
+    ztc.installPackage('enpraxis.leftskin')
+
+    
+# The order here is important: We first call the (deferred) function which
+# installs the products we need for the package. Then, we let 
+# PloneTestCase set up on installation.
+
+setup_leftskin_project()
+setupPloneSite(with_default_memberarea=0, extension_profiles=['enpraxis.leftskin:default',])           
+
+
+oflags = (doctest.ELLIPSIS |
+          doctest.NORMALIZE_WHITESPACE)
+prod = 'enpraxis.leftskin'
+
+class leftskinTestCase(PloneTestCase):
+    """ 
+    Unit test package for lefstkinTestCase
+    """
+    def _setupHomeFolder(self):
+        """ Ugly hack to keep the underlying testing framework from trying to create
+            a user folder. """
+        pass
+
+class leftskinFunctionalTestCase(Functional, leftskinTestCase):
+    """ Base class for functional integration tests. """
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/base_properties.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/base_properties.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/base_properties.txt	(revision 429)
@@ -0,0 +1,46 @@
+==============================================================================
+Test Proper backup and restoration of base_properties on theme change
+==============================================================================
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> portal_url = self.portal.absolute_url()
+    >>> browser.open(portal_url)
+
+Login as an admin
+
+    >>> self.setRoles(['Manager',])
+    >>> self.portal.portal_membership.addMember('manager','secret',('Manager',),())
+    >>> browser.getLink('Log in').click()
+    >>> browser.getControl('Login Name').value = 'manager'
+    >>> browser.getControl('Password').value = 'secret'
+    >>> browser.getControl('Log in').click()
+    >>> browser.open(portal_url)
+
+Navigate to Theme Control Panel
+
+    >>> browser.getLink('Site Setup').click()
+    >>> browser.getLink('Themes').click()
+
+Change to Plone Default Theme
+
+    >>> browser.getControl('Default theme').value = ('Plone Default',)
+    >>> browser.getControl('Save').click()
+
+Check if base_properties was backed up
+    >>> hasattr(self.portal.portal_skins.custom, 'base_properties.leftskin')
+    True
+
+Revert back to Left Skin Theme
+
+    >>> browser.getControl('Default theme').value = ('Left Skin',)
+    >>> browser.getControl('Save').click()
+
+Check to see if base_properties.leftskin was restored
+
+    >>> hasattr(self.portal.portal_skins.custom, 'base_properties.leftskin')
+    False
+    >>> hasattr(self.portal.portal_skins.custom, 'base_properties')
+    True
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/control_panel.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/control_panel.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/control_panel.txt	(revision 429)
@@ -0,0 +1,41 @@
+==============================================================================
+Test to ensure the right controlpanel is available for Left Skin Theme vs Other Themes
+==============================================================================
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> portal_url = self.portal.absolute_url()
+    >>> browser.open(portal_url)
+
+Login as an admin
+
+    >>> self.setRoles(['Manager',])
+    >>> self.portal.portal_membership.addMember('manager','secret',('Manager',),())
+    >>> browser.getLink('Log in').click()
+    >>> browser.getControl('Login Name').value = 'manager'
+    >>> browser.getControl('Password').value = 'secret'
+    >>> browser.getControl('Log in').click()
+    >>> browser.open(portal_url)
+
+Check for Left Skin CSS Helper
+
+    >>> browser.getLink('Site Setup').click()
+    >>> 'Left Skin CSS Settings' in browser.contents
+    True
+    >>> 'CSS Helper' in browser.contents
+    True
+
+Change theme to Plone Default
+
+    >>> browser.getLink('Themes').click()
+    >>> browser.getControl('Default theme').value = ('Plone Default',)
+    >>> browser.getControl('Save').click()
+    >>> browser.getLink('Site Setup').click()
+    >>> 'Left Skin CSS Settings' in browser.contents
+    False
+    >>> 'CSS Helper' in browser.contents
+    True
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/prefs.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/prefs.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/prefs.txt	(revision 429)
@@ -0,0 +1,13 @@
+===========
+Preferences
+===========
+
+Test the prefs control panel for eduCommons.
+
+Get some imports.
+
+    >>> from enpraxis.leftskin.browser.controlpanel import ILeftSkinSchema
+    >>> from Products.CMFPlone.interfaces import IPloneSiteRoot
+    >>> from Products.CMFCore.interfaces import IPropertiesTool
+    >>> from zope.component import getAdapter, getUtility
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_case_change_theme.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_case_change_theme.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_case_change_theme.py	(revision 429)
@@ -0,0 +1,62 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from base import leftskinTestCase
+from Products.CMFCore.utils import getToolByName
+
+class testInstall(leftskinTestCase):
+
+    def test_leftskinInstall(self):
+        self.failUnless('enpraxis.leftskin' in [product['product'] for product in self.portal.portal_setup.listProfileInfo()])
+
+    def test_installControlPanel(self):
+        control_panel = getToolByName(self.portal, 'portal_controlpanel', None)
+        las = ['LeftSkin_basic', 'LeftSkin_adv']
+        for la in las:
+            self.failUnless(la in [listAction.id for listAction in control_panel.listActions()])
+               
+    def test_installJavascriptObjects(self):
+        pjs = getToolByName(self.portal, 'portal_javascripts',None)
+        js_files = ['js/colorpicker.js', 'js/eye.js', 'js/utils.js', 'js/layout.js']
+        for js in js_files:
+            self.assertEqual(pjs.getResource(js).getEnabled(), True)
+
+    def test_installSiteCSS(self):
+        cssreg = getToolByName(self.portal,'portal_css')
+        css_files = ['leftskin.css', 'leftskinRTL.css', 'css/colorpicker.css', 'css/layout.css']
+
+        for css in css_files:
+            css_file = cssreg.getResource('leftskin.css')
+            self.assertEqual(css_file.getCookable(),True)
+
+    def test_installCustomBaseProperties(self):
+        skins_tool = getToolByName(self.portal, 'portal_skins')
+        self.failUnless('base_properties' in skins_tool.custom.aq_explicit)
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(testInstall))
+    return suite
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_case_install.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_case_install.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_case_install.py	(revision 429)
@@ -0,0 +1,62 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from base import leftskinTestCase
+from Products.CMFCore.utils import getToolByName
+
+class testInstall(leftskinTestCase):
+
+    def test_leftskinInstall(self):
+        self.failUnless('enpraxis.leftskin' in [product['product'] for product in self.portal.portal_setup.listProfileInfo()])
+
+    def test_installControlPanel(self):
+        control_panel = getToolByName(self.portal, 'portal_controlpanel', None)
+        las = ['LeftSkin_basic', 'LeftSkin_adv', 'LeftSkin_compl']
+        for la in las:
+            self.failUnless(la in [listAction.id for listAction in control_panel.listActions()])
+               
+    def test_installJavascriptObjects(self):
+        pjs = getToolByName(self.portal, 'portal_javascripts',None)
+        js_files = ['js/colorpicker.js', 'js/eye.js', 'js/utils.js', 'js/layout.js']
+        for js in js_files:
+            self.assertEqual(pjs.getResource(js).getEnabled(), True)
+
+    def test_installSiteCSS(self):
+        cssreg = getToolByName(self.portal,'portal_css')
+        css_files = ['leftskin.css', 'leftskinRTL.css', 'css/colorpicker.css', 'css/layout.css']
+
+        for css in css_files:
+            css_file = cssreg.getResource('leftskin.css')
+            self.assertEqual(css_file.getCookable(),True)
+
+    def test_installCustomBaseProperties(self):
+        skins_tool = getToolByName(self.portal, 'portal_skins')
+        self.failUnless('base_properties' in skins_tool.custom.aq_explicit)
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(testInstall))
+    return suite
+
+
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_doctests.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_doctests.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/tests/test_doctests.py	(revision 429)
@@ -0,0 +1,51 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from base import prod, oflags, leftskinFunctionalTestCase
+from Testing.ZopeTestCase import FunctionalDocFileSuite
+from unittest import TestSuite
+
+
+def test_suite():
+    suite = TestSuite()
+
+    prefs_test = FunctionalDocFileSuite('tests/prefs.txt',
+                                       package=prod,
+                                       test_class=leftskinFunctionalTestCase,
+                                       optionflags=oflags)
+
+    base_properties_test = FunctionalDocFileSuite('tests/base_properties.txt',
+                                       package=prod,
+                                       test_class=leftskinFunctionalTestCase,
+                                       optionflags=oflags)
+
+    control_panel_test = FunctionalDocFileSuite('tests/control_panel.txt',
+                                       package=prod,
+                                       test_class=leftskinFunctionalTestCase,
+                                       optionflags=oflags)
+                                                         
+    suite.addTests((prefs_test,
+                    base_properties_test,
+                    control_panel_test))
+
+    return suite
Index: /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/version.txt
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/version.txt	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/enpraxis/leftskin/version.txt	(revision 429)
@@ -0,0 +1,1 @@
+1.1.0
Index: /enpraxis.leftskin/tags/1.1.0/trunk/setup.cfg
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/setup.cfg	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/setup.cfg	(revision 429)
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
Index: /enpraxis.leftskin/tags/1.1.0/trunk/setup.py
===================================================================
--- /enpraxis.leftskin/tags/1.1.0/trunk/setup.py	(revision 429)
+++ /enpraxis.leftskin/tags/1.1.0/trunk/setup.py	(revision 429)
@@ -0,0 +1,56 @@
+##################################################################################
+#    Copyright (c) 2004-2009 Utah State University, All rights reserved. 
+#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
+#                                                                                 
+#    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.                                          
+#                                                                                 
+#    This program is distributed in the hope that it will be useful,              
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of               
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
+#    GNU General Public License for more details.                                 
+#                                                                                 
+#    You should have received a copy of the GNU General Public License            
+#    along with this program; if not, write to the Free Software                  
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    
+#                                                                                 
+##################################################################################
+
+__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
+__version__   = '$ Revision 0.0 $'[11:-2]
+
+from setuptools import setup, find_packages
+import os
+
+version = '1.1.0'
+
+setup(name='enpraxis.leftskin',
+      version=version,
+      description="leftskin is a skin product that customizes the workflow and look of your Plone site.",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Framework :: Plone",
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='skin leftskin Plone',
+      author='display. It allows the left column to be styled, and retains the ablilty to move',
+      author_email='portlets into and out of it with no additional styling required.',
+      url='http://svn.enpraxis.net/svn/enpraxis.leftskin/trunk',
+      license='GPL',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['enpraxis'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )
