SF.net SVN: morphix: [2615] trunk

[email protected] Sat, 09 Feb 2008 08:30:40 -0800
Newsgroups gmane.linux.morphix.cvs
Message-ID <[email protected]>
Revision: 2615
          http://morphix.svn.sourceforge.net/morphix/?rev=2615&view=rev
Author:   alextreme
Date:     2008-02-09 08:30:37 -0800 (Sat, 09 Feb 2008)

Log Message:
-----------
 * importing templatetool

Added Paths:
-----------
    trunk/templatetool/
    trunk/templatetool/__init__.py
    trunk/templatetool/manage.py
    trunk/templatetool/media/
    trunk/templatetool/media/css/
    trunk/templatetool/media/css/base.css
    trunk/templatetool/media/css/changelists.css
    trunk/templatetool/media/css/dashboard.css
    trunk/templatetool/media/css/forms.css
    trunk/templatetool/media/css/global.css
    trunk/templatetool/media/css/layout.css
    trunk/templatetool/media/css/login.css
    trunk/templatetool/media/css/patch-iewin.css
    trunk/templatetool/media/css/rtl.css
    trunk/templatetool/media/css/widgets.css
    trunk/templatetool/media/img/
    trunk/templatetool/media/img/admin/
    trunk/templatetool/media/img/admin/arrow-down.gif
    trunk/templatetool/media/img/admin/arrow-up.gif
    trunk/templatetool/media/img/admin/changelist-bg.gif
    trunk/templatetool/media/img/admin/chooser-bg.gif
    trunk/templatetool/media/img/admin/chooser_stacked-bg.gif
    trunk/templatetool/media/img/admin/default-bg-reverse.gif
    trunk/templatetool/media/img/admin/default-bg.gif
    trunk/templatetool/media/img/admin/deleted-overlay.gif
    trunk/templatetool/media/img/admin/icon-no.gif
    trunk/templatetool/media/img/admin/icon-unknown.gif
    trunk/templatetool/media/img/admin/icon-yes.gif
    trunk/templatetool/media/img/admin/icon_addlink.gif
    trunk/templatetool/media/img/admin/icon_alert.gif
    trunk/templatetool/media/img/admin/icon_calendar.gif
    trunk/templatetool/media/img/admin/icon_changelink.gif
    trunk/templatetool/media/img/admin/icon_clock.gif
    trunk/templatetool/media/img/admin/icon_deletelink.gif
    trunk/templatetool/media/img/admin/icon_error.gif
    trunk/templatetool/media/img/admin/icon_searchbox.png
    trunk/templatetool/media/img/admin/icon_success.gif
    trunk/templatetool/media/img/admin/inline-delete-8bit.png
    trunk/templatetool/media/img/admin/inline-delete.png
    trunk/templatetool/media/img/admin/inline-restore-8bit.png
    trunk/templatetool/media/img/admin/inline-restore.png
    trunk/templatetool/media/img/admin/inline-splitter-bg.gif
    trunk/templatetool/media/img/admin/nav-bg-grabber.gif
    trunk/templatetool/media/img/admin/nav-bg-reverse.gif
    trunk/templatetool/media/img/admin/nav-bg.gif
    trunk/templatetool/media/img/admin/selector-add.gif
    trunk/templatetool/media/img/admin/selector-addall.gif
    trunk/templatetool/media/img/admin/selector-remove.gif
    trunk/templatetool/media/img/admin/selector-removeall.gif
    trunk/templatetool/media/img/admin/selector-search.gif
    trunk/templatetool/media/img/admin/selector_stacked-add.gif
    trunk/templatetool/media/img/admin/selector_stacked-remove.gif
    trunk/templatetool/media/img/admin/tool-left.gif
    trunk/templatetool/media/img/admin/tool-left_over.gif
    trunk/templatetool/media/img/admin/tool-right.gif
    trunk/templatetool/media/img/admin/tool-right_over.gif
    trunk/templatetool/media/img/admin/tooltag-add.gif
    trunk/templatetool/media/img/admin/tooltag-add_over.gif
    trunk/templatetool/media/img/admin/tooltag-arrowright.gif
    trunk/templatetool/media/img/admin/tooltag-arrowright_over.gif
    trunk/templatetool/media/js/
    trunk/templatetool/media/js/SelectBox.js
    trunk/templatetool/media/js/SelectFilter.js
    trunk/templatetool/media/js/SelectFilter2.js
    trunk/templatetool/media/js/admin/
    trunk/templatetool/media/js/admin/CollapsedFieldsets.js
    trunk/templatetool/media/js/admin/DateTimeShortcuts.js
    trunk/templatetool/media/js/admin/RelatedObjectLookups.js
    trunk/templatetool/media/js/admin/ordering.js
    trunk/templatetool/media/js/calendar.js
    trunk/templatetool/media/js/core.js
    trunk/templatetool/media/js/dateparse.js
    trunk/templatetool/media/js/getElementsBySelector.js
    trunk/templatetool/media/js/timeparse.js
    trunk/templatetool/media/js/urlify.js
    trunk/templatetool/modify/
    trunk/templatetool/modify/__init__.py
    trunk/templatetool/modify/models.py
    trunk/templatetool/modify/urls.py
    trunk/templatetool/modify/views.py
    trunk/templatetool/settings.py
    trunk/templatetool/template.py
    trunk/templatetool/tt_templates/
    trunk/templatetool/tt_templates/modify/
    trunk/templatetool/tt_templates/modify/index.html
    trunk/templatetool/tt_templates/modify/main.html
    trunk/templatetool/tt_templates/modify/template.html
    trunk/templatetool/urls.py

Added: trunk/templatetool/__init__.py
===================================================================

Added: trunk/templatetool/manage.py
===================================================================
--- trunk/templatetool/manage.py	                        (rev 0)
+++ trunk/templatetool/manage.py	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+    import settings # Assumed to be in the same directory.
+except ImportError:
+    import sys
+    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+    sys.exit(1)
+
+if __name__ == "__main__":
+    execute_manager(settings)

Added: trunk/templatetool/media/css/base.css
===================================================================
--- trunk/templatetool/media/css/base.css	                        (rev 0)
+++ trunk/templatetool/media/css/base.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,14 @@
+/*
+    DJANGO Admin
+    by Wilson Miner wilson-W1WbbPd4oPNWk0Htik3J/[email protected]
+*/
+
+/* Block IE 5 */
+@import "null?\"\{";
+
+/* Import other styles */
+@import url('global.css');
+@import url('layout.css');
+
+/* Import patch for IE 6 Windows */
+/*\*/ @import "patch-iewin.css"; /**/
\ No newline at end of file

Added: trunk/templatetool/media/css/changelists.css
===================================================================
--- trunk/templatetool/media/css/changelists.css	                        (rev 0)
+++ trunk/templatetool/media/css/changelists.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,50 @@
+@import url('base.css');
+
+/* CHANGELISTS */
+#changelist { position:relative; width:100%; }
+#changelist table { width:100%; }
+.change-list .filtered table { border-right:1px solid #ddd;  }
+.change-list .filtered { min-height:400px; }
+.change-list .filtered { background:white url(../img/admin/changelist-bg.gif) top right repeat-y !important; }
+.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:160px !important; width:auto !important; }
+.change-list .filtered table tbody th { padding-right:1em; }
+#changelist .toplinks { border-bottom:1px solid #ccc !important; }
+#changelist .paginator { color:#666; border-top:1px solid #eee; border-bottom:1px solid #eee; background:white url(../img/admin/nav-bg.gif) 0 180% repeat-x; overflow:hidden; }
+.change-list .filtered .paginator { border-right:1px solid #ddd; }
+
+/*  CHANGELIST TABLES  */
+#changelist table thead th { white-space:nowrap; }
+#changelist table tbody td { border-left: 1px solid #ddd; }
+#changelist table tfoot { color: #666; }
+
+/*  TOOLBAR  */
+#changelist #toolbar { padding:3px; border-bottom:1px solid #ddd; background:#e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; color:#666; }
+#changelist #toolbar form input { font-size:11px; padding:1px 2px; }
+#changelist #toolbar form #searchbar { padding:2px; }
+#changelist #changelist-search img { vertical-align:middle; }
+
+/*  FILTER COLUMN  */
+#changelist-filter { position:absolute; top:0; right:0; z-index:1000; width:160px; border-left:1px solid #ddd; background:#efefef; margin:0; }
+#changelist-filter h2 { font-size:11px; padding:2px 5px; border-bottom:1px solid #ddd; }
+#changelist-filter h3 { font-size:12px; margin-bottom:0; }
+#changelist-filter ul { padding-left:0;margin-left:10px; }
+#changelist-filter li { list-style-type:none; margin-left:0; padding-left:0; }
+#changelist-filter a { color:#999; }
+#changelist-filter a:hover { color:#036; }
+#changelist-filter li.selected { border-left:5px solid #ccc; padding-left:5px;margin-left:-10px; }
+#changelist-filter li.selected a { color:#5b80b2 !important; }
+
+/*  DATE DRILLDOWN  */
+.change-list ul.toplinks { display:block; background:white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x; border-top:1px solid white; float:left;  padding:0 !important;  margin:0 !important; width:100%; }
+.change-list ul.toplinks li { float: left; width: 9em; padding:3px 6px; font-weight: bold; list-style-type:none; }
+.change-list ul.toplinks .date-back a { color:#999; }
+.change-list ul.toplinks .date-back a:hover { color:#036; }
+
+/* PAGINATOR */
+.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
+.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
+.paginator a.showall { padding:0 !important; border:none !important; }
+.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
+.paginator .end { border-width:2px !important; margin-right:6px; }
+.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
+.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }

Added: trunk/templatetool/media/css/dashboard.css
===================================================================
--- trunk/templatetool/media/css/dashboard.css	                        (rev 0)
+++ trunk/templatetool/media/css/dashboard.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,10 @@
+@import url('base.css');
+
+/* DASHBOARD */
+.dashboard .module table th { width:100%; }
+.dashboard .module table td { white-space:nowrap; }
+.dashboard .module table td a { display:block; padding-right:.6em; }
+
+/*  RECENT ACTIONS MODULE  */
+.module ul.actionlist { margin-left:0; }
+ul.actionlist li { list-style-type:none; }
\ No newline at end of file

Added: trunk/templatetool/media/css/forms.css
===================================================================
--- trunk/templatetool/media/css/forms.css	                        (rev 0)
+++ trunk/templatetool/media/css/forms.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,60 @@
+@import url('base.css');
+@import url('widgets.css');
+
+/* FORM ROWS */
+.form-row { overflow:hidden; padding:8px 12px; font-size:11px; border-bottom:1px solid #eee; }
+.form-row img, .form-row input { vertical-align:middle; }
+form .form-row p { padding-left:0; font-size:11px; }
+
+/* FORM LABELS */
+form h4 { margin:0 !important; padding:0 !important; border:none !important; }
+label { font-weight:normal !important; color:#666; font-size:12px; }
+label.inline { margin-left:20px; }
+.required label, label.required { font-weight:bold !important; color:#333 !important; }
+
+/* RADIO BUTTONS */
+form ul.radiolist li { list-style-type:none; }
+form ul.radiolist label { float:none; display:inline; }
+form ul.inline { margin-left:0; padding:0; }
+form ul.inline li { float:left; padding-right:7px; }
+
+/* ALIGNED FIELDSETS */
+.aligned label { display:block; padding:0 1em 3px 0; float:left; width:8em; }
+.aligned label.inline { display:inline; float:none; }
+.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { width:350px; }
+form .aligned p, form .aligned ul { margin-left:7em; padding-left:30px; }
+form .aligned table p { margin-left:0; padding-left:0; }
+form .aligned p.help { padding-left:38px; }
+.aligned .vCheckboxLabel { float:none !important; display:inline; padding-left:4px; }
+.colM .aligned .vLargeTextField, colM .aligned .vXMLLargeTextField { width:610px; }
+.checkbox-row p.help { margin-left:0; padding-left:0 !important; }
+
+/* WIDE FIELDSETS */
+.wide label { width:15em !important; }
+form .wide p { margin-left:15em; }
+form .wide p.help { padding-left:38px; }
+.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { width:450px; }
+
+/* COLLAPSED FIELDSETS */
+fieldset.collapsed * { display:none; }
+fieldset.collapsed h2, fieldset.collapsed { display:block !important; }
+fieldset.collapsed h2 { background-image:url(../img/admin/nav-bg.gif); background-position:bottom left; color:#999; }
+fieldset.collapsed .collapse-toggle { padding:3px 5px !important; background:transparent; display:inline !important;}
+
+/* MONOSPACE TEXTAREAS */
+fieldset.monospace textarea { font-family:"Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace; }
+
+/* SUBMIT ROW */
+.submit-row { padding:5px 7px; text-align:right; background:white url(../img/admin/nav-bg.gif) 0 100% repeat-x; border:1px solid #ccc; margin:5px 0; }
+.submit-row input { margin:0 0 0 5px; }
+.submit-row p { margin-top:0.3em; }
+.submit-row .deletelink { background:url(../img/admin/icon_deletelink.gif) 0 50% no-repeat; padding-left:14px; }
+
+/* CUSTOM FORM FIELDS */
+.vSelectMultipleField { vertical-align:top !important; }
+.vCheckboxField { border:none; }
+.vDateField, .vTimeField { margin-right:2px; }
+.vURLField { width:30em; }
+.vLargeTextField, .vXMLLargeTextField { width:48em; }
+.flatpages-flatpage #id_content { height:40.2em; }
+.module table .vPositiveSmallIntegerField { width:2.2em; }

Added: trunk/templatetool/media/css/global.css
===================================================================
--- trunk/templatetool/media/css/global.css	                        (rev 0)
+++ trunk/templatetool/media/css/global.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,141 @@
+body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
+
+/* LINKS */
+a:link, a:visited { color: #5b80b2; text-decoration:none; }
+a:hover { color: #036; }
+a img { border:none; }
+
+/* GLOBAL DEFAULTS */
+p, ol, ul, dl { margin:.2em 0 .8em 0; }
+p { padding:0; line-height:140%; }
+
+h1,h2,h3,h4,h5 { font-weight:bold; }
+h1 { font-size:18px; color:#666; padding:0 6px 0 0; margin:0 0 .2em 0; }
+h2 { font-size:16px; margin:1em 0 .5em 0; }
+h2.subhead { font-weight:normal;margin-top:0; }
+h3 { font-size:14px; margin:.8em 0 .3em 0; color:#666; font-weight:bold; }
+h4 { font-size:12px; margin:1em 0 .8em 0; padding-bottom:3px; }
+h5 { font-size:10px; margin:1.5em 0 .5em 0; color:#666; text-transform:uppercase; letter-spacing:1px; }
+
+ul li { list-style-type:square; padding:1px 0; }
+ul.plainlist { margin-left:0 !important; }
+ul.plainlist li { list-style-type:none; }
+li ul { margin-bottom:0; }
+li, dt, dd { font-size:11px; line-height:14px; }
+dt { font-weight:bold; margin-top:4px; }
+dd { margin-left:0; }
+
+form { margin:0; padding:0; }
+fieldset { margin:0; padding:0; }
+
+blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
+code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
+pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
+code strong { color:#930; }
+hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
+
+/* TEXT STYLES & MODIFIERS */
+.small { font-size:11px; }
+.tiny { font-size:10px; }
+p.tiny { margin-top:-2px; }
+.mini { font-size:9px; }
+p.mini { margin-top:-3px; }
+.help, p.help { font-size:10px !important; color:#999; }
+p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
+.quiet, a.quiet:link, a.quiet:visited { color:#999 !important;font-weight:normal !important; }
+.quiet strong { font-weight:bold !important; }
+.float-right { float:right; }
+.float-left { float:left; }
+.clear { clear:both; }
+.align-left { text-align:left; }
+.align-right { text-align:right; }
+.example { margin:10px 0; padding:5px 10px; background:#efefef; }
+.nowrap { white-space:nowrap; }
+
+/* TABLES */
+table { border-collapse:collapse; border-color:#ccc; }
+td, th { font-size:11px; line-height:13px; border-bottom:1px solid #eee; vertical-align:top; padding:5px; font-family:"Lucida Grande", Verdana, Arial, sans-serif; }
+th { text-align:left; font-size:12px; font-weight:bold; }
+thead th, 
+tfoot td { color:#666; padding:2px 5px; font-size:11px; background:#e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; border-left:1px solid #ddd; border-bottom:1px solid #ddd; }
+tfoot td { border-bottom:none; border-top:1px solid #ddd; }
+thead th:first-child, 
+tfoot td:first-child { border-left:none !important; }
+thead th.optional { font-weight:normal !important; }
+fieldset table { border-right:1px solid #eee; }
+tr.row-label td { font-size:9px; padding-top:2px; padding-bottom:0; border-bottom:none; color:#666; margin-top:-1px; }
+tr.alt { background:#f6f6f6; }
+.row1 { background:#EDF3FE; }
+.row2 { background:white; }
+
+/* SORTABLE TABLES */
+thead th a:link, thead th a:visited { color:#666; display:block; }
+table thead th.sorted { background-position:bottom left !important; }
+table thead th.sorted a { padding-right:13px; }
+table thead th.ascending a { background:url(../img/admin/arrow-down.gif) right .4em no-repeat; }
+table thead th.descending a { background:url(../img/admin/arrow-up.gif) right .4em no-repeat; }
+
+/* ORDERABLE TABLES */
+table.orderable tbody tr td:hover { cursor:move; }
+table.orderable tbody tr td:first-child { padding-left:14px; background-image:url(../img/admin/nav-bg-grabber.gif); background-repeat:repeat-y; }
+table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; }
+
+/* FORM DEFAULTS */
+input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
+textarea { vertical-align:top !important; }
+input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
+
+/*  FORM BUTTONS  */
+input[type=submit], input[type=button], .submit-row input { background:white url(../img/admin/nav-bg.gif) bottom repeat-x; padding:3px; color:black; border:1px solid #bbb; border-color:#ddd #aaa #aaa #ddd; }
+input[type=submit]:active, input[type=button]:active { background-image:url(../img/admin/nav-bg-reverse.gif); background-position:top; }
+input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/admin/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; }
+input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
+
+/* MODULES */
+.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
+.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
+.module blockquote { margin-left:12px; }
+.module ul, .module ol { margin-left:1.5em; }
+.module h3 { margin-top:.6em; }
+.module h2, .module caption { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#7CA0C7 url(../img/admin/default-bg.gif) top left repeat-x; color:white; }
+.module table { border-collapse: collapse; }
+
+/* MESSAGES & ERRORS */
+ul.messagelist { padding:0 0 5px 0; margin:0; }
+ul.messagelist li { font-size:12px; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border-bottom:1px solid #ddd; color:#666; background:#ffc url(../img/admin/icon_success.gif) 5px .3em no-repeat; }
+.errornote { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:red;background:#ffc url(../img/admin/icon_error.gif) 5px .3em no-repeat; }
+ul.errorlist { margin:0 !important; padding:0 !important; }
+.errorlist li { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:white; background:red url(../img/admin/icon_alert.gif) 5px .3em no-repeat; }
+td ul.errorlist { margin:0 !important; padding:0 !important; }
+td ul.errorlist li { margin:0 !important; }
+.error { background:#ffc; }
+.error input, .error select { border:1px solid red; }
+div.system-message { background: #ffc; margin: 10px; padding: 6px 8px; font-size: .8em; }
+div.system-message p.system-message-title { padding:4px 5px 4px 25px; margin:0; color:red; background:#ffc url(../img/admin/icon_error.gif) 5px .3em no-repeat; }
+.description { font-size:12px; padding:5px 0 0 12px; }
+
+/* BREADCRUMBS */
+div.breadcrumbs { background:white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x; padding:2px 8px 3px 8px; font-size:11px;  color:#999;  border-top:1px solid white; border-bottom:1px solid #ccc; text-align:left; }
+
+/* ACTION ICONS */
+.addlink { padding-left:12px; background:url(../img/admin/icon_addlink.gif) 0 .2em no-repeat; }
+.changelink { padding-left:12px; background:url(../img/admin/icon_changelink.gif) 0 .2em no-repeat; }
+.deletelink { padding-left:12px; background:url(../img/admin/icon_deletelink.gif) 0 .25em no-repeat; }
+a.deletelink:link, a.deletelink:visited { color:#CC3434; }
+a.deletelink:hover { color:#993333; }
+
+/* OBJECT TOOLS */
+.object-tools { font-size:10px; font-weight:bold; font-family:Arial,Helvetica,sans-serif; padding-left:0; float:right; position:relative; margin-top:-2.4em; margin-bottom:-2em; }
+.form-row .object-tools { margin-top:5px; margin-bottom:5px; float:none; height:2em; padding-left:3.5em; }
+.object-tools li { display:block; float:left; background:url(../img/admin/tool-left.gif) 0 0 no-repeat; padding:0 0 0 8px; margin-left:2px; height:16px; }
+.object-tools li:hover { background:url(../img/admin/tool-left_over.gif) 0 0 no-repeat; }
+.object-tools a:link, .object-tools a:visited { display:block; float:left; color:white; padding:.1em 14px .1em 8px; height:14px; background:#999 url(../img/admin/tool-right.gif) 100% 0 no-repeat; }
+.object-tools a:hover, .object-tools li:hover a { background:#5b80b2 url(../img/admin/tool-right_over.gif) 100% 0 no-repeat; }
+.object-tools a.viewsitelink, .object-tools a.golink { background:#999 url(../img/admin/tooltag-arrowright.gif) top right no-repeat; padding-right:28px; }
+.object-tools a.viewsitelink:hover, .object-tools a.golink:hover { background:#5b80b2 url(../img/admin/tooltag-arrowright_over.gif) top right no-repeat; }
+.object-tools a.addlink { background:#999 url(../img/admin/tooltag-add.gif) top right no-repeat; padding-right:28px; }
+.object-tools a.addlink:hover { background:#5b80b2 url(../img/admin/tooltag-add_over.gif) top right no-repeat; }
+
+/* OBJECT HISTORY */
+table#change-history { width:100%; }
+table#change-history tbody th { width:16em; }

Added: trunk/templatetool/media/css/layout.css
===================================================================
--- trunk/templatetool/media/css/layout.css	                        (rev 0)
+++ trunk/templatetool/media/css/layout.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,29 @@
+/* PAGE STRUCTURE */
+#container { position:relative; width:100%; min-width:760px; padding:0; }
+#content { margin:10px 15px; }
+#header { width:100%; }
+#content-main { float:left; width:100%; }
+#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
+#footer { clear:both; padding:10px; }
+
+/*  COLUMN TYPES  */
+.colMS { margin-right:20em !important; }
+.colSM { margin-left:20em !important; }
+.colSM #content-related { float:left; margin-right:0; margin-left:-19em; }
+.colSM #content-main { float:right; }
+.popup .colM { width:95%; }
+.subcol { float:left; width:46%; margin-right:15px; }
+.dashboard #content { width:500px; }
+
+/*  HEADER  */
+#header { background:#417690; color:#ffc; overflow:hidden; }
+#header a:link, #header a:visited { color:white; }
+#header a:hover { text-decoration:underline; }
+#branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; }
+#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
+#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
+
+/* SIDEBAR */
+#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
+#content-related h4 { font-size:11px; }
+#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
\ No newline at end of file

Added: trunk/templatetool/media/css/login.css
===================================================================
--- trunk/templatetool/media/css/login.css	                        (rev 0)
+++ trunk/templatetool/media/css/login.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,13 @@
+@import url('base.css');
+@import url('layout.css');
+
+/* LOGIN FORM */
+body.login { background:#eee; }
+.login #container { background:white; border:1px solid #ccc; width:28em; min-width:300px; margin-left:auto; margin-right:auto; margin-top:100px; }
+.login #content-main { width:100%; }
+.login form { margin-top:1em; }
+.login .form-row { padding:4px 0; float:left; width:100%; }
+.login .form-row label { float:left; width:9em; padding-right:0.5em; line-height:2em; text-align:right; font-size:1em; color:#333; }
+.login .form-row #id_username, .login .form-row #id_password { width:14em; }
+.login span.help { font-size:10px; display:block; }
+.login .submit-row { clear:both; padding:1em 0 0 9.4em; }
\ No newline at end of file

Added: trunk/templatetool/media/css/patch-iewin.css
===================================================================
--- trunk/templatetool/media/css/patch-iewin.css	                        (rev 0)
+++ trunk/templatetool/media/css/patch-iewin.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,8 @@
+* html #container { position:static; } /* keep header from flowing off the page */
+* html .colMS #content-related { margin-right:0; margin-left:10px; position:static; } /* put the right sidebars back on the page */
+* html .colSM #content-related { margin-right:10px; margin-left:-115px; position:static; } /* put the left sidebars back on the page */
+* html .form-row { height:1%; }
+* html .dashboard #content { width:768px; } /* proper fixed width for dashboard in IE6 */
+* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
+* html #changelist-filter ul { margin-right:-10px; } /* fix right margin for changelist filters in IE6 */
+* html .change-list .filtered { height:400px; } /* IE ignores min-height, but treats height as if it were min-height */
\ No newline at end of file

Added: trunk/templatetool/media/css/rtl.css
===================================================================
--- trunk/templatetool/media/css/rtl.css	                        (rev 0)
+++ trunk/templatetool/media/css/rtl.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,46 @@
+body { direction: rtl; }
+
+/* login styles */
+
+.login .form-row { float:right; }
+.login .form-row label { float:right; padding-left:0.5em; padding-right:0; text-align:left;}
+.login .submit-row { clear:both; padding:1em 9.4em 0 0; }
+
+
+/* global styles */
+th { text-align: right; }
+.module h2, .module caption { text-align: right; }
+.addlink, .changelink { padding-left:0px; padding-right:12px; background-position:100% 0.2em; }
+.deletelink { padding-left:0px; padding-right:12px; background-position:100% 0.25em; }
+.object-tools { float:left; }
+
+
+/* layout styles */
+#user-tools { right:auto; left:0; text-align:left; }
+div.breadcrumbs { text-align:right; }
+#content-main { float:right;}
+#content-related { float:left; margin-left:-19em; margin-right:auto;}
+.colMS { margin-left:20em !important; margin-right:10px !important;}
+
+/* dashboard styles */
+.dashboard .module table td a { padding-left:.6em; padding-right:12px; }
+
+/* changelists styles */
+.change-list .filtered { background:white url(../img/admin/changelist-bg_rtl.gif) top left repeat-y !important; }
+.change-list .filtered table { border-left:1px solid #ddd; border-right:0px none; }
+#changelist-filter { right:auto; left:0; border-left:0px none; border-right:1px solid #ddd;}
+.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:0px !important; margin-left:160px !important; }
+#changelist-filter li.selected { border-left:0px none; padding-left:0px; margin-left:0; border-right:5px solid #ccc; padding-right:5px;margin-right:-10px; }
+
+/* fomrs styles */
+.aligned label { padding:0 0 3px 1em;  float:right; }
+.submit-row { text-align: left }
+.vDateField, .vTimeField { margin-left:2px; }
+
+/* widget styles */
+.calendarnav-previous { top:0; left:auto; right:0; }
+.calendarnav-next { top:0; right:auto; left:0;}
+.calendar caption, .calendarbox h2 { text-align:center; }
+
+.selector { float: right;}
+.selector .selector-filter { text-align: right;}

Added: trunk/templatetool/media/css/widgets.css
===================================================================
--- trunk/templatetool/media/css/widgets.css	                        (rev 0)
+++ trunk/templatetool/media/css/widgets.css	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,101 @@
+/* SELECTOR (FILTER INTERFACE) */
+.selector { width:580px; float:left; }
+.selector select { width:270px; height:17.2em; }
+.selector-available, .selector-chosen { float:left; width:270px; text-align:center; margin-bottom:5px; }
+.selector-available h2, .selector-chosen h2 { border:1px solid #ccc; }
+.selector .selector-available h2 { background:white url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
+.selector .selector-filter { background:white; border:1px solid #ccc; border-width:0 1px; padding:3px; color:#999; font-size:10px; margin:0; text-align:left; }
+.selector .selector-chosen .selector-filter { padding:4px 5px; }
+.selector .selector-available input { width:230px; }
+.selector ul.selector-chooser { float:left; width:22px; height:50px; background:url(../img/admin/chooser-bg.gif) top center no-repeat; margin:8em 3px 0 3px; padding:0; }
+.selector-chooser li { margin:0; padding:3px; list-style-type:none; }
+.selector select { margin-bottom:5px; margin-top:0; }
+.selector-add, .selector-remove { width:16px; height:16px; display:block; text-indent:-3000px; }
+.selector-add { background:url(../img/admin/selector-add.gif) top center no-repeat; margin-bottom:2px; }
+.selector-remove { background:url(../img/admin/selector-remove.gif) top center no-repeat; }
+a.selector-chooseall, a.selector-clearall { display:block; width:6em; text-align:left; margin-left:auto; margin-right:auto; font-weight:bold; color:#666;  padding:3px 0 3px 18px; }
+a.selector-chooseall:hover, a.selector-clearall:hover { color:#036; }
+a.selector-chooseall { width:7em; background:url(../img/admin/selector-addall.gif) left center no-repeat; }
+a.selector-clearall { background:url(../img/admin/selector-removeall.gif) left center no-repeat; }
+
+/* STACKED SELECTORS */
+.stacked { float:left; width:500px; }
+.stacked select { width:480px; height:10.1em; }
+.stacked .selector-available, .stacked .selector-chosen { width:480px; }
+.stacked .selector-available { margin-bottom:0; }
+.stacked .selector-available input { width:442px; }
+.stacked ul.selector-chooser { height:22px; width:50px; margin:0 0 3px 40%; background:url(../img/admin/chooser_stacked-bg.gif) top center no-repeat; }
+.stacked .selector-chooser li { float:left; padding:3px 3px 3px 5px; }
+.stacked .selector-chooseall, .stacked .selector-clearall { display:none; }
+.stacked .selector-add { background-image:url(../img/admin/selector_stacked-add.gif); }
+.stacked .selector-remove { background-image:url(../img/admin/selector_stacked-remove.gif); }
+
+/* DATE AND TIME */
+p.datetime { line-height:20px; margin:0; padding:0; color:#666; font-size:11px; font-weight:bold; }
+.datetime span { font-size:11px; color:#ccc; font-weight:normal; white-space:nowrap; }
+.vDateField { margin-left:4px; }
+table p.datetime { font-size:10px; margin-left:0; padding-left:0; }
+
+/* FILE UPLOADS */
+p.file-upload { line-height:20px; margin:0; padding:0; color:#666; font-size:11px; font-weight:bold; }
+.file-upload a { font-weight:normal; }
+.file-upload .deletelink { margin-left:5px; }
+
+/* CALENDARS & CLOCKS */
+.calendarbox, .clockbox { margin:5px auto; font-size:11px; width:16em; text-align:center; background:white; position:relative; }
+.clockbox { width:9em; }
+.calendar { margin:0; padding: 0; }
+.calendar table { margin:0; padding:0; border-collapse:collapse; background:white; width:99%; }
+.calendar caption, .calendarbox h2 { margin: 0; font-size:11px; text-align:center; border-top:none; }
+.calendar th { font-size:10px; color:#666; padding:2px 3px; text-align:center; background:#e1e1e1 url(../img/admin/nav-bg.gif) 0 50% repeat-x; border-bottom:1px solid #ddd; }
+.calendar td { font-size:11px; text-align: center; padding: 0; border-top:1px solid #eee; border-bottom:none; }
+.calendar td.selected a { background: #C9DBED; }
+.calendar td.nonday { background:#efefef; }
+.calendar td.today a { background:#ffc; }
+.calendar td a, .timelist a { display: block; font-weight:bold; padding:4px; text-decoration: none; color:#444; }
+.calendar td a:hover, .timelist a:hover { background: #5b80b2; color:white; }
+.calendar td a:active, .timelist a:active { background: #036; color:white; }
+.calendarnav { font-size:10px; text-align: center; color:#ccc; margin:0; padding:1px 3px; }
+.calendarnav a:link, #calendarnav a:visited, #calendarnav a:hover { color: #999; }
+.calendar-shortcuts { background:white; font-size:10px; line-height:11px; border-top:1px solid #eee; padding:3px 0 4px; color:#ccc; }
+.calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { display:block; position:absolute; font-weight:bold; font-size:12px; background:#C9DBED url(../img/admin/default-bg.gif) bottom left repeat-x; padding:1px 4px 2px 4px; color:white; }
+.calendarnav-previous:hover, .calendarnav-next:hover { background:#036; }
+.calendarnav-previous { top:0; left:0; }
+.calendarnav-next { top:0; right:0; }
+.calendar-cancel { margin:0 !important; padding:0; font-size:10px; background:#e1e1e1 url(../img/admin/nav-bg.gif) 0 50% repeat-x;  border-top:1px solid #ddd; }
+.calendar-cancel a { padding:2px; color:#999; }
+ul.timelist, .timelist li { list-style-type:none; margin:0; padding:0; }
+.timelist a { padding:2px; }
+
+/* INLINE ORDERER */
+ul.orderer {  position:relative; padding:0 !important; margin:0 !important; list-style-type:none; }
+ul.orderer li { list-style-type:none; display:block; padding:0; margin:0; border:1px solid #bbb; border-width:0 1px 1px 0; white-space:nowrap; overflow:hidden; background:#e2e2e2 url(../img/admin/nav-bg-grabber.gif) repeat-y; }
+ul.orderer li:hover { cursor:move; background-color:#ddd; }
+ul.orderer li a.selector { margin-left:12px; overflow:hidden; width:83%; font-size:10px !important; padding:0.6em 0; }
+ul.orderer li a:link, ul.orderer li a:visited { color:#333; }
+ul.orderer li .inline-deletelink { position:absolute; right:4px; margin-top:0.6em; }
+ul.orderer li.selected { background-color:#f8f8f8; border-right-color:#f8f8f8; }
+ul.orderer li.deleted { background:#bbb url(../img/admin/deleted-overlay.gif); }
+ul.orderer li.deleted a:link, ul.orderer li.deleted a:visited { color:#888; }
+ul.orderer li.deleted .inline-deletelink { background-image:url(../img/admin/inline-restore.png);  }
+ul.orderer li.deleted:hover, ul.orderer li.deleted a.selector:hover { cursor:default; }
+
+/* EDIT INLINE */
+.inline-deletelink { display:block; text-indent:-9999px; background:transparent url(../img/admin/inline-delete.png) no-repeat; width:15px; height:15px; margin:0.4em 0; border: 0px none; }
+.inline-deletelink:hover { background-position:-15px 0; cursor:pointer; }
+.editinline button.addlink { border: 0px none; color: #5b80b2; font-size: 100%; cursor: pointer; }
+.editinline button.addlink:hover { color: #036; cursor: pointer; }
+.editinline table .help { text-align:right; float:right; padding-left:2em; }
+.editinline tfoot .addlink { white-space:nowrap; }
+.editinline table thead th:last-child { border-left:none; }
+.editinline tr.deleted { background:#ddd url(../img/admin/deleted-overlay.gif); }
+.editinline tr.deleted .inline-deletelink { background-image:url(../img/admin/inline-restore.png); }
+.editinline tr.deleted td:hover { cursor:default; }
+.editinline tr.deleted td:first-child { background-image:none !important; }
+
+/* EDIT INLINE - STACKED */
+.editinline-stacked { min-width:758px; }
+.editinline-stacked .inline-object { margin-left:210px; background:white; }
+.editinline-stacked .inline-source { float:left; width:200px; background:#f8f8f8;  }
+.editinline-stacked .inline-splitter { float:left; width:9px; background:#f8f8f8 url(../img/admin/inline-splitter-bg.gif) 50% 50% no-repeat; border-right:1px solid #ccc; }
+.editinline-stacked .controls { clear:both; background:#e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; padding:3px 4px; font-size:11px; border-top:1px solid #ddd; }
\ No newline at end of file

Added: trunk/templatetool/media/img/admin/arrow-down.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/arrow-down.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/arrow-up.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/arrow-up.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/changelist-bg.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/changelist-bg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/chooser-bg.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/chooser-bg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/chooser_stacked-bg.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/chooser_stacked-bg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/default-bg-reverse.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/default-bg-reverse.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/default-bg.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/default-bg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/deleted-overlay.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/deleted-overlay.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon-no.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon-no.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon-unknown.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon-unknown.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon-yes.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon-yes.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_addlink.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_addlink.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_alert.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_alert.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_calendar.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_calendar.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_changelink.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_changelink.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_clock.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_clock.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_deletelink.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_deletelink.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_error.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_error.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_searchbox.png
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_searchbox.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/icon_success.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/icon_success.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/inline-delete-8bit.png
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/inline-delete-8bit.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/inline-delete.png
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/inline-delete.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/inline-restore-8bit.png
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/inline-restore-8bit.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/inline-restore.png
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/inline-restore.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/inline-splitter-bg.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/inline-splitter-bg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/nav-bg-grabber.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/nav-bg-grabber.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/nav-bg-reverse.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/nav-bg-reverse.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/nav-bg.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/nav-bg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/selector-add.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/selector-add.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/selector-addall.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/selector-addall.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/selector-remove.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/selector-remove.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/selector-removeall.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/selector-removeall.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/selector-search.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/selector-search.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/selector_stacked-add.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/selector_stacked-add.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/selector_stacked-remove.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/selector_stacked-remove.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tool-left.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tool-left.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tool-left_over.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tool-left_over.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tool-right.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tool-right.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tool-right_over.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tool-right_over.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tooltag-add.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tooltag-add.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tooltag-add_over.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tooltag-add_over.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tooltag-arrowright.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tooltag-arrowright.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/img/admin/tooltag-arrowright_over.gif
===================================================================
(Binary files differ)


Property changes on: trunk/templatetool/media/img/admin/tooltag-arrowright_over.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/templatetool/media/js/SelectBox.js
===================================================================
--- trunk/templatetool/media/js/SelectBox.js	                        (rev 0)
+++ trunk/templatetool/media/js/SelectBox.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,109 @@
+var SelectBox = {
+    cache: new Object(),
+    init: function(id) {
+        var box = document.getElementById(id);
+        var node;
+        SelectBox.cache[id] = new Array();
+        var cache = SelectBox.cache[id];
+        for (var i = 0; (node = box.options[i]); i++) {
+            cache.push({ value: node.value, text: node.text, displayed: 1 });
+        }
+    },
+    redisplay: function(id) {
+        // Repopulate HTML select box from cache
+        var box = document.getElementById(id);
+        box.options.length = 0; // clear all options
+        for (var i = 0, j = SelectBox.cache[id].length; i < j; i++) {
+            var node = SelectBox.cache[id][i];
+            if (node.displayed) {
+                box.options[box.options.length] = new Option(node.text, node.value, false, false);
+            }
+        }
+    },
+    filter: function(id, text) {
+        // Redisplay the HTML select box, displaying only the choices containing ALL
+        // the words in text. (It's an AND search.)
+        var tokens = text.toLowerCase().split(/\s+/);
+        var node, token;
+        for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
+            node.displayed = 1;
+            for (var j = 0; (token = tokens[j]); j++) {
+                if (node.text.toLowerCase().indexOf(token) == -1) {
+                    node.displayed = 0;
+                }
+            }
+        }
+        SelectBox.redisplay(id);
+    },
+    delete_from_cache: function(id, value) {
+        var node, delete_index = null;
+        for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
+            if (node.value == value) {
+                delete_index = i;
+                break;
+            }
+        }
+        var j = SelectBox.cache[id].length - 1;
+        for (var i = delete_index; i < j; i++) {
+            SelectBox.cache[id][i] = SelectBox.cache[id][i+1];
+        }
+        SelectBox.cache[id].length--;
+    },
+    add_to_cache: function(id, option) {
+        SelectBox.cache[id].push({ value: option.value, text: option.text, displayed: 1 });
+    },
+    cache_contains: function(id, value) {
+        // Check if an item is contained in the cache
+        var node;
+        for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
+            if (node.value == value) {
+                return true;
+            }
+        }
+        return false;
+    },
+    move: function(from, to) {
+        var from_box = document.getElementById(from);
+        var to_box = document.getElementById(to);
+        var option;
+        for (var i = 0; (option = from_box.options[i]); i++) {
+            if (option.selected && SelectBox.cache_contains(from, option.value)) {
+                SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1 });
+                SelectBox.delete_from_cache(from, option.value);
+            }
+        }
+        SelectBox.redisplay(from);
+        SelectBox.redisplay(to);
+    },
+    move_all: function(from, to) {
+        var from_box = document.getElementById(from);
+        var to_box = document.getElementById(to);
+        var option;
+        for (var i = 0; (option = from_box.options[i]); i++) {
+            SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1 });
+            SelectBox.delete_from_cache(from, option.value);
+        }
+        SelectBox.redisplay(from);
+        SelectBox.redisplay(to);
+    },
+    sort: function(id) {
+        SelectBox.cache[id].sort( function(a, b) {
+            a = a.text.toLowerCase();
+            b = b.text.toLowerCase();
+            try {
+                if (a > b) return 1;
+                if (a < b) return -1;
+            }
+            catch (e) {
+                // silently fail on IE 'unknown' exception
+            }
+            return 0;
+        } );
+    },
+    select_all: function(id) {
+        var box = document.getElementById(id);
+        for (var i = 0; i < box.options.length; i++) {
+            box.options[i].selected = 'selected';
+        }
+    }
+}

Added: trunk/templatetool/media/js/SelectFilter.js
===================================================================
--- trunk/templatetool/media/js/SelectFilter.js	                        (rev 0)
+++ trunk/templatetool/media/js/SelectFilter.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,81 @@
+/*
+SelectFilter - Turns a multiple-select box into a filter interface.
+
+Requires SelectBox.js and addevent.js.
+*/
+
+function findForm(node) {
+    // returns the node of the form containing the given node
+    if (node.tagName.toLowerCase() != 'form') {
+        return findForm(node.parentNode);
+    }
+    return node;
+}
+
+var SelectFilter = {
+    init: function(field_id) {
+        var from_box = document.getElementById(field_id);
+        from_box.id += '_from'; // change its ID
+        // Create the INPUT input box
+        var input_box = document.createElement('input');
+        input_box.id = field_id + '_input';
+        input_box.setAttribute('type', 'text');
+        from_box.parentNode.insertBefore(input_box, from_box);
+        from_box.parentNode.insertBefore(document.createElement('br'), input_box.nextSibling);
+        // Create the TO box
+        var to_box = document.createElement('select');
+        to_box.id = field_id + '_to';
+        to_box.setAttribute('multiple', 'multiple');
+        to_box.setAttribute('size', from_box.size);
+        from_box.parentNode.insertBefore(to_box, from_box.nextSibling);
+        to_box.setAttribute('name', from_box.getAttribute('name'));
+        from_box.setAttribute('name', from_box.getAttribute('name') + '_old');
+        // Give the filters a CSS hook
+        from_box.setAttribute('class', 'filtered');
+        to_box.setAttribute('class', 'filtered');
+        // Set up the JavaScript event handlers for the select box filter interface
+        addEvent(input_box, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); });
+        addEvent(input_box, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); });
+        addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); });
+        addEvent(from_box, 'focus', function() { input_box.focus(); });
+        addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); });
+        addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); });
+        SelectBox.init(field_id + '_from');
+        SelectBox.init(field_id + '_to');
+        // Move selected from_box options to to_box
+        SelectBox.move(field_id + '_from', field_id + '_to');
+    },
+    filter_key_up: function(event, field_id) {
+        from = document.getElementById(field_id + '_from');
+        // don't submit form if user pressed Enter
+        if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {
+            from.selectedIndex = 0;
+            SelectBox.move(field_id + '_from', field_id + '_to');
+            from.selectedIndex = 0;
+            return false;
+        }
+        var temp = from.selectedIndex;
+        SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value);
+        from.selectedIndex = temp;
+        return true;
+    },
+    filter_key_down: function(event, field_id) {
+        from = document.getElementById(field_id + '_from');
+        // right arrow -- move across
+        if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) {
+            var old_index = from.selectedIndex;
+            SelectBox.move(field_id + '_from', field_id + '_to');
+            from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index;
+            return false;
+        }
+        // down arrow -- wrap around
+        if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) {
+            from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1;
+        }
+        // up arrow -- wrap around
+        if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) {
+            from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1;
+        }
+        return true;
+    }
+}

Added: trunk/templatetool/media/js/SelectFilter2.js
===================================================================
--- trunk/templatetool/media/js/SelectFilter2.js	                        (rev 0)
+++ trunk/templatetool/media/js/SelectFilter2.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,113 @@
+/*
+SelectFilter2 - Turns a multiple-select box into a filter interface.
+
+Different than SelectFilter because this is coupled to the admin framework.
+
+Requires core.js, SelectBox.js and addevent.js.
+*/
+
+function findForm(node) {
+    // returns the node of the form containing the given node
+    if (node.tagName.toLowerCase() != 'form') {
+        return findForm(node.parentNode);
+    }
+    return node;
+}
+
+var SelectFilter = {
+    init: function(field_id, field_name, is_stacked, admin_media_prefix) {
+        var from_box = document.getElementById(field_id);
+        from_box.id += '_from'; // change its ID
+        from_box.className = 'filtered';
+
+        // Remove <p class="info">, because it just gets in the way.
+        var ps = from_box.parentNode.getElementsByTagName('p');
+        for (var i=0; i<ps.length; i++) {
+            from_box.parentNode.removeChild(ps[i]);
+        }
+
+        // <div class="selector"> or <div class="selector stacked">
+        var selector_div = quickElement('div', from_box.parentNode);
+        selector_div.className = is_stacked ? 'selector stacked' : 'selector';
+
+        // <div class="selector-available">
+        var selector_available = quickElement('div', selector_div, '');
+        selector_available.className = 'selector-available';
+        quickElement('h2', selector_available, interpolate(gettext('Available %s'), [field_name]));
+        var filter_p = quickElement('p', selector_available, '');
+        filter_p.className = 'selector-filter';
+        quickElement('img', filter_p, '', 'src', admin_media_prefix + 'img/admin/selector-search.gif');
+        filter_p.appendChild(document.createTextNode(' '));
+        var filter_input = quickElement('input', filter_p, '', 'type', 'text');
+        filter_input.id = field_id + '_input';
+        selector_available.appendChild(from_box);
+        var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'href', 'javascript: (function(){ SelectBox.move_all("' + field_id + '_from", "' + field_id + '_to"); })()');
+        choose_all.className = 'selector-chooseall';
+
+        // <ul class="selector-chooser">
+        var selector_chooser = quickElement('ul', selector_div, '');
+        selector_chooser.className = 'selector-chooser';
+        var add_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Add'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_from","' + field_id + '_to");})()');
+        add_link.className = 'selector-add';
+        var remove_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Remove'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_to","' + field_id + '_from");})()');
+        remove_link.className = 'selector-remove';
+
+        // <div class="selector-chosen">
+        var selector_chosen = quickElement('div', selector_div, '');
+        selector_chosen.className = 'selector-chosen';
+        quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s'), [field_name]));
+        var selector_filter = quickElement('p', selector_chosen, gettext('Select your choice(s) and click '));
+        selector_filter.className = 'selector-filter';
+        quickElement('img', selector_filter, '', 'src', admin_media_prefix + 'img/admin/selector-add.gif', 'alt', 'Add');
+        var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
+        to_box.className = 'filtered';
+        var clear_all = quickElement('a', selector_chosen, gettext('Clear all'), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from");})()');
+        clear_all.className = 'selector-clearall';
+
+        from_box.setAttribute('name', from_box.getAttribute('name') + '_old');
+
+        // Set up the JavaScript event handlers for the select box filter interface
+        addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); });
+        addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); });
+        addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); });
+        addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); });
+        addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); });
+        SelectBox.init(field_id + '_from');
+        SelectBox.init(field_id + '_to');
+        // Move selected from_box options to to_box
+        SelectBox.move(field_id + '_from', field_id + '_to');
+    },
+    filter_key_up: function(event, field_id) {
+        from = document.getElementById(field_id + '_from');
+        // don't submit form if user pressed Enter
+        if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {
+            from.selectedIndex = 0;
+            SelectBox.move(field_id + '_from', field_id + '_to');
+            from.selectedIndex = 0;
+            return false;
+        }
+        var temp = from.selectedIndex;
+        SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value);
+        from.selectedIndex = temp;
+        return true;
+    },
+    filter_key_down: function(event, field_id) {
+        from = document.getElementById(field_id + '_from');
+        // right arrow -- move across
+        if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) {
+            var old_index = from.selectedIndex;
+            SelectBox.move(field_id + '_from', field_id + '_to');
+            from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index;
+            return false;
+        }
+        // down arrow -- wrap around
+        if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) {
+            from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1;
+        }
+        // up arrow -- wrap around
+        if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) {
+            from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1;
+        }
+        return true;
+    }
+}

Added: trunk/templatetool/media/js/admin/CollapsedFieldsets.js
===================================================================
--- trunk/templatetool/media/js/admin/CollapsedFieldsets.js	                        (rev 0)
+++ trunk/templatetool/media/js/admin/CollapsedFieldsets.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,85 @@
+// Finds all fieldsets with class="collapse", collapses them, and gives each
+// one a "Show" link that uncollapses it. The "Show" link becomes a "Hide"
+// link when the fieldset is visible.
+
+function findForm(node) {
+    // returns the node of the form containing the given node
+    if (node.tagName.toLowerCase() != 'form') {
+        return findForm(node.parentNode);
+    }
+    return node;
+}
+
+var CollapsedFieldsets = {
+    collapse_re: /\bcollapse\b/,   // Class of fieldsets that should be dealt with.
+    collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
+    collapsed_class: 'collapsed',
+    init: function() {
+        var fieldsets = document.getElementsByTagName('fieldset');
+        var collapsed_seen = false;
+        for (var i = 0, fs; fs = fieldsets[i]; i++) {
+            // Collapse this fieldset if it has the correct class, and if it
+            // doesn't have any errors. (Collapsing shouldn't apply in the case
+            // of error messages.)
+            if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
+                collapsed_seen = true;
+                // Give it an additional class, used by CSS to hide it.
+                fs.className += ' ' + CollapsedFieldsets.collapsed_class;
+                // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
+                var collapse_link = document.createElement('a');
+                collapse_link.className = 'collapse-toggle';
+                collapse_link.id = 'fieldsetcollapser' + i;
+                collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
+                collapse_link.href = '#';
+                collapse_link.innerHTML = gettext('Show');
+                var h2 = fs.getElementsByTagName('h2')[0];
+                h2.appendChild(document.createTextNode(' ('));
+                h2.appendChild(collapse_link);
+                h2.appendChild(document.createTextNode(')'));
+            }
+        }
+        if (collapsed_seen) {
+            // Expand all collapsed fieldsets when form is submitted.
+            addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
+        }
+    },
+    fieldset_has_errors: function(fs) {
+        // Returns true if any fields in the fieldset have validation errors.
+        var divs = fs.getElementsByTagName('div');
+        for (var i=0; i<divs.length; i++) {
+            if (divs[i].className.match(/\berror\b/)) {
+                return true;
+            }
+        }
+        return false;
+    },
+    show: function(fieldset_index) {
+        var fs = document.getElementsByTagName('fieldset')[fieldset_index];
+        // Remove the class name that causes the "display: none".
+        fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
+        // Toggle the "Show" link to a "Hide" link
+        var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
+        collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
+        collapse_link.innerHTML = gettext('Hide');
+    },
+    hide: function(fieldset_index) {
+        var fs = document.getElementsByTagName('fieldset')[fieldset_index];
+        // Add the class name that causes the "display: none".
+        fs.className += ' ' + CollapsedFieldsets.collapsed_class;
+        // Toggle the "Hide" link to a "Show" link
+        var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
+        collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
+        collapse_link.innerHTML = gettext('Show');
+    },
+
+    uncollapse_all: function() {
+        var fieldsets = document.getElementsByTagName('fieldset');
+        for (var i=0; i<fieldsets.length; i++) {
+            if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
+                CollapsedFieldsets.show(i);
+            }
+        }
+    }
+}
+
+addEvent(window, 'load', CollapsedFieldsets.init);

Added: trunk/templatetool/media/js/admin/DateTimeShortcuts.js
===================================================================
--- trunk/templatetool/media/js/admin/DateTimeShortcuts.js	                        (rev 0)
+++ trunk/templatetool/media/js/admin/DateTimeShortcuts.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,241 @@
+// Inserts shortcut buttons after all of the following:
+//     <input type="text" class="vDateField">
+//     <input type="text" class="vTimeField">
+
+var DateTimeShortcuts = {
+    calendars: [],
+    calendarInputs: [],
+    clockInputs: [],
+    calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
+    calendarDivName2: 'calendarin',  // name of <div> that contains calendar
+    calendarLinkName: 'calendarlink',// name of the link that is used to toggle
+    clockDivName: 'clockbox',        // name of clock <div> that gets toggled
+    clockLinkName: 'clocklink',      // name of the link that is used to toggle
+    admin_media_prefix: '',
+    init: function() {
+        // Deduce admin_media_prefix by looking at the <script>s in the
+        // current document and finding the URL of *this* module.
+        var scripts = document.getElementsByTagName('script');
+        for (var i=0; i<scripts.length; i++) {
+            if (scripts[i].src.match(/DateTimeShortcuts/)) {
+                var idx = scripts[i].src.indexOf('js/admin/DateTimeShortcuts');
+                DateTimeShortcuts.admin_media_prefix = scripts[i].src.substring(0, idx);
+                break;
+            }
+        }
+
+        var inputs = document.getElementsByTagName('input');
+        for (i=0; i<inputs.length; i++) {
+            var inp = inputs[i];
+            if (inp.getAttribute('type') == 'text' && inp.className.match(/vTimeField/)) {
+                DateTimeShortcuts.addClock(inp);
+            }
+            else if (inp.getAttribute('type') == 'text' && inp.className.match(/vDateField/)) {
+                DateTimeShortcuts.addCalendar(inp);
+            }
+        }
+    },
+    // Add clock widget to a given field
+    addClock: function(inp) {
+        var num = DateTimeShortcuts.clockInputs.length;
+        DateTimeShortcuts.clockInputs[num] = inp;
+
+        // Shortcut links (clock icon and "Now" link)
+        var shortcuts_span = document.createElement('span');
+        inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
+        var now_link = document.createElement('a');
+        now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());");
+        now_link.appendChild(document.createTextNode(gettext('Now')));
+        var clock_link = document.createElement('a');
+        clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
+        clock_link.id = DateTimeShortcuts.clockLinkName + num;
+        quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
+        shortcuts_span.appendChild(document.createTextNode('\240'));
+        shortcuts_span.appendChild(now_link);
+        shortcuts_span.appendChild(document.createTextNode('\240|\240'));
+        shortcuts_span.appendChild(clock_link);
+
+        // Create clock link div
+        //
+        // Markup looks like:
+        // <div id="clockbox1" class="clockbox module">
+        //     <h2>Choose a time</h2>
+        //     <ul class="timelist">
+        //         <li><a href="#">Now</a></li>
+        //         <li><a href="#">Midnight</a></li>
+        //         <li><a href="#">6 a.m.</a></li>
+        //         <li><a href="#">Noon</a></li>
+        //     </ul>
+        //     <p class="calendar-cancel"><a href="#">Cancel</a></p>
+        // </div>
+
+        var clock_box = document.createElement('div');
+        clock_box.style.display = 'none';
+        clock_box.style.position = 'absolute';
+        clock_box.className = 'clockbox module';
+        clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
+        document.body.appendChild(clock_box);
+        addEvent(clock_box, 'click', DateTimeShortcuts.cancelEventPropagation);
+
+        quickElement('h2', clock_box, gettext('Choose a time'));
+        time_list = quickElement('ul', clock_box, '');
+        time_list.className = 'timelist';
+        quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());")
+        quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00:00');")
+        quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00:00');")
+        quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00:00');")
+
+        cancel_p = quickElement('p', clock_box, '');
+        cancel_p.className = 'calendar-cancel';
+        quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
+    },
+    openClock: function(num) {
+        var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
+        var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
+    
+        // Recalculate the clockbox position
+        // is it left-to-right or right-to-left layout ?
+        if (getStyle(document.body,'direction')!='rtl') {
+            clock_box.style.left = findPosX(clock_link) + 17 + 'px';
+        }
+        else {
+            // since style's width is in em, it'd be tough to calculate
+            // px value of it. let's use an estimated px for now
+            // TODO: IE returns wrong value for findPosX when in rtl mode
+            //       (it returns as it was left aligned), needs to be fixed.
+            clock_box.style.left = findPosX(clock_link) - 110 + 'px';
+        }
+        clock_box.style.top = findPosY(clock_link) - 30 + 'px';
+    
+        // Show the clock box
+        clock_box.style.display = 'block';
+        addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
+    },
+    dismissClock: function(num) {
+       document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
+       window.onclick = null;
+    },
+    handleClockQuicklink: function(num, val) {
+       DateTimeShortcuts.clockInputs[num].value = val;
+       DateTimeShortcuts.dismissClock(num);
+    },
+    // Add calendar widget to a given field.
+    addCalendar: function(inp) {
+        var num = DateTimeShortcuts.calendars.length;
+
+        DateTimeShortcuts.calendarInputs[num] = inp;
+
+        // Shortcut links (calendar icon and "Today" link)
+        var shortcuts_span = document.createElement('span');
+        inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
+        var today_link = document.createElement('a');
+        today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
+        today_link.appendChild(document.createTextNode(gettext('Today')));
+        var cal_link = document.createElement('a');
+        cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
+        cal_link.id = DateTimeShortcuts.calendarLinkName + num;
+        quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
+        shortcuts_span.appendChild(document.createTextNode('\240'));
+        shortcuts_span.appendChild(today_link);
+        shortcuts_span.appendChild(document.createTextNode('\240|\240'));
+        shortcuts_span.appendChild(cal_link);
+
+        // Create calendarbox div.
+        //
+        // Markup looks like:
+        //
+        // <div id="calendarbox3" class="calendarbox module">
+        //     <h2>
+        //           <a href="#" class="link-previous">&lsaquo;</a>
+        //           <a href="#" class="link-next">&rsaquo;</a> February 2003
+        //     </h2>
+        //     <div class="calendar" id="calendarin3">
+        //         <!-- (cal) -->
+        //     </div>
+        //     <div class="calendar-shortcuts">
+        //          <a href="#">Yesterday</a> | <a href="#">Today</a> | <a href="#">Tomorrow</a>
+        //     </div>
+        //     <p class="calendar-cancel"><a href="#">Cancel</a></p>
+        // </div>
+        var cal_box = document.createElement('div');
+        cal_box.style.display = 'none';
+        cal_box.style.position = 'absolute';
+        cal_box.className = 'calendarbox module';
+        cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
+        document.body.appendChild(cal_box);
+        addEvent(cal_box, 'click', DateTimeShortcuts.cancelEventPropagation);
+
+        // next-prev links
+        var cal_nav = quickElement('div', cal_box, '');
+        var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
+        cal_nav_prev.className = 'calendarnav-previous';
+        var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
+        cal_nav_next.className = 'calendarnav-next';
+
+        // main box
+        var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
+        cal_main.className = 'calendar';
+        DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
+        DateTimeShortcuts.calendars[num].drawCurrent();
+
+        // calendar shortcuts
+        var shortcuts = quickElement('div', cal_box, '');
+        shortcuts.className = 'calendar-shortcuts';
+        quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
+        shortcuts.appendChild(document.createTextNode('\240|\240'));
+        quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
+        shortcuts.appendChild(document.createTextNode('\240|\240'));
+        quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
+
+        // cancel bar
+        var cancel_p = quickElement('p', cal_box, '');
+        cancel_p.className = 'calendar-cancel';
+        quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
+    },
+    openCalendar: function(num) {
+        var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
+        var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
+    
+        // Recalculate the clockbox position
+        // is it left-to-right or right-to-left layout ?
+        if (getStyle(document.body,'direction')!='rtl') {
+            cal_box.style.left = findPosX(cal_link) + 17 + 'px';
+        }
+        else {
+            // since style's width is in em, it'd be tough to calculate
+            // px value of it. let's use an estimated px for now
+            // TODO: IE returns wrong value for findPosX when in rtl mode
+            //       (it returns as it was left aligned), needs to be fixed.
+            cal_box.style.left = findPosX(cal_link) - 180 + 'px';
+        }
+        cal_box.style.top = findPosY(cal_link) - 75 + 'px';
+    
+        cal_box.style.display = 'block';
+        addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
+    },
+    dismissCalendar: function(num) {
+        document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
+    },
+    drawPrev: function(num) {
+        DateTimeShortcuts.calendars[num].drawPreviousMonth();
+    },
+    drawNext: function(num) {
+        DateTimeShortcuts.calendars[num].drawNextMonth();
+    },
+    handleCalendarCallback: function(num) {
+        return "function(y, m, d) { DateTimeShortcuts.calendarInputs["+num+"].value = y+'-'+m+'-'+d; document.getElementById(DateTimeShortcuts.calendarDivName1+"+num+").style.display='none';}";
+    },
+    handleCalendarQuickLink: function(num, offset) {
+       var d = new Date();
+       d.setDate(d.getDate() + offset)
+       DateTimeShortcuts.calendarInputs[num].value = d.getISODate();
+       DateTimeShortcuts.dismissCalendar(num);
+    },
+    cancelEventPropagation: function(e) {
+        if (!e) e = window.event;
+        e.cancelBubble = true;
+        if (e.stopPropagation) e.stopPropagation();
+    }
+}
+
+addEvent(window, 'load', DateTimeShortcuts.init);

Added: trunk/templatetool/media/js/admin/RelatedObjectLookups.js
===================================================================
--- trunk/templatetool/media/js/admin/RelatedObjectLookups.js	                        (rev 0)
+++ trunk/templatetool/media/js/admin/RelatedObjectLookups.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,57 @@
+// Handles related-objects functionality: lookup link for raw_id_admin=True
+// and Add Another links.
+
+function showRelatedObjectLookupPopup(triggeringLink) {
+    var name = triggeringLink.id.replace(/^lookup_/, '');
+    // IE doesn't like periods in the window name, so convert temporarily.
+    name = name.replace(/\./g, '___');
+    var href;
+    if (triggeringLink.href.search(/\?/) >= 0) {
+        href = triggeringLink.href + '&pop=1';
+    } else {
+        href = triggeringLink.href + '?pop=1';
+    }
+    var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
+    win.focus();
+    return false;
+}
+
+function dismissRelatedLookupPopup(win, chosenId) {
+    var name = win.name.replace(/___/g, '.');
+    var elem = document.getElementById(name);
+    if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
+        elem.value += ',' + chosenId;
+    } else {
+        document.getElementById(name).value = chosenId;
+    }
+    win.close();
+}
+
+function showAddAnotherPopup(triggeringLink) {
+    var name = triggeringLink.id.replace(/^add_/, '');
+    name = name.replace(/\./g, '___');
+    var win = window.open(triggeringLink.href + '?_popup=1', name, 'height=500,width=800,resizable=yes,scrollbars=yes');
+    win.focus();
+    return false;
+}
+
+function dismissAddAnotherPopup(win, newId, newRepr) {
+    var name = win.name.replace(/___/g, '.');
+    var elem = document.getElementById(name);
+    if (elem) {
+        if (elem.nodeName == 'SELECT') {
+            var o = new Option(newRepr, newId);
+            elem.options[elem.options.length] = o;
+            o.selected = true;
+        } else if (elem.nodeName == 'INPUT') {
+            elem.value = newId;
+        }
+    } else {
+        var toId = name + "_to";
+        elem = document.getElementById(toId);
+        var o = new Option(newRepr, newId);
+        SelectBox.add_to_cache(toId, o);
+        SelectBox.redisplay(toId);
+    }
+    win.close();
+}

Added: trunk/templatetool/media/js/admin/ordering.js
===================================================================
--- trunk/templatetool/media/js/admin/ordering.js	                        (rev 0)
+++ trunk/templatetool/media/js/admin/ordering.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,137 @@
+addEvent(window, 'load', reorder_init);
+
+var lis;
+var top = 0;
+var left = 0;
+var height = 30;
+
+function reorder_init() {
+    lis = document.getElementsBySelector('ul#orderthese li');
+    var input = document.getElementsBySelector('input[name=order_]')[0];
+    setOrder(input.value.split(','));
+    input.disabled = true;
+    draw();
+    // Now initialise the dragging behaviour
+    var limit = (lis.length - 1) * height;
+    for (var i = 0; i < lis.length; i++) {
+        var li = lis[i];
+        var img = document.getElementById('handle'+li.id);
+        li.style.zIndex = 1;
+        Drag.init(img, li, left + 10, left + 10, top + 10, top + 10 + limit);
+        li.onDragStart = startDrag;
+        li.onDragEnd = endDrag;
+        img.style.cursor = 'move';
+    }
+}
+
+function submitOrderForm() {
+    var inputOrder = document.getElementsBySelector('input[name=order_]')[0];
+    inputOrder.value = getOrder();
+    inputOrder.disabled=false;
+}
+
+function startDrag() {
+    this.style.zIndex = '10';
+    this.className = 'dragging';
+}
+
+function endDrag(x, y) {
+    this.style.zIndex = '1';
+    this.className = '';
+    // Work out how far along it has been dropped, using x co-ordinate
+    var oldIndex = this.index;
+    var newIndex = Math.round((y - 10 - top) / height);
+    // 'Snap' to the correct position
+    this.style.top = (10 + top + newIndex * height) + 'px';
+    this.index = newIndex;
+    moveItem(oldIndex, newIndex);
+}
+
+function moveItem(oldIndex, newIndex) {
+    // Swaps two items, adjusts the index and left co-ord for all others
+    if (oldIndex == newIndex) {
+        return; // Nothing to swap;
+    }
+    var direction, lo, hi;
+    if (newIndex > oldIndex) {
+        lo = oldIndex;
+        hi = newIndex;
+        direction = -1;
+    } else {
+        direction = 1;
+        hi = oldIndex;
+        lo = newIndex;
+    }
+    var lis2 = new Array(); // We will build the new order in this array
+    for (var i = 0; i < lis.length; i++) {
+        if (i < lo || i > hi) {
+            // Position of items not between the indexes is unaffected
+            lis2[i] = lis[i];
+            continue;
+        } else if (i == newIndex) {
+            lis2[i] = lis[oldIndex];
+            continue;
+        } else {
+            // Item is between the two indexes - move it along 1
+            lis2[i] = lis[i - direction];
+        }
+    }
+    // Re-index everything
+    reIndex(lis2);
+    lis = lis2;
+    draw();
+//    document.getElementById('hiddenOrder').value = getOrder();
+    document.getElementsBySelector('input[name=order_]')[0].value = getOrder();
+}
+
+function reIndex(lis) {
+    for (var i = 0; i < lis.length; i++) {
+        lis[i].index = i;
+    }
+}
+
+function draw() {
+    for (var i = 0; i < lis.length; i++) {
+        var li = lis[i];
+        li.index = i;
+        li.style.position = 'absolute';
+        li.style.left = (10 + left) + 'px';
+        li.style.top = (10 + top + (i * height)) + 'px';
+    }
+}
+
+function getOrder() {
+    var order = new Array(lis.length);
+    for (var i = 0; i < lis.length; i++) {
+        order[i] = lis[i].id.substring(1, 100);
+    }
+    return order.join(',');
+}
+
+function setOrder(id_list) {
+    /* Set the current order to match the lsit of IDs */
+    var temp_lis = new Array();
+    for (var i = 0; i < id_list.length; i++) {
+        var id = 'p' + id_list[i];
+        temp_lis[temp_lis.length] = document.getElementById(id);
+    }
+    reIndex(temp_lis);
+    lis = temp_lis;
+    draw();
+}
+
+function addEvent(elm, evType, fn, useCapture)
+// addEvent and removeEvent
+// cross-browser event handling for IE5+,  NS6 and Mozilla
+// By Scott Andrew
+{
+  if (elm.addEventListener){
+    elm.addEventListener(evType, fn, useCapture);
+    return true;
+  } else if (elm.attachEvent){
+    var r = elm.attachEvent("on"+evType, fn);
+    return r;
+  } else {
+    elm['on'+evType] = fn;
+  }
+}

Added: trunk/templatetool/media/js/calendar.js
===================================================================
--- trunk/templatetool/media/js/calendar.js	                        (rev 0)
+++ trunk/templatetool/media/js/calendar.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,143 @@
+/*
+calendar.js - Calendar functions by Adrian Holovaty
+*/
+
+function removeChildren(a) { // "a" is reference to an object
+    while (a.hasChildNodes()) a.removeChild(a.lastChild);
+}
+
+// quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
+function quickElement() {
+    var obj = document.createElement(arguments[0]);
+    if (arguments[2] != '' && arguments[2] != null) {
+        var textNode = document.createTextNode(arguments[2]);
+        obj.appendChild(textNode);
+    }
+    var len = arguments.length;
+    for (var i = 3; i < len; i += 2) {
+        obj.setAttribute(arguments[i], arguments[i+1]);
+    }
+    arguments[1].appendChild(obj);
+    return obj;
+}
+
+// CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
+var CalendarNamespace = {
+    monthsOfYear: gettext('January February March April May June July August September October November December').split(' '),
+    daysOfWeek: gettext('S M T W T F S').split(' '),
+    isLeapYear: function(year) {
+        return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0));
+    },
+    getDaysInMonth: function(month,year) {
+        var days;
+        if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) {
+            days = 31;
+        }
+        else if (month==4 || month==6 || month==9 || month==11) {
+            days = 30;
+        }
+        else if (month==2 && CalendarNamespace.isLeapYear(year)) {
+            days = 29;
+        }
+        else {
+            days = 28;
+        }
+        return days;
+    },
+    draw: function(month, year, div_id, callback) { // month = 1-12, year = 1-9999
+        month = parseInt(month);
+        year = parseInt(year);
+        var calDiv = document.getElementById(div_id);
+        removeChildren(calDiv);
+        var calTable = document.createElement('table');
+        quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month-1] + ' ' + year);
+        var tableBody = quickElement('tbody', calTable);
+
+        // Draw days-of-week header
+        var tableRow = quickElement('tr', tableBody);
+        for (var i = 0; i < 7; i++) {
+            quickElement('th', tableRow, CalendarNamespace.daysOfWeek[i]);
+        }
+
+        var startingPos = new Date(year, month-1, 1).getDay();
+        var days = CalendarNamespace.getDaysInMonth(month, year);
+
+        // Draw blanks before first of month
+        tableRow = quickElement('tr', tableBody);
+        for (var i = 0; i < startingPos; i++) {
+            var _cell = quickElement('td', tableRow, ' ');
+            _cell.style.backgroundColor = '#f3f3f3';
+        }
+
+        // Draw days of month
+        var currentDay = 1;
+        for (var i = startingPos; currentDay <= days; i++) {
+            if (i%7 == 0 && currentDay != 1) {
+                tableRow = quickElement('tr', tableBody);
+            }
+            var cell = quickElement('td', tableRow, '');
+            quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '('+year+','+month+','+currentDay+'));');
+            currentDay++;
+        }
+
+        // Draw blanks after end of month (optional, but makes for valid code)
+        while (tableRow.childNodes.length < 7) {
+            var _cell = quickElement('td', tableRow, ' ');
+            _cell.style.backgroundColor = '#f3f3f3';
+        }
+
+        calDiv.appendChild(calTable);
+    }
+}
+
+// Calendar -- A calendar instance
+function Calendar(div_id, callback) {
+    // div_id (string) is the ID of the element in which the calendar will
+    //     be displayed
+    // callback (string) is the name of a JavaScript function that will be
+    //     called with the parameters (year, month, day) when a day in the
+    //     calendar is clicked
+    this.div_id = div_id;
+    this.callback = callback;
+    this.today = new Date();
+    this.currentMonth = this.today.getMonth() + 1;
+    this.currentYear = this.today.getFullYear();
+}
+Calendar.prototype = {
+    drawCurrent: function() {
+        CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback);
+    },
+    drawDate: function(month, year) {
+        this.currentMonth = month;
+        this.currentYear = year;
+        this.drawCurrent();
+    },
+    drawPreviousMonth: function() {
+        if (this.currentMonth == 1) {
+            this.currentMonth = 12;
+            this.currentYear--;
+        }
+        else {
+            this.currentMonth--;
+        }
+        this.drawCurrent();
+    },
+    drawNextMonth: function() {
+        if (this.currentMonth == 12) {
+            this.currentMonth = 1;
+            this.currentYear++;
+        }
+        else {
+            this.currentMonth++;
+        }
+        this.drawCurrent();
+    },
+    drawPreviousYear: function() {
+        this.currentYear--;
+        this.drawCurrent();
+    },
+    drawNextYear: function() {
+        this.currentYear++;
+        this.drawCurrent();
+    }
+}

Added: trunk/templatetool/media/js/core.js
===================================================================
--- trunk/templatetool/media/js/core.js	                        (rev 0)
+++ trunk/templatetool/media/js/core.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,164 @@
+// Core javascript helper functions
+
+// Cross-browser event handlers.
+function addEvent(obj, evType, fn) {
+    if (obj.addEventListener) {
+        obj.addEventListener(evType, fn, false);
+        return true;
+    } else if (obj.attachEvent) {
+        var r = obj.attachEvent("on" + evType, fn);
+        return r;
+    } else {
+        return false;
+    }
+}
+
+function removeEvent(obj, evType, fn) {
+    if (obj.removeEventListener) {
+        obj.removeEventListener(evType, fn, false);
+        return true;
+    } else if (obj.detachEvent) {
+        obj.detachEvent("on" + evType, fn);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+// quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
+function quickElement() {
+    var obj = document.createElement(arguments[0]);
+    if (arguments[2] != '' && arguments[2] != null) {
+        var textNode = document.createTextNode(arguments[2]);
+        obj.appendChild(textNode);
+    }
+    var len = arguments.length;
+    for (var i = 3; i < len; i += 2) {
+        obj.setAttribute(arguments[i], arguments[i+1]);
+    }
+    arguments[1].appendChild(obj);
+    return obj;
+}
+
+// ----------------------------------------------------------------------------
+// Cross-browser xmlhttp object
+// from http://jibbering.com/2002/4/httprequest.html
+// ----------------------------------------------------------------------------
+var xmlhttp;
+/*@cc_on @*/
+/*@if (@_jscript_version >= 5)
+    try {
+        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
+    } catch (e) {
+        try {
+            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+        } catch (E) {
+            xmlhttp = false;
+        }
+    }
+@else
+    xmlhttp = false;
+@end @*/
+if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
+  xmlhttp = new XMLHttpRequest();
+}
+
+// ----------------------------------------------------------------------------
+// Find-position functions by PPK
+// See http://www.quirksmode.org/js/findpos.html
+// ----------------------------------------------------------------------------
+function findPosX(obj) {
+    var curleft = 0;
+    if (obj.offsetParent) {
+        while (obj.offsetParent) {
+            curleft += obj.offsetLeft;
+            obj = obj.offsetParent;
+        }
+    } else if (obj.x) {
+        curleft += obj.x;
+    }
+    return curleft;
+}
+
+function findPosY(obj) {
+    var curtop = 0;
+    if (obj.offsetParent) {
+        while (obj.offsetParent) {
+            curtop += obj.offsetTop;
+            obj = obj.offsetParent;
+        }
+    } else if (obj.y) {
+        curtop += obj.y;
+    }
+    return curtop;
+}
+
+//-----------------------------------------------------------------------------
+// Date object extensions
+// ----------------------------------------------------------------------------
+Date.prototype.getCorrectYear = function() {
+    // Date.getYear() is unreliable --
+    // see http://www.quirksmode.org/js/introdate.html#year
+    var y = this.getYear() % 100;
+    return (y < 38) ? y + 2000 : y + 1900;
+}
+
+Date.prototype.getTwoDigitMonth = function() {
+    return (this.getMonth() < 9) ? '0' + (this.getMonth()+1) : (this.getMonth()+1);
+}
+
+Date.prototype.getTwoDigitDate = function() {
+    return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate();
+}
+
+Date.prototype.getTwoDigitHour = function() {
+    return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours();
+}
+
+Date.prototype.getTwoDigitMinute = function() {
+    return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
+}
+
+Date.prototype.getTwoDigitSecond = function() {
+    return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
+}
+
+Date.prototype.getISODate = function() {
+    return this.getCorrectYear() + '-' + this.getTwoDigitMonth() + '-' + this.getTwoDigitDate();
+}
+
+Date.prototype.getHourMinute = function() {
+    return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
+}
+
+Date.prototype.getHourMinuteSecond = function() {
+    return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
+}
+
+// ----------------------------------------------------------------------------
+// String object extensions
+// ----------------------------------------------------------------------------
+String.prototype.pad_left = function(pad_length, pad_string) {
+    var new_string = this;
+    for (var i = 0; new_string.length < pad_length; i++) {
+        new_string = pad_string + new_string;
+    }
+    return new_string;
+}
+
+// ----------------------------------------------------------------------------
+// Get the computed style for and element
+// ----------------------------------------------------------------------------
+function getStyle(oElm, strCssRule){
+    var strValue = "";
+    if(document.defaultView && document.defaultView.getComputedStyle){
+        strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
+    }
+    else if(oElm.currentStyle){
+        strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
+            return p1.toUpperCase();
+        });
+        strValue = oElm.currentStyle[strCssRule];
+    }
+    return strValue;
+}

Added: trunk/templatetool/media/js/dateparse.js
===================================================================
--- trunk/templatetool/media/js/dateparse.js	                        (rev 0)
+++ trunk/templatetool/media/js/dateparse.js	2008-02-09 16:30:37 UTC (rev 2615)
@@ -0,0 +1,233 @@
+/* 'Magic' date parsing, by Simon Willison (6th October 2003)
+   http://simon.incutio.com/archive/2003/10/06/betterDateInput
+   Adapted for 6newslawrence.com, 28th January 2004
+*/
+
+/* Finds the index of the first occurence of item in the array, or -1 if not found */
+if (typeof Array.prototype.indexOf == 'undefined') {
+    Array.prototype.indexOf = function(item) {
+        var len = this.length;
+        for (var i = 0; i < len; i++) {
+            if (this[i] == item) {
+                return i;
+            }
+        }
+        return -1;
+    };
+}
+/* Returns an array of items judged 'true' by the passed in test function */
+if (typeof Array.prototype.filter == 'undefined') {
+    Array.prototype.filter = function(test) {
+        var matches = [];
+        var len = this.length;
+        for (var i = 0; i < len; i++) {
+            if (test(this[i])) {
+                matches[matches.length] = this[i];
+            }
+        }
+        return matches;
+    };
+}
+
+var monthNames = gettext("January February March April May June July August September October November December").split(" ");
+var weekdayNames = gettext("Sunday Monday Tuesday Wednesday Thursday Friday Saturday").split(" ");
+
+/* Takes a string, returns the index of the month matching that string, throws
+   an error if 0 or more than 1 matches
+*/
+function parseMonth(month) {
+    var matches = monthNames.filter(function(item) { 
+        return new RegExp("^" + month, "i").test(item);
+    });
+    if (matches.length == 0) {
+        throw new Error("Invalid month string");
+    }
+    if (matches.length > 1) {
+        throw new Error("Ambiguous month");
+    }
+    return monthNames.indexOf(matches[0]);
+}
+/* Same as parseMonth but for days of the week */
+function parseWeekday(weekday) {
+    var matches = weekdayNames.filter(function(item) {
+        return new RegExp("^" + weekday, "i").test(item);
+    });
+    if (matches.length == 0) {
+        throw new Error("Invalid day string");
+    }
+    if (matches.length > 1) {
+        throw new Error("Ambiguous weekday");
+    }
+    return weekdayNames.indexOf(matches[0]);
+}
+
+/* Array of objects, each has 're', a regular expression and 'handler', a 
+   function for creating a date from something that matches the regular 
+   expression. Handlers may throw errors if string is unparseable. 
+*/
+var dateParsePatterns = [
+    // Today
+    {   re: /^tod/i,
+        handler: function() { 
+            return new Date();
+        } 
+    },
+    // Tomorrow
+    {   re: /^tom/i,
+        handler: function() {
+            var d = new Date(); 
+            d.setDate(d.getDate() + 1); 
+            return d;
+        }
+    },
+    // Yesterday
+    {   re: /^yes/i,
+        handler: function() {
+            var d = new Date();
+            d.setDate(d.getDate() - 1);
+            return d;
+        }
+    },
+    // 4th
+    {   re: /^(\d{1,2})(st|nd|rd|th)?$/i, 
+        handler: function(bits) {
+            var d = new Date();
+            d.setDate(parseInt(bits[1], 10));
+            return d;
+        }
+    },
+    // 4th Jan
+    {   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i, 
+        handler: function(bits) {
+            var d = new Date();
+            d.setDate(parseInt(bits[1], 10));
+            d.setMonth(parseMonth(bits[2]));
+            return d;
+        }
+    },
+    // 4th Jan 2003
+    {   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i,
+        handler: function(bits) {
+            var d = new Date();
+            d.setDate(parseInt(bits[1], 10));
+            d.setMonth(parseMonth(bits[2]));
+            d.setYear(bits[3]);
+            return d;
+        }
+    },
+    // Jan 4th
+    {   re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i, 
+        handler: function(bits) {
+            var d = new Date();

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/