[Jifty-commit] r3766 - in jifty/branches/autoversioning: . examples/Yada/etc examples/Yada/lib examples/Yada/lib/Yada examples/Yada/lib/Yada/View examples/Yada/share/web/static/js examples/Yada/share/web/static/js/Asynapse lib/Jifty lib/Jifty/Manual lib/Jifty/Plugin lib/Jifty/Plugin/ActorMetadata/Mixin/Model lib/Jifty/Plugin/Chart lib/Jifty/Plugin/Chart/Renderer lib/Jifty/Plugin/Chart/Renderer/GD lib/Jifty/Plugin/GoogleMap lib/Jifty/Plugin/REST lib/Jifty/Plugin/SkeletonApp lib/Jifty/Plugin/UUID lib/Jifty/View/Declare lib/Jifty/Web share/plugins/Jifty/Plugin/Chart share/plugins/Jifty/Plugin/Chart/web share/plugins/Jifty/Plugin/Chart/web/static share/plugins/Jifty/Plugin/Chart/web/static/js share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit share/web/static/js share/web/templates/__jifty/webservices t t/TestApp-Plugin-Chart t/TestApp-Plugin-Chart/bin t/TestApp-Plugin-Chart/doc t/TestApp-Plugin-Chart/etc t/TestApp-Plugin-Chart/lib t/TestApp-Plugin-Chart/lib/TestApp t/TestApp-Plugin-Chart/lib/TestApp/Plugin t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart/Model t/TestApp-Plugin-Chart/log t/TestApp-Plugin-Chart/share t/TestApp-Plugin-Chart/share/po t/TestApp-Plugin-Chart/share/web t/TestApp-Plugin-Chart/share/web/static t/TestApp-Plugin-Chart/share/web/templates t/TestApp-Plugin-Chart/t t/TestApp-Plugin-Chart/var t/TestApp-Plugin-Chart/var/mason t/TestApp-Plugin-Chart/var/mason/cache t/TestApp-Plugin-Chart/var/mason/obj t/TestApp/lib/TestApp/Model t/TestApp/t t/clientside

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Thu Aug 2 11:50:24 EDT 2007


Author: jesse
Date: Thu Aug  2 11:50:22 2007
New Revision: 3766

Added:
   jifty/branches/autoversioning/examples/Yada/lib/Yada.pm
   jifty/branches/autoversioning/examples/Yada/share/web/static/js/
   jifty/branches/autoversioning/examples/Yada/share/web/static/js/Asynapse/
   jifty/branches/autoversioning/examples/Yada/share/web/static/js/Asynapse/REST.js
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/Chart.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/GD/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/GD/Graph.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/PlotKit.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Web.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/UUID/
   jifty/branches/autoversioning/lib/Jifty/Plugin/UUID.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/UUID/Widget.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/Compile.pm
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit/MochiKit.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit/__package__.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Base.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Canvas.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/EasyPlot.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Layout.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/PlotKit.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/PlotKit_Packed.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SVG.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SweetCanvas.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SweetSVG.js
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/dummy.svg
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/excanvas.js   (contents, props changed)
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/mochikit.noexport.js
   jifty/branches/autoversioning/share/web/static/js/template_declare.js
   jifty/branches/autoversioning/t/13-sessions.t
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/Makefile.PL
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/bin/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/bin/jifty   (contents, props changed)
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/doc/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/etc/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/etc/config.yml
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/Plugin/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart/Action/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart/Model/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart/View.pm
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/log/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/share/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/share/po/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/share/web/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/share/web/static/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/share/web/templates/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/t/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/t/chart.t
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/t/gd_graph.t
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/var/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/var/mason/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/var/mason/cache/
   jifty/branches/autoversioning/t/TestApp-Plugin-Chart/var/mason/obj/
   jifty/branches/autoversioning/t/clientside/
   jifty/branches/autoversioning/t/clientside/td.t
Modified:
   jifty/branches/autoversioning/   (props changed)
   jifty/branches/autoversioning/AUTHORS
   jifty/branches/autoversioning/META.yml
   jifty/branches/autoversioning/Makefile.PL
   jifty/branches/autoversioning/examples/Yada/etc/config.yml
   jifty/branches/autoversioning/examples/Yada/lib/Yada/View.pm
   jifty/branches/autoversioning/examples/Yada/lib/Yada/View/Todo.pm
   jifty/branches/autoversioning/lib/Jifty/Action.pm
   jifty/branches/autoversioning/lib/Jifty/Manual/Glossary.pod
   jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/ActorMetadata.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/Widget.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/Page.pm
   jifty/branches/autoversioning/lib/Jifty/Web.pm
   jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Session.pm
   jifty/branches/autoversioning/share/web/static/js/jifty.js
   jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml
   jifty/branches/autoversioning/t/TestApp/lib/TestApp/Model/User.pm
   jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t
   jifty/branches/autoversioning/t/TestApp/t/05-editactions-Record.t
   jifty/branches/autoversioning/t/TestApp/t/config-Record

Log:
 r61117 at pinglin (orig r3705):  clkao | 2007-07-20 10:00:23 -0400
 Push milestone 1 of trimclient to trunk.
 
 r61120 at pinglin (orig r3706):  jesse | 2007-07-22 16:21:40 -0400
 
 r61121 at pinglin (orig r3707):  jesse | 2007-07-22 16:21:58 -0400
  r61112 at 106:  jesse | 2007-07-22 10:20:34 -0700
  * The warnings come from the server code after the fork. Test::Log4Perl isn't going to catch them.
 
 r61122 at pinglin (orig r3708):  jesse | 2007-07-22 16:22:02 -0400
  r61115 at 106:  jesse | 2007-07-22 12:48:51 -0700
  * added some pod to help make pod tests pass
 
 r61158 at pinglin (orig r3715):  clkao | 2007-07-24 06:09:47 -0400
 Fix a fragment update regression caused by the trimclient merge.
 
 r64873 at pinglin (orig r3723):  sterling | 2007-07-27 15:53:01 -0400
 
 r64874 at pinglin (orig r3724):  sterling | 2007-07-27 15:54:54 -0400
  r8183 at riddle:  andrew | 2007-07-27 12:49:07 -0700
  Adding a plugin for rendering charts of data.
 
 r64875 at pinglin (orig r3725):  sterling | 2007-07-27 15:56:25 -0400
  r8184 at riddle:  andrew | 2007-07-27 12:49:42 -0700
  Removing a directory that should not have committed previously.
 
 r64876 at pinglin (orig r3726):  sterling | 2007-07-27 15:58:53 -0400
 
 r64877 at pinglin (orig r3727):  sterling | 2007-07-27 16:12:43 -0400
  r8192 at riddle:  andrew | 2007-07-27 13:11:49 -0700
  Reverting mistaken revision r3723
 
 r64878 at pinglin (orig r3728):  sterling | 2007-07-27 16:17:32 -0400
  r8194 at riddle:  andrew | 2007-07-27 13:16:59 -0700
  Reverting mistaken revision r3723, take 2
 
 r64910 at pinglin (orig r3730):  jesse | 2007-07-28 20:31:47 -0400
  r64900 at pinglin:  jesse | 2007-07-28 18:18:31 -0500
  * Moniker bulletproofing. Suggested by Mikko Lapasti
 
 r64912 at pinglin (orig r3731):  sterling | 2007-07-29 16:15:59 -0400
  r8199 at dynpc145:  andrew | 2007-07-29 15:13:38 -0500
  Added documentation to the experimental Chart plugin.
 
 r64913 at pinglin (orig r3732):  sterling | 2007-07-29 16:16:07 -0400
  r8200 at dynpc145:  andrew | 2007-07-29 15:15:21 -0500
  Added the Chart::Base recommendation for the Chart plugin.
 
 r64916 at pinglin (orig r3734):  jesse | 2007-07-29 17:53:45 -0400
  r64915 at pinglin:  jesse | 2007-07-29 17:53:35 -0400
  * Resolve import conflicts now that T::D and J::V::D::Helpers have a thingy with the same name
 
 r64924 at pinglin (orig r3735):  sterling | 2007-07-29 22:16:24 -0400
  r8203 at dynpc145:  andrew | 2007-07-29 21:13:01 -0500
  Adding a test suite for Jifty::Plugin::Chart, but it is having weird troubles loading Chart::* because that seems to disconnect the server output or something.
 
 r64925 at pinglin (orig r3736):  sterling | 2007-07-29 22:16:30 -0400
  r8204 at dynpc145:  andrew | 2007-07-29 21:13:35 -0500
  Adding Image::Info dependency used during testing of Jifty::Plugin::Chart
 
 r64926 at pinglin (orig r3737):  sterling | 2007-07-29 22:16:37 -0400
  r8205 at dynpc145:  andrew | 2007-07-29 21:15:43 -0500
  Regarding Jifty::Plugin::Chart: Added better comments. Fixed some error handling. Switched to using scalar_png(). Switched to using ->require rather than an eval to load Chart classes. Eliminated the need for IO::String. Moved some processing out of View and into Dispatcher.
 
 r64927 at pinglin (orig r3738):  sartak | 2007-07-30 16:57:21 -0400
  r29652 at caladan:  sartak | 2007-07-30 16:56:47 -0400
  Add a load_by_kv to Jifty::Web::Session
 
 r64928 at pinglin (orig r3739):  sartak | 2007-07-30 16:58:18 -0400
  r29654 at caladan:  sartak | 2007-07-30 16:58:03 -0400
  add myself to AUTHORS :)
 
 r64934 at pinglin (orig r3742):  jesse | 2007-07-30 20:38:33 -0400
  r64932 at pinglin:  jesse | 2007-07-30 20:37:16 -0400
  * First cut of a UUID column plugin, with a basic test in the user model
 
 r65010 at pinglin (orig r3747):  sterling | 2007-07-31 22:32:37 -0400
 
 r65011 at pinglin (orig r3748):  sterling | 2007-07-31 22:32:48 -0400
  r8268 at dynpc145:  andrew | 2007-07-31 21:28:14 -0500
  Added a hack to chart.t (forcing an early load of GD) to avoid the segfault that was causing it to fail. Removed the TODO block from the test.
 
 r65012 at pinglin (orig r3749):  sterling | 2007-07-31 22:33:01 -0400
  r8269 at dynpc145:  andrew | 2007-07-31 21:29:42 -0500
  Fixed the way arguments are passed to the render() method in Jifty::Plugin::Chart::Web.
 
 r65013 at pinglin (orig r3750):  sterling | 2007-07-31 22:33:09 -0400
  r8270 at dynpc145:  andrew | 2007-07-31 21:31:01 -0500
  Moved the chart/* dispatch to chart/chart/* to make room for alternate charting mechanisms.
 
 r65014 at pinglin (orig r3751):  sterling | 2007-07-31 22:33:17 -0400
  r8271 at dynpc145:  andrew | 2007-07-31 21:31:21 -0500
  Added a renderer for GD::Graph
 
 r65015 at pinglin (orig r3752):  sterling | 2007-07-31 22:33:32 -0400
  r8272 at dynpc145:  andrew | 2007-07-31 21:31:41 -0500
  Updated the module recommendations for the Chart plugin.
 
 r65016 at pinglin (orig r3753):  sterling | 2007-07-31 22:47:45 -0400
  r8289 at dynpc145:  andrew | 2007-07-31 21:42:52 -0500
  Updated POD and removed an unnecessary extra subroutine call.
 
 r65017 at pinglin (orig r3754):  sterling | 2007-07-31 22:47:56 -0400
  r8290 at dynpc145:  andrew | 2007-07-31 21:44:59 -0500
  Fixed POD coverage issue.
 
 r65018 at pinglin (orig r3755):  sterling | 2007-07-31 22:48:02 -0400
  r8291 at dynpc145:  andrew | 2007-07-31 21:47:05 -0500
  Fixed an eensy POD bug.
 
 r65019 at pinglin (orig r3756):  sterling | 2007-07-31 23:03:26 -0400
  r8296 at dynpc145:  andrew | 2007-07-31 22:03:08 -0500
  Made the chart plugin test smarter and added one for the GD::Graph renderer.
 
 r65020 at pinglin (orig r3757):  trs | 2007-07-31 23:41:50 -0400
  r25774 at zot:  tom | 2007-07-31 23:40:12 -0400
  Basic PlotKit renderer for Chart plugin
 
 r65021 at pinglin (orig r3758):  trs | 2007-08-01 02:49:40 -0400
  r25776 at zot:  tom | 2007-08-01 02:49:29 -0400
  - Uncomment neccessary require
  - Make sure to handle undefined stuff
 
 r65038 at pinglin (orig r3760):  jesse | 2007-08-01 15:15:14 -0400
 
 r65039 at pinglin (orig r3761):  jesse | 2007-08-01 15:15:32 -0400
  r65037 at pinglin:  jesse | 2007-08-01 15:11:00 -0400
   * clean up load_by_kv
 


Modified: jifty/branches/autoversioning/AUTHORS
==============================================================================
--- jifty/branches/autoversioning/AUTHORS	(original)
+++ jifty/branches/autoversioning/AUTHORS	Thu Aug  2 11:50:22 2007
@@ -30,3 +30,4 @@
 Alexander Klink <alech at cpan.org>
 Andreas Koenig <andreas.koenig.7os6VVqR at franz.ak.mind.de>
 sunnavy <sunnavy at gmail.com>
+Shawn M Moore <sartak at gmail.com>

Modified: jifty/branches/autoversioning/META.yml
==============================================================================
--- jifty/branches/autoversioning/META.yml	(original)
+++ jifty/branches/autoversioning/META.yml	Thu Aug  2 11:50:22 2007
@@ -65,6 +65,7 @@
   Email::MIME::ContentType: 0
   Email::MIME::CreateHTML: 0
   Email::MIME::Creator: 0
+  Email::MIME::Modifier: 0
   Email::Send: 1.99_01
   Email::Simple: 0
   Email::Simple::Creator: 0
@@ -97,6 +98,7 @@
   Module::Refresh: 0
   Module::ScanDeps: 0
   Object::Declare: 0.13
+  PadWalker: 0
   Params::Validate: 0
   Pod::Simple: 0
   SQL::ReservedWords: 0

Modified: jifty/branches/autoversioning/Makefile.PL
==============================================================================
--- jifty/branches/autoversioning/Makefile.PL	(original)
+++ jifty/branches/autoversioning/Makefile.PL	Thu Aug  2 11:50:22 2007
@@ -58,6 +58,7 @@
 requires('Module::Refresh');
 requires('Module::ScanDeps');
 requires('Object::Declare' => '0.13');
+requires('PadWalker');
 requires('Params::Validate');
 requires('Scalar::Defer' => '0.10');
 requires('Shell::Command');
@@ -143,7 +144,13 @@
     ],
     'Jifty console' => [
         -default => 0,
-        recommends('Devel::EvalContext')
+        recommends('Devel::EvalContext'),
+    ],
+    'Chart Plugin (none of these must be installed for Charts to work)' => [
+        -default => 0,
+        recommends('Chart::Base'),
+        recommends('GD::Graph'),
+        recommends('Image::Info'), # for testing
     ],
 );
 

Modified: jifty/branches/autoversioning/examples/Yada/etc/config.yml
==============================================================================
--- jifty/branches/autoversioning/examples/Yada/etc/config.yml	(original)
+++ jifty/branches/autoversioning/examples/Yada/etc/config.yml	Thu Aug  2 11:50:22 2007
@@ -2,6 +2,7 @@
 application:
   OpenIDSecret: sekrit13
 framework: 
+  ConfigFileVersion: 2
   AdminMode: 1
   SkipAccessControl: 1
   ApplicationClass: Yada
@@ -16,7 +17,7 @@
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 0
+  DevelMode: 1
   L10N: 
     PoDir: share/po
   LogLevel: INFO
@@ -34,11 +35,13 @@
     - User: {}
     - Authentication::Password: {}
     - OpenID: {}
+    - SinglePage: {}
 
   PubSub: 
     Backend: Memcached
     Enable: ~
   TemplateClass: Yada::View
+  ClientTemplate: 1
   Web: 
     BaseURL: http://localhost
     DataDir: var/mason

Added: jifty/branches/autoversioning/examples/Yada/lib/Yada.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/lib/Yada.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,6 @@
+package Yada;
+
+
+Jifty->web->add_javascript(qw( Asynapse/REST.js trimpath-template.js ) );
+
+1;

Modified: jifty/branches/autoversioning/examples/Yada/lib/Yada/View.pm
==============================================================================
--- jifty/branches/autoversioning/examples/Yada/lib/Yada/View.pm	(original)
+++ jifty/branches/autoversioning/examples/Yada/lib/Yada/View.pm	Thu Aug  2 11:50:22 2007
@@ -1,18 +1,63 @@
 package Yada::View;
 use Jifty::View::Declare -base;
+use strict;
+
+use Jifty::View::Declare::CRUD;
+for (qw/todo/) {
+    Jifty::View::Declare::CRUD->mount_view($_);
+}
 
 template 'index.html' => page {
     my $self = shift;
     title { _('Yada!') };
 
+    render_region('test_region');
+
+    hyperlink(label => 'FAQ',
+	      onclick => [{region => 'test_region',
+			   replace_with => '_faq',
+			  }]);
+
     form {
+	set(item_path => '/todo/view_brief');
 	render_region(name => 'list', path => '/todo/list');
     }
 };
 
-use Jifty::View::Declare::CRUD;
-for (qw/todo/) {
-    Jifty::View::Declare::CRUD->mount_view($_);
-}
+template '_faq' => sub :Static {
+    hyperlink(label => 'close', onclick => [{replace_with => '/__jifty/empty'}]);
+
+    div {
+        attr { id => "faq" };
+        h2 { _('Using Yada') }
+        dl {
+            dt { 'Yada Yada Yada!'}
+            dd {
+                span {
+                    'are we nearly there yet?'
+                }
+	    }
+	};
+    }
+};
+
+template 'signup' => page {
+    title is _('Sign up');
+    render_region(name => 'signup_widget', path => '_signup');
+};
+
+template '_signup' => sub :Action {
+    my $action = Jifty->web->new_action( class => 'Signup', moniker => 'signupnow');
+    my $next = undef;
+#    with ( call => $next ),
+    form {
+	render_param( $action => 'name' , focus => 1);
+	render_param( $action => $_ ) for ( grep {$_ ne 'name'} $action->argument_names );
+
+	form_return( label => _('Sign up'), submit => $action );
+    }
+
+};
+
 
 1;

Modified: jifty/branches/autoversioning/examples/Yada/lib/Yada/View/Todo.pm
==============================================================================
--- jifty/branches/autoversioning/examples/Yada/lib/Yada/View/Todo.pm	(original)
+++ jifty/branches/autoversioning/examples/Yada/lib/Yada/View/Todo.pm	Thu Aug  2 11:50:22 2007
@@ -1,6 +1,21 @@
 package Yada::View::Todo;
 use strict;
-use Jifty::View::Declare -base;
 use base 'Jifty::View::Declare::CRUD';
+use Jifty::View::Declare -base;
+
+template 'view_brief' => sub {
+    my $self = shift;
+    my ( $object_type, $id ) = ( $self->object_type, get('id') );
+    my $record = $self->_get_record($id);
+
+    div { {class is "description" };
+	  outs($record->description);
+	  hyperlink(label => 'details',
+		    onclick => [{region => 'test_region',
+				 replace_with => $self->fragment_for('view'),
+				 args         => { id => $id },
+				}]);
+      };
+};
 
 1;

Added: jifty/branches/autoversioning/examples/Yada/share/web/static/js/Asynapse/REST.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/share/web/static/js/Asynapse/REST.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,285 @@
+if ( typeof Asynapse == 'undefined' ) {
+    Asynapse = {}
+}
+
+if ( typeof Asynapse.REST == 'undefined' ) {
+    Asynapse.REST = {}
+}
+
+Asynapse.REST.VERSION = "0.10"
+
+Asynapse.REST.Model = function(model) {
+    this._model = model
+    return this;
+}
+
+Asynapse.REST.Model.prototype = {
+    /* Corresponds Jifty's REST Pluing API */
+    show_item_field: function(column, key, field) {
+        var url = "/=/model/*/*/*/*.js"
+            .replace("*", this._model)
+            .replace("*", column)
+            .replace("*", key)
+            .replace("*", field)
+
+        return this.eval_ajax_get(url);        
+    },
+    
+    show_item: function(column, key) {
+        var url = "/=/model/*/*/*.js"
+            .replace("*", this._model)
+            .replace("*", column)
+            .replace("*", key)
+
+        return this.eval_ajax_get(url);
+    },
+
+    list_model_items: function(column) {
+        var url = "/=/model/*/*.js"
+            .replace("*", this._model)
+            .replace("*", column)
+
+        return this.eval_ajax_get(url);
+    },
+
+    list_model_columns: function() {
+        var url = "/=/model/*.js"
+            .replace("*", this._model)
+
+        return this.eval_ajax_get(url);
+    },
+
+    list_models: function() {
+        var url = "/=/model.js"
+
+        return this.eval_ajax_get(url);
+    },
+
+    create_item: function(item) {
+        var url ="/=/model/*.js"
+            .replace("*", this._model)
+
+        var req = new Ajax.Request(url, {
+            method: 'post',
+            asynchronous: false,
+            postBody: $H(item).toQueryString()
+        });
+        if ( req.responseIsSuccess() ) {
+            eval(req.transport.responseText);
+            return $H($_)
+        } else {
+            return null;
+        }
+    },
+    
+    replace_item: function(item) {
+        var url = "/=/action/update" + this._model + ".js"
+        new Ajax.Request(url, {
+            method: 'post',
+            contentType: 'application/x-www-form-urlencoded',
+            postBody: $H(item).toQueryString()            
+        });
+    },
+
+    delete_item: function(column, key) {
+        var url = "/=/model/*/*/*"
+            .replace("*", this._model)
+            .replace("*", column)
+            .replace("*", key)
+        
+        new Ajax.Request(url, {
+            method: 'DELETE',
+            contentType: 'application/x-www-form-urlencoded'
+        });
+        return null;
+    },
+    
+    /* Internal Helpers */
+    eval_ajax_get: function(url) {
+        eval(this.ajax_get(url));
+        return $_ ? Object.extend({},$_) : null;
+    },
+    ajax_get: function(url) {
+        var req = new Ajax.Request(url, {
+            method: 'GET',
+            asynchronous: false
+        })
+        if ( req.responseIsSuccess() ) {
+            return req.transport.responseText;
+        }
+        else {
+            return "var $_ = null";
+        }
+    }
+}
+
+Asynapse.REST.Model.ActiveRecord = function(model) {
+    Object.extend(this, new Asynapse.REST.Model(model));
+    this._attributes = {}
+    return this;
+}
+
+Asynapse.REST.Model.ActiveRecord.prototype = {
+    new: function() {
+        return this;
+    },
+    
+    find: function(param) {
+        if ( typeof param == 'number' ) {
+            return this.show_item("id", param)
+        }
+    },
+
+    find_by_id: function(id) {
+        return this.show_item("id", id)
+    },
+
+    create: function(attributes) {
+        var r = this.create_item(attributes);
+
+        if (r.success) {
+            return this.show_item("id", Number(r.content.id) )
+        }
+        return null;
+    },
+
+    delete: function(id) {
+        this.delete_item("id", id)
+        return null
+    },
+
+    update: function(id, attributes) {
+        var obj = this.find(id)
+        obj = Object.extend(obj, attributes)
+        return this.replace_item( obj )
+    },
+
+    write_attribute: function(attr, value) {
+    }
+}
+
+/* Great Aliases */
+Asynapse.Model = Asynapse.REST.Model
+Asynapse.ActiveRecord = Asynapse.REST.Model.ActiveRecord
+AsynapseRecord = Asynapse.REST.Model.ActiveRecord
+
+/**
+=head1 NAME
+
+Asynapse.REST - Asynapse REST Client
+
+=head1 VERSION
+
+This document describes Asynapse.REST version 0.10
+
+=head1 SYNOPSIS
+
+    # Define Your own AsynapseRecord Class.
+    Person = new AsynapseRecord('person')
+
+    # Use it
+    var p = Person.find(1)
+
+=head1 DESCRIPTION
+
+Asynapse.REST is the namespace for being a general REST client in
+Asynapse framework. Under this namespace, so far we arrange
+C<Asynapse.REST.Model> for Asynapse Model Classes. It means to
+provide an abstration layer for data existing at given REST server(s).
+
+With many flavours of data abstration layer in the world, we choose
+to emulate ActiveRecord as our first target, which has a plain
+simple object semantics, and very compatible to javascript.
+The implementation of it called C<AsynapseRecord>.
+
+To use it, you must first create your own record classes, like this:
+
+    Person = new AsynapseRecord('person')
+
+After this, Person becomes your Person model class, and then you
+can do:
+
+    var p = Person.find(1)
+
+To find a person by its id. Besides C<find>, C<create>, C<update>,
+and C<delete> are also implemented.
+
+Here's more detail about how to use these interfaces. They are all
+"class methods".
+
+=over
+
+=item find( id )
+
+Retrieve a record from this model with given id.
+
+=item create( attr )
+
+Create a new with attributes specified in attr hash.
+
+=item update( id, attr )
+
+Update the record with primary key id with new sets of
+attributes specified in attr hash.
+
+=item delete( id )
+
+Remove the record with given id.
+
+=back
+
+=head1 CONFIGURATION AND ENVIRONMENT
+
+AsynapseRecord requires no configuration files or environment
+variables.  However, you need a Jifty instance with REST plugin
+(which is given by default now.)
+
+Since JavaScript cannot do XSS, it assumed the your Jifty instance's
+URL resides at C</>, and entry points of REST servces starts from
+C</=/>. It should be made possible to change this assumption in the
+future to match more presets in different frameworks.
+
+=head1 BUGS AND LIMITATIONS
+
+The asynapse project is hosted at L<http://code.google.com/p/asynapse/>.
+You may contact the authors or submit issues using the web interface.
+
+=head1 AUTHOR
+
+Kang-min Liu  C<< <gugod at gugod.org> >>
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2007, Kang-min Liu C<< <gugod at gugod.org> >>. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+*/ 
+

Modified: jifty/branches/autoversioning/lib/Jifty/Action.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Action.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Action.pm	Thu Aug  2 11:50:22 2007
@@ -119,6 +119,26 @@
         $self->_get_current_user();
     }
 
+
+    if ( $args{'moniker'} ) {
+        if ( $args{'moniker'} =~ /[\;]/ ) {
+            $args{'moniker'} =~ s/[\;]/_/g;
+            $self->log->warn(
+                "Moniker @{[$args{'moniker'}]} contains invalid characters. It should not contain any ';' characters. "
+                    . "It has been autocorrected, but you should correct your code"
+            );
+        }
+        if ( $args{'moniker'} =~ /^\d/ ) {
+            $args{'moniker'} = "fixup-" . $args{'moniker'};
+            $self->log->warn(
+                "Moniker @{[$args{'moniker'}]} contains invalid characters. It can not begin with a digit. "
+                    . "It has been autocorrected, but you should correct your code"
+            );
+
+        }
+    }
+
+
     $self->moniker($args{'moniker'} || $self->_generate_moniker);
     $self->order($args{'order'});
 

Modified: jifty/branches/autoversioning/lib/Jifty/Manual/Glossary.pod
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Manual/Glossary.pod	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Manual/Glossary.pod	Thu Aug  2 11:50:22 2007
@@ -102,13 +102,15 @@
 
 =item moniker
 
-Every instance of a L<Jifty::Action> has a B<moniker>.  A moniker is
-an arbitrary-length nonempty string containing no semicolons.
-Monikers serve as identifiers for actions, to associate arguments with
-actions and to access specific actions "by name".  Monikers need not
-be globally unique, but they must be unique within a single request.
+Every instance of a L<Jifty::Action> has a B<moniker>.  Monikers
+serve as identifiers for actions, to associate arguments with actions
+and to access specific actions "by name".  Monikers need not be
+globally unique, but they must be unique within a single request.
 Monikers have no semantic meaning. See L<Jifty::Action/monikers>
 
+A moniker is an arbitrary-length nonempty string containing no
+semicolons. It may not begin with a digit.
+
 =item parameter
 
 A B<parameter> is a named parameter to an L</action>.  Jifty generally renders

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata.pm	Thu Aug  2 11:50:22 2007
@@ -4,4 +4,30 @@
 package Jifty::Plugin::ActorMetadata;
 use base qw/Jifty::Plugin/;
 
+=head1 NAME
+
+Jifty::Plugin::ActorMetadata
+
+=head1 DESCRIPTION
+ 
+This plugin adds a model mixin which adds C<created_by>, C<created_on> and C<updated_on> columns to a model class.
+
+=head1 EXAMPLE 
+
+use strict;
+ use warnings;
+ 
+ package MeetMeow::Model::Cat;
+ use Jifty::DBI::Schema;
+ 
+ use MeetMeow::Record schema {
+ 
+         ...
+ 
+ };
+ use Jifty::Plugin::ActorMetadata::Mixin::Model::ActorMetadata; # created_by, created_on, updated_on
+ 
+
+=cut
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/ActorMetadata.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/ActorMetadata.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/ActorMetadata.pm	Thu Aug  2 11:50:22 2007
@@ -84,6 +84,12 @@
     $self->add_trigger(name => 'before_create', callback => \&before_create);
 }
 
+=head2 before_create
+
+Sets C<created_by>, C<created_on>, C<updated_on> based on the current user and time.
+
+=cut
+
 sub before_create {
     my $self = shift;
     my $args = shift;
@@ -94,7 +100,15 @@
     return 1;
 }
 
+=head2 current_user_can
+
+Rejects creation unless there's a current_user. 
+Rejects update or deletion unless the current_user is the creator.  (Jesse says: this feels like wrong logic for this mixin)
+
+=cut
+
 # XXX: Move this to an abortable trigger
+
 sub current_user_can {
     my $self = shift;
     my $action = shift;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,110 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart;
+use base qw/ Jifty::Plugin Class::Accessor::Fast /;
+
+use Jifty::Plugin::Chart::Web;
+
+__PACKAGE__->mk_accessors(qw/ renderer /);
+
+=head1 NAME
+
+Jifty::Plugin::Chart - A charting API for Jifty
+
+=head1 SYNOPSIS
+
+In your F<config.yml>:
+
+  Plugins:
+    - Chart: {}
+
+In your Mason templates:
+
+  <% Jifty->web->chart(
+      type   => 'Bar',
+      width  => 400,
+      height => 300,
+      data   => [
+          [ '2004', '2005', '2006', '2007' ], # labels
+          [ 14,     15,     17,     22     ], # first data set
+          [ 22,     25,     20,     21     ], # second data set
+      ],
+  ) %>
+
+=head1 DESCRIPTION
+
+B<CAUTION:> This plugin is experimental. The API I<will> change.
+
+This plugin provides a charting API that can be used by Jifty applications to build data visualizations without regard to the underlying rendering mechanism.
+
+As of this writing, the API is a barely veiled interface over L<Chart>. However, I intend to expand the interface to apply to something like Maani's XML/SWF Charts or Imprise Javascript charts or even something like OpenLaszlo (or something Open Source and Perl if I can find or build such a thing in time).
+
+=head1 INTERFACE
+
+By adding this method to the plugin configuration for your Jifty application, you will cause L<Jifty::Web> to inherit a new method, C<chart>, which is the cornerstone of this API.
+
+This method is described in L<Jifty::Plugin::Chart::Web> and an example is shown in the L</SYNOPSIS> above.
+
+=head1 CONFIGURATION
+
+The plugin takes a single configuration option called C<renderer>. This may be set to a chart renderer class, which is just an implementation of L<Jifty::Plugin::Chart::Renderer>. The default, L<Jifty::Plugin::Chart::Renderer::Chart>, uses L<Chart> to render charts as PNG files which are then included in your pages for you.
+
+Here is an example configuration for F<config.yml>:
+
+  Plugins:
+    - Chart:
+        renderer: Chart
+
+=head1 METHODS
+
+=head2 init
+
+Adds the L<Jifty::Plugin::Chart::Web/chart> method to L<Jifty::Web>.
+
+=cut
+
+sub init {
+    my $self = shift;
+    my %args = (
+        renderer => 'Chart',
+        @_,
+    );
+
+    if ( $args{renderer} !~ /::/ ) {
+        $args{renderer} = __PACKAGE__.'::Renderer::'.$args{renderer};
+    }
+
+    eval "use $args{renderer}";
+    warn $@ if $@;
+    $self->renderer( $args{renderer} );
+
+    if ( $self->renderer =~ 'PlotKit' ) {
+        # XXX TODO: Why does MochiKit need to be loaded before everything else?
+        Jifty->web->javascript_libs([
+            'MochiKit/MochiKit.js',
+            @{ Jifty->web->javascript_libs },
+            'PlotKit/PlotKit_Packed.js'
+        ]);
+    }
+
+    push @Jifty::Web::ISA, 'Jifty::Plugin::Chart::Web';
+}
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin>, L<Jifty::Web>, L<Jifty::Plugin::Chart::Renderer>, L<Jifty::Plugin::Chart::Renderer::Chart>, L<Jifty::Plugin::Chart::View>
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp C<< <andrew.hanenkamp at boomer.com> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Boomer Consulting, Inc.
+
+This is free software and may be modified and redistributed under the same terms as Perl itself.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Dispatcher.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,93 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart::Dispatcher;
+use Jifty::Dispatcher -base;
+
+use Jifty::YAML;
+
+=head1 NAME
+
+Jifty::Plugin::Chart::Dispatcher - Dispatcher for the chart API plugin
+
+=head1 RULES
+
+=head2 chart/chart/*
+
+Grabs the chart configuration stored in the key indicated in C<$1> and unpacks it using L<YAML>. It then passes it to the L<Jifty::Plugin::Chart::View/chart> template.
+
+=cut
+
+on 'chart/chart/*' => run {
+    # Create a session ID to lookup the chart configuration
+    my $session_id = 'chart_' . $1;
+
+    # Unpack the data and then clear it from the session
+    my $args = Jifty::YAML::Load( Jifty->web->session->get( $session_id ) );
+    Jifty->web->session->remove( $session_id );
+
+    # No data? Act like a 404
+    last_rule unless defined $args;
+
+    # Use the "type" to determine which class to use
+    my $class = 'Chart::' . $args->{type};
+
+    # Load that class or die if it does not exist
+    $class->require;
+
+    # Remember the class name for the view
+    $args->{class} = $class;
+
+    # Send them on to chart the chart
+    set 'args' => $args;
+    show 'chart/chart'
+};
+
+=head2 chart/gd_graph/*
+
+Grabs the chart configuration stored in the key indicated in C<$1> and unpacks it using L<YAML>. It then passes it to the L<Jifty::Plugin::Chart::View/chart> template.
+
+=cut
+
+on 'chart/gd_graph/*' => run {
+    # Create a session ID to lookup the chart configuration
+    my $session_id = 'chart_' . $1;
+
+    # Unpack the data and then clear it from the session
+    my $args = Jifty::YAML::Load( Jifty->web->session->get( $session_id ) );
+    Jifty->web->session->remove( $session_id );
+
+    # No data? Act like a 404
+    last_rule unless defined $args;
+
+    # Use the "type" to determine which class to use
+    my $class = 'GD::Graph::' . $args->{type};
+
+    # Load that class or die if it does not exist
+    $class->require;
+
+    # Remember the class name for the view
+    $args->{class} = $class;
+
+    # Send them on to chart the chart
+    set 'args' => $args;
+    show 'chart/gd_graph'
+};
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Chart::View>
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp C<< <andrew.hanenkamp at boomer.com> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Boomer Consulting, Inc.
+
+This is free software and may be modified and redistributed under the same terms as Perl itself.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,68 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart::Renderer;
+
+=head1 NAME
+
+Jifty::Plugin::Chart::Renderer - Base class for chart rendering classes
+
+=head1 SYNOPSIS
+
+In your F<config.yml>:
+
+  Plugins:
+    - Chart:
+        renderer: MyApp::Renderer;
+
+In F<lib/MyApp/Renderer.pm>:
+
+  package MyApp::Renderer;
+  use base qw/ Jifty::Plugin::Chart::Renderer /;
+
+  sub render {
+      my $self = shift;
+      my %args = (
+          type   => 'points',
+          width  => 400,
+          height => 300,
+          data   => [],
+          @_,
+      );
+
+      # Output your chart
+      Jifty->web->out( #{ Output your chart here... } );
+
+      # You could also return it as a string...
+      return;
+  }
+
+=head1 METHODS
+
+Your renderer implementation must subclass this package and implement the following methods:
+
+=head2 render
+
+  Jifty->web->out($renderer->render(%args));
+
+See L<Jifty::Plugin::Chart::Web> for the arguments. It must (at least) accept the arguments given to the L<Jifty::Plugin::Chart::Web/chart> method.
+
+The C<render> method may either return it's output or print it out using L<Jifty::Web::out>.
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Chart::Web>, L<Jifty::Plugin::Chart::Renderer::Chart>
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp C<< <andrew.hanenkamp at boomer.com> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Boomer Consulting, Inc.
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/Chart.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/Chart.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,60 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart::Renderer::Chart;
+use base qw/ Jifty::Plugin::Chart::Renderer /;
+
+use Jifty::YAML;
+
+=head1 NAME
+
+Jifty::Plugin::Chart::Renderer::Chart - A chart renderer using PNG charts
+
+=head1 DESCRIPTION
+
+This is the default chart renderer used by the L<Jifty::Plugin::Chart> plugin. It works by rendering an IMG tag in the HTML output, which then points to a URL which, when dispatched, retrieves the stored configuration and renders the chart using the L<Chart> package.
+
+=head1 METHODS
+
+=head2 render
+
+Implemented the L<Jifty::Plugin::Chart::Renderer/render> method interface.
+
+=cut
+
+sub render {
+    my $self = shift;
+    my %args = @_;
+
+    # Make sure the type is ready to be used as a class name
+    $args{type} = ucfirst lc $args{type};
+
+    # Save the data for retrieval from the session later
+    my $chart_id   = Jifty->web->serial;
+    my $session_id = 'chart_' . $chart_id;
+    Jifty->web->session->set( $session_id => Jifty::YAML::Dump(\%args) );
+
+    # Output the <img> tag and include the chart's configuration key
+    Jifty->web->out(qq{<img src="/chart/chart/$chart_id" width="$args{width}" height="$args{height}"/>});
+
+    # Make sure we don't return anything that will get output
+    return;
+}
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Chart>, L<Jifty::Plugin::Chart::Renderer>
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp C<< <andrew.hanenkamp at boomer.com> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Boomer Consulting, Inc.
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/GD/Graph.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/GD/Graph.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,62 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart::Renderer::GD::Graph;
+use base qw/ Jifty::Plugin::Chart::Renderer /;
+
+=head1 NAME
+
+Jifty::Plugin::Chart::Renderer::GD::Graph - A chart renderer using GD::Graph
+
+=head1 SYNOPSIS
+
+In F<config.yml>:
+
+  Plugins:
+    - Chart:
+        renderer: Jifty::Plugin::Chart::Renderer::GD::Graph
+
+=head1 DESCRIPTION
+
+This is a chart renderer that uses L<GD::Graph> to build charts.
+
+=head1 METHODS
+
+=head2 render
+
+Renders an IMG tag referring to the L<GD::Graph> image view.
+
+=cut
+
+sub render {
+    my $self = shift;
+    my %args = @_;
+
+    # Convert the type to lowercase
+    $args{type} = lc $args{type};
+
+    # Save the data for retrieval from the session later
+    my $chart_id   = Jifty->web->serial;
+    my $session_id = 'chart_' . $chart_id;
+    Jifty->web->session->set( $session_id => Jifty::YAML::Dump(\%args) );
+
+    # Output the <img> tag and include the chart's configuration key
+    Jifty->web->out(qq{<img src="/chart/gd_graph/$chart_id" width="$args{width}" height="$args{height}"/>});
+
+    # Make sure we don't return anything that will get output
+    return;
+}
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp C<< <andrew.hanenkamp at boomer.com> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Boomer Consulting, Inc.
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/PlotKit.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Renderer/PlotKit.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,114 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart::Renderer::PlotKit;
+use base qw/ Jifty::Plugin::Chart::Renderer /;
+
+use Jifty::YAML;
+
+=head1 NAME
+
+Jifty::Plugin::Chart::Renderer::PlotKit - A chart renderer using PlotKit
+
+=head1 DESCRIPTION
+
+This is an alternate chart renderer used by the L<Jifty::Plugin::Chart> plugin. It works by rendering a <div> tag in the HTML output and some JavaScript in a <script> tag.
+
+=head1 METHODS
+
+=head2 render
+
+Implemented the L<Jifty::Plugin::Chart::Renderer/render> method interface.
+
+=cut
+
+sub render {
+    my $self = shift;
+    my %args = ( options => {}, @_ );
+
+    # Turn any subs into values returned
+    for my $key (keys %args) {
+        $args{$key} = $args{$key}->(\%args) if ref $args{$key} eq 'CODE';
+    }
+
+    my %types = (
+        Lines   => 'line',
+        Bars    => 'bar',
+        Pie     => 'pie',
+    );
+
+    # Make sure the type is ready to be used
+    $args{type} = $types{ ucfirst lc $args{type} } || undef;
+
+    if ( not defined $args{type} ) {
+        Jifty->log->warn("Unsupported chart type: $args{type}!");
+        return;
+    }
+
+    $self->_transform_data( \%args );
+
+    # Save the data for retrieval from the session later
+    my $chart_id   = 'chart_' . Jifty->web->serial;
+
+    # Output the <canvas> tag and include the chart's JS
+    Jifty->web->out(<<"    END_OF_HTML");
+<div id="$chart_id" height="$args{height}" width="$args{width}"></div>
+
+<script type="text/javascript">
+var plot = function() {
+    var plotter = PlotKit.EasyPlot(
+        "$args{type}",
+        @{[Jifty::JSON::objToJson( $args{options} )]},
+        \$("$chart_id"),
+        @{[Jifty::JSON::objToJson( $args{data} )]}
+    );
+};
+YAHOO.util.Event.addListener( window, "load", plot );
+</script>
+    END_OF_HTML
+
+    # Make sure we don't return anything that will get output
+    return;
+}
+
+sub _transform_data {
+    my $self = shift;
+    my $args = shift;
+
+    my @data;
+    my $labels = shift @{ $args->{data} };
+
+    for ( my $i = 0; $i < @$labels; $i++ ) {
+        push @{$args->{options}{xTicks}}, { v => $i, label => $labels->[$i] }
+            if defined $labels->[$i];
+    }
+    
+    for my $dataset ( @{ $args->{data} } ) {
+        my @ds;
+        for ( my $i = 0; $i < @$dataset; $i++ ) {
+            # PlotKit can't deal with undefined values
+            push @ds, [ $i, defined $dataset->[$i] ? $dataset->[$i] : '0' ];
+        }
+        push @data, \@ds;
+    }
+
+    $args->{data} = \@data;
+}
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Chart>, L<Jifty::Plugin::Chart::Renderer>
+
+=head1 AUTHOR
+
+Thomas Sibley
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Best Practical Solutions, LLC
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/View.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,88 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart::View;
+use Jifty::View::Declare -base;
+
+=head1 NAME
+
+Jifty::Plugin::Chart::View - Views for the renderers built into the Chart plugin
+
+=head1 TEMPLATES
+
+=head2 chart/chart
+
+This shows a chart using L<Chart>. It expects to find the arguments in the C<args> parameter, which is setup for it in L<Jifty::Plugin::Chart::Dispatcher>.
+
+This will output a PNG file unless there is an error building the chart.
+
+=cut
+
+template 'chart/chart' => sub {
+    # Load the arguments
+    my $args = get 'args';
+
+    # Set the output type to the PNG file type
+    Jifty->handler->apache->content_type('image/png');
+
+    # Render the chart and output the PNG file generated
+    eval {
+        my $chart = $args->{class}->new( $args->{width}, $args->{height} );
+        # XXX scalar_png() is undocumented!!! Might bad to rely upon.
+        outs_raw($chart->scalar_png($args->{data}));
+    };
+
+    # Should have thrown an error if bad stuff happened, handle that
+    if ($@) {
+        Jifty->log->error("Failed to render chart: $@");
+        die $@;
+    }
+};
+
+=head2 chart/gd_graph
+
+This shows a chart using L<GD::Graph>. It expects to find the arguments in the C<args> parameter, which is setup for it in L<Jifty::Plugin::Chart::Dispatcher>.
+
+This will output a PNG file unless there is an error building the chart.
+
+=cut
+
+template 'chart/gd_graph' => sub {
+    # Load the arguments
+    my $args = get 'args';
+
+    # Set the output type to the PNG file type
+    Jifty->handler->apache->content_type('image/png');
+
+    # Render the chart and output the PNG file generated
+    eval {
+        my $graph = $args->{class}->new( $args->{width}, $args->{height} );
+        my $gd    = $graph->plot($args->{data})
+            or die $graph->error;
+        outs_raw($gd->png);
+    };
+
+    # Should have thrown an error if bad stuff happened, handle that
+    if ($@) {
+        Jifty->log->error("Failed to render chart: $@");
+        die $@;
+    }
+};
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Chart::Dispatcher>
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp C<< <andrew.hanenkamp at boomer.com> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Boomer Consulting, Inc.
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Web.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Chart/Web.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,129 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Chart::Web;
+
+=head1 NAME
+
+Jifty::Plugin::Chart::Web - Base class to add to Jifty::Web's ISA
+
+=head1 DESCRIPTION
+
+When the L<Jifty::Plugin::Chart> is loaded, this class is added as a base class for L<Jifty::Web> to add the L</chart> method to that class.
+
+=head1 METHODS
+
+=head2 chart
+
+  Jifty->web->out(Jifty->web->chart(%args));
+
+The arguments passed in C<%args> may include:
+
+=over
+
+=item type
+
+This will be one of the following scalar values indicating the kind of chart:
+
+=over
+
+=item Points
+
+This is the default value. A scatter plot with each dataset represented using differnet dot styles.
+
+=item Lines
+
+A line plot with each dataset presented as separate line.
+
+=item Bars
+
+A bar chart with each dataset set side-by-side.
+
+=item StackedBars
+
+A bar chart with each dataset stacked on top of each other.
+
+=item Pie
+
+A pie chart with a single dataset representing the values for different pieces of the pie.
+
+=item HorizontalBars
+
+A bar chart turned sideways.
+
+=back
+
+=item width
+
+The width, in pixels, the chart should take on the page. Defaults to 400.
+
+=item height
+
+The height, in pixels, the chart should take on the page. Defaults to 300.
+
+=item data
+
+An array of arrays containing the data. The first array in the parent array is a list of labels. Each following array is the set of data points matching each label in the first array.
+
+Defaults to no data (i.e., it must be given if anything useful is to happen).
+
+=back
+
+Here's an example:
+
+  <% Jifty->web->chart(
+      type   => 'Pie',
+      width  => 400,
+      height => 300,
+      data   => sub {
+          [
+              [ 2004, 2005, 2006, 2007 ],
+              [ 26, 37, 12, 42 ]
+          ];
+      },
+  ) %>
+
+Be sure to output anything returned by the method (unless it returns undef).
+
+=cut
+
+sub chart {
+    my $self = shift;
+    my ($plugin) = Jifty->find_plugin('Jifty::Plugin::Chart');
+
+    # TODO It might be a good idea to make this config.yml-able
+    # Setup the defaults
+    my %args = (
+        type   => 'points',
+        width  => 400,
+        height => 300,
+        data   => [],
+        @_,
+    );
+
+    # Turn any subs into values returned
+    for my $key (keys %args) {
+        $args{$key} = $args{$key}->(\%args) if ref $args{$key} eq 'CODE';
+    }
+
+    # Call the rendering plugin's render method
+    return $plugin->renderer->render(%args);
+}
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Chart>, L<Jifty::Plugin::Chart::Renderer>
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp C<< <andrew.hanenkamp at boomer.com> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Boomer Consulting, Inc.
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/Widget.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/Widget.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/Widget.pm	Thu Aug  2 11:50:22 2007
@@ -14,6 +14,13 @@
 
 =cut
 
+=head2 accessors
+
+Returns this class's Clas::Accessor based accessors
+
+=cut
+
+
 sub accessors { shift->SUPER::accessors() };
 
 =head2 render_widget

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm	Thu Aug  2 11:50:22 2007
@@ -215,6 +215,11 @@
     elsif ($accept =~ /j(?:ava)?s|ecmascript/i) {
         $apache->header_out('Content-Type' => 'application/javascript; charset=UTF-8');
         $apache->send_http_header;
+	# XXX: temporary hack to fix _() that aren't respected by json dumper
+	for (values %{$_[0]}) {
+	    $_->{label} = "$_->{label}" if exists $_->{label} && defined ref $_->{label};
+	    $_->{hints} = "$_->{hints}" if exists $_->{hints} && defined ref $_->{hints};
+	}
         print 'var $_ = ', Jifty::JSON::objToJson( @_, { singlequote => 1 } );
     }
     elsif ($accept =~ qr{^(?:application/x-)?(?:perl|pl)$}i) {
@@ -592,6 +597,7 @@
     label
     hints
     mandatory
+    ajax_validates
     length
 );
 

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm	Thu Aug  2 11:50:22 2007
@@ -42,7 +42,7 @@
         Jifty->web->navigation->render_as_menu; };
 };
 
-template '__jifty/empty' => sub {
+template '__jifty/empty' => sub :Static {
         '';
 };
 

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/UUID.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/UUID.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,46 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::UUID;
+use base qw/Jifty::Plugin Class::Accessor::Fast/;
+
+=head1 NAME
+
+Jifty::Plugin::UUID
+
+=head1 SYNOPSIS
+
+In your model class schema description, add the following:
+
+    column photo => is UUID;
+
+
+=head1 DESCRIPTION
+
+This plugin provides user pictures for Jifty;
+
+
+=cut
+
+use Jifty::DBI::Schema;
+use Data::UUID;
+use Scalar::Defer;
+my $UUID_GEN = Data::UUID->new();
+
+my $UUID = lazy { $UUID_GEN->create_str() } ;
+sub _uuid {
+    my ($column, $from) = @_;
+    $column->readable(1);
+    $column->writable(1);
+    $column->default($UUID);
+    $column->type('varchar(32)');
+}
+
+Jifty::DBI::Schema->register_types(
+    UUID => sub {  _init_handler is \&_uuid,  render_as 'Jifty::Plugin::UUID::Widget'},
+);
+
+
+
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/UUID/Widget.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/UUID/Widget.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,43 @@
+use strict;
+use warnings;
+
+
+package Jifty::Plugin::UUID::Widget;
+
+use base qw/Jifty::Web::Form::Field/;
+
+=head1 NAME
+
+Jifty::Plugin::UUID::Widget - 
+
+=head1 METHODS
+
+
+=cut
+
+sub accessors { shift->SUPER::accessors() };
+
+=head2 render_widget
+
+Renders form fields as a uuid;
+
+=cut
+
+sub render_widget {
+    warn "Rendering form field";
+    my $self     = shift;
+    my $action   = $self->action;
+    my $readonly = 1;
+    
+        my $name = $self->name;
+    if ( $action->record->$name() ) {
+        Jifty->web->out(  $action->record->$name() );
+    } else { 
+        Jifty->web->out("<i>"._('No value yet')."</i>");
+
+    }
+    '';
+}
+
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm	Thu Aug  2 11:50:22 2007
@@ -4,8 +4,7 @@
 use warnings;
 use base qw/Exporter Jifty::View::Declare::Helpers/;
 use Scalar::Defer;
-use Template::Declare::Tags;
-
+use PadWalker;
 
 use Jifty::View::Declare::Helpers;
 
@@ -54,6 +53,40 @@
     }
 }
 
+sub _actual_td_code {
+    my $class = shift;
+    my $path = shift;
+    my $code = Template::Declare->resolve_template($path) or return;
+    my $closed_over = PadWalker::closed_over($code)->{'$coderef'};
+    return $closed_over ? $$closed_over : $code;
+}
+
+use Attribute::Handlers;
+my (%Static, %Action);
+sub Static :ATTR(CODE,BEGIN) {
+    $Static{$_[2]}++;
+}
+
+sub Action :ATTR(CODE,BEGIN) {
+    $Action{$_[2]}++;
+}
+
+=head2 client_cacheable
+
+Returns the type of cacheable object for client
+
+=cut
+
+sub client_cacheable {
+    my $self = shift;
+    my $path = shift;
+    my $code = $self->_actual_td_code($path) or return;
+
+    return 'static' if $Static{$code};
+    return 'action' if $Action{$code};
+    return;
+}
+
 
 =head2 show templatename arguments
 

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm	Thu Aug  2 11:50:22 2007
@@ -4,6 +4,14 @@
 package Jifty::View::Declare::CRUD;
 use Jifty::View::Declare -base;
 
+# XXX: should register 'template type' handler, so the
+# client_cache_content & the TD sub here agrees with the arguments.
+use Attribute::Handlers;
+my %VIEW;
+sub CRUDView :ATTR(CODE,BEGIN) {
+    $VIEW{$_[2]}++;
+}
+
 
 =head1 NAME
 
@@ -38,6 +46,19 @@
     *{$vclass."::object_type"} = sub { $model };
 }
 
+sub _dispatch_template {
+    my $class = shift;
+    my $code  = shift;
+    if ($VIEW{$code} && !UNIVERSAL::isa($_[0], 'Evil')) {
+	my ( $object_type, $id ) = ( $class->object_type, get('id') );
+	@_ = ($class, $class->_get_record($id), @_);
+    }
+    else {
+	unshift @_, $class;
+    }
+    goto $code;
+}
+
 
 =head2 object_type
 
@@ -163,26 +184,23 @@
         }
 };
 
-
 =head2 view
 
 This template displays the data held by a single model record.
 
 =cut
 
-template 'view' => sub {
-    my $self = shift;
-    my ( $object_type, $id ) = ( $self->object_type, get('id') );
-      my $record =   $self->_get_record($id);
+template 'view' => sub :CRUDView {
+    my ($self, $record) = @_;
     my $update = new_action(
-        class   => 'Update' . $object_type,
+        class   => 'Update' . $self->object_type,
         moniker => "update-" . Jifty->web->serial,
-        record  => $record 
+        record  => $record,
     );
 
     div {
         { class is 'crud read item inline' };
-        my @fields =$self->display_columns($update);
+        my @fields = $self->display_columns($update);
         render_action( $update, \@fields, { render_mode => 'read' } );
 
         show ('./view_item_controls', $record, $update); 
@@ -202,7 +220,7 @@
             class   => "editlink",
             onclick => {
                 replace_with => $self->fragment_for('update'),
-                args         => { object_type => $self->object_type, id => $record->id }
+                args         => { id => $record->id }
             },
         );
     }
@@ -317,6 +335,13 @@
 
 };
 
+=head2 per_page
+
+This routine returns how many items should be shown on each page of a listing.
+The default is 25.
+
+=cut
+
 sub per_page { 25 }
 
 sub _current_collection {

Added: jifty/branches/autoversioning/lib/Jifty/View/Declare/Compile.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/Compile.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,210 @@
+package Jifty::View::Declare::Compile;
+use strict;
+use base 'B::Deparse';
+use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
+	 OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST
+	 OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL OPf_MOD
+	 OPpLVAL_INTRO OPpOUR_INTRO OPpENTERSUB_AMPER OPpSLICE OPpCONST_BARE
+	 OPpTRANS_SQUASH OPpTRANS_DELETE OPpTRANS_COMPLEMENT OPpTARGET_MY
+	 OPpCONST_ARYBASE OPpEXISTS_SUB OPpSORT_NUMERIC OPpSORT_INTEGER
+	 OPpSORT_REVERSE OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED
+	 SVf_IOK SVf_NOK SVf_ROK SVf_POK SVpad_OUR SVf_FAKE SVs_RMG SVs_SMG
+         CVf_METHOD CVf_LOCKED CVf_LVALUE CVf_ASSERTION
+	 PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE PMf_SKIPWHITE
+	 PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED);
+BEGIN {
+    die "You need a custom version of B::Deparse from http://svn.jifty.org/svn/jifty.org/B/"
+        unless B::Deparse->can('e_method')
+}
+sub is_scope { goto \&B::Deparse::is_scope }
+sub is_state { goto \&B::Deparse::is_state }
+sub null { goto \&B::Deparse::null }
+
+sub padname {
+    my $self = shift;
+    my $targ = shift;
+    return substr($self->padname_sv($targ)->PVX, 1);
+}
+
+require CGI;
+our %TAGS = (
+    map { $_ => +{} }
+        map {@{$_||[]}} @CGI::EXPORT_TAGS{qw/:html2 :html3 :html4 :netscape :form/}
+);
+
+sub deparse {
+    my $self = shift;
+    my $ret = $self->SUPER::deparse(@_);
+    return '' if $ret =~ m/use (strict|warnings)/;
+    return $ret;
+}
+
+sub loop_common {
+    my $self = shift;
+    my($op, $cx, $init) = @_;
+    my $enter = $op->first;
+    my $kid = $enter->sibling;
+    if ($enter->name eq "enteriter") { # foreach
+	my $ary = $enter->first->sibling; # first was pushmark
+	my $var = $ary->sibling;
+
+	if ($ary->name eq 'null' and $enter->private & OPpITER_REVERSED) {
+	    # "reverse" was optimised away
+	    return $self->SUPER::loop_common(@_);
+	} elsif ($enter->flags & OPf_STACKED
+	    and not null $ary->first->sibling->sibling)
+	{
+	    return $self->SUPER::loop_common(@_);
+	} else {
+	    $ary = $self->deparse($ary, 1);
+	}
+
+	if (null $var) {
+	    if ($enter->flags & OPf_SPECIAL) { # thread special var
+		$var = $self->pp_threadsv($enter, 1);
+	    } else { # regular my() variable
+		$var = $self->padname($enter->targ);
+	    }
+	} elsif ($var->name eq "rv2gv") {
+	    $var = $self->pp_rv2sv($var, 1);
+	    if ($enter->private & OPpOUR_INTRO) {
+		# our declarations don't have package names
+		$var =~ s/^(.).*::/$1/;
+		$var = "our $var";
+	    }
+	} elsif ($var->name eq "gv") {
+	    $var = $self->deparse($var, 1);
+	    $var = '$' . $var if $var eq '_';
+	}
+	else {
+	    return $self->SUPER::loop_common(@_);
+	}
+
+
+	my $body = $kid->first->first->sibling; # skip OP_AND and OP_ITER
+	# statement() foreach (@foo);
+	if (!is_state $body->first and $body->first->name ne "stub") {
+	    Carp::confess unless $var eq '$_';
+	    $body = $body->first;
+	    return "$ary.each(function (\$_) {".$self->deparse($body, 2)."} )";
+	}
+	# XXX not handling cont block here yet
+	return "$ary.each(function ($var) {".$self->deparse($body, 0)."} )";
+    }
+    return $self->SUPER::loop_common(@_);
+}
+
+sub maybe_my {
+    my $self = shift;
+    my($op, $cx, $text) = @_;
+    if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) {
+	if (B::Deparse::want_scalar($op)) {
+	    return "var $text";
+	} else {
+	    return $self->maybe_parens_func("my", $text, $cx, 16);
+	}
+    } else {
+	return $text;
+    }
+}
+
+sub maybe_parens_func {
+    my $self = shift;
+    my($func, $text, $cx, $prec) = @_;
+    return "$func($text)";
+
+}
+
+sub const {
+    my $self = shift;
+    my($sv, $cx) = @_;
+    if (class($sv) eq "NULL") {
+       return 'null';
+    }
+    return $self->SUPER::const(@_);
+}
+
+sub pp_undef { 'null' }
+sub pp_sne { shift->binop(@_, "!=", 14) }
+sub pp_grepwhile { shift->mapop(@_, "grep") }
+
+sub mapop {
+    my $self = shift;
+    my($op, $cx, $name) = @_;
+    return $self->SUPER::mapop(@_) unless $name eq 'grep';
+    my($expr, @exprs);
+    my $kid = $op->first; # this is the (map|grep)start
+    $kid = $kid->first->sibling; # skip a pushmark
+    my $code = $kid->first; # skip a null
+    if (is_scope $code) {
+	$code = "{" . $self->deparse($code, 0) . "} ";
+    } else {
+	$code = $self->deparse($code, 24) . ", ";
+    }
+    $kid = $kid->sibling;
+    for (; !null($kid); $kid = $kid->sibling) {
+	$expr = $self->deparse($kid, 6);
+	push @exprs, $expr if defined $expr;
+    }
+    return "(".join(", ", @exprs).").select(function (\$_) $code)";
+}
+
+sub e_anoncode {
+    my ($self, $info) = @_;
+    my $text = $self->deparse_sub($info->{code});
+    return "function () " . $text;
+}
+
+sub e_anonhash {
+    my ($self, $info) = @_;
+    my @exprs = @{$info->{exprs}};
+    my @pairs;
+    while (my @p = splice(@exprs, 0, 2)) {
+	push @pairs, join(': ', map { $self->deparse($_, 6) } @p);
+    }
+    return '{' . join(", ", @pairs) . '}';
+}
+
+sub pp_entersub {
+    my $self = shift;
+    my $ret = $self->SUPER::pp_entersub(@_);
+    $ret =~ s/return\s*\((.*)\)/return [$1]/ if $ret =~ m/^attr/;
+
+    return $ret;
+}
+
+sub e_method {
+    my ($self, $info) = @_;
+    my $obj = $info->{object};
+    if ($obj->name eq 'const') {
+        $obj = $self->const_sv($obj)->PV;
+    }
+    else {
+        $obj = $self->deparse($obj, 24);
+    }
+
+    my $meth = $info->{method};
+    $meth = $self->deparse($meth, 1) if $info->{variable_method};
+    my $args = join(", ", map { $self->deparse($_, 6) } @{$info->{args}} );
+    my $kid = $obj . "." . $meth;
+    return $kid . "(" . $args . ")"; # parens mandatory
+}
+
+sub walk_lineseq {
+    my ($self, $op, $kids, $callback) = @_;
+    my $xcallback = $callback;
+    if ((!$op || $op->next->name eq 'grepwhile') && $kids->[-1]->name ne 'return') {
+	$callback = sub { my ($expr, $index) = @_;
+			  $expr = "return ($expr)" if $index == $#{$kids};
+			  $xcallback->($expr, $index) };
+    }
+    $self->SUPER::walk_lineseq($op, $kids, $callback);
+}
+
+sub compile_to_js {
+    my $class = shift;
+    my $code = shift;
+    return 'function() '.$class->new->coderef2text($code);
+}
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm	Thu Aug  2 11:50:22 2007
@@ -2,10 +2,10 @@
 use strict;
 
 package Jifty::View::Declare::Helpers;
-use base qw/Template::Declare Exporter/;
 use Template::Declare::Tags;
+use base qw/Template::Declare Exporter/;
 
-our @EXPORT = ( qw(form hyperlink tangent redirect new_action form_submit form_return form_next_page page content wrapper request get set render_param current_user render_action render_region), @Template::Declare::Tags::EXPORT);
+our @EXPORT = ( qw(hyperlink tangent redirect new_action form_submit form_return form_next_page page content wrapper request get set render_param current_user render_action render_region), @Template::Declare::Tags::EXPORT);
 
 =head1 NAME
 
@@ -29,7 +29,7 @@
 
  {
     no warnings qw/redefine/;
-    sub form (&) {
+    sub form (&;$) {
         my $code = shift;
 
         smart_tag_wrapper {

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/Page.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/Page.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/Page.pm	Thu Aug  2 11:50:22 2007
@@ -2,7 +2,6 @@
 use strict;
 use warnings;
 use base qw/Template::Declare Class::Accessor::Fast/;
-use Template::Declare::Tags;
 
 =head1 NAME
 

Modified: jifty/branches/autoversioning/lib/Jifty/Web.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web.pm	Thu Aug  2 11:50:22 2007
@@ -50,6 +50,7 @@
     scriptaculous/effects.js
     scriptaculous/controls.js
     formatDate.js
+    template_declare.js
     jifty.js
     jifty_utils.js
     jifty_subs.js

Modified: jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm	Thu Aug  2 11:50:22 2007
@@ -384,4 +384,30 @@
     return "#region-" . $self->qualified_name . ' ' . join(' ', @_);
 }
 
+my $can_compile = eval 'use Jifty::View::Declare::Compile; 1' ? 1 : 0;
+
+=head2 client_cacheable
+
+=cut
+
+sub client_cacheable {
+    my $self = shift;
+    return unless $can_compile;
+
+    return Jifty::View::Declare::BaseClass->client_cacheable($self->path);
+}
+
+=head2 client_cacheable
+
+=cut
+
+sub client_cache_content {
+    my $self = shift;
+    return unless $can_compile;
+
+    return Jifty::View::Declare::Compile->compile_to_js(
+        Jifty::View::Declare::BaseClass->_actual_td_code($self->path)
+    );
+}
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Session.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Session.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Session.pm	Thu Aug  2 11:50:22 2007
@@ -5,6 +5,7 @@
 use base qw/Jifty::Object/;
 use CGI::Cookie ();
 use DateTime ();
+use Storable ();
  
 =head1 NAME
 
@@ -76,6 +77,41 @@
     $self->{cache} = undef;
 }
 
+=head2 load_by_kv key => value 
+
+Load up the current session from the given (key, value) pair. If no matching
+session could be found, it will create a new session with the key, value set.
+Be sure that what you're loading by is unique. If you're loading a session
+based on, say, a timestamp, then you're asking for trouble.
+
+=cut
+
+sub load_by_kv {
+    my $self = shift;
+    my $k    = shift;
+    my $v    = shift;
+    my $session_id;
+
+    # tried doing this with load_by_cols but it never returned any rows
+    my $sessions = Jifty::Model::SessionCollection->new;
+    $sessions->limit( column => 'key_type', value => 'key' );
+    $sessions->limit( column => 'data_key', value => $k );
+
+    # XXX TODO: we store this data in a storable. so we now want to match on the storable version
+    # It would be so nice if Jifty::DBI could do this for us.
+    $Storable::Deparse = 1;
+    my $value = Storable::nfreeze(\$v);
+
+    $sessions->limit( column => 'value' => value => $value );
+
+    while ( my $row = $sessions->next ) {
+        $session_id = $row->session_id;
+        last;
+    }
+    $self->load($session_id);
+    $self->set( $k => $v ) if !$session_id;
+}
+
 sub _get_session_id_from_client {
         my $self = shift;
         my %cookies    = CGI::Cookie->fetch();

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit/MochiKit.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit/MochiKit.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,4802 @@
+/***
+
+    MochiKit.MochiKit 1.3.1 : PACKED VERSION
+
+    THIS FILE IS AUTOMATICALLY GENERATED.  If creating patches, please
+    diff against the source tree, not this file.
+
+    See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+    (c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Base");
+}
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.Base)=="undefined"){
+MochiKit.Base={};
+}
+MochiKit.Base.VERSION="1.3.1";
+MochiKit.Base.NAME="MochiKit.Base";
+MochiKit.Base.update=function(_1,_2){
+if(_1===null){
+_1={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="undefined"&&o!==null){
+for(var k in o){
+_1[k]=o[k];
+}
+}
+}
+return _1;
+};
+MochiKit.Base.update(MochiKit.Base,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},counter:function(n){
+if(arguments.length===0){
+n=1;
+}
+return function(){
+return n++;
+};
+},clone:function(_7){
+var me=arguments.callee;
+if(arguments.length==1){
+me.prototype=_7;
+return new me();
+}
+},flattenArguments:function(_9){
+var res=[];
+var m=MochiKit.Base;
+var _12=m.extend(null,arguments);
+while(_12.length){
+var o=_12.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+for(var i=o.length-1;i>=0;i--){
+_12.unshift(o[i]);
+}
+}else{
+res.push(o);
+}
+}
+return res;
+},extend:function(_13,obj,_15){
+if(!_15){
+_15=0;
+}
+if(obj){
+var l=obj.length;
+if(typeof (l)!="number"){
+if(typeof (MochiKit.Iter)!="undefined"){
+obj=MochiKit.Iter.list(obj);
+l=obj.length;
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(!_13){
+_13=[];
+}
+for(var i=_15;i<l;i++){
+_13.push(obj[i]);
+}
+}
+return _13;
+},updatetree:function(_17,obj){
+if(_17===null){
+_17={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="undefined"&&o!==null){
+for(var k in o){
+var v=o[k];
+if(typeof (_17[k])=="object"&&typeof (v)=="object"){
+arguments.callee(_17[k],v);
+}else{
+_17[k]=v;
+}
+}
+}
+}
+return _17;
+},setdefault:function(_19,obj){
+if(_19===null){
+_19={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+for(var k in o){
+if(!(k in _19)){
+_19[k]=o[k];
+}
+}
+}
+return _19;
+},keys:function(obj){
+var _20=[];
+for(var _21 in obj){
+_20.push(_21);
+}
+return _20;
+},items:function(obj){
+var _22=[];
+var e;
+for(var _24 in obj){
+var v;
+try{
+v=obj[_24];
+}
+catch(e){
+continue;
+}
+_22.push([_24,v]);
+}
+return _22;
+},_newNamedError:function(_25,_26,_27){
+_27.prototype=new MochiKit.Base.NamedError(_25.NAME+"."+_26);
+_25[_26]=_27;
+},operator:{truth:function(a){
+return !!a;
+},lognot:function(a){
+return !a;
+},identity:function(a){
+return a;
+},not:function(a){
+return ~a;
+},neg:function(a){
+return -a;
+},add:function(a,b){
+return a+b;
+},sub:function(a,b){
+return a-b;
+},div:function(a,b){
+return a/b;
+},mod:function(a,b){
+return a%b;
+},mul:function(a,b){
+return a*b;
+},and:function(a,b){
+return a&b;
+},or:function(a,b){
+return a|b;
+},xor:function(a,b){
+return a^b;
+},lshift:function(a,b){
+return a<<b;
+},rshift:function(a,b){
+return a>>b;
+},zrshift:function(a,b){
+return a>>>b;
+},eq:function(a,b){
+return a==b;
+},ne:function(a,b){
+return a!=b;
+},gt:function(a,b){
+return a>b;
+},ge:function(a,b){
+return a>=b;
+},lt:function(a,b){
+return a<b;
+},le:function(a,b){
+return a<=b;
+},ceq:function(a,b){
+return MochiKit.Base.compare(a,b)===0;
+},cne:function(a,b){
+return MochiKit.Base.compare(a,b)!==0;
+},cgt:function(a,b){
+return MochiKit.Base.compare(a,b)==1;
+},cge:function(a,b){
+return MochiKit.Base.compare(a,b)!=-1;
+},clt:function(a,b){
+return MochiKit.Base.compare(a,b)==-1;
+},cle:function(a,b){
+return MochiKit.Base.compare(a,b)!=1;
+},logand:function(a,b){
+return a&&b;
+},logor:function(a,b){
+return a||b;
+},contains:function(a,b){
+return b in a;
+}},forwardCall:function(_30){
+return function(){
+return this[_30].apply(this,arguments);
+};
+},itemgetter:function(_31){
+return function(arg){
+return arg[_31];
+};
+},typeMatcher:function(){
+var _33={};
+for(var i=0;i<arguments.length;i++){
+var typ=arguments[i];
+_33[typ]=typ;
+}
+return function(){
+for(var i=0;i<arguments.length;i++){
+if(!(typeof (arguments[i]) in _33)){
+return false;
+}
+}
+return true;
+};
+},isNull:function(){
+for(var i=0;i<arguments.length;i++){
+if(arguments[i]!==null){
+return false;
+}
+}
+return true;
+},isUndefinedOrNull:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(!(typeof (o)=="undefined"||o===null)){
+return false;
+}
+}
+return true;
+},isEmpty:function(obj){
+return !MochiKit.Base.isNotEmpty.apply(this,arguments);
+},isNotEmpty:function(obj){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(!(o&&o.length)){
+return false;
+}
+}
+return true;
+},isArrayLike:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+var typ=typeof (o);
+if((typ!="object"&&!(typ=="function"&&typeof (o.item)=="function"))||o===null||typeof (o.length)!="number"){
+return false;
+}
+}
+return true;
+},isDateLike:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="object"||o===null||typeof (o.getTime)!="function"){
+return false;
+}
+}
+return true;
+},xmap:function(fn){
+if(fn===null){
+return MochiKit.Base.extend(null,arguments,1);
+}
+var _36=[];
+for(var i=1;i<arguments.length;i++){
+_36.push(fn(arguments[i]));
+}
+return _36;
+},map:function(fn,lst){
+var m=MochiKit.Base;
+var itr=MochiKit.Iter;
+var _39=m.isArrayLike;
+if(arguments.length<=2){
+if(!_39(lst)){
+if(itr){
+lst=itr.list(lst);
+if(fn===null){
+return lst;
+}
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(fn===null){
+return m.extend(null,lst);
+}
+var _40=[];
+for(var i=0;i<lst.length;i++){
+_40.push(fn(lst[i]));
+}
+return _40;
+}else{
+if(fn===null){
+fn=Array;
+}
+var _41=null;
+for(i=1;i<arguments.length;i++){
+if(!_39(arguments[i])){
+if(itr){
+return itr.list(itr.imap.apply(null,arguments));
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+var l=arguments[i].length;
+if(_41===null||_41>l){
+_41=l;
+}
+}
+_40=[];
+for(i=0;i<_41;i++){
+var _42=[];
+for(var j=1;j<arguments.length;j++){
+_42.push(arguments[j][i]);
+}
+_40.push(fn.apply(this,_42));
+}
+return _40;
+}
+},xfilter:function(fn){
+var _44=[];
+if(fn===null){
+fn=MochiKit.Base.operator.truth;
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(fn(o)){
+_44.push(o);
+}
+}
+return _44;
+},filter:function(fn,lst,_45){
+var _46=[];
+var m=MochiKit.Base;
+if(!m.isArrayLike(lst)){
+if(MochiKit.Iter){
+lst=MochiKit.Iter.list(lst);
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(fn===null){
+fn=m.operator.truth;
+}
+if(typeof (Array.prototype.filter)=="function"){
+return Array.prototype.filter.call(lst,fn,_45);
+}else{
+if(typeof (_45)=="undefined"||_45===null){
+for(var i=0;i<lst.length;i++){
+var o=lst[i];
+if(fn(o)){
+_46.push(o);
+}
+}
+}else{
+for(i=0;i<lst.length;i++){
+o=lst[i];
+if(fn.call(_45,o)){
+_46.push(o);
+}
+}
+}
+}
+return _46;
+},_wrapDumbFunction:function(_47){
+return function(){
+switch(arguments.length){
+case 0:
+return _47();
+case 1:
+return _47(arguments[0]);
+case 2:
+return _47(arguments[0],arguments[1]);
+case 3:
+return _47(arguments[0],arguments[1],arguments[2]);
+}
+var _48=[];
+for(var i=0;i<arguments.length;i++){
+_48.push("arguments["+i+"]");
+}
+return eval("(func("+_48.join(",")+"))");
+};
+},method:function(_49,_50){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([_50,_49],arguments,2));
+},bind:function(_51,_52){
+if(typeof (_51)=="string"){
+_51=_52[_51];
+}
+var _53=_51.im_func;
+var _54=_51.im_preargs;
+var _55=_51.im_self;
+var m=MochiKit.Base;
+if(typeof (_51)=="function"&&typeof (_51.apply)=="undefined"){
+_51=m._wrapDumbFunction(_51);
+}
+if(typeof (_53)!="function"){
+_53=_51;
+}
+if(typeof (_52)!="undefined"){
+_55=_52;
+}
+if(typeof (_54)=="undefined"){
+_54=[];
+}else{
+_54=_54.slice();
+}
+m.extend(_54,arguments,2);
+var _56=function(){
+var _57=arguments;
+var me=arguments.callee;
+if(me.im_preargs.length>0){
+_57=m.concat(me.im_preargs,_57);
+}
+var _52=me.im_self;
+if(!_52){
+_52=this;
+}
+return me.im_func.apply(_52,_57);
+};
+_56.im_self=_55;
+_56.im_func=_53;
+_56.im_preargs=_54;
+return _56;
+},bindMethods:function(_58){
+var _59=MochiKit.Base.bind;
+for(var k in _58){
+var _60=_58[k];
+if(typeof (_60)=="function"){
+_58[k]=_59(_60,_58);
+}
+}
+},registerComparator:function(_61,_62,_63,_64){
+MochiKit.Base.comparatorRegistry.register(_61,_62,_63,_64);
+},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){
+if(a==b){
+return 0;
+}
+var _65=(typeof (a)=="undefined"||a===null);
+var _66=(typeof (b)=="undefined"||b===null);
+if(_65&&_66){
+return 0;
+}else{
+if(_65){
+return -1;
+}else{
+if(_66){
+return 1;
+}
+}
+}
+var m=MochiKit.Base;
+var _67=m._primitives;
+if(!(typeof (a) in _67&&typeof (b) in _67)){
+try{
+return m.comparatorRegistry.match(a,b);
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+}
+if(a<b){
+return -1;
+}else{
+if(a>b){
+return 1;
+}
+}
+var _68=m.repr;
+throw new TypeError(_68(a)+" and "+_68(b)+" can not be compared");
+},compareDateLike:function(a,b){
+return MochiKit.Base.compare(a.getTime(),b.getTime());
+},compareArrayLike:function(a,b){
+var _69=MochiKit.Base.compare;
+var _70=a.length;
+var _71=0;
+if(_70>b.length){
+_71=1;
+_70=b.length;
+}else{
+if(_70<b.length){
+_71=-1;
+}
+}
+for(var i=0;i<_70;i++){
+var cmp=_69(a[i],b[i]);
+if(cmp){
+return cmp;
+}
+}
+return _71;
+},registerRepr:function(_73,_74,_75,_76){
+MochiKit.Base.reprRegistry.register(_73,_74,_75,_76);
+},repr:function(o){
+if(typeof (o)=="undefined"){
+return "undefined";
+}else{
+if(o===null){
+return "null";
+}
+}
+try{
+if(typeof (o.__repr__)=="function"){
+return o.__repr__();
+}else{
+if(typeof (o.repr)=="function"&&o.repr!=arguments.callee){
+return o.repr();
+}
+}
+return MochiKit.Base.reprRegistry.match(o);
+}
+catch(e){
+if(typeof (o.NAME)=="string"&&(o.toString==Function.prototype.toString||o.toString==Object.prototype.toString)){
+return o.NAME;
+}
+}
+try{
+var _77=(o+"");
+}
+catch(e){
+return "["+typeof (o)+"]";
+}
+if(typeof (o)=="function"){
+o=_77.replace(/^\s+/,"");
+var idx=o.indexOf("{");
+if(idx!=-1){
+o=o.substr(0,idx)+"{...}";
+}
+}
+return _77;
+},reprArrayLike:function(o){
+var m=MochiKit.Base;
+return "["+m.map(m.repr,o).join(", ")+"]";
+},reprString:function(o){
+return ("\""+o.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");
+},reprNumber:function(o){
+return o+"";
+},registerJSON:function(_79,_80,_81,_82){
+MochiKit.Base.jsonRegistry.register(_79,_80,_81,_82);
+},evalJSON:function(){
+return eval("("+arguments[0]+")");
+},serializeJSON:function(o){
+var _83=typeof (o);
+if(_83=="undefined"){
+return "undefined";
+}else{
+if(_83=="number"||_83=="boolean"){
+return o+"";
+}else{
+if(o===null){
+return "null";
+}
+}
+}
+var m=MochiKit.Base;
+var _84=m.reprString;
+if(_83=="string"){
+return _84(o);
+}
+var me=arguments.callee;
+var _85;
+if(typeof (o.__json__)=="function"){
+_85=o.__json__();
+if(o!==_85){
+return me(_85);
+}
+}
+if(typeof (o.json)=="function"){
+_85=o.json();
+if(o!==_85){
+return me(_85);
+}
+}
+if(_83!="function"&&typeof (o.length)=="number"){
+var res=[];
+for(var i=0;i<o.length;i++){
+var val=me(o[i]);
+if(typeof (val)!="string"){
+val="undefined";
+}
+res.push(val);
+}
+return "["+res.join(", ")+"]";
+}
+try{
+_85=m.jsonRegistry.match(o);
+return me(_85);
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+if(_83=="function"){
+return null;
+}
+res=[];
+for(var k in o){
+var _87;
+if(typeof (k)=="number"){
+_87="\""+k+"\"";
+}else{
+if(typeof (k)=="string"){
+_87=_84(k);
+}else{
+continue;
+}
+}
+val=me(o[k]);
+if(typeof (val)!="string"){
+continue;
+}
+res.push(_87+":"+val);
+}
+return "{"+res.join(", ")+"}";
+},objEqual:function(a,b){
+return (MochiKit.Base.compare(a,b)===0);
+},arrayEqual:function(_88,arr){
+if(_88.length!=arr.length){
+return false;
+}
+return (MochiKit.Base.compare(_88,arr)===0);
+},concat:function(){
+var _90=[];
+var _91=MochiKit.Base.extend;
+for(var i=0;i<arguments.length;i++){
+_91(_90,arguments[i]);
+}
+return _90;
+},keyComparator:function(key){
+var m=MochiKit.Base;
+var _93=m.compare;
+if(arguments.length==1){
+return function(a,b){
+return _93(a[key],b[key]);
+};
+}
+var _94=m.extend(null,arguments);
+return function(a,b){
+var _95=0;
+for(var i=0;(_95===0)&&(i<_94.length);i++){
+var key=_94[i];
+_95=_93(a[key],b[key]);
+}
+return _95;
+};
+},reverseKeyComparator:function(key){
+var _96=MochiKit.Base.keyComparator.apply(this,arguments);
+return function(a,b){
+return _96(b,a);
+};
+},partial:function(_97){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([_97,undefined],arguments,1));
+},listMinMax:function(_98,lst){
+if(lst.length===0){
+return null;
+}
+var cur=lst[0];
+var _100=MochiKit.Base.compare;
+for(var i=1;i<lst.length;i++){
+var o=lst[i];
+if(_100(o,cur)==_98){
+cur=o;
+}
+}
+return cur;
+},objMax:function(){
+return MochiKit.Base.listMinMax(1,arguments);
+},objMin:function(){
+return MochiKit.Base.listMinMax(-1,arguments);
+},findIdentical:function(lst,_101,_102,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+for(var i=(_102||0);i<end;i++){
+if(lst[i]===_101){
+return i;
+}
+}
+return -1;
+},findValue:function(lst,_104,_105,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+var cmp=MochiKit.Base.compare;
+for(var i=(_105||0);i<end;i++){
+if(cmp(lst[i],_104)===0){
+return i;
+}
+}
+return -1;
+},nodeWalk:function(node,_107){
+var _108=[node];
+var _109=MochiKit.Base.extend;
+while(_108.length){
+var res=_107(_108.shift());
+if(res){
+_109(_108,res);
+}
+}
+},nameFunctions:function(_110){
+var base=_110.NAME;
+if(typeof (base)=="undefined"){
+base="";
+}else{
+base=base+".";
+}
+for(var name in _110){
+var o=_110[name];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+name;
+}
+catch(e){
+}
+}
+}
+},queryString:function(_113,_114){
+if(typeof (MochiKit.DOM)!="undefined"&&arguments.length==1&&(typeof (_113)=="string"||(typeof (_113.nodeType)!="undefined"&&_113.nodeType>0))){
+var kv=MochiKit.DOM.formContents(_113);
+_113=kv[0];
+_114=kv[1];
+}else{
+if(arguments.length==1){
+var o=_113;
+_113=[];
+_114=[];
+for(var k in o){
+var v=o[k];
+if(typeof (v)!="function"){
+_113.push(k);
+_114.push(v);
+}
+}
+}
+}
+var rval=[];
+var len=Math.min(_113.length,_114.length);
+var _118=MochiKit.Base.urlEncode;
+for(var i=0;i<len;i++){
+v=_114[i];
+if(typeof (v)!="undefined"&&v!==null){
+rval.push(_118(_113[i])+"="+_118(v));
+}
+}
+return rval.join("&");
+},parseQueryString:function(_119,_120){
+var _121=_119.replace(/\+/g,"%20").split("&");
+var o={};
+var _122;
+if(typeof (decodeURIComponent)!="undefined"){
+_122=decodeURIComponent;
+}else{
+_122=unescape;
+}
+if(_120){
+for(var i=0;i<_121.length;i++){
+var pair=_121[i].split("=");
+var name=_122(pair[0]);
+var arr=o[name];
+if(!(arr instanceof Array)){
+arr=[];
+o[name]=arr;
+}
+arr.push(_122(pair[1]));
+}
+}else{
+for(i=0;i<_121.length;i++){
+pair=_121[i].split("=");
+o[_122(pair[0])]=_122(pair[1]);
+}
+}
+return o;
+}});
+MochiKit.Base.AdapterRegistry=function(){
+this.pairs=[];
+};
+MochiKit.Base.AdapterRegistry.prototype={register:function(name,_124,wrap,_126){
+if(_126){
+this.pairs.unshift([name,_124,wrap]);
+}else{
+this.pairs.push([name,_124,wrap]);
+}
+},match:function(){
+for(var i=0;i<this.pairs.length;i++){
+var pair=this.pairs[i];
+if(pair[1].apply(this,arguments)){
+return pair[2].apply(this,arguments);
+}
+}
+throw MochiKit.Base.NotFound;
+},unregister:function(name){
+for(var i=0;i<this.pairs.length;i++){
+var pair=this.pairs[i];
+if(pair[0]==name){
+this.pairs.splice(i,1);
+return true;
+}
+}
+return false;
+}};
+MochiKit.Base.EXPORT=["counter","clone","extend","update","updatetree","setdefault","keys","items","NamedError","operator","forwardCall","itemgetter","typeMatcher","isCallable","isUndefined","isUndefinedOrNull","isNull","isEmpty","isNotEmpty","isArrayLike","isDateLike","xmap","map","xfilter","filter","bind","bindMethods","NotFound","AdapterRegistry","registerComparator","compare","registerRepr","repr","objEqual","arrayEqual","concat","keyComparator","reverseKeyComparator","partial","merge","listMinMax","listMax","listMin","objMax","objMin","nodeWalk","zip","urlEncode","queryString","serializeJSON","registerJSON","evalJSON","parseQueryString","findValue","findIdentical","flattenArguments","method"];
+MochiKit.Base.EXPORT_OK=["nameFunctions","comparatorRegistry","reprRegistry","jsonRegistry","compareDateLike","compareArrayLike","reprArrayLike","reprString","reprNumber"];
+MochiKit.Base._exportSymbols=function(_127,_128){
+if(typeof (MochiKit.__export__)=="undefined"){
+MochiKit.__export__=(MochiKit.__compat__||(typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined"));
+}
+if(!MochiKit.__export__){
+return;
+}
+var all=_128.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_127[all[i]]=_128[all[i]];
+}
+};
+MochiKit.Base.__new__=function(){
+var m=this;
+m.forward=m.forwardCall;
+m.find=m.findValue;
+if(typeof (encodeURIComponent)!="undefined"){
+m.urlEncode=function(_130){
+return encodeURIComponent(_130).replace(/\'/g,"%27");
+};
+}else{
+m.urlEncode=function(_131){
+return escape(_131).replace(/\+/g,"%2B").replace(/\"/g,"%22").rval.replace(/\'/g,"%27");
+};
+}
+m.NamedError=function(name){
+this.message=name;
+this.name=name;
+};
+m.NamedError.prototype=new Error();
+m.update(m.NamedError.prototype,{repr:function(){
+if(this.message&&this.message!=this.name){
+return this.name+"("+m.repr(this.message)+")";
+}else{
+return this.name+"()";
+}
+},toString:m.forwardCall("repr")});
+m.NotFound=new m.NamedError("MochiKit.Base.NotFound");
+m.listMax=m.partial(m.listMinMax,1);
+m.listMin=m.partial(m.listMinMax,-1);
+m.isCallable=m.typeMatcher("function");
+m.isUndefined=m.typeMatcher("undefined");
+m.merge=m.partial(m.update,null);
+m.zip=m.partial(m.map,null);
+m.comparatorRegistry=new m.AdapterRegistry();
+m.registerComparator("dateLike",m.isDateLike,m.compareDateLike);
+m.registerComparator("arrayLike",m.isArrayLike,m.compareArrayLike);
+m.reprRegistry=new m.AdapterRegistry();
+m.registerRepr("arrayLike",m.isArrayLike,m.reprArrayLike);
+m.registerRepr("string",m.typeMatcher("string"),m.reprString);
+m.registerRepr("numbers",m.typeMatcher("number","boolean"),m.reprNumber);
+m.jsonRegistry=new m.AdapterRegistry();
+var all=m.concat(m.EXPORT,m.EXPORT_OK);
+m.EXPORT_TAGS={":common":m.concat(m.EXPORT_OK),":all":all};
+m.nameFunctions(this);
+};
+MochiKit.Base.__new__();
+if(!MochiKit.__compat__){
+compare=MochiKit.Base.compare;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Base);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Iter");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Iter depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.Iter)=="undefined"){
+MochiKit.Iter={};
+}
+MochiKit.Iter.NAME="MochiKit.Iter";
+MochiKit.Iter.VERSION="1.3.1";
+MochiKit.Base.update(MochiKit.Iter,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},registerIteratorFactory:function(name,_132,_133,_134){
+MochiKit.Iter.iteratorRegistry.register(name,_132,_133,_134);
+},iter:function(_135,_136){
+var self=MochiKit.Iter;
+if(arguments.length==2){
+return self.takewhile(function(a){
+return a!=_136;
+},_135);
+}
+if(typeof (_135.next)=="function"){
+return _135;
+}else{
+if(typeof (_135.iter)=="function"){
+return _135.iter();
+}
+}
+try{
+return self.iteratorRegistry.match(_135);
+}
+catch(e){
+var m=MochiKit.Base;
+if(e==m.NotFound){
+e=new TypeError(typeof (_135)+": "+m.repr(_135)+" is not iterable");
+}
+throw e;
+}
+},count:function(n){
+if(!n){
+n=0;
+}
+var m=MochiKit.Base;
+return {repr:function(){
+return "count("+n+")";
+},toString:m.forwardCall("repr"),next:m.counter(n)};
+},cycle:function(p){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+var lst=[];
+var _139=self.iter(p);
+return {repr:function(){
+return "cycle(...)";
+},toString:m.forwardCall("repr"),next:function(){
+try{
+var rval=_139.next();
+lst.push(rval);
+return rval;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+if(lst.length===0){
+this.next=function(){
+throw self.StopIteration;
+};
+}else{
+var i=-1;
+this.next=function(){
+i=(i+1)%lst.length;
+return lst[i];
+};
+}
+return this.next();
+}
+}};
+},repeat:function(elem,n){
+var m=MochiKit.Base;
+if(typeof (n)=="undefined"){
+return {repr:function(){
+return "repeat("+m.repr(elem)+")";
+},toString:m.forwardCall("repr"),next:function(){
+return elem;
+}};
+}
+return {repr:function(){
+return "repeat("+m.repr(elem)+", "+n+")";
+},toString:m.forwardCall("repr"),next:function(){
+if(n<=0){
+throw MochiKit.Iter.StopIteration;
+}
+n-=1;
+return elem;
+}};
+},next:function(_141){
+return _141.next();
+},izip:function(p,q){
+var m=MochiKit.Base;
+var next=MochiKit.Iter.next;
+var _144=m.map(iter,arguments);
+return {repr:function(){
+return "izip(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return m.map(next,_144);
+}};
+},ifilter:function(pred,seq){
+var m=MochiKit.Base;
+seq=MochiKit.Iter.iter(seq);
+if(pred===null){
+pred=m.operator.truth;
+}
+return {repr:function(){
+return "ifilter(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(true){
+var rval=seq.next();
+if(pred(rval)){
+return rval;
+}
+}
+return undefined;
+}};
+},ifilterfalse:function(pred,seq){
+var m=MochiKit.Base;
+seq=MochiKit.Iter.iter(seq);
+if(pred===null){
+pred=m.operator.truth;
+}
+return {repr:function(){
+return "ifilterfalse(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(true){
+var rval=seq.next();
+if(!pred(rval)){
+return rval;
+}
+}
+return undefined;
+}};
+},islice:function(seq){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+seq=self.iter(seq);
+var _147=0;
+var stop=0;
+var step=1;
+var i=-1;
+if(arguments.length==2){
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_147=arguments[1];
+stop=arguments[2];
+}else{
+_147=arguments[1];
+stop=arguments[2];
+step=arguments[3];
+}
+}
+return {repr:function(){
+return "islice("+["...",_147,stop,step].join(", ")+")";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+while(i<_147){
+rval=seq.next();
+i++;
+}
+if(_147>=stop){
+throw self.StopIteration;
+}
+_147+=step;
+return rval;
+}};
+},imap:function(fun,p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var _151=m.map(self.iter,m.extend(null,arguments,1));
+var map=m.map;
+var next=self.next;
+return {repr:function(){
+return "imap(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return fun.apply(this,map(next,_151));
+}};
+},applymap:function(fun,seq,self){
+seq=MochiKit.Iter.iter(seq);
+var m=MochiKit.Base;
+return {repr:function(){
+return "applymap(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return fun.apply(self,seq.next());
+}};
+},chain:function(p,q){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+if(arguments.length==1){
+return self.iter(arguments[0]);
+}
+var _153=m.map(self.iter,arguments);
+return {repr:function(){
+return "chain(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(_153.length>1){
+try{
+return _153[0].next();
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+_153.shift();
+}
+}
+if(_153.length==1){
+var arg=_153.shift();
+this.next=m.bind("next",arg);
+return this.next();
+}
+throw self.StopIteration;
+}};
+},takewhile:function(pred,seq){
+var self=MochiKit.Iter;
+seq=self.iter(seq);
+return {repr:function(){
+return "takewhile(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=seq.next();
+if(!pred(rval)){
+this.next=function(){
+throw self.StopIteration;
+};
+this.next();
+}
+return rval;
+}};
+},dropwhile:function(pred,seq){
+seq=MochiKit.Iter.iter(seq);
+var m=MochiKit.Base;
+var bind=m.bind;
+return {"repr":function(){
+return "dropwhile(...)";
+},"toString":m.forwardCall("repr"),"next":function(){
+while(true){
+var rval=seq.next();
+if(!pred(rval)){
+break;
+}
+}
+this.next=bind("next",seq);
+return rval;
+}};
+},_tee:function(_155,sync,_157){
+sync.pos[_155]=-1;
+var m=MochiKit.Base;
+var _158=m.listMin;
+return {repr:function(){
+return "tee("+_155+", ...)";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+var i=sync.pos[_155];
+if(i==sync.max){
+rval=_157.next();
+sync.deque.push(rval);
+sync.max+=1;
+sync.pos[_155]+=1;
+}else{
+rval=sync.deque[i-sync.min];
+sync.pos[_155]+=1;
+if(i==sync.min&&_158(sync.pos)!=sync.min){
+sync.min+=1;
+sync.deque.shift();
+}
+}
+return rval;
+}};
+},tee:function(_159,n){
+var rval=[];
+var sync={"pos":[],"deque":[],"max":-1,"min":-1};
+if(arguments.length==1){
+n=2;
+}
+var self=MochiKit.Iter;
+_159=self.iter(_159);
+var _tee=self._tee;
+for(var i=0;i<n;i++){
+rval.push(_tee(i,sync,_159));
+}
+return rval;
+},list:function(_161){
+var m=MochiKit.Base;
+if(typeof (_161.slice)=="function"){
+return _161.slice();
+}else{
+if(m.isArrayLike(_161)){
+return m.concat(_161);
+}
+}
+var self=MochiKit.Iter;
+_161=self.iter(_161);
+var rval=[];
+try{
+while(true){
+rval.push(_161.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return rval;
+}
+return undefined;
+},reduce:function(fn,_162,_163){
+var i=0;
+var x=_163;
+var self=MochiKit.Iter;
+_162=self.iter(_162);
+if(arguments.length<3){
+try{
+x=_162.next();
+}
+catch(e){
+if(e==self.StopIteration){
+e=new TypeError("reduce() of empty sequence with no initial value");
+}
+throw e;
+}
+i++;
+}
+try{
+while(true){
+x=fn(x,_162.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},range:function(){
+var _165=0;
+var stop=0;
+var step=1;
+if(arguments.length==1){
+stop=arguments[0];
+}else{
+if(arguments.length==2){
+_165=arguments[0];
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_165=arguments[0];
+stop=arguments[1];
+step=arguments[2];
+}else{
+throw new TypeError("range() takes 1, 2, or 3 arguments!");
+}
+}
+}
+if(step===0){
+throw new TypeError("range() step must not be 0");
+}
+return {next:function(){
+if((step>0&&_165>=stop)||(step<0&&_165<=stop)){
+throw MochiKit.Iter.StopIteration;
+}
+var rval=_165;
+_165+=step;
+return rval;
+},repr:function(){
+return "range("+[_165,stop,step].join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+},sum:function(_166,_167){
+var x=_167||0;
+var self=MochiKit.Iter;
+_166=self.iter(_166);
+try{
+while(true){
+x+=_166.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},exhaust:function(_168){
+var self=MochiKit.Iter;
+_168=self.iter(_168);
+try{
+while(true){
+_168.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+},forEach:function(_169,func,self){
+var m=MochiKit.Base;
+if(arguments.length>2){
+func=m.bind(func,self);
+}
+if(m.isArrayLike(_169)){
+try{
+for(var i=0;i<_169.length;i++){
+func(_169[i]);
+}
+}
+catch(e){
+if(e!=MochiKit.Iter.StopIteration){
+throw e;
+}
+}
+}else{
+self=MochiKit.Iter;
+self.exhaust(self.imap(func,_169));
+}
+},every:function(_171,func){
+var self=MochiKit.Iter;
+try{
+self.ifilterfalse(func,_171).next();
+return false;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return true;
+}
+},sorted:function(_172,cmp){
+var rval=MochiKit.Iter.list(_172);
+if(arguments.length==1){
+cmp=MochiKit.Base.compare;
+}
+rval.sort(cmp);
+return rval;
+},reversed:function(_173){
+var rval=MochiKit.Iter.list(_173);
+rval.reverse();
+return rval;
+},some:function(_174,func){
+var self=MochiKit.Iter;
+try{
+self.ifilter(func,_174).next();
+return true;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return false;
+}
+},iextend:function(lst,_175){
+if(MochiKit.Base.isArrayLike(_175)){
+for(var i=0;i<_175.length;i++){
+lst.push(_175[i]);
+}
+}else{
+var self=MochiKit.Iter;
+_175=self.iter(_175);
+try{
+while(true){
+lst.push(_175.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+}
+return lst;
+},groupby:function(_176,_177){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_177=m.operator.identity;
+}
+_176=self.iter(_176);
+var pk=undefined;
+var k=undefined;
+var v;
+function fetch(){
+v=_176.next();
+k=_177(v);
+}
+function eat(){
+var ret=v;
+v=undefined;
+return ret;
+}
+var _180=true;
+return {repr:function(){
+return "groupby(...)";
+},next:function(){
+while(k==pk){
+fetch();
+if(_180){
+_180=false;
+break;
+}
+}
+pk=k;
+return [k,{next:function(){
+if(v==undefined){
+fetch();
+}
+if(k!=pk){
+throw self.StopIteration;
+}
+return eat();
+}}];
+}};
+},groupby_as_array:function(_181,_182){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_182=m.operator.identity;
+}
+_181=self.iter(_181);
+var _183=[];
+var _184=true;
+var _185;
+while(true){
+try{
+var _186=_181.next();
+var key=_182(_186);
+}
+catch(e){
+if(e==self.StopIteration){
+break;
+}
+throw e;
+}
+if(_184||key!=_185){
+var _187=[];
+_183.push([key,_187]);
+}
+_187.push(_186);
+_184=false;
+_185=key;
+}
+return _183;
+},arrayLikeIter:function(_188){
+var i=0;
+return {repr:function(){
+return "arrayLikeIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+if(i>=_188.length){
+throw MochiKit.Iter.StopIteration;
+}
+return _188[i++];
+}};
+},hasIterateNext:function(_189){
+return (_189&&typeof (_189.iterateNext)=="function");
+},iterateNextIter:function(_190){
+return {repr:function(){
+return "iterateNextIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=_190.iterateNext();
+if(rval===null||rval===undefined){
+throw MochiKit.Iter.StopIteration;
+}
+return rval;
+}};
+}});
+MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter",];
+MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"];
+MochiKit.Iter.__new__=function(){
+var m=MochiKit.Base;
+this.StopIteration=new m.NamedError("StopIteration");
+this.iteratorRegistry=new m.AdapterRegistry();
+this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter);
+this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Iter.__new__();
+if(!MochiKit.__compat__){
+reduce=MochiKit.Iter.reduce;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Iter);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Logging");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Logging depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.Logging)=="undefined"){
+MochiKit.Logging={};
+}
+MochiKit.Logging.NAME="MochiKit.Logging";
+MochiKit.Logging.VERSION="1.3.1";
+MochiKit.Logging.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Logging.toString=function(){
+return this.__repr__();
+};
+MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"];
+MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"];
+MochiKit.Logging.LogMessage=function(num,_192,info){
+this.num=num;
+this.level=_192;
+this.info=info;
+this.timestamp=new Date();
+};
+MochiKit.Logging.LogMessage.prototype={repr:function(){
+var m=MochiKit.Base;
+return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_194){
+var self=MochiKit.Logging;
+if(typeof (_194)=="string"){
+_194=self.LogLevel[_194];
+}
+return function(msg){
+var _196=msg.level;
+if(typeof (_196)=="string"){
+_196=self.LogLevel[_196];
+}
+return _196>=_194;
+};
+},isLogMessage:function(){
+var _197=MochiKit.Logging.LogMessage;
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof _197)){
+return false;
+}
+}
+return true;
+},compareLogMessage:function(a,b){
+return MochiKit.Base.compare([a.level,a.info],[b.level,b.info]);
+},alertListener:function(msg){
+alert("num: "+msg.num+"\nlevel: "+msg.level+"\ninfo: "+msg.info.join(" "));
+}});
+MochiKit.Logging.Logger=function(_198){
+this.counter=0;
+if(typeof (_198)=="undefined"||_198===null){
+_198=-1;
+}
+this.maxSize=_198;
+this._messages=[];
+this.listeners={};
+this.useNativeConsole=false;
+};
+MochiKit.Logging.Logger.prototype={clear:function(){
+this._messages.splice(0,this._messages.length);
+},logToConsole:function(msg){
+if(typeof (window)!="undefined"&&window.console&&window.console.log){
+window.console.log(msg);
+}else{
+if(typeof (opera)!="undefined"&&opera.postError){
+opera.postError(msg);
+}else{
+if(typeof (printfire)=="function"){
+printfire(msg);
+}
+}
+}
+},dispatchListeners:function(msg){
+for(var k in this.listeners){
+var pair=this.listeners[k];
+if(pair.ident!=k||(pair[0]&&!pair[0](msg))){
+continue;
+}
+pair[1](msg);
+}
+},addListener:function(_199,_200,_201){
+if(typeof (_200)=="string"){
+_200=MochiKit.Logging.logLevelAtLeast(_200);
+}
+var _202=[_200,_201];
+_202.ident=_199;
+this.listeners[_199]=_202;
+},removeListener:function(_203){
+delete this.listeners[_203];
+},baseLog:function(_204,_205){
+var msg=new MochiKit.Logging.LogMessage(this.counter,_204,MochiKit.Base.extend(null,arguments,1));
+this._messages.push(msg);
+this.dispatchListeners(msg);
+if(this.useNativeConsole){
+this.logToConsole(msg.level+": "+msg.info.join(" "));
+}
+this.counter+=1;
+while(this.maxSize>=0&&this._messages.length>this.maxSize){
+this._messages.shift();
+}
+},getMessages:function(_206){
+var _207=0;
+if(!(typeof (_206)=="undefined"||_206===null)){
+_207=Math.max(0,this._messages.length-_206);
+}
+return this._messages.slice(_207);
+},getMessageText:function(_208){
+if(typeof (_208)=="undefined"||_208===null){
+_208=30;
+}
+var _209=this.getMessages(_208);
+if(_209.length){
+var lst=map(function(m){
+return "\n  ["+m.num+"] "+m.level+": "+m.info.join(" ");
+},_209);
+lst.unshift("LAST "+_209.length+" MESSAGES:");
+return lst.join("");
+}
+return "";
+},debuggingBookmarklet:function(_210){
+if(typeof (MochiKit.LoggingPane)=="undefined"){
+alert(this.getMessageText());
+}else{
+MochiKit.LoggingPane.createLoggingPane(_210||false);
+}
+}};
+MochiKit.Logging.__new__=function(){
+this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10};
+var m=MochiKit.Base;
+m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage);
+var _211=m.partial;
+var _212=this.Logger;
+var _213=_212.prototype.baseLog;
+m.update(this.Logger.prototype,{debug:_211(_213,"DEBUG"),log:_211(_213,"INFO"),error:_211(_213,"ERROR"),fatal:_211(_213,"FATAL"),warning:_211(_213,"WARNING")});
+var self=this;
+var _214=function(name){
+return function(){
+self.logger[name].apply(self.logger,arguments);
+};
+};
+this.log=_214("log");
+this.logError=_214("error");
+this.logDebug=_214("debug");
+this.logFatal=_214("fatal");
+this.logWarning=_214("warning");
+this.logger=new _212();
+this.logger.useNativeConsole=true;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){
+printfire=function(){
+printfire.args=arguments;
+var ev=document.createEvent("Events");
+ev.initEvent("printfire",false,true);
+dispatchEvent(ev);
+};
+}
+MochiKit.Logging.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Logging);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.DateTime");
+}
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.DateTime)=="undefined"){
+MochiKit.DateTime={};
+}
+MochiKit.DateTime.NAME="MochiKit.DateTime";
+MochiKit.DateTime.VERSION="1.3.1";
+MochiKit.DateTime.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DateTime.toString=function(){
+return this.__repr__();
+};
+MochiKit.DateTime.isoDate=function(str){
+str=str+"";
+if(typeof (str)!="string"||str.length===0){
+return null;
+}
+var iso=str.split("-");
+if(iso.length===0){
+return null;
+}
+return new Date(iso[0],iso[1]-1,iso[2]);
+};
+MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
+MochiKit.DateTime.isoTimestamp=function(str){
+str=str+"";
+if(typeof (str)!="string"||str.length===0){
+return null;
+}
+var res=str.match(MochiKit.DateTime._isoRegexp);
+if(typeof (res)=="undefined"||res===null){
+return null;
+}
+var year,month,day,hour,min,sec,msec;
+year=parseInt(res[1],10);
+if(typeof (res[2])=="undefined"||res[2]===""){
+return new Date(year);
+}
+month=parseInt(res[2],10)-1;
+day=parseInt(res[3],10);
+if(typeof (res[4])=="undefined"||res[4]===""){
+return new Date(year,month,day);
+}
+hour=parseInt(res[4],10);
+min=parseInt(res[5],10);
+sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0;
+if(typeof (res[7])!="undefined"&&res[7]!==""){
+msec=Math.round(1000*parseFloat("0."+res[7]));
+}else{
+msec=0;
+}
+if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){
+return new Date(year,month,day,hour,min,sec,msec);
+}
+var ofs;
+if(typeof (res[9])!="undefined"&&res[9]!==""){
+ofs=parseInt(res[10],10)*3600000;
+if(typeof (res[11])!="undefined"&&res[11]!==""){
+ofs+=parseInt(res[11],10)*60000;
+}
+if(res[9]=="-"){
+ofs=-ofs;
+}
+}else{
+ofs=0;
+}
+return new Date(Date.UTC(year,month,day,hour,min,sec,msec)-ofs);
+};
+MochiKit.DateTime.toISOTime=function(date,_221){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var hh=date.getHours();
+var mm=date.getMinutes();
+var ss=date.getSeconds();
+var lst=[((_221&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];
+return lst.join(":");
+};
+MochiKit.DateTime.toISOTimestamp=function(date,_225){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var sep=_225?"T":" ";
+var foot=_225?"Z":"";
+if(_225){
+date=new Date(date.getTime()+(date.getTimezoneOffset()*60000));
+}
+return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_225)+foot;
+};
+MochiKit.DateTime.toISODate=function(date){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var _228=MochiKit.DateTime._padTwo;
+return [date.getFullYear(),_228(date.getMonth()+1),_228(date.getDate())].join("-");
+};
+MochiKit.DateTime.americanDate=function(d){
+d=d+"";
+if(typeof (d)!="string"||d.length===0){
+return null;
+}
+var a=d.split("/");
+return new Date(a[2],a[0]-1,a[1]);
+};
+MochiKit.DateTime._padTwo=function(n){
+return (n>9)?n:"0"+n;
+};
+MochiKit.DateTime.toPaddedAmericanDate=function(d){
+if(typeof (d)=="undefined"||d===null){
+return null;
+}
+var _230=MochiKit.DateTime._padTwo;
+return [_230(d.getMonth()+1),_230(d.getDate()),d.getFullYear()].join("/");
+};
+MochiKit.DateTime.toAmericanDate=function(d){
+if(typeof (d)=="undefined"||d===null){
+return null;
+}
+return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/");
+};
+MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"];
+MochiKit.DateTime.EXPORT_OK=[];
+MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT};
+MochiKit.DateTime.__new__=function(){
+var base=this.NAME+".";
+for(var k in this){
+var o=this[k];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+k;
+}
+catch(e){
+}
+}
+}
+};
+MochiKit.DateTime.__new__();
+if(typeof (MochiKit.Base)!="undefined"){
+MochiKit.Base._exportSymbols(this,MochiKit.DateTime);
+}else{
+(function(_231,_232){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){
+var all=_232.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_231[all[i]]=_232[all[i]];
+}
+}
+})(this,MochiKit.DateTime);
+}
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Format");
+}
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.Format)=="undefined"){
+MochiKit.Format={};
+}
+MochiKit.Format.NAME="MochiKit.Format";
+MochiKit.Format.VERSION="1.3.1";
+MochiKit.Format.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Format.toString=function(){
+return this.__repr__();
+};
+MochiKit.Format._numberFormatter=function(_233,_234,_235,_236,_237,_238,_239,_240,_241){
+return function(num){
+num=parseFloat(num);
+if(typeof (num)=="undefined"||num===null||isNaN(num)){
+return _233;
+}
+var _242=_234;
+var _243=_235;
+if(num<0){
+num=-num;
+}else{
+_242=_242.replace(/-/,"");
+}
+var me=arguments.callee;
+var fmt=MochiKit.Format.formatLocale(_236);
+if(_237){
+num=num*100;
+_243=fmt.percent+_243;
+}
+num=MochiKit.Format.roundToFixed(num,_238);
+var _245=num.split(/\./);
+var _246=_245[0];
+var frac=(_245.length==1)?"":_245[1];
+var res="";
+while(_246.length<_239){
+_246="0"+_246;
+}
+if(_240){
+while(_246.length>_240){
+var i=_246.length-_240;
+res=fmt.separator+_246.substring(i,_246.length)+res;
+_246=_246.substring(0,i);
+}
+}
+res=_246+res;
+if(_238>0){
+while(frac.length<_241){
+frac=frac+"0";
+}
+res=res+fmt.decimal+frac;
+}
+return _242+res+_243;
+};
+};
+MochiKit.Format.numberFormatter=function(_248,_249,_250){
+if(typeof (_249)=="undefined"){
+_249="";
+}
+var _251=_248.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
+if(!_251){
+throw TypeError("Invalid pattern");
+}
+var _252=_248.substr(0,_251.index);
+var _253=_248.substr(_251.index+_251[0].length);
+if(_252.search(/-/)==-1){
+_252=_252+"-";
+}
+var _254=_251[1];
+var frac=(typeof (_251[2])=="string"&&_251[2]!="")?_251[2]:"";
+var _255=(typeof (_251[3])=="string"&&_251[3]!="");
+var tmp=_254.split(/,/);
+var _257;
+if(typeof (_250)=="undefined"){
+_250="default";
+}
+if(tmp.length==1){
+_257=null;
+}else{
+_257=tmp[1].length;
+}
+var _258=_254.length-_254.replace(/0/g,"").length;
+var _259=frac.length-frac.replace(/0/g,"").length;
+var _260=frac.length;
+var rval=MochiKit.Format._numberFormatter(_249,_252,_253,_250,_255,_260,_258,_257,_259);
+var m=MochiKit.Base;
+if(m){
+var fn=arguments.callee;
+var args=m.concat(arguments);
+rval.repr=function(){
+return [self.NAME,"(",map(m.repr,args).join(", "),")"].join("");
+};
+}
+return rval;
+};
+MochiKit.Format.formatLocale=function(_262){
+if(typeof (_262)=="undefined"||_262===null){
+_262="default";
+}
+if(typeof (_262)=="string"){
+var rval=MochiKit.Format.LOCALE[_262];
+if(typeof (rval)=="string"){
+rval=arguments.callee(rval);
+MochiKit.Format.LOCALE[_262]=rval;
+}
+return rval;
+}else{
+return _262;
+}
+};
+MochiKit.Format.twoDigitAverage=function(_263,_264){
+if(_264){
+var res=_263/_264;
+if(!isNaN(res)){
+return MochiKit.Format.twoDigitFloat(_263/_264);
+}
+}
+return "0";
+};
+MochiKit.Format.twoDigitFloat=function(_265){
+var sign=(_265<0?"-":"");
+var s=Math.floor(Math.abs(_265)*100).toString();
+if(s=="0"){
+return s;
+}
+if(s.length<3){
+while(s.charAt(s.length-1)=="0"){
+s=s.substring(0,s.length-1);
+}
+return sign+"0."+s;
+}
+var head=sign+s.substring(0,s.length-2);
+var tail=s.substring(s.length-2,s.length);
+if(tail=="00"){
+return head;
+}else{
+if(tail.charAt(1)=="0"){
+return head+"."+tail.charAt(0);
+}else{
+return head+"."+tail;
+}
+}
+};
+MochiKit.Format.lstrip=function(str,_270){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_270){
+return str.replace(/^\s+/,"");
+}else{
+return str.replace(new RegExp("^["+_270+"]+"),"");
+}
+};
+MochiKit.Format.rstrip=function(str,_271){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_271){
+return str.replace(/\s+$/,"");
+}else{
+return str.replace(new RegExp("["+_271+"]+$"),"");
+}
+};
+MochiKit.Format.strip=function(str,_272){
+var self=MochiKit.Format;
+return self.rstrip(self.lstrip(str,_272),_272);
+};
+MochiKit.Format.truncToFixed=function(_273,_274){
+_273=Math.floor(_273*Math.pow(10,_274));
+var res=(_273*Math.pow(10,-_274)).toFixed(_274);
+if(res.charAt(0)=="."){
+res="0"+res;
+}
+return res;
+};
+MochiKit.Format.roundToFixed=function(_275,_276){
+return MochiKit.Format.truncToFixed(_275+0.5*Math.pow(10,-_276),_276);
+};
+MochiKit.Format.percentFormat=function(_277){
+return MochiKit.Format.twoDigitFloat(100*_277)+"%";
+};
+MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"];
+MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"};
+MochiKit.Format.EXPORT_OK=[];
+MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT};
+MochiKit.Format.__new__=function(){
+var base=this.NAME+".";
+var k,v,o;
+for(k in this.LOCALE){
+o=this.LOCALE[k];
+if(typeof (o)=="object"){
+o.repr=function(){
+return this.NAME;
+};
+o.NAME=base+"LOCALE."+k;
+}
+}
+for(k in this){
+o=this[k];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+k;
+}
+catch(e){
+}
+}
+}
+};
+MochiKit.Format.__new__();
+if(typeof (MochiKit.Base)!="undefined"){
+MochiKit.Base._exportSymbols(this,MochiKit.Format);
+}else{
+(function(_278,_279){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){
+var all=_279.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_278[all[i]]=_279[all[i]];
+}
+}
+})(this,MochiKit.Format);
+}
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Async");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Async depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.Async)=="undefined"){
+MochiKit.Async={};
+}
+MochiKit.Async.NAME="MochiKit.Async";
+MochiKit.Async.VERSION="1.3.1";
+MochiKit.Async.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Async.toString=function(){
+return this.__repr__();
+};
+MochiKit.Async.Deferred=function(_280){
+this.chain=[];
+this.id=this._nextId();
+this.fired=-1;
+this.paused=0;
+this.results=[null,null];
+this.canceller=_280;
+this.silentlyCancelled=false;
+this.chained=false;
+};
+MochiKit.Async.Deferred.prototype={repr:function(){
+var _281;
+if(this.fired==-1){
+_281="unfired";
+}else{
+if(this.fired===0){
+_281="success";
+}else{
+_281="error";
+}
+}
+return "Deferred("+this.id+", "+_281+")";
+},toString:MochiKit.Base.forwardCall("repr"),_nextId:MochiKit.Base.counter(),cancel:function(){
+var self=MochiKit.Async;
+if(this.fired==-1){
+if(this.canceller){
+this.canceller(this);
+}else{
+this.silentlyCancelled=true;
+}
+if(this.fired==-1){
+this.errback(new self.CancelledError(this));
+}
+}else{
+if((this.fired===0)&&(this.results[0] instanceof self.Deferred)){
+this.results[0].cancel();
+}
+}
+},_pause:function(){
+this.paused++;
+},_unpause:function(){
+this.paused--;
+if((this.paused===0)&&(this.fired>=0)){
+this._fire();
+}
+},_continue:function(res){
+this._resback(res);
+this._unpause();
+},_resback:function(res){
+this.fired=((res instanceof Error)?1:0);
+this.results[this.fired]=res;
+this._fire();
+},_check:function(){
+if(this.fired!=-1){
+if(!this.silentlyCancelled){
+throw new MochiKit.Async.AlreadyCalledError(this);
+}
+this.silentlyCancelled=false;
+return;
+}
+},callback:function(res){
+this._check();
+if(res instanceof MochiKit.Async.Deferred){
+throw new Error("Deferred instances can only be chained if they are the result of a callback");
+}
+this._resback(res);
+},errback:function(res){
+this._check();
+var self=MochiKit.Async;
+if(res instanceof self.Deferred){
+throw new Error("Deferred instances can only be chained if they are the result of a callback");
+}
+if(!(res instanceof Error)){
+res=new self.GenericError(res);
+}
+this._resback(res);
+},addBoth:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(fn,fn);
+},addCallback:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(fn,null);
+},addErrback:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(null,fn);
+},addCallbacks:function(cb,eb){
+if(this.chained){
+throw new Error("Chained Deferreds can not be re-used");
+}
+this.chain.push([cb,eb]);
+if(this.fired>=0){
+this._fire();
+}
+return this;
+},_fire:function(){
+var _284=this.chain;
+var _285=this.fired;
+var res=this.results[_285];
+var self=this;
+var cb=null;
+while(_284.length>0&&this.paused===0){
+var pair=_284.shift();
+var f=pair[_285];
+if(f===null){
+continue;
+}
+try{
+res=f(res);
+_285=((res instanceof Error)?1:0);
+if(res instanceof MochiKit.Async.Deferred){
+cb=function(res){
+self._continue(res);
+};
+this._pause();
+}
+}
+catch(err){
+_285=1;
+if(!(err instanceof Error)){
+err=new MochiKit.Async.GenericError(err);
+}
+res=err;
+}
+}
+this.fired=_285;
+this.results[_285]=res;
+if(cb&&this.paused){
+res.addBoth(cb);
+res.chained=true;
+}
+}};
+MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(){
+return eval("("+arguments[0].responseText+")");
+},succeed:function(_287){
+var d=new MochiKit.Async.Deferred();
+d.callback.apply(d,arguments);
+return d;
+},fail:function(_288){
+var d=new MochiKit.Async.Deferred();
+d.errback.apply(d,arguments);
+return d;
+},getXMLHttpRequest:function(){
+var self=arguments.callee;
+if(!self.XMLHttpRequest){
+var _289=[function(){
+return new XMLHttpRequest();
+},function(){
+return new ActiveXObject("Msxml2.XMLHTTP");
+},function(){
+return new ActiveXObject("Microsoft.XMLHTTP");
+},function(){
+return new ActiveXObject("Msxml2.XMLHTTP.4.0");
+},function(){
+throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
+}];
+for(var i=0;i<_289.length;i++){
+var func=_289[i];
+try{
+self.XMLHttpRequest=func;
+return func();
+}
+catch(e){
+}
+}
+}
+return self.XMLHttpRequest();
+},_nothing:function(){
+},_xhr_onreadystatechange:function(d){
+if(this.readyState==4){
+try{
+this.onreadystatechange=null;
+}
+catch(e){
+try{
+this.onreadystatechange=MochiKit.Async._nothing;
+}
+catch(e){
+}
+}
+var _290=null;
+try{
+_290=this.status;
+if(!_290&&MochiKit.Base.isNotEmpty(this.responseText)){
+_290=304;
+}
+}
+catch(e){
+}
+if(_290==200||_290==304){
+d.callback(this);
+}else{
+var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed");
+if(err.number){
+d.errback(err);
+}else{
+d.errback(err);
+}
+}
+}
+},_xhr_canceller:function(req){
+try{
+req.onreadystatechange=null;
+}
+catch(e){
+try{
+req.onreadystatechange=MochiKit.Async._nothing;
+}
+catch(e){
+}
+}
+req.abort();
+},sendXMLHttpRequest:function(req,_293){
+if(typeof (_293)=="undefined"||_293===null){
+_293="";
+}
+var m=MochiKit.Base;
+var self=MochiKit.Async;
+var d=new self.Deferred(m.partial(self._xhr_canceller,req));
+try{
+req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d);
+req.send(_293);
+}
+catch(e){
+try{
+req.onreadystatechange=null;
+}
+catch(ignore){
+}
+d.errback(e);
+}
+return d;
+},doSimpleXMLHttpRequest:function(url){
+var self=MochiKit.Async;
+var req=self.getXMLHttpRequest();
+if(arguments.length>1){
+var m=MochiKit.Base;
+var qs=m.queryString.apply(null,m.extend(null,arguments,1));
+if(qs){
+url+="?"+qs;
+}
+}
+req.open("GET",url,true);
+return self.sendXMLHttpRequest(req);
+},loadJSONDoc:function(url){
+var self=MochiKit.Async;
+var d=self.doSimpleXMLHttpRequest.apply(self,arguments);
+d=d.addCallback(self.evalJSONRequest);
+return d;
+},wait:function(_296,_297){
+var d=new MochiKit.Async.Deferred();
+var m=MochiKit.Base;
+if(typeof (_297)!="undefined"){
+d.addCallback(function(){
+return _297;
+});
+}
+var _298=setTimeout(m.bind("callback",d),Math.floor(_296*1000));
+d.canceller=function(){
+try{
+clearTimeout(_298);
+}
+catch(e){
+}
+};
+return d;
+},callLater:function(_299,func){
+var m=MochiKit.Base;
+var _300=m.partial.apply(m,m.extend(null,arguments,1));
+return MochiKit.Async.wait(_299).addCallback(function(res){
+return _300();
+});
+}});
+MochiKit.Async.DeferredLock=function(){
+this.waiting=[];
+this.locked=false;
+this.id=this._nextId();
+};
+MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){
+d=new MochiKit.Async.Deferred();
+if(this.locked){
+this.waiting.push(d);
+}else{
+this.locked=true;
+d.callback(this);
+}
+return d;
+},release:function(){
+if(!this.locked){
+throw TypeError("Tried to release an unlocked DeferredLock");
+}
+this.locked=false;
+if(this.waiting.length>0){
+this.locked=true;
+this.waiting.shift().callback(this);
+}
+},_nextId:MochiKit.Base.counter(),repr:function(){
+var _301;
+if(this.locked){
+_301="locked, "+this.waiting.length+" waiting";
+}else{
+_301="unlocked";
+}
+return "DeferredLock("+this.id+", "+_301+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Async.DeferredList=function(list,_303,_304,_305,_306){
+this.list=list;
+this.resultList=new Array(this.list.length);
+this.chain=[];
+this.id=this._nextId();
+this.fired=-1;
+this.paused=0;
+this.results=[null,null];
+this.canceller=_306;
+this.silentlyCancelled=false;
+if(this.list.length===0&&!_303){
+this.callback(this.resultList);
+}
+this.finishedCount=0;
+this.fireOnOneCallback=_303;
+this.fireOnOneErrback=_304;
+this.consumeErrors=_305;
+var _307=0;
+MochiKit.Base.map(MochiKit.Base.bind(function(d){
+d.addCallback(MochiKit.Base.bind(this._cbDeferred,this),_307,true);
+d.addErrback(MochiKit.Base.bind(this._cbDeferred,this),_307,false);
+_307+=1;
+},this),this.list);
+};
+MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,MochiKit.Async.Deferred.prototype);
+MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,{_cbDeferred:function(_308,_309,_310){
+this.resultList[_308]=[_309,_310];
+this.finishedCount+=1;
+if(this.fired!==0){
+if(_309&&this.fireOnOneCallback){
+this.callback([_308,_310]);
+}else{
+if(!_309&&this.fireOnOneErrback){
+this.errback(_310);
+}else{
+if(this.finishedCount==this.list.length){
+this.callback(this.resultList);
+}
+}
+}
+}
+if(!_309&&this.consumeErrors){
+_310=null;
+}
+return _310;
+}});
+MochiKit.Async.gatherResults=function(_311){
+var d=new MochiKit.Async.DeferredList(_311,false,true,false);
+d.addCallback(function(_312){
+var ret=[];
+for(var i=0;i<_312.length;i++){
+ret.push(_312[i][1]);
+}
+return ret;
+});
+return d;
+};
+MochiKit.Async.maybeDeferred=function(func){
+var self=MochiKit.Async;
+var _313;
+try{
+var r=func.apply(null,MochiKit.Base.extend([],arguments,1));
+if(r instanceof self.Deferred){
+_313=r;
+}else{
+if(r instanceof Error){
+_313=self.fail(r);
+}else{
+_313=self.succeed(r);
+}
+}
+}
+catch(e){
+_313=self.fail(e);
+}
+return _313;
+};
+MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred"];
+MochiKit.Async.EXPORT_OK=["evalJSONRequest"];
+MochiKit.Async.__new__=function(){
+var m=MochiKit.Base;
+var ne=m.partial(m._newNamedError,this);
+ne("AlreadyCalledError",function(_316){
+this.deferred=_316;
+});
+ne("CancelledError",function(_317){
+this.deferred=_317;
+});
+ne("BrowserComplianceError",function(msg){
+this.message=msg;
+});
+ne("GenericError",function(msg){
+this.message=msg;
+});
+ne("XMLHttpRequestError",function(req,msg){
+this.req=req;
+this.message=msg;
+try{
+this.number=req.status;
+}
+catch(e){
+}
+});
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Async.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Async);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.DOM");
+dojo.require("MochiKit.Iter");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Iter",[]);
+}
+try{
+if(typeof (MochiKit.Iter)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.DOM depends on MochiKit.Iter!";
+}
+if(typeof (MochiKit.DOM)=="undefined"){
+MochiKit.DOM={};
+}
+MochiKit.DOM.NAME="MochiKit.DOM";
+MochiKit.DOM.VERSION="1.3.1";
+MochiKit.DOM.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DOM.toString=function(){
+return this.__repr__();
+};
+MochiKit.DOM.EXPORT=["formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","getNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","replaceChildNodes","removeElement","swapDOM","BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG","getElement","$","computedStyle","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","escapeHTML","toHTML","emitHTML","setDisplayForElement","hideElement","showElement","scrapeText","elementDimensions","elementPosition","setElementDimensions","setElementPosition","getViewportDimensions","setOpacity"];
+MochiKit.DOM.EXPORT_OK=["domConverters"];
+MochiKit.DOM.Dimensions=function(w,h){
+this.w=w;
+this.h=h;
+};
+MochiKit.DOM.Dimensions.prototype.repr=function(){
+var repr=MochiKit.Base.repr;
+return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}";
+};
+MochiKit.DOM.Coordinates=function(x,y){
+this.x=x;
+this.y=y;
+};
+MochiKit.DOM.Coordinates.prototype.repr=function(){
+var repr=MochiKit.Base.repr;
+return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}";
+};
+MochiKit.DOM.Coordinates.prototype.toString=function(){
+return this.repr();
+};
+MochiKit.Base.update(MochiKit.DOM,{setOpacity:function(elem,o){
+elem=MochiKit.DOM.getElement(elem);
+MochiKit.DOM.updateNodeAttributes(elem,{"style":{"opacity":o,"-moz-opacity":o,"-khtml-opacity":o,"filter":" alpha(opacity="+(o*100)+")"}});
+},getViewportDimensions:function(){
+var d=new MochiKit.DOM.Dimensions();
+var w=MochiKit.DOM._window;
+var b=MochiKit.DOM._document.body;
+if(w.innerWidth){
+d.w=w.innerWidth;
+d.h=w.innerHeight;
+}else{
+if(b.parentElement.clientWidth){
+d.w=b.parentElement.clientWidth;
+d.h=b.parentElement.clientHeight;
+}else{
+if(b&&b.clientWidth){
+d.w=b.clientWidth;
+d.h=b.clientHeight;
+}
+}
+}
+return d;
+},elementDimensions:function(elem){
+var self=MochiKit.DOM;
+if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){
+return new self.Dimensions(elem.w||0,elem.h||0);
+}
+elem=self.getElement(elem);
+if(!elem){
+return undefined;
+}
+if(self.computedStyle(elem,"display")!="none"){
+return new self.Dimensions(elem.offsetWidth||0,elem.offsetHeight||0);
+}
+var s=elem.style;
+var _322=s.visibility;
+var _323=s.position;
+s.visibility="hidden";
+s.position="absolute";
+s.display="";
+var _324=elem.offsetWidth;
+var _325=elem.offsetHeight;
+s.display="none";
+s.position=_323;
+s.visibility=_322;
+return new self.Dimensions(_324,_325);
+},elementPosition:function(elem,_326){
+var self=MochiKit.DOM;
+elem=self.getElement(elem);
+if(!elem){
+return undefined;
+}
+var c=new self.Coordinates(0,0);
+if(elem.x&&elem.y){
+c.x+=elem.x||0;
+c.y+=elem.y||0;
+return c;
+}else{
+if(elem.parentNode===null||self.computedStyle(elem,"display")=="none"){
+return undefined;
+}
+}
+var box=null;
+var _329=null;
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var b=d.body;
+if(elem.getBoundingClientRect){
+box=elem.getBoundingClientRect();
+c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||b.clientLeft);
+c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||b.clientTop);
+}else{
+if(d.getBoxObjectFor){
+box=d.getBoxObjectFor(elem);
+c.x+=box.x;
+c.y+=box.y;
+}else{
+if(elem.offsetParent){
+c.x+=elem.offsetLeft;
+c.y+=elem.offsetTop;
+_329=elem.offsetParent;
+if(_329!=elem){
+while(_329){
+c.x+=_329.offsetLeft;
+c.y+=_329.offsetTop;
+_329=_329.offsetParent;
+}
+}
+var ua=navigator.userAgent.toLowerCase();
+if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("safari")!=-1&&self.computedStyle(elem,"position")=="absolute")){
+c.x-=b.offsetLeft;
+c.y-=b.offsetTop;
+}
+}
+}
+}
+if(typeof (_326)!="undefined"){
+_326=arguments.callee(_326);
+if(_326){
+c.x-=(_326.x||0);
+c.y-=(_326.y||0);
+}
+}
+if(elem.parentNode){
+_329=elem.parentNode;
+}else{
+_329=null;
+}
+while(_329&&_329.tagName!="BODY"&&_329.tagName!="HTML"){
+c.x-=_329.scrollLeft;
+c.y-=_329.scrollTop;
+if(_329.parentNode){
+_329=_329.parentNode;
+}else{
+_329=null;
+}
+}
+return c;
+},setElementDimensions:function(elem,_332,_333){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_333)=="undefined"){
+_333="px";
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":{"width":_332.w+_333,"height":_332.h+_333}});
+},setElementPosition:function(elem,_334,_335){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_335)=="undefined"){
+_335="px";
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":{"left":_334.x+_335,"top":_334.y+_335}});
+},currentWindow:function(){
+return MochiKit.DOM._window;
+},currentDocument:function(){
+return MochiKit.DOM._document;
+},withWindow:function(win,func){
+var self=MochiKit.DOM;
+var _337=self._document;
+var _338=self._win;
+var rval;
+try{
+self._window=win;
+self._document=win.document;
+rval=func();
+}
+catch(e){
+self._window=_338;
+self._document=_337;
+throw e;
+}
+self._window=_338;
+self._document=_337;
+return rval;
+},formContents:function(elem){
+var _339=[];
+var _340=[];
+var m=MochiKit.Base;
+var self=MochiKit.DOM;
+if(typeof (elem)=="undefined"||elem===null){
+elem=self._document;
+}else{
+elem=self.getElement(elem);
+}
+m.nodeWalk(elem,function(elem){
+var name=elem.name;
+if(m.isNotEmpty(name)){
+var _341=elem.nodeName;
+if(_341=="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){
+return null;
+}
+if(_341=="SELECT"){
+if(elem.selectedIndex>=0){
+var opt=elem.options[elem.selectedIndex];
+_339.push(name);
+_340.push((opt.value)?opt.value:opt.text);
+return null;
+}
+_339.push(name);
+_340.push("");
+return null;
+}
+if(_341=="FORM"||_341=="P"||_341=="SPAN"||_341=="DIV"){
+return elem.childNodes;
+}
+_339.push(name);
+_340.push(elem.value||"");
+return null;
+}
+return elem.childNodes;
+});
+return [_339,_340];
+},withDocument:function(doc,func){
+var self=MochiKit.DOM;
+var _344=self._document;
+var rval;
+try{
+self._document=doc;
+rval=func();
+}
+catch(e){
+self._document=_344;
+throw e;
+}
+self._document=_344;
+return rval;
+},registerDOMConverter:function(name,_345,wrap,_346){
+MochiKit.DOM.domConverters.register(name,_345,wrap,_346);
+},coerceToDOM:function(node,ctx){
+var im=MochiKit.Iter;
+var self=MochiKit.DOM;
+var iter=im.iter;
+var _350=im.repeat;
+var imap=im.imap;
+var _352=self.domConverters;
+var _353=self.coerceToDOM;
+var _354=MochiKit.Base.NotFound;
+while(true){
+if(typeof (node)=="undefined"||node===null){
+return null;
+}
+if(typeof (node.nodeType)!="undefined"&&node.nodeType>0){
+return node;
+}
+if(typeof (node)=="number"||typeof (node)=="boolean"){
+node=node.toString();
+}
+if(typeof (node)=="string"){
+return self._document.createTextNode(node);
+}
+if(typeof (node.toDOM)=="function"){
+node=node.toDOM(ctx);
+continue;
+}
+if(typeof (node)=="function"){
+node=node(ctx);
+continue;
+}
+var _355=null;
+try{
+_355=iter(node);
+}
+catch(e){
+}
+if(_355){
+return imap(_353,_355,_350(ctx));
+}
+try{
+node=_352.match(node,ctx);
+continue;
+}
+catch(e){
+if(e!=_354){
+throw e;
+}
+}
+return self._document.createTextNode(node.toString());
+}
+return undefined;
+},setNodeAttribute:function(node,attr,_357){
+var o={};
+o[attr]=_357;
+try{
+return MochiKit.DOM.updateNodeAttributes(node,o);
+}
+catch(e){
+}
+return null;
+},getNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _358=self.attributeArray.renames[attr];
+node=self.getElement(node);
+try{
+if(_358){
+return node[_358];
+}
+return node.getAttribute(attr);
+}
+catch(e){
+}
+return null;
+},updateNodeAttributes:function(node,_359){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+if(_359){
+var _360=MochiKit.Base.updatetree;
+if(self.attributeArray.compliant){
+for(var k in _359){
+var v=_359[k];
+if(typeof (v)=="object"&&typeof (elem[k])=="object"){
+_360(elem[k],v);
+}else{
+if(k.substring(0,2)=="on"){
+if(typeof (v)=="string"){
+v=new Function(v);
+}
+elem[k]=v;
+}else{
+elem.setAttribute(k,v);
+}
+}
+}
+}else{
+var _361=self.attributeArray.renames;
+for(k in _359){
+v=_359[k];
+var _362=_361[k];
+if(k=="style"&&typeof (v)=="string"){
+elem.style.cssText=v;
+}else{
+if(typeof (_362)=="string"){
+elem[_362]=v;
+}else{
+if(typeof (elem[k])=="object"&&typeof (v)=="object"){
+_360(elem[k],v);
+}else{
+if(k.substring(0,2)=="on"){
+if(typeof (v)=="string"){
+v=new Function(v);
+}
+elem[k]=v;
+}else{
+elem.setAttribute(k,v);
+}
+}
+}
+}
+}
+}
+}
+return elem;
+},appendChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _363=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _364=MochiKit.Base.concat;
+while(_363.length){
+var n=_363.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+elem.appendChild(n);
+}else{
+_363=_364(n,_363);
+}
+}
+}
+return elem;
+},replaceChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+arguments[0]=elem;
+}
+var _365;
+while((_365=elem.firstChild)){
+elem.removeChild(_365);
+}
+if(arguments.length<2){
+return elem;
+}else{
+return self.appendChildNodes.apply(this,arguments);
+}
+},createDOM:function(name,_366){
+var elem;
+var self=MochiKit.DOM;
+var m=MochiKit.Base;
+if(typeof (_366)=="string"||typeof (_366)=="number"){
+var args=m.extend([name,null],arguments,1);
+return arguments.callee.apply(this,args);
+}
+if(typeof (name)=="string"){
+if(_366&&"name" in _366&&!self.attributeArray.compliant){
+name=("<"+name+" name=\""+self.escapeHTML(_366.name)+"\">");
+}
+elem=self._document.createElement(name);
+}else{
+elem=name;
+}
+if(_366){
+self.updateNodeAttributes(elem,_366);
+}
+if(arguments.length<=2){
+return elem;
+}else{
+var args=m.extend([elem],arguments,2);
+return self.appendChildNodes.apply(this,args);
+}
+},createDOMFunc:function(){
+var m=MochiKit.Base;
+return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments));
+},swapDOM:function(dest,src){
+var self=MochiKit.DOM;
+dest=self.getElement(dest);
+var _369=dest.parentNode;
+if(src){
+src=self.getElement(src);
+_369.replaceChild(src,dest);
+}else{
+_369.removeChild(dest);
+}
+return src;
+},getElement:function(id){
+var self=MochiKit.DOM;
+if(arguments.length==1){
+return ((typeof (id)=="string")?self._document.getElementById(id):id);
+}else{
+return MochiKit.Base.map(self.getElement,arguments);
+}
+},computedStyle:function(_371,_372,_373){
+if(arguments.length==2){
+_373=_372;
+}
+var self=MochiKit.DOM;
+var el=self.getElement(_371);
+var _375=self._document;
+if(!el||el==_375){
+return undefined;
+}
+if(el.currentStyle){
+return el.currentStyle[_372];
+}
+if(typeof (_375.defaultView)=="undefined"){
+return undefined;
+}
+if(_375.defaultView===null){
+return undefined;
+}
+var _376=_375.defaultView.getComputedStyle(el,null);
+if(typeof (_376)=="undefined"||_376===null){
+return undefined;
+}
+return _376.getPropertyValue(_373);
+},getElementsByTagAndClassName:function(_377,_378,_379){
+var self=MochiKit.DOM;
+if(typeof (_377)=="undefined"||_377===null){
+_377="*";
+}
+if(typeof (_379)=="undefined"||_379===null){
+_379=self._document;
+}
+_379=self.getElement(_379);
+var _380=(_379.getElementsByTagName(_377)||self._document.all);
+if(typeof (_378)=="undefined"||_378===null){
+return MochiKit.Base.extend(null,_380);
+}
+var _381=[];
+for(var i=0;i<_380.length;i++){
+var _382=_380[i];
+var _383=_382.className.split(" ");
+for(var j=0;j<_383.length;j++){
+if(_383[j]==_378){
+_381.push(_382);
+break;
+}
+}
+}
+return _381;
+},_newCallStack:function(path,once){
+var rval=function(){
+var _386=arguments.callee.callStack;
+for(var i=0;i<_386.length;i++){
+if(_386[i].apply(this,arguments)===false){
+break;
+}
+}
+if(once){
+try{
+this[path]=null;
+}
+catch(e){
+}
+}
+};
+rval.callStack=[];
+return rval;
+},addToCallStack:function(_387,path,func,once){
+var self=MochiKit.DOM;
+var _388=_387[path];
+var _389=_388;
+if(!(typeof (_388)=="function"&&typeof (_388.callStack)=="object"&&_388.callStack!==null)){
+_389=self._newCallStack(path,once);
+if(typeof (_388)=="function"){
+_389.callStack.push(_388);
+}
+_387[path]=_389;
+}
+_389.callStack.push(func);
+},addLoadEvent:function(func){
+var self=MochiKit.DOM;
+self.addToCallStack(self._window,"onload",func,true);
+},focusOnLoad:function(_390){
+var self=MochiKit.DOM;
+self.addLoadEvent(function(){
+_390=self.getElement(_390);
+if(_390){
+_390.focus();
+}
+});
+},setElementClass:function(_391,_392){
+var self=MochiKit.DOM;
+var obj=self.getElement(_391);
+if(self.attributeArray.compliant){
+obj.setAttribute("class",_392);
+}else{
+obj.setAttribute("className",_392);
+}
+},toggleElementClass:function(_393){
+var self=MochiKit.DOM;
+for(var i=1;i<arguments.length;i++){
+var obj=self.getElement(arguments[i]);
+if(!self.addElementClass(obj,_393)){
+self.removeElementClass(obj,_393);
+}
+}
+},addElementClass:function(_394,_395){
+var self=MochiKit.DOM;
+var obj=self.getElement(_394);
+var cls=obj.className;
+if(cls.length===0){
+self.setElementClass(obj,_395);
+return true;
+}
+if(cls==_395){
+return false;
+}
+var _397=obj.className.split(" ");
+for(var i=0;i<_397.length;i++){
+if(_397[i]==_395){
+return false;
+}
+}
+self.setElementClass(obj,cls+" "+_395);
+return true;
+},removeElementClass:function(_398,_399){
+var self=MochiKit.DOM;
+var obj=self.getElement(_398);
+var cls=obj.className;
+if(cls.length===0){
+return false;
+}
+if(cls==_399){
+self.setElementClass(obj,"");
+return true;
+}
+var _400=obj.className.split(" ");
+for(var i=0;i<_400.length;i++){
+if(_400[i]==_399){
+_400.splice(i,1);
+self.setElementClass(obj,_400.join(" "));
+return true;
+}
+}
+return false;
+},swapElementClass:function(_401,_402,_403){
+var obj=MochiKit.DOM.getElement(_401);
+var res=MochiKit.DOM.removeElementClass(obj,_402);
+if(res){
+MochiKit.DOM.addElementClass(obj,_403);
+}
+return res;
+},hasElementClass:function(_404,_405){
+var obj=MochiKit.DOM.getElement(_404);
+var _406=obj.className.split(" ");
+for(var i=1;i<arguments.length;i++){
+var good=false;
+for(var j=0;j<_406.length;j++){
+if(_406[j]==arguments[i]){
+good=true;
+break;
+}
+}
+if(!good){
+return false;
+}
+}
+return true;
+},escapeHTML:function(s){
+return s.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
+},toHTML:function(dom){
+return MochiKit.DOM.emitHTML(dom).join("");
+},emitHTML:function(dom,lst){
+if(typeof (lst)=="undefined"||lst===null){
+lst=[];
+}
+var _409=[dom];
+var self=MochiKit.DOM;
+var _410=self.escapeHTML;
+var _411=self.attributeArray;
+while(_409.length){
+dom=_409.pop();
+if(typeof (dom)=="string"){
+lst.push(dom);
+}else{
+if(dom.nodeType==1){
+lst.push("<"+dom.nodeName.toLowerCase());
+var _412=[];
+var _413=_411(dom);
+for(var i=0;i<_413.length;i++){
+var a=_413[i];
+_412.push([" ",a.name,"=\"",_410(a.value),"\""]);
+}
+_412.sort();
+for(i=0;i<_412.length;i++){
+var _414=_412[i];
+for(var j=0;j<_414.length;j++){
+lst.push(_414[j]);
+}
+}
+if(dom.hasChildNodes()){
+lst.push(">");
+_409.push("</"+dom.nodeName.toLowerCase()+">");
+var _415=dom.childNodes;
+for(i=_415.length-1;i>=0;i--){
+_409.push(_415[i]);
+}
+}else{
+lst.push("/>");
+}
+}else{
+if(dom.nodeType==3){
+lst.push(_410(dom.nodeValue));
+}
+}
+}
+}
+return lst;
+},setDisplayForElement:function(_416,_417){
+var m=MochiKit.Base;
+var _418=m.extend(null,arguments,1);
+MochiKit.Iter.forEach(m.filter(null,m.map(MochiKit.DOM.getElement,_418)),function(_417){
+_417.style.display=_416;
+});
+},scrapeText:function(node,_419){
+var rval=[];
+(function(node){
+var cn=node.childNodes;
+if(cn){
+for(var i=0;i<cn.length;i++){
+arguments.callee.call(this,cn[i]);
+}
+}
+var _421=node.nodeValue;
+if(typeof (_421)=="string"){
+rval.push(_421);
+}
+})(MochiKit.DOM.getElement(node));
+if(_419){
+return rval;
+}else{
+return rval.join("");
+}
+},__new__:function(win){
+var m=MochiKit.Base;
+this._document=document;
+this._window=win;
+this.domConverters=new m.AdapterRegistry();
+var _422=this._document.createElement("span");
+var _423;
+if(_422&&_422.attributes&&_422.attributes.length>0){
+var _424=m.filter;
+_423=function(node){
+return _424(_423.ignoreAttrFilter,node.attributes);
+};
+_423.ignoreAttr={};
+MochiKit.Iter.forEach(_422.attributes,function(a){
+_423.ignoreAttr[a.name]=a.value;
+});
+_423.ignoreAttrFilter=function(a){
+return (_423.ignoreAttr[a.name]!=a.value);
+};
+_423.compliant=false;
+_423.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor"};
+}else{
+_423=function(node){
+return node.attributes;
+};
+_423.compliant=true;
+_423.renames={};
+}
+this.attributeArray=_423;
+var _425=this.createDOMFunc;
+this.UL=_425("ul");
+this.OL=_425("ol");
+this.LI=_425("li");
+this.TD=_425("td");
+this.TR=_425("tr");
+this.TBODY=_425("tbody");
+this.THEAD=_425("thead");
+this.TFOOT=_425("tfoot");
+this.TABLE=_425("table");
+this.TH=_425("th");
+this.INPUT=_425("input");
+this.SPAN=_425("span");
+this.A=_425("a");
+this.DIV=_425("div");
+this.IMG=_425("img");
+this.BUTTON=_425("button");
+this.TT=_425("tt");
+this.PRE=_425("pre");
+this.H1=_425("h1");
+this.H2=_425("h2");
+this.H3=_425("h3");
+this.BR=_425("br");
+this.HR=_425("hr");
+this.LABEL=_425("label");
+this.TEXTAREA=_425("textarea");
+this.FORM=_425("form");
+this.P=_425("p");
+this.SELECT=_425("select");
+this.OPTION=_425("option");
+this.OPTGROUP=_425("optgroup");
+this.LEGEND=_425("legend");
+this.FIELDSET=_425("fieldset");
+this.STRONG=_425("strong");
+this.CANVAS=_425("canvas");
+this.hideElement=m.partial(this.setDisplayForElement,"none");
+this.showElement=m.partial(this.setDisplayForElement,"block");
+this.removeElement=this.swapDOM;
+this.$=this.getElement;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.DOM.__new__(((typeof (window)=="undefined")?this:window));
+if(!MochiKit.__compat__){
+withWindow=MochiKit.DOM.withWindow;
+withDocument=MochiKit.DOM.withDocument;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.DOM);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.LoggingPane");
+dojo.require("MochiKit.Logging");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Logging",[]);
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.Logging)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!";
+}
+if(typeof (MochiKit.LoggingPane)=="undefined"){
+MochiKit.LoggingPane={};
+}
+MochiKit.LoggingPane.NAME="MochiKit.LoggingPane";
+MochiKit.LoggingPane.VERSION="1.3.1";
+MochiKit.LoggingPane.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.LoggingPane.toString=function(){
+return this.__repr__();
+};
+MochiKit.LoggingPane.createLoggingPane=function(_426){
+var m=MochiKit.LoggingPane;
+_426=!(!_426);
+if(m._loggingPane&&m._loggingPane.inline!=_426){
+m._loggingPane.closePane();
+m._loggingPane=null;
+}
+if(!m._loggingPane||m._loggingPane.closed){
+m._loggingPane=new m.LoggingPane(_426,MochiKit.Logging.logger);
+}
+return m._loggingPane;
+};
+MochiKit.LoggingPane.LoggingPane=function(_427,_428){
+if(typeof (_428)=="undefined"||_428===null){
+_428=MochiKit.Logging.logger;
+}
+this.logger=_428;
+var _429=MochiKit.Base.update;
+var _430=MochiKit.Base.updatetree;
+var bind=MochiKit.Base.bind;
+var _431=MochiKit.Base.clone;
+var win=window;
+var uid="_MochiKit_LoggingPane";
+if(typeof (MochiKit.DOM)!="undefined"){
+win=MochiKit.DOM.currentWindow();
+}
+if(!_427){
+var url=win.location.href.split("?")[0].replace(/[:\/.><&]/g,"_");
+var name=uid+"_"+url;
+var nwin=win.open("",name,"dependent,resizable,height=200");
+if(!nwin){
+alert("Not able to open debugging window due to pop-up blocking.");
+return undefined;
+}
+nwin.document.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" "+"\"http://www.w3.org/TR/html4/loose.dtd\">"+"<html><head><title>[MochiKit.LoggingPane]</title></head>"+"<body></body></html>");
+nwin.document.close();
+nwin.document.title+=" "+win.document.title;
+win=nwin;
+}
+var doc=win.document;
+this.doc=doc;
+var _434=doc.getElementById(uid);
+var _435=!!_434;
+if(_434&&typeof (_434.loggingPane)!="undefined"){
+_434.loggingPane.logger=this.logger;
+_434.loggingPane.buildAndApplyFilter();
+return _434.loggingPane;
+}
+if(_435){
+var _436;
+while((_436=_434.firstChild)){
+_434.removeChild(_436);
+}
+}else{
+_434=doc.createElement("div");
+_434.id=uid;
+}
+_434.loggingPane=this;
+var _437=doc.createElement("input");
+var _438=doc.createElement("input");
+var _439=doc.createElement("button");
+var _440=doc.createElement("button");
+var _441=doc.createElement("button");
+var _442=doc.createElement("button");
+var _443=doc.createElement("div");
+var _444=doc.createElement("div");
+var _445=uid+"_Listener";
+this.colorTable=_431(this.colorTable);
+var _446=[];
+var _447=null;
+var _448=function(msg){
+var _449=msg.level;
+if(typeof (_449)=="number"){
+_449=MochiKit.Logging.LogLevel[_449];
+}
+return _449;
+};
+var _450=function(msg){
+return msg.info.join(" ");
+};
+var _451=bind(function(msg){
+var _452=_448(msg);
+var text=_450(msg);
+var c=this.colorTable[_452];
+var p=doc.createElement("span");
+p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_452;
+p.style.cssText="margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: "+c;
+p.appendChild(doc.createTextNode(_452+": "+text));
+_444.appendChild(p);
+_444.appendChild(doc.createElement("br"));
+if(_443.offsetHeight>_443.scrollHeight){
+_443.scrollTop=0;
+}else{
+_443.scrollTop=_443.scrollHeight;
+}
+},this);
+var _454=function(msg){
+_446[_446.length]=msg;
+_451(msg);
+};
+var _455=function(){
+var _456,infore;
+try{
+_456=new RegExp(_437.value);
+infore=new RegExp(_438.value);
+}
+catch(e){
+logDebug("Error in filter regex: "+e.message);
+return null;
+}
+return function(msg){
+return (_456.test(_448(msg))&&infore.test(_450(msg)));
+};
+};
+var _457=function(){
+while(_444.firstChild){
+_444.removeChild(_444.firstChild);
+}
+};
+var _458=function(){
+_446=[];
+_457();
+};
+var _459=bind(function(){
+if(this.closed){
+return;
+}
+this.closed=true;
+if(MochiKit.LoggingPane._loggingPane==this){
+MochiKit.LoggingPane._loggingPane=null;
+}
+this.logger.removeListener(_445);
+_434.loggingPane=null;
+if(_427){
+_434.parentNode.removeChild(_434);
+}else{
+this.win.close();
+}
+},this);
+var _460=function(){
+_457();
+for(var i=0;i<_446.length;i++){
+var msg=_446[i];
+if(_447===null||_447(msg)){
+_451(msg);
+}
+}
+};
+this.buildAndApplyFilter=function(){
+_447=_455();
+_460();
+this.logger.removeListener(_445);
+this.logger.addListener(_445,_447,_454);
+};
+var _461=bind(function(){
+_446=this.logger.getMessages();
+_460();
+},this);
+var _462=bind(function(_463){
+_463=_463||window.event;
+key=_463.which||_463.keyCode;
+if(key==13){
+this.buildAndApplyFilter();
+}
+},this);
+var _464="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont;
+if(_427){
+_464+="; height: 10em; border-top: 2px solid black";
+}else{
+_464+="; height: 100%;";
+}
+_434.style.cssText=_464;
+if(!_435){
+doc.body.appendChild(_434);
+}
+_464={"cssText":"width: 33%; display: inline; font: "+this.logFont};
+_430(_437,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_462,"style":_464});
+_434.appendChild(_437);
+_430(_438,{"value":".*","onkeypress":_462,"style":_464});
+_434.appendChild(_438);
+_464="width: 8%; display:inline; font: "+this.logFont;
+_439.appendChild(doc.createTextNode("Filter"));
+_439.onclick=bind("buildAndApplyFilter",this);
+_439.style.cssText=_464;
+_434.appendChild(_439);
+_440.appendChild(doc.createTextNode("Load"));
+_440.onclick=_461;
+_440.style.cssText=_464;
+_434.appendChild(_440);
+_441.appendChild(doc.createTextNode("Clear"));
+_441.onclick=_458;
+_441.style.cssText=_464;
+_434.appendChild(_441);
+_442.appendChild(doc.createTextNode("Close"));
+_442.onclick=_459;
+_442.style.cssText=_464;
+_434.appendChild(_442);
+_443.style.cssText="overflow: auto; width: 100%";
+_444.style.cssText="width: 100%; height: "+(_427?"8em":"100%");
+_443.appendChild(_444);
+_434.appendChild(_443);
+this.buildAndApplyFilter();
+_461();
+if(_427){
+this.win=undefined;
+}else{
+this.win=win;
+}
+this.inline=_427;
+this.closePane=_459;
+this.closed=false;
+return this;
+};
+MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}};
+MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"];
+MochiKit.LoggingPane.EXPORT=["createLoggingPane"];
+MochiKit.LoggingPane.__new__=function(){
+this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)};
+MochiKit.Base.nameFunctions(this);
+MochiKit.LoggingPane._loggingPane=null;
+};
+MochiKit.LoggingPane.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Color");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.Base";
+}
+if(typeof (MochiKit.Color)=="undefined"){
+MochiKit.Color={};
+}
+MochiKit.Color.NAME="MochiKit.Color";
+MochiKit.Color.VERSION="1.3.1";
+MochiKit.Color.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Color.toString=function(){
+return this.__repr__();
+};
+MochiKit.Color.Color=function(red,_466,blue,_468){
+if(typeof (_468)=="undefined"||_468===null){
+_468=1;
+}
+this.rgb={r:red,g:_466,b:blue,a:_468};
+};
+MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_469){
+var rgb=this.rgb;
+var m=MochiKit.Color;
+return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_469);
+},colorWithHue:function(hue){
+var hsl=this.asHSL();
+hsl.h=hue;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithSaturation:function(_473){
+var hsl=this.asHSL();
+hsl.s=_473;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithLightness:function(_474){
+var hsl=this.asHSL();
+hsl.l=_474;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},darkerColorWithLevel:function(_475){
+var hsl=this.asHSL();
+hsl.l=Math.max(hsl.l-_475,0);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},lighterColorWithLevel:function(_476){
+var hsl=this.asHSL();
+hsl.l=Math.min(hsl.l+_476,1);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},blendedColor:function(_477,_478){
+if(typeof (_478)=="undefined"||_478===null){
+_478=0.5;
+}
+var sf=1-_478;
+var s=this.rgb;
+var d=_477.rgb;
+var df=_478;
+return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df));
+},compareRGB:function(_481){
+var a=this.asRGB();
+var b=_481.asRGB();
+return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]);
+},isLight:function(){
+return this.asHSL().b>0.5;
+},isDark:function(){
+return (!this.isLight());
+},toHSLString:function(){
+var c=this.asHSL();
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._hslString;
+if(!rval){
+var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%");
+var a=c.a;
+if(a>=1){
+a=1;
+rval="hsl("+mid+")";
+}else{
+if(a<=0){
+a=0;
+}
+rval="hsla("+mid+","+a+")";
+}
+this._hslString=rval;
+}
+return rval;
+},toRGBString:function(){
+var c=this.rgb;
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._rgbString;
+if(!rval){
+var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0));
+if(c.a!=1){
+rval="rgba("+mid+","+c.a+")";
+}else{
+rval="rgb("+mid+")";
+}
+this._rgbString=rval;
+}
+return rval;
+},asRGB:function(){
+return MochiKit.Base.clone(this.rgb);
+},toHexString:function(){
+var m=MochiKit.Color;
+var c=this.rgb;
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._hexString;
+if(!rval){
+rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255)));
+this._hexString=rval;
+}
+return rval;
+},asHSV:function(){
+var hsv=this.hsv;
+var c=this.rgb;
+if(typeof (hsv)=="undefined"||hsv===null){
+hsv=MochiKit.Color.rgbToHSV(this.rgb);
+this.hsv=hsv;
+}
+return MochiKit.Base.clone(hsv);
+},asHSL:function(){
+var hsl=this.hsl;
+var c=this.rgb;
+if(typeof (hsl)=="undefined"||hsl===null){
+hsl=MochiKit.Color.rgbToHSL(this.rgb);
+this.hsl=hsl;
+}
+return MochiKit.Base.clone(hsl);
+},toString:function(){
+return this.toRGBString();
+},repr:function(){
+var c=this.rgb;
+var col=[c.r,c.g,c.b,c.a];
+return this.__class__.NAME+"("+col.join(", ")+")";
+}};
+MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_486,blue,_487){
+var _488=MochiKit.Color.Color;
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_486=rgb.g;
+blue=rgb.b;
+if(typeof (rgb.a)=="undefined"){
+_487=undefined;
+}else{
+_487=rgb.a;
+}
+}
+return new _488(red,_486,blue,_487);
+},fromHSL:function(hue,_489,_490,_491){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hslToRGB.apply(m,arguments));
+},fromHSV:function(hue,_492,_493,_494){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments));
+},fromName:function(name){
+var _495=MochiKit.Color.Color;
+if(name.charAt(0)=="\""){
+name=name.substr(1,name.length-2);
+}
+var _496=_495._namedColors[name.toLowerCase()];
+if(typeof (_496)=="string"){
+return _495.fromHexString(_496);
+}else{
+if(name=="transparent"){
+return _495.transparentColor();
+}
+}
+return null;
+},fromString:function(_497){
+var self=MochiKit.Color.Color;
+var _498=_497.substr(0,3);
+if(_498=="rgb"){
+return self.fromRGBString(_497);
+}else{
+if(_498=="hsl"){
+return self.fromHSLString(_497);
+}else{
+if(_497.charAt(0)=="#"){
+return self.fromHexString(_497);
+}
+}
+}
+return self.fromName(_497);
+},fromHexString:function(_499){
+if(_499.charAt(0)=="#"){
+_499=_499.substring(1);
+}
+var _500=[];
+var i,hex;
+if(_499.length==3){
+for(i=0;i<3;i++){
+hex=_499.substr(i,1);
+_500.push(parseInt(hex+hex,16)/255);
+}
+}else{
+for(i=0;i<6;i+=2){
+hex=_499.substr(i,2);
+_500.push(parseInt(hex,16)/255);
+}
+}
+var _501=MochiKit.Color.Color;
+return _501.fromRGB.apply(_501,_500);
+},_fromColorString:function(pre,_503,_504,_505){
+if(_505.indexOf(pre)===0){
+_505=_505.substring(_505.indexOf("(",3)+1,_505.length-1);
+}
+var _506=_505.split(/\s*,\s*/);
+var _507=[];
+for(var i=0;i<_506.length;i++){
+var c=_506[i];
+var val;
+var _508=c.substring(c.length-3);
+if(c.charAt(c.length-1)=="%"){
+val=0.01*parseFloat(c.substring(0,c.length-1));
+}else{
+if(_508=="deg"){
+val=parseFloat(c)/360;
+}else{
+if(_508=="rad"){
+val=parseFloat(c)/(Math.PI*2);
+}else{
+val=_504[i]*parseFloat(c);
+}
+}
+}
+_507.push(val);
+}
+return this[_503].apply(this,_507);
+},fromComputedStyle:function(elem,_509,_510){
+var d=MochiKit.DOM;
+var cls=MochiKit.Color.Color;
+for(elem=d.getElement(elem);elem;elem=elem.parentNode){
+var _511=d.computedStyle.apply(d,arguments);
+if(!_511){
+continue;
+}
+var _512=cls.fromString(_511);
+if(!_512){
+break;
+}
+if(_512.asRGB().a>0){
+return _512;
+}
+}
+return null;
+},fromBackground:function(elem){
+var cls=MochiKit.Color.Color;
+return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor();
+},fromText:function(elem){
+var cls=MochiKit.Color.Color;
+return cls.fromComputedStyle(elem,"color","color")||cls.blackColor();
+},namedColors:function(){
+return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
+}});
+MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_513){
+v*=_513;
+if(v<0){
+return 0;
+}else{
+if(v>_513){
+return _513;
+}else{
+return v;
+}
+}
+},_hslValue:function(n1,n2,hue){
+if(hue>6){
+hue-=6;
+}else{
+if(hue<0){
+hue+=6;
+}
+}
+var val;
+if(hue<1){
+val=n1+(n2-n1)*hue;
+}else{
+if(hue<3){
+val=n2;
+}else{
+if(hue<4){
+val=n1+(n2-n1)*(4-hue);
+}else{
+val=n1;
+}
+}
+}
+return val;
+},hsvToRGB:function(hue,_516,_517,_518){
+if(arguments.length==1){
+var hsv=hue;
+hue=hsv.h;
+_516=hsv.s;
+_517=hsv.v;
+_518=hsv.a;
+}
+var red;
+var _519;
+var blue;
+if(_516===0){
+red=0;
+_519=0;
+blue=0;
+}else{
+var i=Math.floor(hue*6);
+var f=(hue*6)-i;
+var p=_517*(1-_516);
+var q=_517*(1-(_516*f));
+var t=_517*(1-(_516*(1-f)));
+switch(i){
+case 1:
+red=q;
+_519=_517;
+blue=p;
+break;
+case 2:
+red=p;
+_519=_517;
+blue=t;
+break;
+case 3:
+red=p;
+_519=q;
+blue=_517;
+break;
+case 4:
+red=t;
+_519=p;
+blue=_517;
+break;
+case 5:
+red=_517;
+_519=p;
+blue=q;
+break;
+case 6:
+case 0:
+red=_517;
+_519=t;
+blue=p;
+break;
+}
+}
+return {r:red,g:_519,b:blue,a:_518};
+},hslToRGB:function(hue,_521,_522,_523){
+if(arguments.length==1){
+var hsl=hue;
+hue=hsl.h;
+_521=hsl.s;
+_522=hsl.l;
+_523=hsl.a;
+}
+var red;
+var _524;
+var blue;
+if(_521===0){
+red=_522;
+_524=_522;
+blue=_522;
+}else{
+var m2;
+if(_522<=0.5){
+m2=_522*(1+_521);
+}else{
+m2=_522+_521-(_522*_521);
+}
+var m1=(2*_522)-m2;
+var f=MochiKit.Color._hslValue;
+var h6=hue*6;
+red=f(m1,m2,h6+2);
+_524=f(m1,m2,h6);
+blue=f(m1,m2,h6-2);
+}
+return {r:red,g:_524,b:blue,a:_523};
+},rgbToHSV:function(red,_528,blue,_529){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_528=rgb.g;
+blue=rgb.b;
+_529=rgb.a;
+}
+var max=Math.max(Math.max(red,_528),blue);
+var min=Math.min(Math.min(red,_528),blue);
+var hue;
+var _532;
+var _533=max;
+if(min==max){
+hue=0;
+_532=0;
+}else{
+var _534=(max-min);
+_532=_534/max;
+if(red==max){
+hue=(_528-blue)/_534;
+}else{
+if(_528==max){
+hue=2+((blue-red)/_534);
+}else{
+hue=4+((red-_528)/_534);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_532,v:_533,a:_529};
+},rgbToHSL:function(red,_535,blue,_536){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_535=rgb.g;
+blue=rgb.b;
+_536=rgb.a;
+}
+var max=Math.max(red,Math.max(_535,blue));
+var min=Math.min(red,Math.min(_535,blue));
+var hue;
+var _537;
+var _538=(max+min)/2;
+var _539=max-min;
+if(_539===0){
+hue=0;
+_537=0;
+}else{
+if(_538<=0.5){
+_537=_539/(max+min);
+}else{
+_537=_539/(2-max-min);
+}
+if(red==max){
+hue=(_535-blue)/_539;
+}else{
+if(_535==max){
+hue=2+((blue-red)/_539);
+}else{
+hue=4+((red-_535)/_539);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_537,l:_538,a:_536};
+},toColorPart:function(num){
+num=Math.round(num);
+var _540=num.toString(16);
+if(num<16){
+return "0"+_540;
+}
+return _540;
+},__new__:function(){
+var m=MochiKit.Base;
+this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]);
+this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]);
+var _541=1/3;
+var _542={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_541,_541,_541],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_541,2*_541,2*_541],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]};
+var _543=function(name,r,g,b,a){
+var rval=this.fromRGB(r,g,b,a);
+this[name]=function(){
+return rval;
+};
+return rval;
+};
+for(var k in _542){
+var name=k+"Color";
+var _545=m.concat([_543,this.Color,name],_542[k]);
+this.Color[name]=m.bind.apply(null,_545);
+}
+var _546=function(){
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof Color)){
+return false;
+}
+}
+return true;
+};
+var _547=function(a,b){
+return a.compareRGB(b);
+};
+m.nameFunctions(this);
+m.registerComparator(this.Color.NAME,_546,_547);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+}});
+MochiKit.Color.EXPORT=["Color"];
+MochiKit.Color.EXPORT_OK=["clampColorComponent","rgbToHSL","hslToRGB","rgbToHSV","hsvToRGB","toColorPart"];
+MochiKit.Color.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Color);
+MochiKit.Color.Color._namedColors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Signal");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Signal depends on MochiKit.Base!";
+}
+try{
+if(typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Signal depends on MochiKit.DOM!";
+}
+if(typeof (MochiKit.Signal)=="undefined"){
+MochiKit.Signal={};
+}
+MochiKit.Signal.NAME="MochiKit.Signal";
+MochiKit.Signal.VERSION="1.3.1";
+MochiKit.Signal._observers=[];
+MochiKit.Signal.Event=function(src,e){
+this._event=e||window.event;
+this._src=src;
+};
+MochiKit.Base.update(MochiKit.Signal.Event.prototype,{__repr__:function(){
+var repr=MochiKit.Base.repr;
+var str="{event(): "+repr(this.event())+", src(): "+repr(this.src())+", type(): "+repr(this.type())+", target(): "+repr(this.target())+", modifier(): "+"{alt: "+repr(this.modifier().alt)+", ctrl: "+repr(this.modifier().ctrl)+", meta: "+repr(this.modifier().meta)+", shift: "+repr(this.modifier().shift)+", any: "+repr(this.modifier().any)+"}";
+if(this.type()&&this.type().indexOf("key")===0){
+str+=", key(): {code: "+repr(this.key().code)+", string: "+repr(this.key().string)+"}";
+}
+if(this.type()&&(this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu")){
+str+=", mouse(): {page: "+repr(this.mouse().page)+", client: "+repr(this.mouse().client);
+if(this.type()!="mousemove"){
+str+=", button: {left: "+repr(this.mouse().button.left)+", middle: "+repr(this.mouse().button.middle)+", right: "+repr(this.mouse().button.right)+"}}";
+}else{
+str+="}";
+}
+}
+if(this.type()=="mouseover"||this.type()=="mouseout"){
+str+=", relatedTarget(): "+repr(this.relatedTarget());
+}
+str+="}";
+return str;
+},toString:function(){
+return this.__repr__();
+},src:function(){
+return this._src;
+},event:function(){
+return this._event;
+},type:function(){
+return this._event.type||undefined;
+},target:function(){
+return this._event.target||this._event.srcElement;
+},relatedTarget:function(){
+if(this.type()=="mouseover"){
+return (this._event.relatedTarget||this._event.fromElement);
+}else{
+if(this.type()=="mouseout"){
+return (this._event.relatedTarget||this._event.toElement);
+}
+}
+return undefined;
+},modifier:function(){
+var m={};
+m.alt=this._event.altKey;
+m.ctrl=this._event.ctrlKey;
+m.meta=this._event.metaKey||false;
+m.shift=this._event.shiftKey;
+m.any=m.alt||m.ctrl||m.shift||m.meta;
+return m;
+},key:function(){
+var k={};
+if(this.type()&&this.type().indexOf("key")===0){
+if(this.type()=="keydown"||this.type()=="keyup"){
+k.code=this._event.keyCode;
+k.string=(MochiKit.Signal._specialKeys[k.code]||"KEY_UNKNOWN");
+return k;
+}else{
+if(this.type()=="keypress"){
+k.code=0;
+k.string="";
+if(typeof (this._event.charCode)!="undefined"&&this._event.charCode!==0&&!MochiKit.Signal._specialMacKeys[this._event.charCode]){
+k.code=this._event.charCode;
+k.string=String.fromCharCode(k.code);
+}else{
+if(this._event.keyCode&&typeof (this._event.charCode)=="undefined"){
+k.code=this._event.keyCode;
+k.string=String.fromCharCode(k.code);
+}
+}
+return k;
+}
+}
+}
+return undefined;
+},mouse:function(){
+var m={};
+var e=this._event;
+if(this.type()&&(this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu")){
+m.client=new MochiKit.DOM.Coordinates(0,0);
+if(e.clientX||e.clientY){
+m.client.x=(!e.clientX||e.clientX<0)?0:e.clientX;
+m.client.y=(!e.clientY||e.clientY<0)?0:e.clientY;
+}
+m.page=new MochiKit.DOM.Coordinates(0,0);
+if(e.pageX||e.pageY){
+m.page.x=(!e.pageX||e.pageX<0)?0:e.pageX;
+m.page.y=(!e.pageY||e.pageY<0)?0:e.pageY;
+}else{
+var de=MochiKit.DOM._document.documentElement;
+var b=MochiKit.DOM._document.body;
+m.page.x=e.clientX+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||b.clientLeft);
+m.page.y=e.clientY+(de.scrollTop||b.scrollTop)-(de.clientTop||b.clientTop);
+}
+if(this.type()!="mousemove"){
+m.button={};
+m.button.left=false;
+m.button.right=false;
+m.button.middle=false;
+if(e.which){
+m.button.left=(e.which==1);
+m.button.middle=(e.which==2);
+m.button.right=(e.which==3);
+}else{
+m.button.left=!!(e.button&1);
+m.button.right=!!(e.button&2);
+m.button.middle=!!(e.button&4);
+}
+}
+return m;
+}
+return undefined;
+},stop:function(){
+this.stopPropagation();
+this.preventDefault();
+},stopPropagation:function(){
+if(this._event.stopPropagation){
+this._event.stopPropagation();
+}else{
+this._event.cancelBubble=true;
+}
+},preventDefault:function(){
+if(this._event.preventDefault){
+this._event.preventDefault();
+}else{
+this._event.returnValue=false;
+}
+}});
+MochiKit.Signal._specialMacKeys={3:"KEY_ENTER",63289:"KEY_NUM_PAD_CLEAR",63276:"KEY_PAGE_UP",63277:"KEY_PAGE_DOWN",63275:"KEY_END",63273:"KEY_HOME",63234:"KEY_ARROW_LEFT",63232:"KEY_ARROW_UP",63235:"KEY_ARROW_RIGHT",63233:"KEY_ARROW_DOWN",63302:"KEY_INSERT",63272:"KEY_DELETE"};
+for(i=63236;i<=63242;i++){
+MochiKit.Signal._specialMacKeys[i]="KEY_F"+(i-63236+1);
+}
+MochiKit.Signal._specialKeys={8:"KEY_BACKSPACE",9:"KEY_TAB",12:"KEY_NUM_PAD_CLEAR",13:"KEY_ENTER",16:"KEY_SHIFT",17:"KEY_CTRL",18:"KEY_ALT",19:"KEY_PAUSE",20:"KEY_CAPS_LOCK",27:"KEY_ESCAPE",32:"KEY_SPACEBAR",33:"KEY_PAGE_UP",34:"KEY_PAGE_DOWN",35:"KEY_END",36:"KEY_HOME",37:"KEY_ARROW_LEFT",38:"KEY_ARROW_UP",39:"KEY_ARROW_RIGHT",40:"KEY_ARROW_DOWN",44:"KEY_PRINT_SCREEN",45:"KEY_INSERT",46:"KEY_DELETE",59:"KEY_SEMICOLON",91:"KEY_WINDOWS_LEFT",92:"KEY_WINDOWS_RIGHT",93:"KEY_SELECT",106:"KEY_NUM_PAD_ASTERISK",107:"KEY_NUM_PAD_PLUS_SIGN",109:"KEY_NUM_PAD_HYPHEN-MINUS",110:"KEY_NUM_PAD_FULL_STOP",111:"KEY_NUM_PAD_SOLIDUS",144:"KEY_NUM_LOCK",145:"KEY_SCROLL_LOCK",186:"KEY_SEMICOLON",187:"KEY_EQUALS_SIGN",188:"KEY_COMMA",189:"KEY_HYPHEN-MINUS",190:"KEY_FULL_STOP",191:"KEY_SOLIDUS",192:"KEY_GRAVE_ACCENT",219:"KEY_LEFT_SQUARE_BRACKET",220:"KEY_REVERSE_SOLIDUS",221:"KEY_RIGHT_SQUARE_BRACKET",222:"KEY_APOSTROPHE"};
+for(var i=48;i<=57;i++){
+MochiKit.Signal._specialKeys[i]="KEY_"+(i-48);
+}
+for(i=65;i<=90;i++){
+MochiKit.Signal._specialKeys[i]="KEY_"+String.fromCharCode(i);
+}
+for(i=96;i<=105;i++){
+MochiKit.Signal._specialKeys[i]="KEY_NUM_PAD_"+(i-96);
+}
+for(i=112;i<=123;i++){
+MochiKit.Signal._specialKeys[i]="KEY_F"+(i-112+1);
+}
+MochiKit.Base.update(MochiKit.Signal,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},_unloadCache:function(){
+var self=MochiKit.Signal;
+var _548=self._observers;
+for(var i=0;i<_548.length;i++){
+self._disconnect(_548[i]);
+}
+delete self._observers;
+try{
+window.onload=undefined;
+}
+catch(e){
+}
+try{
+window.onunload=undefined;
+}
+catch(e){
+}
+},_listener:function(src,func,obj,_549){
+var E=MochiKit.Signal.Event;
+if(!_549){
+return MochiKit.Base.bind(func,obj);
+}
+obj=obj||src;
+if(typeof (func)=="string"){
+return function(_551){
+obj[func].apply(obj,[new E(src,_551)]);
+};
+}else{
+return function(_552){
+func.apply(obj,[new E(src,_552)]);
+};
+}
+},connect:function(src,sig,_554,_555){
+src=MochiKit.DOM.getElement(src);
+var self=MochiKit.Signal;
+if(typeof (sig)!="string"){
+throw new Error("'sig' must be a string");
+}
+var obj=null;
+var func=null;
+if(typeof (_555)!="undefined"){
+obj=_554;
+func=_555;
+if(typeof (_555)=="string"){
+if(typeof (_554[_555])!="function"){
+throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
+}
+}else{
+if(typeof (_555)!="function"){
+throw new Error("'funcOrStr' must be a function or string");
+}
+}
+}else{
+if(typeof (_554)!="function"){
+throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
+}else{
+func=_554;
+}
+}
+if(typeof (obj)=="undefined"||obj===null){
+obj=src;
+}
+var _556=!!(src.addEventListener||src.attachEvent);
+var _557=self._listener(src,func,obj,_556);
+if(src.addEventListener){
+src.addEventListener(sig.substr(2),_557,false);
+}else{
+if(src.attachEvent){
+src.attachEvent(sig,_557);
+}
+}
+var _558=[src,sig,_557,_556,_554,_555];
+self._observers.push(_558);
+return _558;
+},_disconnect:function(_559){
+if(!_559[3]){
+return;
+}
+var src=_559[0];
+var sig=_559[1];
+var _560=_559[2];
+if(src.removeEventListener){
+src.removeEventListener(sig.substr(2),_560,false);
+}else{
+if(src.detachEvent){
+src.detachEvent(sig,_560);
+}else{
+throw new Error("'src' must be a DOM element");
+}
+}
+},disconnect:function(_561){
+var self=MochiKit.Signal;
+var _562=self._observers;
+var m=MochiKit.Base;
+if(arguments.length>1){
+var src=MochiKit.DOM.getElement(arguments[0]);
+var sig=arguments[1];
+var obj=arguments[2];
+var func=arguments[3];
+for(var i=_562.length-1;i>=0;i--){
+var o=_562[i];
+if(o[0]===src&&o[1]===sig&&o[4]===obj&&o[5]===func){
+self._disconnect(o);
+_562.splice(i,1);
+return true;
+}
+}
+}else{
+var idx=m.findIdentical(_562,_561);
+if(idx>=0){
+self._disconnect(_561);
+_562.splice(idx,1);
+return true;
+}
+}
+return false;
+},disconnectAll:function(src,sig){
+src=MochiKit.DOM.getElement(src);
+var m=MochiKit.Base;
+var _563=m.flattenArguments(m.extend(null,arguments,1));
+var self=MochiKit.Signal;
+var _564=self._disconnect;
+var _565=self._observers;
+if(_563.length===0){
+for(var i=_565.length-1;i>=0;i--){
+var _566=_565[i];
+if(_566[0]===src){
+_564(_566);
+_565.splice(i,1);
+}
+}
+}else{
+var sigs={};
+for(var i=0;i<_563.length;i++){
+sigs[_563[i]]=true;
+}
+for(var i=_565.length-1;i>=0;i--){
+var _566=_565[i];
+if(_566[0]===src&&_566[1] in sigs){
+_564(_566);
+_565.splice(i,1);
+}
+}
+}
+},signal:function(src,sig){
+var _568=MochiKit.Signal._observers;
+src=MochiKit.DOM.getElement(src);
+var args=MochiKit.Base.extend(null,arguments,2);
+var _569=[];
+for(var i=0;i<_568.length;i++){
+var _570=_568[i];
+if(_570[0]===src&&_570[1]===sig){
+try{
+_570[2].apply(src,args);
+}
+catch(e){
+_569.push(e);
+}
+}
+}
+if(_569.length==1){
+throw _569[0];
+}else{
+if(_569.length>1){
+var e=new Error("Multiple errors thrown in handling 'sig', see errors property");
+e.errors=_569;
+throw e;
+}
+}
+}});
+MochiKit.Signal.EXPORT_OK=[];
+MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll"];
+MochiKit.Signal.__new__=function(win){
+var m=MochiKit.Base;
+this._document=document;
+this._window=win;
+try{
+this.connect(window,"onunload",this._unloadCache);
+}
+catch(e){
+}
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Signal.__new__(this);
+if(!MochiKit.__compat__){
+connect=MochiKit.Signal.connect;
+disconnect=MochiKit.Signal.disconnect;
+disconnectAll=MochiKit.Signal.disconnectAll;
+signal=MochiKit.Signal.signal;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Signal);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Visual");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Color");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Color",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM and MochiKit.Color!";
+}
+if(typeof (MochiKit.Visual)=="undefined"){
+MochiKit.Visual={};
+}
+MochiKit.Visual.NAME="MochiKit.Visual";
+MochiKit.Visual.VERSION="1.3.1";
+MochiKit.Visual.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Visual.toString=function(){
+return this.__repr__();
+};
+MochiKit.Visual._RoundCorners=function(e,_571){
+e=MochiKit.DOM.getElement(e);
+this._setOptions(_571);
+if(this.options.__unstable__wrapElement){
+e=this._doWrap(e);
+}
+var _572=this.options.color;
+var C=MochiKit.Color.Color;
+if(this.options.color=="fromElement"){
+_572=C.fromBackground(e);
+}else{
+if(!(_572 instanceof C)){
+_572=C.fromString(_572);
+}
+}
+this.isTransparent=(_572.asRGB().a<=0);
+var _574=this.options.bgColor;
+if(this.options.bgColor=="fromParent"){
+_574=C.fromBackground(e.offsetParent);
+}else{
+if(!(_574 instanceof C)){
+_574=C.fromString(_574);
+}
+}
+this._roundCornersImpl(e,_572,_574);
+};
+MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){
+var _575=e.parentNode;
+var doc=MochiKit.DOM.currentDocument();
+if(typeof (doc.defaultView)=="undefined"||doc.defaultView===null){
+return e;
+}
+var _576=doc.defaultView.getComputedStyle(e,null);
+if(typeof (_576)=="undefined"||_576===null){
+return e;
+}
+var _577=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_576.getPropertyValue("padding-top"),marginRight:_576.getPropertyValue("padding-right"),marginBottom:_576.getPropertyValue("padding-bottom"),marginLeft:_576.getPropertyValue("padding-left"),padding:"0px"}});
+_577.innerHTML=e.innerHTML;
+e.innerHTML="";
+e.appendChild(_577);
+return e;
+},_roundCornersImpl:function(e,_578,_579){
+if(this.options.border){
+this._renderBorder(e,_579);
+}
+if(this._isTopRounded()){
+this._roundTopCorners(e,_578,_579);
+}
+if(this._isBottomRounded()){
+this._roundBottomCorners(e,_578,_579);
+}
+},_renderBorder:function(el,_580){
+var _581="1px solid "+this._borderColor(_580);
+var _582="border-left: "+_581;
+var _583="border-right: "+_581;
+var _584="style='"+_582+";"+_583+"'";
+el.innerHTML="<div "+_584+">"+el.innerHTML+"</div>";
+},_roundTopCorners:function(el,_585,_586){
+var _587=this._createCorner(_586);
+for(var i=0;i<this.options.numSlices;i++){
+_587.appendChild(this._createCornerSlice(_585,_586,i,"top"));
+}
+el.style.paddingTop=0;
+el.insertBefore(_587,el.firstChild);
+},_roundBottomCorners:function(el,_588,_589){
+var _590=this._createCorner(_589);
+for(var i=(this.options.numSlices-1);i>=0;i--){
+_590.appendChild(this._createCornerSlice(_588,_589,i,"bottom"));
+}
+el.style.paddingBottom=0;
+el.appendChild(_590);
+},_createCorner:function(_591){
+var dom=MochiKit.DOM;
+return dom.DIV({style:{backgroundColor:_591.toString()}});
+},_createCornerSlice:function(_592,_593,n,_594){
+var _595=MochiKit.DOM.SPAN();
+var _596=_595.style;
+_596.backgroundColor=_592.toString();
+_596.display="block";
+_596.height="1px";
+_596.overflow="hidden";
+_596.fontSize="1px";
+var _597=this._borderColor(_592,_593);
+if(this.options.border&&n===0){
+_596.borderTopStyle="solid";
+_596.borderTopWidth="1px";
+_596.borderLeftWidth="0px";
+_596.borderRightWidth="0px";
+_596.borderBottomWidth="0px";
+_596.height="0px";
+_596.borderColor=_597.toString();
+}else{
+if(_597){
+_596.borderColor=_597.toString();
+_596.borderStyle="solid";
+_596.borderWidth="0px 1px";
+}
+}
+if(!this.options.compact&&(n==(this.options.numSlices-1))){
+_596.height="2px";
+}
+this._setMargin(_595,n,_594);
+this._setBorder(_595,n,_594);
+return _595;
+},_setOptions:function(_598){
+this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false};
+MochiKit.Base.update(this.options,_598);
+this.options.numSlices=(this.options.compact?2:4);
+},_whichSideTop:function(){
+var _599=this.options.corners;
+if(this._hasString(_599,"all","top")){
+return "";
+}
+var _600=(_599.indexOf("tl")!=-1);
+var _601=(_599.indexOf("tr")!=-1);
+if(_600&&_601){
+return "";
+}
+if(_600){
+return "left";
+}
+if(_601){
+return "right";
+}
+return "";
+},_whichSideBottom:function(){
+var _602=this.options.corners;
+if(this._hasString(_602,"all","bottom")){
+return "";
+}
+var _603=(_602.indexOf("bl")!=-1);
+var _604=(_602.indexOf("br")!=-1);
+if(_603&&_604){
+return "";
+}
+if(_603){
+return "left";
+}
+if(_604){
+return "right";
+}
+return "";
+},_borderColor:function(_605,_606){
+if(_605=="transparent"){
+return _606;
+}else{
+if(this.options.border){
+return this.options.border;
+}else{
+if(this.options.blend){
+return _606.blendedColor(_605);
+}
+}
+}
+return "";
+},_setMargin:function(el,n,_607){
+var _608=this._marginSize(n)+"px";
+var _609=(_607=="top"?this._whichSideTop():this._whichSideBottom());
+var _610=el.style;
+if(_609=="left"){
+_610.marginLeft=_608;
+_610.marginRight="0px";
+}else{
+if(_609=="right"){
+_610.marginRight=_608;
+_610.marginLeft="0px";
+}else{
+_610.marginLeft=_608;
+_610.marginRight=_608;
+}
+}
+},_setBorder:function(el,n,_611){
+var _612=this._borderSize(n)+"px";
+var _613=(_611=="top"?this._whichSideTop():this._whichSideBottom());
+var _614=el.style;
+if(_613=="left"){
+_614.borderLeftWidth=_612;
+_614.borderRightWidth="0px";
+}else{
+if(_613=="right"){
+_614.borderRightWidth=_612;
+_614.borderLeftWidth="0px";
+}else{
+_614.borderLeftWidth=_612;
+_614.borderRightWidth=_612;
+}
+}
+},_marginSize:function(n){
+if(this.isTransparent){
+return 0;
+}
+var o=this.options;
+if(o.compact&&o.blend){
+var _615=[1,0];
+return _615[n];
+}else{
+if(o.compact){
+var _616=[2,1];
+return _616[n];
+}else{
+if(o.blend){
+var _617=[3,2,1,0];
+return _617[n];
+}else{
+var _618=[5,3,2,1];
+return _618[n];
+}
+}
+}
+},_borderSize:function(n){
+var o=this.options;
+var _619;
+if(o.compact&&(o.blend||this.isTransparent)){
+return 1;
+}else{
+if(o.compact){
+_619=[1,0];
+}else{
+if(o.blend){
+_619=[2,1,1,1];
+}else{
+if(o.border){
+_619=[0,2,0,0];
+}else{
+if(this.isTransparent){
+_619=[5,3,2,1];
+}else{
+return 0;
+}
+}
+}
+}
+}
+return _619[n];
+},_hasString:function(str){
+for(var i=1;i<arguments.length;i++){
+if(str.indexOf(arguments[i])!=-1){
+return true;
+}
+}
+return false;
+},_isTopRounded:function(){
+return this._hasString(this.options.corners,"all","top","tl","tr");
+},_isBottomRounded:function(){
+return this._hasString(this.options.corners,"all","bottom","bl","br");
+},_hasSingleTextChild:function(el){
+return (el.childNodes.length==1&&el.childNodes[0].nodeType==3);
+}};
+MochiKit.Visual.roundElement=function(e,_620){
+new MochiKit.Visual._RoundCorners(e,_620);
+};
+MochiKit.Visual.roundClass=function(_621,_622,_623){
+var _624=MochiKit.DOM.getElementsByTagAndClassName(_621,_622);
+for(var i=0;i<_624.length;i++){
+MochiKit.Visual.roundElement(_624[i],_623);
+}
+};
+MochiKit.Visual.Color=MochiKit.Color.Color;
+MochiKit.Visual.getElementsComputedStyle=MochiKit.DOM.computedStyle;
+MochiKit.Visual.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+MochiKit.Visual.EXPORT=["roundElement","roundClass"];
+MochiKit.Visual.EXPORT_OK=[];
+MochiKit.Visual.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Visual);
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.MochiKit)=="undefined"){
+MochiKit.MochiKit={};
+}
+MochiKit.MochiKit.NAME="MochiKit.MochiKit";
+MochiKit.MochiKit.VERSION="1.3.1";
+MochiKit.MochiKit.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.MochiKit.toString=function(){
+return this.__repr__();
+};
+MochiKit.MochiKit.SUBMODULES=["Base","Iter","Logging","DateTime","Format","Async","DOM","LoggingPane","Color","Signal","Visual"];
+if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.MochiKit");
+dojo.require("MochiKit.*");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.Iter",[]);
+JSAN.use("MochiKit.Logging",[]);
+JSAN.use("MochiKit.DateTime",[]);
+JSAN.use("MochiKit.Format",[]);
+JSAN.use("MochiKit.Async",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.LoggingPane",[]);
+JSAN.use("MochiKit.Color",[]);
+JSAN.use("MochiKit.Signal",[]);
+JSAN.use("MochiKit.Visual",[]);
+}
+(function(){
+var _625=MochiKit.Base.extend;
+var self=MochiKit.MochiKit;
+var _626=self.SUBMODULES;
+var _627=[];
+var _628=[];
+var _629={};
+var i,k,m,all;
+for(i=0;i<_626.length;i++){
+m=MochiKit[_626[i]];
+_625(_627,m.EXPORT);
+_625(_628,m.EXPORT_OK);
+for(k in m.EXPORT_TAGS){
+_629[k]=_625(_629[k],m.EXPORT_TAGS[k]);
+}
+all=m.EXPORT_TAGS[":all"];
+if(!all){
+all=_625(null,m.EXPORT,m.EXPORT_OK);
+}
+var j;
+for(j=0;j<all.length;j++){
+k=all[j];
+self[k]=m[k];
+}
+}
+self.EXPORT=_627;
+self.EXPORT_OK=_628;
+self.EXPORT_TAGS=_629;
+}());
+}else{
+if(typeof (MochiKit.__compat__)=="undefined"){
+MochiKit.__compat__=true;
+}
+(function(){
+var _630=document.getElementsByTagName("script");
+var _631="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+var base=null;
+var _632=null;
+var _633={};
+var i;
+for(i=0;i<_630.length;i++){
+var src=_630[i].getAttribute("src");
+if(!src){
+continue;
+}
+_633[src]=true;
+if(src.match(/MochiKit.js$/)){
+base=src.substring(0,src.lastIndexOf("MochiKit.js"));
+_632=_630[i];
+}
+}
+if(base===null){
+return;
+}
+var _634=MochiKit.MochiKit.SUBMODULES;
+for(var i=0;i<_634.length;i++){
+if(MochiKit[_634[i]]){
+continue;
+}
+var uri=base+_634[i]+".js";
+if(uri in _633){
+continue;
+}
+if(document.documentElement&&document.documentElement.namespaceURI==_631){
+var s=document.createElementNS(_631,"script");
+s.setAttribute("id","MochiKit_"+base+_634[i]);
+s.setAttribute("src",uri);
+s.setAttribute("type","application/x-javascript");
+_632.parentNode.appendChild(s);
+}else{
+document.write("<script src=\""+uri+"\" type=\"text/javascript\"></script>");
+}
+}
+})();
+}
+
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit/__package__.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/MochiKit/__package__.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,2 @@
+dojo.hostenv.conditionalLoadModule({"common": ["MochiKit.MochiKit"]});
+dojo.hostenv.moduleLoaded("MochiKit.*");

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Base.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Base.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,406 @@
+/*
+    PlotKit
+    =======
+    PlotKit is a collection of Javascript classes that allows
+    you to quickly visualise data using different types of charts.
+
+    For license/info/documentation: http://www.liquidx.net/plotkit/
+
+    Copyright
+    ---------
+    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
+    For use under the BSD license. <http://www.liquidx.net/plotkit>
+*/
+
+// --------------------------------------------------------------------
+// Check required components
+// --------------------------------------------------------------------
+
+try {    
+    if (typeof(MochiKit.Base) == 'undefined'   ||
+        typeof(MochiKit.DOM) == 'undefined'    ||
+        typeof(MochiKit.Color) == 'undefined'  ||
+        typeof(MochiKit.Format) == 'undefined')
+    {
+        throw "";    
+    }
+} 
+catch (e) {    
+    throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format}"
+}
+
+// -------------------------------------------------------------------
+// Inject Common Shortcuts we use into MochiKit.Color.Color
+// -------------------------------------------------------------------
+
+MochiKit.Base.update(MochiKit.Color.Color.prototype, {
+    asFillColor: function() {
+        return this.lighterColorWithLevel(0.3);
+    },
+        
+    asStrokeColor: function() {
+        return this.darkerColorWithLevel(0.1);
+    },
+
+    asPointColor: function() {
+        return this.lighterColorWithLevel(0.1);
+    }
+});
+
+
+// -------------------------------------------------------------------
+// Define our own PlotKit namespace
+// -------------------------------------------------------------------
+
+if (typeof(PlotKit) == 'undefined') {
+    PlotKit = {};
+}
+
+PlotKit.NAME = "PlotKit";
+PlotKit.VERSION = "0.8";
+PlotKit.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.toString = function() {
+    return this.__repr__();
+}
+
+// -------------------------------------------------------------------
+//  Encapsulate all our utility function into it's own namespace.
+// -------------------------------------------------------------------
+
+if (typeof(PlotKit.Base) == 'undefined') {
+    PlotKit.Base = {};
+}
+
+PlotKit.Base.NAME = 'PlotKit.Base';
+PlotKit.Base.VERSION = PlotKit.VERSION;
+
+PlotKit.Base.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.Base.toString = function() {
+    return this.__repr__();
+}
+
+
+// Detect whether we are using prototype.js
+PlotKit.Base.usingPrototype =  function() {
+    try {
+        return (typeof(Object.extend) == 'function');
+    }
+    catch (e) {
+        return false;
+    }
+}
+
+
+MochiKit.Base.update(PlotKit.Base, {
+    roundInterval: function(range, intervals, precision) {
+        // We want to make the interval look regular,
+        var trunc = MochiKit.Format.roundToFixed;
+        var sep = range/intervals;
+        return parseFloat(trunc(sep, precision));
+    },
+
+    collapse: function(lst) {
+        var m = MochiKit.Base;
+        var biggerList = new Array();
+        for (var i = 0; i < lst.length; i++) {
+            biggerList = m.concat(biggerList, lst[i]);
+        }
+        if (PlotKit.Base.usingPrototype()) {
+            delete biggerList.extend;
+            delete biggerList.from;
+            delete biggerList.inspect;
+        }
+        
+        return biggerList;
+    },
+    
+    uniq: function(sortedList) {
+        // get unique elements in list, exactly the same as unix shell's uniq.
+        var m = MochiKit.Base;
+        
+        if (!m.isArrayLike(sortedList) || (sortedList.length < 1))
+            return new Array();
+
+        var uniq = new Array();
+        var lastElem = sortedList[0];    
+        uniq.push(sortedList[0]);
+        for (var i = 1; i < sortedList.length; i++) {
+            if (m.compare(sortedList[i], lastElem) != 0) {
+                lastElem = sortedList[i];
+                uniq.push(sortedList[i]);            
+            }
+        }
+        return uniq;
+    },
+    
+    colorScheme: function() {
+        var mb = MochiKit.Base;
+        var mc = MochiKit.Color
+        var scheme = ["red", "orange", "yellow", "green", "cyan", "blue", "purple", "magenta"];
+        
+        var makeColor = function(name) {
+            return mc.Color[name + "Color"]()
+        };
+        
+        return mb.map(makeColor, scheme);
+    },
+
+    baseDarkPrimaryColors: function () {
+        var hexColor = MochiKit.Color.Color.fromHexString;
+        return [hexColor("#ad3f40"),
+                hexColor("#ddac2c"),
+                hexColor("#dfdd0c"),
+                hexColor("#5276c4"),
+                hexColor("#739c5a")];
+    },
+
+    basePrimaryColors: function () {
+        var hexColor = MochiKit.Color.Color.fromHexString;
+        return [hexColor("#d24c4d"),
+                hexColor("#f2b32f"),
+                hexColor("#ece90e"),
+                hexColor("#5d83da"),
+                hexColor("#78a15d")];
+    },
+    
+    baseBlueColors: function () {
+         var hexColor = MochiKit.Color.Color.fromHexString;
+         return [hexColor("#4b6b94"), hexColor("#5d81b4"), hexColor("#acbad2")];
+    },
+
+    palette: function(baseColor, fromLevel, toLevel, increment) {
+        var isNil = MochiKit.Base.isUndefinedOrNull;
+        var fractions = new Array();
+        if (isNil(increment))
+            increment = 0.1;
+        if (isNil(toLevel))
+            toLevel = 0.4;
+        if (isNil(fromLevel))
+            fromLevel = -0.2;
+
+        var level = fromLevel;
+        while (level <= toLevel) {
+            fractions.push(level);
+            level += increment;
+        }
+            
+        var makeColor = function(color, fraction) {
+            return color.lighterColorWithLevel(fraction);
+        };
+        return MochiKit.Base.map(partial(makeColor, baseColor), fractions);
+    },
+    
+    excanvasSupported: function() {
+         if (/MSIE/.test(navigator.userAgent) && !window.opera) {
+             return true;
+         }
+         return false;
+    },
+
+    // The following functions are from quirksmode.org
+    // http://www.quirksmode.org/js/findpos.html
+
+    findPosX: function(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;
+    },
+                       
+   findPosY: function(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;
+   },
+   
+   isFuncLike: function(obj) {
+       return (typeof(obj) == 'function');
+   }
+});    
+
+//
+// Prototype.js aware (crippled) versions of map and items.
+//
+
+PlotKit.Base.map = function(fn, lst) {
+    if (PlotKit.Base.usingPrototype()) {
+        var rval = [];
+        for (var x in lst) {
+            if (typeof(lst[x]) == 'function') continue;
+            rval.push(fn(lst[x]));
+        }
+        return rval;
+    }
+    else {
+        return MochiKit.Base.map(fn, lst);
+    }
+};
+
+PlotKit.Base.items = function(lst) {
+    if (PlotKit.Base.usingPrototype()) {
+        var rval = [];
+         for (var x in lst) {
+             if (typeof(lst[x]) == 'function') continue;
+             rval.push([x, lst[x]]);
+         }
+         return rval;
+    }
+    else {
+        return MochiKit.Base.items(lst);
+    }
+};
+
+PlotKit.Base.keys = function(lst) {
+    if (PlotKit.Base.usingPrototype()) {
+        var rval = [];
+         for (var x in lst) {
+             if (typeof(lst[x]) == 'function') continue;
+             rval.push(x);
+         }
+         return rval;
+    }
+    else {
+        return MochiKit.Base.keys(lst);
+    }
+};
+
+// 
+// colour schemes
+//
+
+PlotKit.Base.baseColors = function () {
+   var hexColor = MochiKit.Color.Color.fromHexString;
+   return [hexColor("#476fb2"),
+           hexColor("#be2c2b"),
+           hexColor("#85b730"),
+           hexColor("#734a99"),
+           hexColor("#26a1c5"),
+           hexColor("#fb8707"),
+           hexColor("#000000")];
+};
+
+PlotKit.Base.officeBaseStyle = {
+    "axisLineWidth": 2.0,
+    "axisLabelColor": Color.grayColor(),
+    "axisLineColor": Color.whiteColor(),
+    "padding": {top: 5, bottom: 10, left: 30, right: 30}
+};    
+
+MochiKit.Base.update(PlotKit.Base,{
+    officeBlue: function() {
+        var r = {
+        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),
+        "backgroundColor": PlotKit.Base.baseColors()[0].lighterColorWithLevel(0.45)
+        };
+        MochiKit.Base.update(r, PlotKit.Base.officeBaseStyle);
+        return r;
+    },
+    officeRed: function() {
+        var r = {
+        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),
+        "backgroundColor": PlotKit.Base.baseColors()[1].lighterColorWithLevel(0.5)
+        };
+        MochiKit.Base.update(r, PlotKit.Base.officeBaseStyle);
+        return r;
+    },
+    officeGreen: function() {
+        var r = {
+        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[2]),
+        "backgroundColor": PlotKit.Base.baseColors()[2].lighterColorWithLevel(0.5)
+        };
+        MochiKit.Base.update(r, PlotKit.Base.officeBaseStyle);
+        return r;
+    },
+    officePurple: function() {
+        var r = {
+        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[3]),
+        "backgroundColor": PlotKit.Base.baseColors()[3].lighterColorWithLevel(0.5)
+        };
+        MochiKit.Base.update(r, PlotKit.Base.officeBaseStyle);
+        return r;
+    },
+    
+    officeCyan: function() {
+        var r = {
+            "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[4]),
+            "backgroundColor": PlotKit.Base.baseColors()[4].lighterColorWithLevel(0.5)
+            };
+        MochiKit.Base.update(r, PlotKit.Base.officeBaseStyle);
+        return r;
+    },
+    
+    officeOrange: function() {
+        var r = {
+            "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[5]),
+            "backgroundColor": PlotKit.Base.baseColors()[5].lighterColorWithLevel(0.4)
+            };
+        MochiKit.Base.update(r, PlotKit.Base.officeBaseStyle);
+        return r;
+    },
+    
+    officeBlack: function() {
+        var r = {
+        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[6], 0.0, 0.6),
+        "backgroundColor": PlotKit.Base.baseColors()[6].lighterColorWithLevel(0.9)
+        };
+        MochiKit.Base.update(r, PlotKit.Base.officeBaseStyle);
+        return r;
+    }
+});
+
+
+PlotKit.Base.EXPORT = [
+   "baseColors",
+   "collapse",
+   "colorScheme",
+   "findPosX",
+   "findPosY",
+   "officeBaseStyle",
+   "officeBlue",
+   "officeRed",
+   "officeGreen",
+   "officePurple",
+   "officeCyan",
+   "officeOrange",
+   "officeBlack",
+   "roundInterval",
+   "uniq",
+   "isFuncLike",
+   "excanvasSupported"
+];
+
+PlotKit.Base.EXPORT_OK = [];
+
+PlotKit.Base.__new__ = function() {
+    var m = MochiKit.Base;
+    
+    m.nameFunctions(this);
+    
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+PlotKit.Base.__new__();
+MochiKit.Base._exportSymbols(this, PlotKit.Base);
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Canvas.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Canvas.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,683 @@
+/* 
+    PlotKit Canvas
+    ==============
+    
+    Provides HTML Canvas Renderer. This is supported under:
+    
+    - Safari 2.0
+    - Mozilla Firefox 1.5
+    - Opera 9.0 preview 2
+    - IE 6 (via VML Emulation)
+    
+    It uses DIVs for labels.
+    
+    Copyright
+    ---------
+    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
+    For use under the BSD license. <http://www.liquidx.net/plotkit>
+    
+*/
+// --------------------------------------------------------------------
+// Check required components
+// --------------------------------------------------------------------
+
+try {    
+    if ((typeof(PlotKit.Base) == 'undefined') ||
+        (typeof(PlotKit.Layout) == 'undefined'))
+    {
+        throw "";    
+    }
+} 
+catch (e) {    
+    throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Base,Layout}"
+}
+
+
+// ------------------------------------------------------------------------
+//  Defines the renderer class
+// ------------------------------------------------------------------------
+
+if (typeof(PlotKit.CanvasRenderer) == 'undefined') {
+    PlotKit.CanvasRenderer = {};
+}
+
+PlotKit.CanvasRenderer.NAME = "PlotKit.CanvasRenderer";
+PlotKit.CanvasRenderer.VERSION = PlotKit.VERSION;
+
+PlotKit.CanvasRenderer.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.CanvasRenderer.toString = function() {
+    return this.__repr__();
+}
+
+PlotKit.CanvasRenderer = function(element, layout, options) {
+    if (arguments.length  > 0)
+        this.__init__(element, layout, options);
+};
+
+PlotKit.CanvasRenderer.prototype.__init__ = function(element, layout, options) {
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+    var Color = MochiKit.Color.Color;
+    
+    // default options
+    this.options = {
+        "drawBackground": true,
+        "backgroundColor": Color.whiteColor(),
+        "padding": {left: 30, right: 30, top: 5, bottom: 10},
+        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),
+        "strokeColor": Color.whiteColor(),
+        "strokeColorTransform": "asStrokeColor",
+        "strokeWidth": 0.5,
+        "shouldFill": true,
+        "shouldStroke": true,
+        "drawXAxis": true,
+        "drawYAxis": true,
+        "axisLineColor": Color.blackColor(),
+        "axisLineWidth": 0.5,
+        "axisTickSize": 3,
+        "axisLabelColor": Color.blackColor(),
+        "axisLabelFont": "Arial",
+        "axisLabelFontSize": 9,
+		"axisLabelWidth": 50,
+		"pieRadius": 0.4,
+        "enableEvents": true
+    };
+    MochiKit.Base.update(this.options, options ? options : {});
+
+    this.layout = layout;
+    this.element = MochiKit.DOM.getElement(element);
+    this.container = this.element.parentNode;
+
+    // Stuff relating to Canvas on IE support    
+    this.isIE = PlotKit.Base.excanvasSupported();
+
+    if (this.isIE && !isNil(G_vmlCanvasManager)) {
+        this.IEDelay = 0.5;
+        this.maxTries = 5;
+        this.renderDelay = null;
+        this.clearDelay = null;
+        this.element = G_vmlCanvasManager.initElement(this.element);
+    }
+
+    this.height = this.element.height;
+    this.width = this.element.width;
+
+    // --- check whether everything is ok before we return
+
+    if (isNil(this.element))
+        throw "CanvasRenderer() - passed canvas is not found";
+
+    if (!this.isIE && !(PlotKit.CanvasRenderer.isSupported(this.element)))
+        throw "CanvasRenderer() - Canvas is not supported.";
+
+    if (isNil(this.container) || (this.container.nodeName.toLowerCase() != "div"))
+        throw "CanvasRenderer() - <canvas> needs to be enclosed in <div>";
+
+    // internal state
+    this.xlabels = new Array();
+    this.ylabels = new Array();
+    this.isFirstRender = true;
+
+    this.area = {
+        x: this.options.padding.left,
+        y: this.options.padding.top,
+        w: this.width - this.options.padding.left - this.options.padding.right,
+        h: this.height - this.options.padding.top - this.options.padding.bottom
+    };
+
+    MochiKit.DOM.updateNodeAttributes(this.container, 
+    {"style":{ "position": "relative", "width": this.width + "px"}});
+
+    // load event system if we have Signals
+    /* Disabled until we have a proper implementation
+    try {
+        this.event_isinside = null;
+        if (MochiKit.Signal && this.options.enableEvents) {
+            this._initialiseEvents();
+        }
+    }
+    catch (e) {
+        // still experimental
+    }
+    */
+};
+
+PlotKit.CanvasRenderer.prototype.render = function() {
+    if (this.isIE) {
+        // VML takes a while to start up, so we just poll every this.IEDelay
+        try {
+            if (this.renderDelay) {
+                this.renderDelay.cancel();
+                this.renderDelay = null;
+            }
+            var context = this.element.getContext("2d");
+        }
+        catch (e) {
+            this.isFirstRender = false;
+            if (this.maxTries-- > 0) {
+                this.renderDelay = MochiKit.Async.wait(this.IEDelay);
+                this.renderDelay.addCallback(bind(this.render, this));
+            }
+            return;
+        }
+    }
+
+    if (this.options.drawBackground)
+        this._renderBackground();
+
+    if (this.layout.style == "bar") {
+        this._renderBarChart();
+		this._renderBarAxis(); 
+	}
+    else if (this.layout.style == "pie") {
+        this._renderPieChart();
+		this._renderPieAxis();
+	}
+    else if (this.layout.style == "line") {
+        this._renderLineChart();
+		this._renderLineAxis();
+	}
+};
+
+PlotKit.CanvasRenderer.prototype._renderBarChartWrap = function(data, plotFunc) {
+    var context = this.element.getContext("2d");
+    var colorCount = this.options.colorScheme.length;
+    var colorScheme = this.options.colorScheme;
+    var setNames = MochiKit.Base.keys(this.layout.datasets);
+    var setCount = setNames.length;
+
+    for (var i = 0; i < setCount; i++) {
+        var setName = setNames[i];
+        var color = colorScheme[i%colorCount];
+        context.save();
+        context.fillStyle = color.toRGBString();
+        if (this.options.strokeColor)
+            context.strokeStyle = this.options.strokeColor.toRGBString();
+        else if (this.options.strokeColorTransform) 
+            context.strokeStyle = color[this.options.strokeColorTransform]().toRGBString();
+        
+        context.lineWidth = this.options.strokeWidth;
+        var forEachFunc = function(obj) {
+            if (obj.name == setName)
+                plotFunc(context, obj);
+        };                
+
+        MochiKit.Iter.forEach(data, bind(forEachFunc, this));
+        context.restore();
+    }
+};
+
+PlotKit.CanvasRenderer.prototype._renderBarChart = function() {
+    var bind = MochiKit.Base.bind;
+
+    var drawRect = function(context, bar) {
+        var x = this.area.w * bar.x + this.area.x;
+        var y = this.area.h * bar.y + this.area.y;
+        var w = this.area.w * bar.w;
+        var h = this.area.h * bar.h;       
+        if ((w < 1) || (h < 1))
+            return;
+        if (this.options.shouldFill)
+            context.fillRect(x, y, w, h);
+        if (this.options.shouldStroke)
+            context.strokeRect(x, y, w, h);                
+    };
+    this._renderBarChartWrap(this.layout.bars, bind(drawRect, this));
+};
+
+PlotKit.CanvasRenderer.prototype._renderLineChart = function() {
+    var context = this.element.getContext("2d");
+    var colorCount = this.options.colorScheme.length;
+    var colorScheme = this.options.colorScheme;
+    var setNames = MochiKit.Base.keys(this.layout.datasets);
+    var setCount = setNames.length;
+    var bind = MochiKit.Base.bind;
+    var partial = MochiKit.Base.partial;
+
+    for (var i = 0; i < setCount; i++) {
+        var setName = setNames[i];
+        var color = colorScheme[i%colorCount];
+        var strokeX = this.options.strokeColorTransform;
+
+        // setup graphics context
+        context.save();
+        context.fillStyle = color.toRGBString();
+        if (this.options.strokeColor)
+            context.strokeStyle = this.options.strokeColor.toRGBString();
+        else if (this.options.strokeColorTransform) 
+            context.strokeStyle = color[strokeX]().toRGBString();
+        
+        context.lineWidth = this.options.strokeWidth;
+        
+        // create paths
+        var makePath = function(ctx) {
+            ctx.beginPath();
+            ctx.moveTo(this.area.x, this.area.y + this.area.h);
+            var addPoint = function(ctx_, point) {
+                if (point.name == setName)
+                    ctx_.lineTo(this.area.w * point.x + this.area.x,
+                                this.area.h * point.y + this.area.y);
+            };
+            MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
+            ctx.lineTo(this.area.w + this.area.x,
+                           this.area.h + this.area.y);
+            ctx.lineTo(this.area.x, this.area.y + this.area.h);
+            ctx.closePath();
+        };
+
+        if (this.options.shouldFill) {
+            bind(makePath, this)(context);
+            context.fill();
+        }
+        if (this.options.shouldStroke) {
+            bind(makePath, this)(context);
+            context.stroke();
+        }
+
+        context.restore();
+    }
+};
+
+PlotKit.CanvasRenderer.prototype._renderPieChart = function() {
+    var context = this.element.getContext("2d");
+    var colorCount = this.options.colorScheme.length;
+    var slices = this.layout.slices;
+
+    var centerx = this.area.x + this.area.w * 0.5;
+    var centery = this.area.y + this.area.h * 0.5;
+    var radius = Math.min(this.area.w * this.options.pieRadius, 
+                          this.area.h * this.options.pieRadius);
+
+    if (this.isIE) {
+        centerx = parseInt(centerx);
+        centery = parseInt(centery);
+        radius = parseInt(radius);
+    }
+
+
+	// NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1
+	// so we have to subtract 90 degrees to make it start at y = 1, x = 0
+
+    for (var i = 0; i < slices.length; i++) {
+        var color = this.options.colorScheme[i%colorCount];
+        context.save();
+        context.fillStyle = color.toRGBString();
+
+        var makePath = function() {
+            context.beginPath();
+            context.moveTo(centerx, centery);
+            context.arc(centerx, centery, radius, 
+                        slices[i].startAngle - Math.PI/2,
+                        slices[i].endAngle - Math.PI/2,
+                        false);
+            context.lineTo(centerx, centery);
+            context.closePath();
+        };
+
+        if (Math.abs(slices[i].startAngle - slices[i].endAngle) > 0.001) {
+            if (this.options.shouldFill) {
+                makePath();
+                context.fill();
+            }
+            
+            if (this.options.shouldStroke) {
+                makePath();
+                context.lineWidth = this.options.strokeWidth;
+                if (this.options.strokeColor)
+                    context.strokeStyle = this.options.strokeColor.toRGBString();
+                else if (this.options.strokeColorTransform)
+                    context.strokeStyle = color[this.options.strokeColorTransform]().toRGBString();
+                context.stroke();
+            }
+        }
+        context.restore();
+    }
+};
+
+PlotKit.CanvasRenderer.prototype._renderBarAxis = function() {
+	this._renderAxis();
+}
+
+PlotKit.CanvasRenderer.prototype._renderLineAxis = function() {
+	this._renderAxis();
+};
+
+
+PlotKit.CanvasRenderer.prototype._renderAxis = function() {
+    if (!this.options.drawXAxis && !this.options.drawYAxis)
+        return;
+
+    var context = this.element.getContext("2d");
+
+    var labelStyle = {"style":
+         {"position": "absolute",
+          "fontSize": this.options.axisLabelFontSize + "px",
+          "zIndex": 10,
+          "color": this.options.axisLabelColor.toRGBString(),
+          "width": this.options.axisLabelWidth + "px",
+          "overflow": "hidden"
+         }
+    };
+
+    // axis lines
+    context.save();
+    context.strokeStyle = this.options.axisLineColor.toRGBString();
+    context.lineWidth = this.options.axisLineWidth;
+
+
+    if (this.options.drawYAxis) {
+        if (this.layout.yticks) {
+            var drawTick = function(tick) {
+                if (typeof(tick) == "function") return;
+                var x = this.area.x;
+                var y = this.area.y + tick[0] * this.area.h;
+                context.beginPath();
+                context.moveTo(x, y);
+                context.lineTo(x - this.options.axisTickSize, y);
+                context.closePath();
+                context.stroke();
+
+                var label = DIV(labelStyle, tick[1]);
+                label.style.top = (y - this.options.axisLabelFontSize) + "px";
+                label.style.left = (x - this.options.padding.left - this.options.axisTickSize) + "px";
+                label.style.textAlign = "right";
+                label.style.width = (this.options.padding.left - this.options.axisTickSize * 2) + "px";
+                MochiKit.DOM.appendChildNodes(this.container, label);
+                this.ylabels.push(label);
+            };
+            
+            MochiKit.Iter.forEach(this.layout.yticks, bind(drawTick, this));
+        }
+
+        context.beginPath();
+        context.moveTo(this.area.x, this.area.y);
+        context.lineTo(this.area.x, this.area.y + this.area.h);
+        context.closePath();
+        context.stroke();
+    }
+
+    if (this.options.drawXAxis) {
+        if (this.layout.xticks) {
+            var drawTick = function(tick) {
+                if (typeof(dataset) == "function") return;
+                
+                var x = this.area.x + tick[0] * this.area.w;
+                var y = this.area.y + this.area.h;
+                context.beginPath();
+                context.moveTo(x, y);
+                context.lineTo(x, y + this.options.axisTickSize);
+                context.closePath();
+                context.stroke();
+
+                var label = DIV(labelStyle, tick[1]);
+                label.style.top = (y + this.options.axisTickSize) + "px";
+                label.style.left = (x - this.options.axisLabelWidth/2) + "px";
+                label.style.textAlign = "center";
+                label.style.width = this.options.axisLabelWidth + "px";
+                MochiKit.DOM.appendChildNodes(this.container, label);
+                this.xlabels.push(label);
+            };
+            
+            MochiKit.Iter.forEach(this.layout.xticks, bind(drawTick, this));
+        }
+
+        context.beginPath();
+        context.moveTo(this.area.x, this.area.y + this.area.h);
+        context.lineTo(this.area.x + this.area.w, this.area.y + this.area.h);
+        context.closePath();
+        context.stroke();
+    }
+
+    context.restore();
+
+};
+
+PlotKit.CanvasRenderer.prototype._renderPieAxis = function() {
+    if (!this.options.drawXAxis)
+        return;
+
+	if (this.layout.xticks) {
+		// make a lookup dict for x->slice values
+		var lookup = new Array();
+		for (var i = 0; i < this.layout.slices.length; i++) {
+			lookup[this.layout.slices[i].xval] = this.layout.slices[i];
+		}
+		
+		var centerx = this.area.x + this.area.w * 0.5;
+	    var centery = this.area.y + this.area.h * 0.5;
+	    var radius = Math.min(this.area.w * this.options.pieRadius,
+	                          this.area.h * this.options.pieRadius);
+		var labelWidth = this.options.axisLabelWidth;
+		
+		for (var i = 0; i < this.layout.xticks.length; i++) {
+			var slice = lookup[this.layout.xticks[i][0]];
+			if (MochiKit.Base.isUndefinedOrNull(slice))
+				continue;
+				
+				
+			var angle = (slice.startAngle + slice.endAngle)/2;
+			// normalize the angle
+			var normalisedAngle = angle;
+			if (normalisedAngle > Math.PI * 2)
+				normalisedAngle = normalisedAngle - Math.PI * 2;
+			else if (normalisedAngle < 0)
+				normalisedAngle = normalisedAngle + Math.PI * 2;
+				
+			var labelx = centerx + Math.sin(normalisedAngle) * (radius + 10);
+	        var labely = centery - Math.cos(normalisedAngle) * (radius + 10);
+
+			var attrib = {"position": "absolute",
+	                      "zIndex": 11,
+	                      "width": labelWidth + "px",
+	                      "fontSize": this.options.axisLabelFontSize + "px",
+	                      "overflow": "hidden",
+						  "color": this.options.axisLabelColor.toHexString()
+						};
+
+			if (normalisedAngle <= Math.PI * 0.5) {
+	            // text on top and align left
+	            attrib["textAlign"] = "left";
+	            attrib["verticalAlign"] = "top";
+	            attrib["left"] = labelx + "px";
+	            attrib["top"] = (labely - this.options.axisLabelFontSize) + "px";
+	        }
+	        else if ((normalisedAngle > Math.PI * 0.5) && (normalisedAngle <= Math.PI)) {
+	            // text on bottom and align left
+	            attrib["textAlign"] = "left";
+	            attrib["verticalAlign"] = "bottom";     
+	            attrib["left"] = labelx + "px";
+	            attrib["top"] = labely + "px";
+
+	        }
+	        else if ((normalisedAngle > Math.PI) && (normalisedAngle <= Math.PI*1.5)) {
+	            // text on bottom and align right
+	            attrib["textAlign"] = "right";
+	            attrib["verticalAlign"] = "bottom"; 
+	            attrib["left"] = (labelx  - labelWidth) + "px";
+	            attrib["top"] = labely + "px";
+	        }
+	        else {
+	            // text on top and align right
+	            attrib["textAlign"] = "right";
+	            attrib["verticalAlign"] = "bottom";  
+	            attrib["left"] = (labelx  - labelWidth) + "px";
+	            attrib["top"] = (labely - this.options.axisLabelFontSize) + "px";
+	        }
+	
+			var label = DIV({'style': attrib}, this.layout.xticks[i][1]);
+			this.xlabels.push(label);
+			MochiKit.DOM.appendChildNodes(this.container, label);
+	  }
+		
+	}
+};
+
+PlotKit.CanvasRenderer.prototype._renderBackground = function() {
+    var context = this.element.getContext("2d");
+    context.save();
+    context.fillStyle = this.options.backgroundColor.toRGBString();
+    context.fillRect(0, 0, this.width, this.height);
+    context.restore();
+};
+
+PlotKit.CanvasRenderer.prototype.clear = function() {
+    if (this.isIE) {
+        // VML takes a while to start up, so we just poll every this.IEDelay
+        try {
+            if (this.clearDelay) {
+                this.clearDelay.cancel();
+                this.clearDelay = null;
+            }
+            var context = this.element.getContext("2d");
+        }
+        catch (e) {
+            this.isFirstRender = false;
+            this.clearDelay = MochiKit.Async.wait(this.IEDelay);
+            this.clearDelay.addCallback(bind(this.clear, this));
+            return;
+        }
+    }
+
+    var context = this.element.getContext("2d");
+    context.clearRect(0, 0, this.width, this.height);
+
+    MochiKit.Iter.forEach(this.xlabels, MochiKit.DOM.removeElement);
+    MochiKit.Iter.forEach(this.ylabels, MochiKit.DOM.removeElement);
+    this.xlabels = new Array();
+    this.ylabels = new Array();
+};
+
+// ----------------------------------------------------------------
+//  Everything below here is experimental and undocumented.
+// ----------------------------------------------------------------
+
+PlotKit.CanvasRenderer.prototype._initialiseEvents = function() {
+    var connect = MochiKit.Signal.connect;
+    var bind = MochiKit.Base.bind;
+    //MochiKit.Signal.registerSignals(this, ['onmouseover', 'onclick', 'onmouseout', 'onmousemove']);
+    //connect(this.element, 'onmouseover', bind(this.onmouseover, this));
+    //connect(this.element, 'onmouseout', bind(this.onmouseout, this));
+    //connect(this.element, 'onmousemove', bind(this.onmousemove, this));
+    connect(this.element, 'onclick', bind(this.onclick, this));
+};
+
+PlotKit.CanvasRenderer.prototype._resolveObject = function(e) {
+    // does not work in firefox
+	//var x = (e.event().offsetX - this.area.x) / this.area.w;
+	//var y = (e.event().offsetY - this.area.y) / this.area.h;
+
+    var x = (e.mouse().page.x - PlotKit.Base.findPosX(this.element) - this.area.x) / this.area.w;
+    var y = (e.mouse().page.y - PlotKit.Base.findPosY(this.element) - this.area.y) / this.area.h;
+	
+    //log(x, y);
+
+    var isHit = this.layout.hitTest(x, y);
+    if (isHit)
+        return isHit;
+    return null;
+};
+
+PlotKit.CanvasRenderer.prototype._createEventObject = function(layoutObj, e) {
+    if (layoutObj == null) {
+        return null;
+    }
+
+    e.chart = layoutObj
+    return e;
+};
+
+
+PlotKit.CanvasRenderer.prototype.onclick = function(e) {
+    var layoutObject = this._resolveObject(e);
+    var eventObject = this._createEventObject(layoutObject, e);
+    if (eventObject != null)
+        MochiKit.Signal.signal(this, "onclick", eventObject);
+};
+
+PlotKit.CanvasRenderer.prototype.onmouseover = function(e) {
+    var layoutObject = this._resolveObject(e);
+    var eventObject = this._createEventObject(layoutObject, e);
+    if (eventObject != null) 
+        signal(this, "onmouseover", eventObject);
+};
+
+PlotKit.CanvasRenderer.prototype.onmouseout = function(e) {
+    var layoutObject = this._resolveObject(e);
+    var eventObject = this._createEventObject(layoutObject, e);
+    if (eventObject == null)
+        signal(this, "onmouseout", e);
+    else 
+        signal(this, "onmouseout", eventObject);
+
+};
+
+PlotKit.CanvasRenderer.prototype.onmousemove = function(e) {
+    var layoutObject = this._resolveObject(e);
+    var eventObject = this._createEventObject(layoutObject, e);
+
+    if ((layoutObject == null) && (this.event_isinside == null)) {
+        // TODO: should we emit an event anyway?
+        return;
+    }
+
+    if ((layoutObject != null) && (this.event_isinside == null))
+        signal(this, "onmouseover", eventObject);
+
+    if ((layoutObject == null) && (this.event_isinside != null))
+        signal(this, "onmouseout", eventObject);
+
+    if ((layoutObject != null) && (this.event_isinside != null))
+        signal(this, "onmousemove", eventObject);
+
+    this.event_isinside = layoutObject;
+    //log("move", x, y);    
+};
+
+PlotKit.CanvasRenderer.isSupported = function(canvasName) {
+    var canvas = null;
+    try {
+        if (MochiKit.Base.isUndefinedOrNull(canvasName)) 
+            canvas = MochiKit.DOM.CANVAS({});
+        else
+            canvas = MochiKit.DOM.getElement(canvasName);
+        var context = canvas.getContext("2d");
+    }
+    catch (e) {
+        var ie = navigator.appVersion.match(/MSIE (\d\.\d)/);
+        var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
+        if ((!ie) || (ie[1] < 6) || (opera))
+            return false;
+        return true;
+    }
+    return true;
+};
+
+// Namespace Iniitialisation
+
+PlotKit.Canvas = {}
+PlotKit.Canvas.CanvasRenderer = PlotKit.CanvasRenderer;
+
+PlotKit.Canvas.EXPORT = [
+    "CanvasRenderer"
+];
+
+PlotKit.Canvas.EXPORT_OK = [
+    "CanvasRenderer"
+];
+
+PlotKit.Canvas.__new__ = function() {
+    var m = MochiKit.Base;
+    
+    m.nameFunctions(this);
+    
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+PlotKit.Canvas.__new__();
+MochiKit.Base._exportSymbols(this, PlotKit.Canvas);
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/EasyPlot.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/EasyPlot.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,161 @@
+/* 
+    PlotKit EasyPlot
+    ================
+
+    User friendly wrapper around the common plotting functions.
+
+    Copyright
+    ---------
+    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
+    For use under the BSD license. <http://www.liquidx.net/plotkit>
+    
+*/
+
+try {    
+    if (typeof(PlotKit.CanvasRenderer) == 'undefined')
+    {
+        throw ""
+    }
+} 
+catch (e) {    
+    throw "PlotKit.EasyPlot depends on all of PlotKit's components";
+}
+
+// --------------------------------------------------------------------
+// Start of EasyPlot definition
+// --------------------------------------------------------------------
+
+if (typeof(PlotKit.EasyPlot) == 'undefined') {
+    PlotKit.EasyPlot = {};
+}
+
+PlotKit.EasyPlot.NAME = "PlotKit.EasyPlot";
+PlotKit.EasyPlot.VERSION = PlotKit.VERSION;
+
+PlotKit.EasyPlot.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.EasyPlot.toString = function() {
+    return this.__repr__();
+}
+
+// --------------------------------------------------------------------
+// Start of EasyPlot definition
+// --------------------------------------------------------------------
+
+PlotKit.EasyPlot = function(style, options, divElem, datasources) {
+    this.layout = new Layout(style, options);
+    this.divElem = divElem;
+    this.width = parseInt(divElem.getAttribute('width'));
+    this.height = parseInt(divElem.getAttribute('height'));
+    this.deferredCount = 0;
+
+    // make sure we have non-zero width
+    if (this.width < 1) {
+        this.width = this.divElem.width ? this.divElem.width : 300;
+    }
+    
+    if (this.height < 1) {
+        this.height = this.divElem.height ? this.divElem.height : 300;
+    }
+    
+    // load data sources
+    if (isArrayLike(datasources)) {
+        for (var i = 0; i < datasources.length; i++) {
+            if (typeof(datasources[i]) == "string") {
+                this.deferredCount++;
+                // load CSV via ajax
+                var d = MochiKit.Async.doSimpleXMLHttpRequest(datasources[i]);
+                d.addCallback(MochiKit.Base.bind(PlotKit.EasyPlot.onDataLoaded, this));
+            }
+            else if (isArrayLike(datasources[i])) {
+                this.layout.addDataset("data-" + i, datasources[i]);
+            }
+        }
+    }
+    else if (!isUndefinedOrNull(datasources)) {
+        throw "Passed datasources are not Array like";
+    }
+    
+    // setup canvas to render
+    
+    if (CanvasRenderer.isSupported()) {
+        this.element = CANVAS({"id": this.divElem.getAttribute("id") + "-canvas",
+                               "width": this.width,
+                               "height": this.height}, "");
+        this.divElem.appendChild(this.element);
+        this.renderer = new SweetCanvasRenderer(this.element, this.layout, options);
+    }
+    else if (SVGRenderer.isSupported()) {
+        this.element = SVGRenderer.SVG({"id": this.divElem.getAttribute("id") + "-svg",
+                                        "width": this.width,
+                                        "height": this.height,
+                                        "version": "1.1",
+                                        "baseProfile": "full"}, "");
+        this.divElem.appendChild(this.element);
+        this.renderer = new SweetSVGRenderer(this.element, this.layout, options);
+    }
+    
+    if ((this.deferredCount == 0) && (PlotKit.Base.keys(this.layout.datasets).length > 0)) {
+        this.layout.evaluate();
+        this.renderer.clear();
+        this.renderer.render();    
+    }
+    
+};
+
+PlotKit.EasyPlot.onDataLoaded = function(request) {
+    
+    // very primitive CSV parser, should fix to make it more compliant.
+    var table = new Array();
+    var lines = request.responseText.split('\n');
+    for (var i = 0; i < lines.length; i++) {
+        var stripped = MochiKit.Format.strip(lines[i]);
+        if ((stripped.length > 1) && (stripped.charAt(0) != '#')) {
+            table.push(stripped.split(','));
+        }
+    }
+  
+    this.layout.addDataset("data-ajax-" + this.deferredCount, table);
+    this.deferredCount--;
+    
+    if ((this.deferredCount == 0) && (PlotKit.Base.keys(this.layout.datasets).length > 0)) {
+        this.layout.evaluate();
+        this.renderer.clear();
+        this.renderer.render();
+    }
+};
+
+PlotKit.EasyPlot.prototype.reload = function() {
+    this.layout.evaluate();
+    this.renderer.clear();
+    this.renderer.render();
+};
+
+// Namespace Iniitialisation
+
+PlotKit.EasyPlotModule = {};
+PlotKit.EasyPlotModule.EasyPlot = PlotKit.EasyPlot;
+
+PlotKit.EasyPlotModule.EXPORT = [
+    "EasyPlot"
+];
+
+PlotKit.EasyPlotModule.EXPORT_OK = [];
+
+PlotKit.EasyPlotModule.__new__ = function() {
+    var m = MochiKit.Base;
+    
+    m.nameFunctions(this);
+    
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+PlotKit.EasyPlotModule.__new__();
+MochiKit.Base._exportSymbols(this, PlotKit.EasyPlotModule);
+
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Layout.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/Layout.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,756 @@
+/* 
+    PlotKit Layout
+    ==============
+    
+    Handles laying out data on to a virtual canvas square canvas between 0.0 
+    and 1.0. If you want to add new chart/plot types such as point plots,
+    you need to add them here.
+    
+    Copyright
+    ---------
+    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
+    For use under the BSD license. <http://www.liquidx.net/plotkit>
+    
+*/
+
+try {    
+    if (typeof(PlotKit.Base) == 'undefined')
+    {
+        throw ""
+    }
+} 
+catch (e) {    
+    throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Base"
+}
+
+// --------------------------------------------------------------------
+// Start of Layout definition
+// --------------------------------------------------------------------
+
+if (typeof(PlotKit.Layout) == 'undefined') {
+    PlotKit.Layout = {};
+}
+
+PlotKit.Layout.NAME = "PlotKit.Layout";
+PlotKit.Layout.VERSION = PlotKit.VERSION;
+
+PlotKit.Layout.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.Layout.toString = function() {
+    return this.__repr__();
+}
+
+PlotKit.Layout.valid_styles = ["bar", "line", "pie", "point"];
+
+// --------------------------------------------------------------------
+// Start of Layout definition
+// --------------------------------------------------------------------
+
+PlotKit.Layout = function(style, options) {
+  
+    this.options = {
+        "barWidthFillFraction": 0.75,
+        "barOrientation": "vertical",
+        "xOriginIsZero": true,
+        "yOriginIsZero": true,
+        "xAxis": null, // [xmin, xmax]
+        "yAxis": null, // [ymin, ymax]
+        "xTicks": null, // [{label: "somelabel", v: value}, ..] (label opt.)
+        "yTicks": null, // [{label: "somelabel", v: value}, ..] (label opt.)
+        "xNumberOfTicks": 10,
+        "yNumberOfTicks": 5,
+        "xTickPrecision": 1,
+        "yTickPrecision": 1,
+        "pieRadius": 0.4
+    };
+
+    // valid external options : TODO: input verification
+    this.style = style; 
+    MochiKit.Base.update(this.options, options ? options : {});
+
+    // externally visible states
+    // overriden if xAxis and yAxis are set in options
+    if (!MochiKit.Base.isUndefinedOrNull(this.options.xAxis)) {
+        this.minxval = this.options.xAxis[0];
+        this.maxxval = this.options.xAxis[1];
+        this.xscale = this.maxxval - this.minxval; 
+    }
+    else {
+        this.minxval = 0;
+        this.maxxval = null;
+        this.xscale = null; // val -> pos factor (eg, xval * xscale = xpos)
+    }
+
+    if (!MochiKit.Base.isUndefinedOrNull(this.options.yAxis)) {
+        this.minyval = this.options.yAxis[0];
+        this.maxyval = this.options.yAxis[1];
+        this.yscale = this.maxyval - this.minyval;
+    }
+    else {
+        this.minyval = 0;
+        this.maxyval = null;
+        this.yscale = null;
+    }
+
+    this.bars = new Array();   // array of bars to plot for bar charts
+    this.points = new Array(); // array of points to plot for line plots
+    this.slices = new Array(); // array of slices to draw for pie charts
+
+    this.xticks = new Array();
+    this.yticks = new Array();
+
+    // internal states
+    this.datasets = new Array();
+    this.minxdelta = 0;
+    this.xrange = 1;
+    this.yrange = 1;
+
+    this.hitTestCache = {x2maxy: null};
+    
+};
+
+// --------------------------------------------------------------------
+// Dataset Manipulation
+// --------------------------------------------------------------------
+
+
+PlotKit.Layout.prototype.addDataset = function(setname, set_xy) {
+    this.datasets[setname] = set_xy;
+};
+
+PlotKit.Layout.prototype.removeDataset = function(setname, set_xy) {
+    delete this.datasets[setname];
+};
+
+PlotKit.Layout.prototype.addDatasetFromTable = function(name, tableElement, xcol, ycol,  lcol) {
+	var isNil = MochiKit.Base.isUndefinedOrNull;
+	var scrapeText = MochiKit.DOM.scrapeText;
+	var strip = MochiKit.Format.strip;
+	
+	if (isNil(xcol))
+		xcol = 0;
+	if (isNil(ycol))
+		ycol = 1;
+	if (isNil(lcol))
+	    lcol = -1;
+        
+    var rows = tableElement.tBodies[0].rows;
+    var data = new Array();
+    var labels = new Array();
+    
+    if (!isNil(rows)) {
+        for (var i = 0; i < rows.length; i++) {
+            data.push([parseFloat(strip(scrapeText(rows[i].cells[xcol]))),
+                       parseFloat(strip(scrapeText(rows[i].cells[ycol])))]);
+            if (lcol >= 0){
+               labels.push({v: parseFloat(strip(scrapeText(rows[i].cells[xcol]))),
+                            label:  strip(scrapeText(rows[i].cells[lcol]))});
+            }
+        }
+        this.addDataset(name, data);
+        if (lcol >= 0) {
+            this.options.xTicks = labels;
+        }
+        return true;
+    }
+    return false;
+};
+
+// --------------------------------------------------------------------
+// Evaluates the layout for the current data and style.
+// --------------------------------------------------------------------
+
+PlotKit.Layout.prototype.evaluate = function() {
+    this._evaluateLimits();
+    this._evaluateScales();
+    if (this.style == "bar") {
+        if (this.options.barOrientation == "horizontal") {
+            this._evaluateHorizBarCharts();
+        }
+        else {
+            this._evaluateBarCharts();
+        }
+        this._evaluateBarTicks();
+    }
+    else if (this.style == "line") {
+        this._evaluateLineCharts();
+        this._evaluateLineTicks();
+    }
+    else if (this.style == "pie") {
+        this._evaluatePieCharts();
+        this._evaluatePieTicks();
+    }
+};
+
+
+
+// Given the fractional x, y positions, report the corresponding
+// x, y values.
+PlotKit.Layout.prototype.hitTest = function(x, y) {
+    // TODO: make this more efficient with better datastructures
+    //       for this.bars, this.points and this.slices
+
+    var f = MochiKit.Format.twoDigitFloat;
+
+    if ((this.style == "bar") && this.bars && (this.bars.length > 0)) {
+        for (var i = 0; i < this.bars.length; i++) {
+            var bar = this.bars[i];
+            if ((x >= bar.x) && (x <= bar.x + bar.w) 
+                && (y >= bar.y) && (y - bar.y <= bar.h))
+                return bar;
+        }
+    }
+
+    else if (this.style == "line") {
+        if (this.hitTestCache.x2maxy == null) {
+            this._regenerateHitTestCache();
+        }
+
+        // 1. find the xvalues that equal or closest to the give x
+        var xval = x / this.xscale;
+        var xvalues = this.hitTestCache.xvalues;
+        var xbefore = null;
+        var xafter = null;
+
+        for (var i = 1; i < xvalues.length; i++) {
+            if (xvalues[i] > xval) {
+                xbefore = xvalues[i-1];
+                xafter = xvalues[i];
+                break;
+            }
+        }
+
+        if ((xbefore != null)) {
+            var ybefore = this.hitTestCache.x2maxy[xbefore];
+            var yafter = this.hitTestCache.x2maxy[xafter];
+            var yval = (1.0 - y)/this.yscale;
+
+            // interpolate whether we will fall inside or outside
+            var gradient = (yafter - ybefore) / (xafter - xbefore);
+            var projmaxy = ybefore + gradient * (xval - xbefore);
+            if (projmaxy >= yval) {
+                // inside the highest curve (roughly)
+                var obj = {xval: xval, yval: yval,
+                           xafter: xafter, yafter: yafter,
+                           xbefore: xbefore, ybefore: ybefore,
+                           yprojected: projmaxy
+                };
+                return obj;
+            }
+        }
+    }
+
+    else if (this.style == "pie") {
+        var dist = Math.sqrt((y-0.5)*(y-0.5) + (x-0.5)*(x-0.5));
+        if (dist > this.options.pieRadius)
+            return null;
+
+        // TODO: actually doesn't work if we don't know how the Canvas
+        //       lays it out, need to fix!
+        var angle = Math.atan2(y - 0.5, x - 0.5) - Math.PI/2;
+        for (var i = 0; i < this.slices.length; i++) {
+            var slice = this.slices[i];
+            if (slice.startAngle < angle && slice.endAngle >= angle)
+                return slice;
+        }
+    }
+
+    return null;
+};
+
+// Reports valid position rectangle for X value (only valid for bar charts)
+PlotKit.Layout.prototype.rectForX = function(x) {
+    return null;
+};
+
+// Reports valid angles through which X value encloses (only valid for pie charts)
+PlotKit.Layout.prototype.angleRangeForX = function(x) {
+    return null;
+};
+
+// --------------------------------------------------------------------
+// START Internal Functions
+// --------------------------------------------------------------------
+
+PlotKit.Layout.prototype._evaluateLimits = function() {
+    // take all values from all datasets and find max and min
+    var map = PlotKit.Base.map;
+    var items = PlotKit.Base.items;
+    var itemgetter = MochiKit.Base.itemgetter;
+    var collapse = PlotKit.Base.collapse;
+    var listMin = MochiKit.Base.listMin;
+    var listMax = MochiKit.Base.listMax;
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+
+
+    var all = collapse(map(itemgetter(1), items(this.datasets)));
+    if (isNil(this.options.xAxis)) {
+        if (this.options.xOriginIsZero)
+            this.minxval = 0;
+        else
+            this.minxval = listMin(map(parseFloat, map(itemgetter(0), all)));
+
+        this.maxxval = listMax(map(parseFloat, map(itemgetter(0), all)));
+    }
+    else {
+        this.minxval = this.options.xAxis[0];
+        this.maxxval = this.options.xAxis[1];
+        this.xscale = this.maxval - this.minxval;
+    }
+    
+    if (isNil(this.options.yAxis)) {
+        if (this.options.yOriginIsZero)
+            this.minyval = 0;
+        else
+            this.minyval = listMin(map(parseFloat, map(itemgetter(1), all)));
+
+        this.maxyval = listMax(map(parseFloat, map(itemgetter(1), all)));
+    }
+    else {
+        this.minyval = this.options.yAxis[0];
+        this.maxyval = this.options.yAxis[1];
+        this.yscale = this.maxyval - this.minyval;
+    }
+
+};
+
+PlotKit.Layout.prototype._evaluateScales = function() {
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+
+    this.xrange = this.maxxval - this.minxval;
+    if (this.xrange == 0)
+        this.xscale = 1.0;
+    else
+        this.xscale = 1/this.xrange;
+
+    this.yrange = this.maxyval - this.minyval;
+    if (this.yrange == 0)
+        this.yscale = 1.0;
+    else
+        this.yscale = 1/this.yrange;
+};
+
+PlotKit.Layout.prototype._uniqueXValues = function() {
+    var collapse = PlotKit.Base.collapse;
+    var map = PlotKit.Base.map;
+    var uniq = PlotKit.Base.uniq;
+    var getter = MochiKit.Base.itemgetter;
+    var items = PlotKit.Base.items;
+    
+    var xvalues = map(parseFloat, map(getter(0), collapse(map(getter(1), items(this.datasets)))));
+    xvalues.sort(MochiKit.Base.compare);
+    return uniq(xvalues);
+};
+
+// Create the bars
+PlotKit.Layout.prototype._evaluateBarCharts = function() {
+    var items = PlotKit.Base.items;
+
+    var setCount = items(this.datasets).length;
+
+    // work out how far separated values are
+    var xdelta = 10000000;
+    var xvalues = this._uniqueXValues();
+    for (var i = 1; i < xvalues.length; i++) {
+        xdelta = Math.min(Math.abs(xvalues[i] - xvalues[i-1]), xdelta);
+    }
+
+    var barWidth = 0;
+    var barWidthForSet = 0;
+    var barMargin = 0;
+    if (xvalues.length == 1) {
+        // note we have to do something smarter if we only plot one value
+        xdelta = 1.0;
+        this.xscale = 1.0;
+        this.minxval = xvalues[0];
+        barWidth = 1.0 * this.options.barWidthFillFraction;
+        barWidthForSet = barWidth/setCount;
+        barMargin = (1.0 - this.options.barWidthFillFraction)/2;
+    }
+    else {
+        // readjust xscale to fix with bar charts
+        if (this.xrange == 1) {
+            this.xscale = 0.5;
+        }
+        else if (this.xrange == 2) {
+            this.xscale = 1/3.0;
+        }
+        else {
+            this.xscale = (1.0 - xdelta/this.xrange)/this.xrange;
+        }
+        barWidth = xdelta * this.xscale * this.options.barWidthFillFraction;
+        barWidthForSet = barWidth / setCount;
+        barMargin = xdelta * this.xscale * (1.0 - this.options.barWidthFillFraction)/2;
+    }
+    
+    this.minxdelta = xdelta; // need this for tick positions
+
+    // add all the rects
+    this.bars = new Array();
+    var i = 0;
+    for (var setName in this.datasets) {
+        var dataset = this.datasets[setName];
+        if (PlotKit.Base.isFuncLike(dataset)) continue;
+        for (var j = 0; j < dataset.length; j++) {
+            var item = dataset[j];
+            var rect = {
+                x: ((parseFloat(item[0]) - this.minxval) * this.xscale) + (i * barWidthForSet) + barMargin,
+                y: 1.0 - ((parseFloat(item[1]) - this.minyval) * this.yscale),
+                w: barWidthForSet,
+                h: ((parseFloat(item[1]) - this.minyval) * this.yscale),
+                xval: parseFloat(item[0]),
+                yval: parseFloat(item[1]),
+                name: setName
+            };
+            if ((rect.x >= 0.0) && (rect.x <= 1.0) && 
+                (rect.y >= 0.0) && (rect.y <= 1.0)) {
+                this.bars.push(rect);
+            }
+        }
+        i++;
+    }
+};
+
+// Create the horizontal bars
+PlotKit.Layout.prototype._evaluateHorizBarCharts = function() {
+    var items = PlotKit.Base.items;
+
+    var setCount = items(this.datasets).length;
+
+    // work out how far separated values are
+    var xdelta = 10000000;
+    var xvalues = this._uniqueXValues();
+    for (var i = 1; i < xvalues.length; i++) {
+        xdelta = Math.min(Math.abs(xvalues[i] - xvalues[i-1]), xdelta);
+    }
+
+    var barWidth = 0;
+    var barWidthForSet = 0;
+    var barMargin = 0;
+    
+    // work out how far each far each bar is separated
+    if (xvalues.length == 1) {
+        // do something smarter if we only plot one value
+        xdelta = 1.0;
+        this.xscale = 1.0;
+        this.minxval = xvalues[0];
+        barWidth = 1.0 * this.options.barWidthFillFraction;
+        barWidthForSet = barWidth/setCount;
+        barMargin = (1.0 - this.options.barWidthFillFraction)/2;
+    }
+    else {
+        // readjust yscale to fix with bar charts
+        this.xscale = (1.0 - xdelta/this.xrange)/this.xrange;
+        barWidth = xdelta * this.xscale * this.options.barWidthFillFraction;
+        barWidthForSet = barWidth / setCount;
+        barMargin = xdelta * this.xscale * (1.0 - this.options.barWidthFillFraction)/2;
+    }
+
+    this.minxdelta = xdelta; // need this for tick positions
+
+    // add all the rects
+    this.bars = new Array();
+    var i = 0;
+    for (var setName in this.datasets) {
+        var dataset = this.datasets[setName];
+        if (PlotKit.Base.isFuncLike(dataset)) continue;
+        for (var j = 0; j < dataset.length; j++) {
+            var item = dataset[j];
+            var rect = {
+                y: ((parseFloat(item[0]) - this.minxval) * this.xscale) + (i * barWidthForSet) + barMargin,
+                x: 0.0,
+                h: barWidthForSet,
+                w: ((parseFloat(item[1]) - this.minyval) * this.yscale),
+                xval: parseFloat(item[0]),
+                yval: parseFloat(item[1]),
+                name: setName
+            };
+
+            // limit the x, y values so they do not overdraw
+            if (rect.y <= 0.0) {
+                rect.y = 0.0;
+            }
+            if (rect.y >= 1.0) {
+                rect.y = 1.0;
+            }
+            if ((rect.x >= 0.0) && (rect.x <= 1.0)) {
+                this.bars.push(rect);
+            }
+        }
+        i++;
+    }
+};
+
+
+// Create the line charts
+PlotKit.Layout.prototype._evaluateLineCharts = function() {
+    var items = PlotKit.Base.items;
+
+    var setCount = items(this.datasets).length;
+
+    // add all the rects
+    this.points = new Array();
+    var i = 0;
+    for (var setName in this.datasets) {
+        var dataset = this.datasets[setName];
+        if (PlotKit.Base.isFuncLike(dataset)) continue;
+        dataset.sort(function(a, b) { return compare(parseFloat(a[0]), parseFloat(b[0])); });
+        for (var j = 0; j < dataset.length; j++) {
+            var item = dataset[j];
+            var point = {
+                x: ((parseFloat(item[0]) - this.minxval) * this.xscale),
+                y: 1.0 - ((parseFloat(item[1]) - this.minyval) * this.yscale),
+                xval: parseFloat(item[0]),
+                yval: parseFloat(item[1]),
+                name: setName
+            };
+
+            // limit the x, y values so they do not overdraw
+            if (point.y <= 0.0) {
+                point.y = 0.0;
+            }
+            if (point.y >= 1.0) {
+                point.y = 1.0;
+            }
+            if ((point.x >= 0.0) && (point.x <= 1.0)) {
+                this.points.push(point);
+            }
+        }
+        i++;
+    }
+};
+
+// Create the pie charts
+PlotKit.Layout.prototype._evaluatePieCharts = function() {
+    var items = PlotKit.Base.items;
+    var sum = MochiKit.Iter.sum;
+    var getter = MochiKit.Base.itemgetter;
+
+    var setCount = items(this.datasets).length;
+
+    // we plot the y values of the first dataset
+    var dataset = items(this.datasets)[0][1];
+    var total = sum(map(getter(1), dataset));
+
+    this.slices = new Array();
+    var currentAngle = 0.0;
+    for (var i = 0; i < dataset.length; i++) {
+        var fraction = dataset[i][1] / total;
+		var startAngle = currentAngle * Math.PI * 2;
+		var endAngle = (currentAngle + fraction) * Math.PI * 2;
+			
+        var slice = {fraction: fraction,
+                     xval: dataset[i][0],
+                     yval: dataset[i][1],
+                     startAngle: startAngle,
+                     endAngle: endAngle
+        };
+        if (dataset[i][1] != 0) {
+            this.slices.push(slice);
+        }
+        currentAngle += fraction;
+    }
+};
+
+PlotKit.Layout.prototype._evaluateLineTicksForXAxis = function() {
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+    
+    if (this.options.xTicks) {
+        // we use use specified ticks with optional labels
+
+        this.xticks = new Array();
+        var makeTicks = function(tick) {
+            var label = tick.label;
+            if (isNil(label))
+                label = tick.v.toString();
+            var pos = this.xscale * (tick.v - this.minxval);
+            if ((pos >= 0.0) && (pos <= 1.0)) {
+                this.xticks.push([pos, label]);
+            }
+        };
+        MochiKit.Iter.forEach(this.options.xTicks, bind(makeTicks, this));
+    }
+    else if (this.options.xNumberOfTicks) {
+        // we use defined number of ticks as hint to auto generate
+        var xvalues = this._uniqueXValues();
+        var roughSeparation = this.xrange / this.options.xNumberOfTicks;
+        var tickCount = 0;
+
+        this.xticks = new Array();
+        for (var i = 0; i <= xvalues.length; i++) {
+            if ((xvalues[i] - this.minxval) >= (tickCount * roughSeparation)) {
+                var pos = this.xscale * (xvalues[i] - this.minxval);
+                if ((pos > 1.0) || (pos < 0.0))
+                    continue;
+                this.xticks.push([pos, xvalues[i]]);
+                tickCount++;
+            }
+            if (tickCount > this.options.xNumberOfTicks)
+                break;
+        }
+    }
+};
+
+PlotKit.Layout.prototype._evaluateLineTicksForYAxis = function() {
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+
+
+    if (this.options.yTicks) {
+        this.yticks = new Array();
+        var makeTicks = function(tick) {
+            var label = tick.label;
+            if (isNil(label))
+                label = tick.v.toString();
+            var pos = 1.0 - (this.yscale * (tick.v - this.minyval));
+            if ((pos >= 0.0) && (pos <= 1.0)) {
+                this.yticks.push([pos, label]);
+            }
+        };
+        MochiKit.Iter.forEach(this.options.yTicks, bind(makeTicks, this));
+    }
+    else if (this.options.yNumberOfTicks) {
+        // We use the optionally defined number of ticks as a guide        
+        this.yticks = new Array();
+
+        // if we get this separation right, we'll have good looking graphs
+        var roundInt = PlotKit.Base.roundInterval;
+        var prec = this.options.yTickPrecision;
+        var roughSeparation = roundInt(this.yrange, 
+                                       this.options.yNumberOfTicks, prec);
+
+        // round off each value of the y-axis to the precision
+        // eg. 1.3333 at precision 1 -> 1.3
+        for (var i = 0; i <= this.options.yNumberOfTicks; i++) {
+            var yval = this.minyval + (i * roughSeparation);
+            var pos = 1.0 - ((yval - this.minyval) * this.yscale);
+            if ((pos > 1.0) || (pos < 0.0))
+                continue;
+            this.yticks.push([pos, MochiKit.Format.roundToFixed(yval, prec)]);
+        }
+    }
+};
+
+PlotKit.Layout.prototype._evaluateLineTicks = function() {
+    this._evaluateLineTicksForXAxis();
+    this._evaluateLineTicksForYAxis();
+};
+
+PlotKit.Layout.prototype._evaluateBarTicks = function() {
+    this._evaluateLineTicks();
+    var centerInBar = function(tick) {
+        return [tick[0] + (this.minxdelta * this.xscale)/2, tick[1]];
+    };
+    this.xticks = MochiKit.Base.map(bind(centerInBar, this), this.xticks);
+    
+    if (this.options.barOrientation == "horizontal") {
+        // swap scales
+        var tempticks = this.xticks;
+        this.xticks = this.yticks;
+        this.yticks = tempticks;
+
+        // we need to invert the "yaxis" (which is now the xaxis when drawn)
+        var invert = function(tick) {
+            return [1.0 - tick[0], tick[1]];
+        }
+        this.xticks = MochiKit.Base.map(invert, this.xticks);
+    }
+};
+
+PlotKit.Layout.prototype._evaluatePieTicks = function() {
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+	var formatter = MochiKit.Format.numberFormatter("#%");
+
+    this.xticks = new Array();
+	if (this.options.xTicks) {
+		// make a lookup dict for x->slice values
+		var lookup = new Array();
+		for (var i = 0; i < this.slices.length; i++) {
+			lookup[this.slices[i].xval] = this.slices[i];
+		}
+		
+		for (var i =0; i < this.options.xTicks.length; i++) {
+			var tick = this.options.xTicks[i];
+			var slice = lookup[tick.v]; 
+            var label = tick.label;
+			if (slice) {
+                if (isNil(label))
+                    label = tick.v.toString();
+				label += " (" + formatter(slice.fraction) + ")";
+				this.xticks.push([tick.v, label]);
+			}
+		}
+	}
+	else {
+		// we make our own labels from all the slices
+		for (var i =0; i < this.slices.length; i++) {
+			var slice = this.slices[i];
+			var label = slice.xval + " (" + formatter(slice.fraction) + ")";
+			this.xticks.push([slice.xval, label]);
+		}
+	}
+};
+
+PlotKit.Layout.prototype._regenerateHitTestCache = function() {
+    this.hitTestCache.xvalues = this._uniqueXValues();
+    this.hitTestCache.xlookup = new Array();
+    this.hitTestCache.x2maxy = new Array();
+
+    var listMax = MochiKit.Base.listMax;
+    var itemgetter = MochiKit.Base.itemgetter;
+    var map = MochiKit.Base.map;
+
+    // generate a lookup table for x values to y values
+    var setNames = keys(this.datasets);
+    for (var i = 0; i < setNames.length; i++) {
+        var dataset = this.datasets[setNames[i]];
+        for (var j = 0; j < dataset.length; j++) {
+            var xval = dataset[j][0];
+            var yval = dataset[j][1];
+            if (this.hitTestCache.xlookup[xval])
+                this.hitTestCache.xlookup[xval].push([yval, setNames[i]]);
+            else 
+                this.hitTestCache.xlookup[xval] = [[yval, setNames[i]]];
+        }
+    }
+
+    for (var x in this.hitTestCache.xlookup) {
+        var yvals = this.hitTestCache.xlookup[x];
+        this.hitTestCache.x2maxy[x] = listMax(map(itemgetter(0), yvals));
+    }
+
+
+};
+
+// --------------------------------------------------------------------
+// END Internal Functions
+// --------------------------------------------------------------------
+
+
+// Namespace Iniitialisation
+
+PlotKit.LayoutModule = {};
+PlotKit.LayoutModule.Layout = PlotKit.Layout;
+
+PlotKit.LayoutModule.EXPORT = [
+    "Layout"
+];
+
+PlotKit.LayoutModule.EXPORT_OK = [];
+
+PlotKit.LayoutModule.__new__ = function() {
+    var m = MochiKit.Base;
+    
+    m.nameFunctions(this);
+    
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+PlotKit.LayoutModule.__new__();
+MochiKit.Base._exportSymbols(this, PlotKit.LayoutModule);
+
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/PlotKit.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/PlotKit.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,151 @@
+/***
+
+PlotKit Autoload Javascript Module.
+
+This file was adapted from MochiKit.
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+Modified by Alastair Tse, 2006, for PlotKit.
+
+***/
+
+if (typeof(PlotKit) == 'undefined') {
+    PlotKit = {};
+}
+
+if (typeof(PlotKit.PlotKit) == 'undefined') {
+    PlotKit.PlotKit = {};
+}
+
+PlotKit.PlotKit.NAME = "PlotKit.PlotKit";
+PlotKit.PlotKit.VERSION = "0.9.1";
+PlotKit.PlotKit.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.PlotKit.toString = function () {
+    return this.__repr__();
+};
+
+PlotKit.PlotKit.SUBMODULES = [
+    "Base",
+    "Layout",
+    "Canvas",
+    "SVG",
+    "SweetCanvas",
+    "SweetSVG",
+    "EasyPlot"
+];
+
+if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') {
+    if (typeof(dojo) != 'undefined') {
+        dojo.provide('PlotKit.PlotKit');
+        dojo.require("PlotKit.*");
+    }
+    if (typeof(JSAN) != 'undefined') {
+        // hopefully this makes it easier for static analysis?
+        JSAN.use("PlotKit.Base", []);
+        JSAN.use("PlotKit.Layout", []);
+        JSAN.use("PlotKit.Canvas", []);
+        JSAN.use("PlotKit.SweetCanvas", []);
+        JSAN.use("PlotKit.SVG", []);
+        JSAN.use("PlotKit.SweetSVG", []);
+    }
+    (function () {
+        var extend = MochiKit.Base.extend;
+        var self = PlotKit.PlotKit;
+        var modules = self.SUBMODULES;
+        var EXPORT = [];
+        var EXPORT_OK = [];
+        var EXPORT_TAGS = {};
+        var i, k, m, all;
+        for (i = 0; i < modules.length; i++) {
+            m = PlotKit[modules[i]];
+            extend(EXPORT, m.EXPORT);
+            extend(EXPORT_OK, m.EXPORT_OK);
+            for (k in m.EXPORT_TAGS) {
+                EXPORT_TAGS[k] = extend(EXPORT_TAGS[k], m.EXPORT_TAGS[k]);
+            }
+            all = m.EXPORT_TAGS[":all"];
+            if (!all) {
+                all = extend(null, m.EXPORT, m.EXPORT_OK);
+            }
+            var j;
+            for (j = 0; j < all.length; j++) {
+                k = all[j];
+                self[k] = m[k];
+            }
+        }
+        self.EXPORT = EXPORT;
+        self.EXPORT_OK = EXPORT_OK;
+        self.EXPORT_TAGS = EXPORT_TAGS;
+    }());
+    
+} else {
+    if (typeof(PlotKit.__compat__) == 'undefined') {
+        PlotKit.__compat__ = true;
+    }
+    (function () {
+        if (typeof(document) == "undefined") {
+              return;
+        }
+        
+        var scripts = document.getElementsByTagName("script");
+        var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+        var base = null;
+        var baseElem = null;
+        var allScripts = {};
+        var i;
+        for (i = 0; i < scripts.length; i++) {
+            var src = scripts[i].getAttribute("src");
+            if (!src) {
+                continue;
+            }
+            allScripts[src] = true;
+            if (src.match(/PlotKit.js$/)) {
+                base = src.substring(0, src.lastIndexOf('PlotKit.js'));
+                baseElem = scripts[i];
+            }
+
+        }
+
+        if (base === null) {
+            return;
+        }
+        var modules = PlotKit.PlotKit.SUBMODULES;
+        for (var i = 0; i < modules.length; i++) {
+            if (PlotKit[modules[i]]) {
+                continue;
+            }
+            var uri = base + modules[i] + '.js';
+            if (uri in allScripts) {
+                continue;
+            }
+            if (document.documentElement &&
+                document.documentElement.namespaceURI == kXULNSURI) {
+                // XUL
+                var s = document.createElementNS(kXULNSURI, 'script');
+                s.setAttribute("id", "PlotKit_" + base + modules[i]);
+                s.setAttribute("src", uri);
+                s.setAttribute("type", "application/x-javascript");
+                baseElem.parentNode.appendChild(s);
+            } else {
+                // HTML
+                /*
+                    DOM can not be used here because Safari does
+                    deferred loading of scripts unless they are
+                    in the document or inserted with document.write
+
+                    This is not XHTML compliant.  If you want XHTML
+                    compliance then you must use the packed version of MochiKit
+                    or include each script individually (basically unroll
+                    these document.write calls into your XHTML source)
+
+                */
+                document.write('<script src="' + uri +
+                    '" type="text/javascript"></script>');
+            }
+        };
+    })();
+}

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/PlotKit_Packed.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/PlotKit_Packed.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,2177 @@
+/***
+
+    PlotKit.PlotKit 0.9.1 : PACKED VERSION
+
+    THIS FILE IS AUTOMATICALLY GENERATED.  If creating patches, please
+    diff against the source tree, not this file.
+
+    For more information, <http://www.liquidx.net/plotkit/>.
+    
+    Copyright (c) 2006. Alastair Tse.
+
+***/
+
+try{
+if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"||typeof (MochiKit.Format)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format}";
+}
+MochiKit.Base.update(MochiKit.Color.Color.prototype,{asFillColor:function(){
+return this.lighterColorWithLevel(0.3);
+},asStrokeColor:function(){
+return this.darkerColorWithLevel(0.1);
+},asPointColor:function(){
+return this.lighterColorWithLevel(0.1);
+}});
+if(typeof (PlotKit)=="undefined"){
+PlotKit={};
+}
+PlotKit.NAME="PlotKit";
+PlotKit.VERSION="0.8";
+PlotKit.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.toString=function(){
+return this.__repr__();
+};
+if(typeof (PlotKit.Base)=="undefined"){
+PlotKit.Base={};
+}
+PlotKit.Base.NAME="PlotKit.Base";
+PlotKit.Base.VERSION=PlotKit.VERSION;
+PlotKit.Base.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.Base.toString=function(){
+return this.__repr__();
+};
+PlotKit.Base.usingPrototype=function(){
+try{
+return (typeof (Object.extend)=="function");
+}
+catch(e){
+return false;
+}
+};
+MochiKit.Base.update(PlotKit.Base,{roundInterval:function(_1,_2,_3){
+var _4=MochiKit.Format.roundToFixed;
+var _5=_1/_2;
+return parseFloat(_4(_5,_3));
+},collapse:function(_6){
+var m=MochiKit.Base;
+var _8=new Array();
+for(var i=0;i<_6.length;i++){
+_8=m.concat(_8,_6[i]);
+}
+if(PlotKit.Base.usingPrototype()){
+delete _8.extend;
+delete _8.from;
+delete _8.inspect;
+}
+return _8;
+},uniq:function(_10){
+var m=MochiKit.Base;
+if(!m.isArrayLike(_10)||(_10.length<1)){
+return new Array();
+}
+var _11=new Array();
+var _12=_10[0];
+_11.push(_10[0]);
+for(var i=1;i<_10.length;i++){
+if(m.compare(_10[i],_12)!=0){
+_12=_10[i];
+_11.push(_10[i]);
+}
+}
+return _11;
+},colorScheme:function(){
+var mb=MochiKit.Base;
+var mc=MochiKit.Color;
+var _15=["red","orange","yellow","green","cyan","blue","purple","magenta"];
+var _16=function(_17){
+return mc.Color[_17+"Color"]();
+};
+return mb.map(_16,_15);
+},baseDarkPrimaryColors:function(){
+var _18=MochiKit.Color.Color.fromHexString;
+return [_18("#ad3f40"),_18("#ddac2c"),_18("#dfdd0c"),_18("#5276c4"),_18("#739c5a")];
+},basePrimaryColors:function(){
+var _19=MochiKit.Color.Color.fromHexString;
+return [_19("#d24c4d"),_19("#f2b32f"),_19("#ece90e"),_19("#5d83da"),_19("#78a15d")];
+},baseBlueColors:function(){
+var _20=MochiKit.Color.Color.fromHexString;
+return [_20("#4b6b94"),_20("#5d81b4"),_20("#acbad2")];
+},palette:function(_21,_22,_23,_24){
+var _25=MochiKit.Base.isUndefinedOrNull;
+var _26=new Array();
+if(_25(_24)){
+_24=0.1;
+}
+if(_25(_23)){
+_23=0.4;
+}
+if(_25(_22)){
+_22=-0.2;
+}
+var _27=_22;
+while(_27<=_23){
+_26.push(_27);
+_27+=_24;
+}
+var _28=function(_29,_30){
+return _29.lighterColorWithLevel(_30);
+};
+return MochiKit.Base.map(partial(_28,_21),_26);
+},excanvasSupported:function(){
+if(/MSIE/.test(navigator.userAgent)&&!window.opera){
+return true;
+}
+return false;
+},findPosX:function(obj){
+var _32=0;
+if(obj.offsetParent){
+while(obj.offsetParent){
+_32+=obj.offsetLeft;
+obj=obj.offsetParent;
+}
+}else{
+if(obj.x){
+_32+=obj.x;
+}
+}
+return _32;
+},findPosY:function(obj){
+var _33=0;
+if(obj.offsetParent){
+while(obj.offsetParent){
+_33+=obj.offsetTop;
+obj=obj.offsetParent;
+}
+}else{
+if(obj.y){
+_33+=obj.y;
+}
+}
+return _33;
+},isFuncLike:function(obj){
+return (typeof (obj)=="function");
+}});
+PlotKit.Base.map=function(fn,lst){
+if(PlotKit.Base.usingPrototype()){
+var _36=[];
+for(var x in lst){
+if(typeof (lst[x])=="function"){
+continue;
+}
+_36.push(fn(lst[x]));
+}
+return _36;
+}else{
+return MochiKit.Base.map(fn,lst);
+}
+};
+PlotKit.Base.items=function(lst){
+if(PlotKit.Base.usingPrototype()){
+var _38=[];
+for(var x in lst){
+if(typeof (lst[x])=="function"){
+continue;
+}
+_38.push([x,lst[x]]);
+}
+return _38;
+}else{
+return MochiKit.Base.items(lst);
+}
+};
+PlotKit.Base.keys=function(lst){
+if(PlotKit.Base.usingPrototype()){
+var _39=[];
+for(var x in lst){
+if(typeof (lst[x])=="function"){
+continue;
+}
+_39.push(x);
+}
+return _39;
+}else{
+return MochiKit.Base.keys(lst);
+}
+};
+PlotKit.Base.baseColors=function(){
+var _40=MochiKit.Color.Color.fromHexString;
+return [_40("#476fb2"),_40("#be2c2b"),_40("#85b730"),_40("#734a99"),_40("#26a1c5"),_40("#fb8707"),_40("#000000")];
+};
+PlotKit.Base.officeBaseStyle={"axisLineWidth":2,"axisLabelColor":Color.grayColor(),"axisLineColor":Color.whiteColor(),"padding":{top:5,bottom:10,left:30,right:30}};
+MochiKit.Base.update(PlotKit.Base,{officeBlue:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"backgroundColor":PlotKit.Base.baseColors()[0].lighterColorWithLevel(0.45)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeRed:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),"backgroundColor":PlotKit.Base.baseColors()[1].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeGreen:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[2]),"backgroundColor":PlotKit.Base.baseColors()[2].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officePurple:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[3]),"backgroundColor":PlotKit.Base.baseColors()[3].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeCyan:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[4]),"backgroundColor":PlotKit.Base.baseColors()[4].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeOrange:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[5]),"backgroundColor":PlotKit.Base.baseColors()[5].lighterColorWithLevel(0.4)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeBlack:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[6],0,0.6),"backgroundColor":PlotKit.Base.baseColors()[6].lighterColorWithLevel(0.9)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+}});
+PlotKit.Base.EXPORT=["baseColors","collapse","colorScheme","findPosX","findPosY","officeBaseStyle","officeBlue","officeRed","officeGreen","officePurple","officeCyan","officeOrange","officeBlack","roundInterval","uniq","isFuncLike","excanvasSupported"];
+PlotKit.Base.EXPORT_OK=[];
+PlotKit.Base.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.Base.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.Base);
+try{
+if(typeof (PlotKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Base";
+}
+if(typeof (PlotKit.Layout)=="undefined"){
+PlotKit.Layout={};
+}
+PlotKit.Layout.NAME="PlotKit.Layout";
+PlotKit.Layout.VERSION=PlotKit.VERSION;
+PlotKit.Layout.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.Layout.toString=function(){
+return this.__repr__();
+};
+PlotKit.Layout.valid_styles=["bar","line","pie","point"];
+PlotKit.Layout=function(_42,_43){
+this.options={"barWidthFillFraction":0.75,"barOrientation":"vertical","xOriginIsZero":true,"yOriginIsZero":true,"xAxis":null,"yAxis":null,"xTicks":null,"yTicks":null,"xNumberOfTicks":10,"yNumberOfTicks":5,"xTickPrecision":1,"yTickPrecision":1,"pieRadius":0.4};
+this.style=_42;
+MochiKit.Base.update(this.options,_43?_43:{});
+if(!MochiKit.Base.isUndefinedOrNull(this.options.xAxis)){
+this.minxval=this.options.xAxis[0];
+this.maxxval=this.options.xAxis[1];
+this.xscale=this.maxxval-this.minxval;
+}else{
+this.minxval=0;
+this.maxxval=null;
+this.xscale=null;
+}
+if(!MochiKit.Base.isUndefinedOrNull(this.options.yAxis)){
+this.minyval=this.options.yAxis[0];
+this.maxyval=this.options.yAxis[1];
+this.yscale=this.maxyval-this.minyval;
+}else{
+this.minyval=0;
+this.maxyval=null;
+this.yscale=null;
+}
+this.bars=new Array();
+this.points=new Array();
+this.slices=new Array();
+this.xticks=new Array();
+this.yticks=new Array();
+this.datasets=new Array();
+this.minxdelta=0;
+this.xrange=1;
+this.yrange=1;
+this.hitTestCache={x2maxy:null};
+};
+PlotKit.Layout.prototype.addDataset=function(_44,_45){
+this.datasets[_44]=_45;
+};
+PlotKit.Layout.prototype.removeDataset=function(_46,_47){
+delete this.datasets[_46];
+};
+PlotKit.Layout.prototype.addDatasetFromTable=function(_48,_49,_50,_51,_52){
+var _53=MochiKit.Base.isUndefinedOrNull;
+var _54=MochiKit.DOM.scrapeText;
+var _55=MochiKit.Format.strip;
+if(_53(_50)){
+_50=0;
+}
+if(_53(_51)){
+_51=1;
+}
+if(_53(_52)){
+_52=-1;
+}
+var _56=_49.tBodies[0].rows;
+var _57=new Array();
+var _58=new Array();
+if(!_53(_56)){
+for(var i=0;i<_56.length;i++){
+_57.push([parseFloat(_55(_54(_56[i].cells[_50]))),parseFloat(_55(_54(_56[i].cells[_51])))]);
+if(_52>=0){
+_58.push({v:parseFloat(_55(_54(_56[i].cells[_50]))),label:_55(_54(_56[i].cells[_52]))});
+}
+}
+this.addDataset(_48,_57);
+if(_52>=0){
+this.options.xTicks=_58;
+}
+return true;
+}
+return false;
+};
+PlotKit.Layout.prototype.evaluate=function(){
+this._evaluateLimits();
+this._evaluateScales();
+if(this.style=="bar"){
+if(this.options.barOrientation=="horizontal"){
+this._evaluateHorizBarCharts();
+}else{
+this._evaluateBarCharts();
+}
+this._evaluateBarTicks();
+}else{
+if(this.style=="line"){
+this._evaluateLineCharts();
+this._evaluateLineTicks();
+}else{
+if(this.style=="pie"){
+this._evaluatePieCharts();
+this._evaluatePieTicks();
+}
+}
+}
+};
+PlotKit.Layout.prototype.hitTest=function(x,y){
+var f=MochiKit.Format.twoDigitFloat;
+if((this.style=="bar")&&this.bars&&(this.bars.length>0)){
+for(var i=0;i<this.bars.length;i++){
+var bar=this.bars[i];
+if((x>=bar.x)&&(x<=bar.x+bar.w)&&(y>=bar.y)&&(y-bar.y<=bar.h)){
+return bar;
+}
+}
+}else{
+if(this.style=="line"){
+if(this.hitTestCache.x2maxy==null){
+this._regenerateHitTestCache();
+}
+var _62=x/this.xscale;
+var _63=this.hitTestCache.xvalues;
+var _64=null;
+var _65=null;
+for(var i=1;i<_63.length;i++){
+if(_63[i]>_62){
+_64=_63[i-1];
+_65=_63[i];
+break;
+}
+}
+if((_64!=null)){
+var _66=this.hitTestCache.x2maxy[_64];
+var _67=this.hitTestCache.x2maxy[_65];
+var _68=(1-y)/this.yscale;
+var _69=(_67-_66)/(_65-_64);
+var _70=_66+_69*(_62-_64);
+if(_70>=_68){
+var obj={xval:_62,yval:_68,xafter:_65,yafter:_67,xbefore:_64,ybefore:_66,yprojected:_70};
+return obj;
+}
+}
+}else{
+if(this.style=="pie"){
+var _71=Math.sqrt((y-0.5)*(y-0.5)+(x-0.5)*(x-0.5));
+if(_71>this.options.pieRadius){
+return null;
+}
+var _72=Math.atan2(y-0.5,x-0.5)-Math.PI/2;
+for(var i=0;i<this.slices.length;i++){
+var _73=this.slices[i];
+if(_73.startAngle<_72&&_73.endAngle>=_72){
+return _73;
+}
+}
+}
+}
+}
+return null;
+};
+PlotKit.Layout.prototype.rectForX=function(x){
+return null;
+};
+PlotKit.Layout.prototype.angleRangeForX=function(x){
+return null;
+};
+PlotKit.Layout.prototype._evaluateLimits=function(){
+var map=PlotKit.Base.map;
+var _75=PlotKit.Base.items;
+var _76=MochiKit.Base.itemgetter;
+var _77=PlotKit.Base.collapse;
+var _78=MochiKit.Base.listMin;
+var _79=MochiKit.Base.listMax;
+var _80=MochiKit.Base.isUndefinedOrNull;
+var all=_77(map(_76(1),_75(this.datasets)));
+if(_80(this.options.xAxis)){
+if(this.options.xOriginIsZero){
+this.minxval=0;
+}else{
+this.minxval=_78(map(parseFloat,map(_76(0),all)));
+}
+this.maxxval=_79(map(parseFloat,map(_76(0),all)));
+}else{
+this.minxval=this.options.xAxis[0];
+this.maxxval=this.options.xAxis[1];
+this.xscale=this.maxval-this.minxval;
+}
+if(_80(this.options.yAxis)){
+if(this.options.yOriginIsZero){
+this.minyval=0;
+}else{
+this.minyval=_78(map(parseFloat,map(_76(1),all)));
+}
+this.maxyval=_79(map(parseFloat,map(_76(1),all)));
+}else{
+this.minyval=this.options.yAxis[0];
+this.maxyval=this.options.yAxis[1];
+this.yscale=this.maxyval-this.minyval;
+}
+};
+PlotKit.Layout.prototype._evaluateScales=function(){
+var _82=MochiKit.Base.isUndefinedOrNull;
+this.xrange=this.maxxval-this.minxval;
+if(this.xrange==0){
+this.xscale=1;
+}else{
+this.xscale=1/this.xrange;
+}
+this.yrange=this.maxyval-this.minyval;
+if(this.yrange==0){
+this.yscale=1;
+}else{
+this.yscale=1/this.yrange;
+}
+};
+PlotKit.Layout.prototype._uniqueXValues=function(){
+var _83=PlotKit.Base.collapse;
+var map=PlotKit.Base.map;
+var _84=PlotKit.Base.uniq;
+var _85=MochiKit.Base.itemgetter;
+var _86=PlotKit.Base.items;
+var _87=map(parseFloat,map(_85(0),_83(map(_85(1),_86(this.datasets)))));
+_87.sort(MochiKit.Base.compare);
+return _84(_87);
+};
+PlotKit.Layout.prototype._evaluateBarCharts=function(){
+var _88=PlotKit.Base.items;
+var _89=_88(this.datasets).length;
+var _90=10000000;
+var _91=this._uniqueXValues();
+for(var i=1;i<_91.length;i++){
+_90=Math.min(Math.abs(_91[i]-_91[i-1]),_90);
+}
+var _92=0;
+var _93=0;
+var _94=0;
+if(_91.length==1){
+_90=1;
+this.xscale=1;
+this.minxval=_91[0];
+_92=1*this.options.barWidthFillFraction;
+_93=_92/_89;
+_94=(1-this.options.barWidthFillFraction)/2;
+}else{
+if(this.xrange==1){
+this.xscale=0.5;
+}else{
+if(this.xrange==2){
+this.xscale=1/3;
+}else{
+this.xscale=(1-_90/this.xrange)/this.xrange;
+}
+}
+_92=_90*this.xscale*this.options.barWidthFillFraction;
+_93=_92/_89;
+_94=_90*this.xscale*(1-this.options.barWidthFillFraction)/2;
+}
+this.minxdelta=_90;
+this.bars=new Array();
+var i=0;
+for(var _95 in this.datasets){
+var _96=this.datasets[_95];
+if(PlotKit.Base.isFuncLike(_96)){
+continue;
+}
+for(var j=0;j<_96.length;j++){
+var _98=_96[j];
+var _99={x:((parseFloat(_98[0])-this.minxval)*this.xscale)+(i*_93)+_94,y:1-((parseFloat(_98[1])-this.minyval)*this.yscale),w:_93,h:((parseFloat(_98[1])-this.minyval)*this.yscale),xval:parseFloat(_98[0]),yval:parseFloat(_98[1]),name:_95};
+if((_99.x>=0)&&(_99.x<=1)&&(_99.y>=0)&&(_99.y<=1)){
+this.bars.push(_99);
+}
+}
+i++;
+}
+};
+PlotKit.Layout.prototype._evaluateHorizBarCharts=function(){
+var _100=PlotKit.Base.items;
+var _101=_100(this.datasets).length;
+var _102=10000000;
+var _103=this._uniqueXValues();
+for(var i=1;i<_103.length;i++){
+_102=Math.min(Math.abs(_103[i]-_103[i-1]),_102);
+}
+var _104=0;
+var _105=0;
+var _106=0;
+if(_103.length==1){
+_102=1;
+this.xscale=1;
+this.minxval=_103[0];
+_104=1*this.options.barWidthFillFraction;
+_105=_104/_101;
+_106=(1-this.options.barWidthFillFraction)/2;
+}else{
+this.xscale=(1-_102/this.xrange)/this.xrange;
+_104=_102*this.xscale*this.options.barWidthFillFraction;
+_105=_104/_101;
+_106=_102*this.xscale*(1-this.options.barWidthFillFraction)/2;
+}
+this.minxdelta=_102;
+this.bars=new Array();
+var i=0;
+for(var _107 in this.datasets){
+var _108=this.datasets[_107];
+if(PlotKit.Base.isFuncLike(_108)){
+continue;
+}
+for(var j=0;j<_108.length;j++){
+var item=_108[j];
+var rect={y:((parseFloat(item[0])-this.minxval)*this.xscale)+(i*_105)+_106,x:0,h:_105,w:((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_107};
+if(rect.y<=0){
+rect.y=0;
+}
+if(rect.y>=1){
+rect.y=1;
+}
+if((rect.x>=0)&&(rect.x<=1)){
+this.bars.push(rect);
+}
+}
+i++;
+}
+};
+PlotKit.Layout.prototype._evaluateLineCharts=function(){
+var _111=PlotKit.Base.items;
+var _112=_111(this.datasets).length;
+this.points=new Array();
+var i=0;
+for(var _113 in this.datasets){
+var _114=this.datasets[_113];
+if(PlotKit.Base.isFuncLike(_114)){
+continue;
+}
+_114.sort(function(a,b){
+return compare(parseFloat(a[0]),parseFloat(b[0]));
+});
+for(var j=0;j<_114.length;j++){
+var item=_114[j];
+var _117={x:((parseFloat(item[0])-this.minxval)*this.xscale),y:1-((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_113};
+if(_117.y<=0){
+_117.y=0;
+}
+if(_117.y>=1){
+_117.y=1;
+}
+if((_117.x>=0)&&(_117.x<=1)){
+this.points.push(_117);
+}
+}
+i++;
+}
+};
+PlotKit.Layout.prototype._evaluatePieCharts=function(){
+var _118=PlotKit.Base.items;
+var sum=MochiKit.Iter.sum;
+var _120=MochiKit.Base.itemgetter;
+var _121=_118(this.datasets).length;
+var _122=_118(this.datasets)[0][1];
+var _123=sum(map(_120(1),_122));
+this.slices=new Array();
+var _124=0;
+for(var i=0;i<_122.length;i++){
+var _125=_122[i][1]/_123;
+var _126=_124*Math.PI*2;
+var _127=(_124+_125)*Math.PI*2;
+var _128={fraction:_125,xval:_122[i][0],yval:_122[i][1],startAngle:_126,endAngle:_127};
+if(_122[i][1]!=0){
+this.slices.push(_128);
+}
+_124+=_125;
+}
+};
+PlotKit.Layout.prototype._evaluateLineTicksForXAxis=function(){
+var _129=MochiKit.Base.isUndefinedOrNull;
+if(this.options.xTicks){
+this.xticks=new Array();
+var _130=function(tick){
+var _132=tick.label;
+if(_129(_132)){
+_132=tick.v.toString();
+}
+var pos=this.xscale*(tick.v-this.minxval);
+if((pos>=0)&&(pos<=1)){
+this.xticks.push([pos,_132]);
+}
+};
+MochiKit.Iter.forEach(this.options.xTicks,bind(_130,this));
+}else{
+if(this.options.xNumberOfTicks){
+var _134=this._uniqueXValues();
+var _135=this.xrange/this.options.xNumberOfTicks;
+var _136=0;
+this.xticks=new Array();
+for(var i=0;i<=_134.length;i++){
+if((_134[i]-this.minxval)>=(_136*_135)){
+var pos=this.xscale*(_134[i]-this.minxval);
+if((pos>1)||(pos<0)){
+continue;
+}
+this.xticks.push([pos,_134[i]]);
+_136++;
+}
+if(_136>this.options.xNumberOfTicks){
+break;
+}
+}
+}
+}
+};
+PlotKit.Layout.prototype._evaluateLineTicksForYAxis=function(){
+var _137=MochiKit.Base.isUndefinedOrNull;
+if(this.options.yTicks){
+this.yticks=new Array();
+var _138=function(tick){
+var _139=tick.label;
+if(_137(_139)){
+_139=tick.v.toString();
+}
+var pos=1-(this.yscale*(tick.v-this.minyval));
+if((pos>=0)&&(pos<=1)){
+this.yticks.push([pos,_139]);
+}
+};
+MochiKit.Iter.forEach(this.options.yTicks,bind(_138,this));
+}else{
+if(this.options.yNumberOfTicks){
+this.yticks=new Array();
+var _140=PlotKit.Base.roundInterval;
+var prec=this.options.yTickPrecision;
+var _142=_140(this.yrange,this.options.yNumberOfTicks,prec);
+for(var i=0;i<=this.options.yNumberOfTicks;i++){
+var yval=this.minyval+(i*_142);
+var pos=1-((yval-this.minyval)*this.yscale);
+if((pos>1)||(pos<0)){
+continue;
+}
+this.yticks.push([pos,MochiKit.Format.roundToFixed(yval,prec)]);
+}
+}
+}
+};
+PlotKit.Layout.prototype._evaluateLineTicks=function(){
+this._evaluateLineTicksForXAxis();
+this._evaluateLineTicksForYAxis();
+};
+PlotKit.Layout.prototype._evaluateBarTicks=function(){
+this._evaluateLineTicks();
+var _144=function(tick){
+return [tick[0]+(this.minxdelta*this.xscale)/2,tick[1]];
+};
+this.xticks=MochiKit.Base.map(bind(_144,this),this.xticks);
+if(this.options.barOrientation=="horizontal"){
+var _145=this.xticks;
+this.xticks=this.yticks;
+this.yticks=_145;
+var _146=function(tick){
+return [1-tick[0],tick[1]];
+};
+this.xticks=MochiKit.Base.map(_146,this.xticks);
+}
+};
+PlotKit.Layout.prototype._evaluatePieTicks=function(){
+var _147=MochiKit.Base.isUndefinedOrNull;
+var _148=MochiKit.Format.numberFormatter("#%");
+this.xticks=new Array();
+if(this.options.xTicks){
+var _149=new Array();
+for(var i=0;i<this.slices.length;i++){
+_149[this.slices[i].xval]=this.slices[i];
+}
+for(var i=0;i<this.options.xTicks.length;i++){
+var tick=this.options.xTicks[i];
+var _150=_149[tick.v];
+var _151=tick.label;
+if(_150){
+if(_147(_151)){
+_151=tick.v.toString();
+}
+_151+=" ("+_148(_150.fraction)+")";
+this.xticks.push([tick.v,_151]);
+}
+}
+}else{
+for(var i=0;i<this.slices.length;i++){
+var _150=this.slices[i];
+var _151=_150.xval+" ("+_148(_150.fraction)+")";
+this.xticks.push([_150.xval,_151]);
+}
+}
+};
+PlotKit.Layout.prototype._regenerateHitTestCache=function(){
+this.hitTestCache.xvalues=this._uniqueXValues();
+this.hitTestCache.xlookup=new Array();
+this.hitTestCache.x2maxy=new Array();
+var _152=MochiKit.Base.listMax;
+var _153=MochiKit.Base.itemgetter;
+var map=MochiKit.Base.map;
+var _154=keys(this.datasets);
+for(var i=0;i<_154.length;i++){
+var _155=this.datasets[_154[i]];
+for(var j=0;j<_155.length;j++){
+var xval=_155[j][0];
+var yval=_155[j][1];
+if(this.hitTestCache.xlookup[xval]){
+this.hitTestCache.xlookup[xval].push([yval,_154[i]]);
+}else{
+this.hitTestCache.xlookup[xval]=[[yval,_154[i]]];
+}
+}
+}
+for(var x in this.hitTestCache.xlookup){
+var _157=this.hitTestCache.xlookup[x];
+this.hitTestCache.x2maxy[x]=_152(map(_153(0),_157));
+}
+};
+PlotKit.LayoutModule={};
+PlotKit.LayoutModule.Layout=PlotKit.Layout;
+PlotKit.LayoutModule.EXPORT=["Layout"];
+PlotKit.LayoutModule.EXPORT_OK=[];
+PlotKit.LayoutModule.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.LayoutModule.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.LayoutModule);
+try{
+if((typeof (PlotKit.Base)=="undefined")||(typeof (PlotKit.Layout)=="undefined")){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Base,Layout}";
+}
+if(typeof (PlotKit.CanvasRenderer)=="undefined"){
+PlotKit.CanvasRenderer={};
+}
+PlotKit.CanvasRenderer.NAME="PlotKit.CanvasRenderer";
+PlotKit.CanvasRenderer.VERSION=PlotKit.VERSION;
+PlotKit.CanvasRenderer.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.CanvasRenderer.toString=function(){
+return this.__repr__();
+};
+PlotKit.CanvasRenderer=function(_158,_159,_160){
+if(arguments.length>0){
+this.__init__(_158,_159,_160);
+}
+};
+PlotKit.CanvasRenderer.prototype.__init__=function(_161,_162,_163){
+var _164=MochiKit.Base.isUndefinedOrNull;
+var _165=MochiKit.Color.Color;
+this.options={"drawBackground":true,"backgroundColor":_165.whiteColor(),"padding":{left:30,right:30,top:5,bottom:10},"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"strokeColor":_165.whiteColor(),"strokeColorTransform":"asStrokeColor","strokeWidth":0.5,"shouldFill":true,"shouldStroke":true,"drawXAxis":true,"drawYAxis":true,"axisLineColor":_165.blackColor(),"axisLineWidth":0.5,"axisTickSize":3,"axisLabelColor":_165.blackColor(),"axisLabelFont":"Arial","axisLabelFontSize":9,"axisLabelWidth":50,"pieRadius":0.4,"enableEvents":true};
+MochiKit.Base.update(this.options,_163?_163:{});
+this.layout=_162;
+this.element=MochiKit.DOM.getElement(_161);
+this.container=this.element.parentNode;
+this.isIE=PlotKit.Base.excanvasSupported();
+if(this.isIE&&!_164(G_vmlCanvasManager)){
+this.IEDelay=0.5;
+this.maxTries=5;
+this.renderDelay=null;
+this.clearDelay=null;
+this.element=G_vmlCanvasManager.initElement(this.element);
+}
+this.height=this.element.height;
+this.width=this.element.width;
+if(_164(this.element)){
+throw "CanvasRenderer() - passed canvas is not found";
+}
+if(!this.isIE&&!(PlotKit.CanvasRenderer.isSupported(this.element))){
+throw "CanvasRenderer() - Canvas is not supported.";
+}
+if(_164(this.container)||(this.container.nodeName.toLowerCase()!="div")){
+throw "CanvasRenderer() - <canvas> needs to be enclosed in <div>";
+}
+this.xlabels=new Array();
+this.ylabels=new Array();
+this.isFirstRender=true;
+this.area={x:this.options.padding.left,y:this.options.padding.top,w:this.width-this.options.padding.left-this.options.padding.right,h:this.height-this.options.padding.top-this.options.padding.bottom};
+MochiKit.DOM.updateNodeAttributes(this.container,{"style":{"position":"relative","width":this.width+"px"}});
+};
+PlotKit.CanvasRenderer.prototype.render=function(){
+if(this.isIE){
+try{
+if(this.renderDelay){
+this.renderDelay.cancel();
+this.renderDelay=null;
+}
+var _166=this.element.getContext("2d");
+}
+catch(e){
+this.isFirstRender=false;
+if(this.maxTries-->0){
+this.renderDelay=MochiKit.Async.wait(this.IEDelay);
+this.renderDelay.addCallback(bind(this.render,this));
+}
+return;
+}
+}
+if(this.options.drawBackground){
+this._renderBackground();
+}
+if(this.layout.style=="bar"){
+this._renderBarChart();
+this._renderBarAxis();
+}else{
+if(this.layout.style=="pie"){
+this._renderPieChart();
+this._renderPieAxis();
+}else{
+if(this.layout.style=="line"){
+this._renderLineChart();
+this._renderLineAxis();
+}
+}
+}
+};
+PlotKit.CanvasRenderer.prototype._renderBarChartWrap=function(data,_168){
+var _169=this.element.getContext("2d");
+var _170=this.options.colorScheme.length;
+var _171=this.options.colorScheme;
+var _172=MochiKit.Base.keys(this.layout.datasets);
+var _173=_172.length;
+for(var i=0;i<_173;i++){
+var _174=_172[i];
+var _175=_171[i%_170];
+_169.save();
+_169.fillStyle=_175.toRGBString();
+if(this.options.strokeColor){
+_169.strokeStyle=this.options.strokeColor.toRGBString();
+}else{
+if(this.options.strokeColorTransform){
+_169.strokeStyle=_175[this.options.strokeColorTransform]().toRGBString();
+}
+}
+_169.lineWidth=this.options.strokeWidth;
+var _176=function(obj){
+if(obj.name==_174){
+_168(_169,obj);
+}
+};
+MochiKit.Iter.forEach(data,bind(_176,this));
+_169.restore();
+}
+};
+PlotKit.CanvasRenderer.prototype._renderBarChart=function(){
+var bind=MochiKit.Base.bind;
+var _178=function(_179,bar){
+var x=this.area.w*bar.x+this.area.x;
+var y=this.area.h*bar.y+this.area.y;
+var w=this.area.w*bar.w;
+var h=this.area.h*bar.h;
+if((w<1)||(h<1)){
+return;
+}
+if(this.options.shouldFill){
+_179.fillRect(x,y,w,h);
+}
+if(this.options.shouldStroke){
+_179.strokeRect(x,y,w,h);
+}
+};
+this._renderBarChartWrap(this.layout.bars,bind(_178,this));
+};
+PlotKit.CanvasRenderer.prototype._renderLineChart=function(){
+var _182=this.element.getContext("2d");
+var _183=this.options.colorScheme.length;
+var _184=this.options.colorScheme;
+var _185=MochiKit.Base.keys(this.layout.datasets);
+var _186=_185.length;
+var bind=MochiKit.Base.bind;
+var _187=MochiKit.Base.partial;
+for(var i=0;i<_186;i++){
+var _188=_185[i];
+var _189=_184[i%_183];
+var _190=this.options.strokeColorTransform;
+_182.save();
+_182.fillStyle=_189.toRGBString();
+if(this.options.strokeColor){
+_182.strokeStyle=this.options.strokeColor.toRGBString();
+}else{
+if(this.options.strokeColorTransform){
+_182.strokeStyle=_189[_190]().toRGBString();
+}
+}
+_182.lineWidth=this.options.strokeWidth;
+var _191=function(ctx){
+ctx.beginPath();
+ctx.moveTo(this.area.x,this.area.y+this.area.h);
+var _193=function(ctx_,_195){
+if(_195.name==_188){
+ctx_.lineTo(this.area.w*_195.x+this.area.x,this.area.h*_195.y+this.area.y);
+}
+};
+MochiKit.Iter.forEach(this.layout.points,_187(_193,ctx),this);
+ctx.lineTo(this.area.w+this.area.x,this.area.h+this.area.y);
+ctx.lineTo(this.area.x,this.area.y+this.area.h);
+ctx.closePath();
+};
+if(this.options.shouldFill){
+bind(_191,this)(_182);
+_182.fill();
+}
+if(this.options.shouldStroke){
+bind(_191,this)(_182);
+_182.stroke();
+}
+_182.restore();
+}
+};
+PlotKit.CanvasRenderer.prototype._renderPieChart=function(){
+var _196=this.element.getContext("2d");
+var _197=this.options.colorScheme.length;
+var _198=this.layout.slices;
+var _199=this.area.x+this.area.w*0.5;
+var _200=this.area.y+this.area.h*0.5;
+var _201=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius);
+if(this.isIE){
+_199=parseInt(_199);
+_200=parseInt(_200);
+_201=parseInt(_201);
+}
+for(var i=0;i<_198.length;i++){
+var _202=this.options.colorScheme[i%_197];
+_196.save();
+_196.fillStyle=_202.toRGBString();
+var _203=function(){
+_196.beginPath();
+_196.moveTo(_199,_200);
+_196.arc(_199,_200,_201,_198[i].startAngle-Math.PI/2,_198[i].endAngle-Math.PI/2,false);
+_196.lineTo(_199,_200);
+_196.closePath();
+};
+if(Math.abs(_198[i].startAngle-_198[i].endAngle)>0.001){
+if(this.options.shouldFill){
+_203();
+_196.fill();
+}
+if(this.options.shouldStroke){
+_203();
+_196.lineWidth=this.options.strokeWidth;
+if(this.options.strokeColor){
+_196.strokeStyle=this.options.strokeColor.toRGBString();
+}else{
+if(this.options.strokeColorTransform){
+_196.strokeStyle=_202[this.options.strokeColorTransform]().toRGBString();
+}
+}
+_196.stroke();
+}
+}
+_196.restore();
+}
+};
+PlotKit.CanvasRenderer.prototype._renderBarAxis=function(){
+this._renderAxis();
+};
+PlotKit.CanvasRenderer.prototype._renderLineAxis=function(){
+this._renderAxis();
+};
+PlotKit.CanvasRenderer.prototype._renderAxis=function(){
+if(!this.options.drawXAxis&&!this.options.drawYAxis){
+return;
+}
+var _204=this.element.getContext("2d");
+var _205={"style":{"position":"absolute","fontSize":this.options.axisLabelFontSize+"px","zIndex":10,"color":this.options.axisLabelColor.toRGBString(),"width":this.options.axisLabelWidth+"px","overflow":"hidden"}};
+_204.save();
+_204.strokeStyle=this.options.axisLineColor.toRGBString();
+_204.lineWidth=this.options.axisLineWidth;
+if(this.options.drawYAxis){
+if(this.layout.yticks){
+var _206=function(tick){
+if(typeof (tick)=="function"){
+return;
+}
+var x=this.area.x;
+var y=this.area.y+tick[0]*this.area.h;
+_204.beginPath();
+_204.moveTo(x,y);
+_204.lineTo(x-this.options.axisTickSize,y);
+_204.closePath();
+_204.stroke();
+var _207=DIV(_205,tick[1]);
+_207.style.top=(y-this.options.axisLabelFontSize)+"px";
+_207.style.left=(x-this.options.padding.left-this.options.axisTickSize)+"px";
+_207.style.textAlign="right";
+_207.style.width=(this.options.padding.left-this.options.axisTickSize*2)+"px";
+MochiKit.DOM.appendChildNodes(this.container,_207);
+this.ylabels.push(_207);
+};
+MochiKit.Iter.forEach(this.layout.yticks,bind(_206,this));
+}
+_204.beginPath();
+_204.moveTo(this.area.x,this.area.y);
+_204.lineTo(this.area.x,this.area.y+this.area.h);
+_204.closePath();
+_204.stroke();
+}
+if(this.options.drawXAxis){
+if(this.layout.xticks){
+var _206=function(tick){
+if(typeof (dataset)=="function"){
+return;
+}
+var x=this.area.x+tick[0]*this.area.w;
+var y=this.area.y+this.area.h;
+_204.beginPath();
+_204.moveTo(x,y);
+_204.lineTo(x,y+this.options.axisTickSize);
+_204.closePath();
+_204.stroke();
+var _208=DIV(_205,tick[1]);
+_208.style.top=(y+this.options.axisTickSize)+"px";
+_208.style.left=(x-this.options.axisLabelWidth/2)+"px";
+_208.style.textAlign="center";
+_208.style.width=this.options.axisLabelWidth+"px";
+MochiKit.DOM.appendChildNodes(this.container,_208);
+this.xlabels.push(_208);
+};
+MochiKit.Iter.forEach(this.layout.xticks,bind(_206,this));
+}
+_204.beginPath();
+_204.moveTo(this.area.x,this.area.y+this.area.h);
+_204.lineTo(this.area.x+this.area.w,this.area.y+this.area.h);
+_204.closePath();
+_204.stroke();
+}
+_204.restore();
+};
+PlotKit.CanvasRenderer.prototype._renderPieAxis=function(){
+if(!this.options.drawXAxis){
+return;
+}
+if(this.layout.xticks){
+var _209=new Array();
+for(var i=0;i<this.layout.slices.length;i++){
+_209[this.layout.slices[i].xval]=this.layout.slices[i];
+}
+var _210=this.area.x+this.area.w*0.5;
+var _211=this.area.y+this.area.h*0.5;
+var _212=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius);
+var _213=this.options.axisLabelWidth;
+for(var i=0;i<this.layout.xticks.length;i++){
+var _214=_209[this.layout.xticks[i][0]];
+if(MochiKit.Base.isUndefinedOrNull(_214)){
+continue;
+}
+var _215=(_214.startAngle+_214.endAngle)/2;
+var _216=_215;
+if(_216>Math.PI*2){
+_216=_216-Math.PI*2;
+}else{
+if(_216<0){
+_216=_216+Math.PI*2;
+}
+}
+var _217=_210+Math.sin(_216)*(_212+10);
+var _218=_211-Math.cos(_216)*(_212+10);
+var _219={"position":"absolute","zIndex":11,"width":_213+"px","fontSize":this.options.axisLabelFontSize+"px","overflow":"hidden","color":this.options.axisLabelColor.toHexString()};
+if(_216<=Math.PI*0.5){
+_219["textAlign"]="left";
+_219["verticalAlign"]="top";
+_219["left"]=_217+"px";
+_219["top"]=(_218-this.options.axisLabelFontSize)+"px";
+}else{
+if((_216>Math.PI*0.5)&&(_216<=Math.PI)){
+_219["textAlign"]="left";
+_219["verticalAlign"]="bottom";
+_219["left"]=_217+"px";
+_219["top"]=_218+"px";
+}else{
+if((_216>Math.PI)&&(_216<=Math.PI*1.5)){
+_219["textAlign"]="right";
+_219["verticalAlign"]="bottom";
+_219["left"]=(_217-_213)+"px";
+_219["top"]=_218+"px";
+}else{
+_219["textAlign"]="right";
+_219["verticalAlign"]="bottom";
+_219["left"]=(_217-_213)+"px";
+_219["top"]=(_218-this.options.axisLabelFontSize)+"px";
+}
+}
+}
+var _220=DIV({"style":_219},this.layout.xticks[i][1]);
+this.xlabels.push(_220);
+MochiKit.DOM.appendChildNodes(this.container,_220);
+}
+}
+};
+PlotKit.CanvasRenderer.prototype._renderBackground=function(){
+var _221=this.element.getContext("2d");
+_221.save();
+_221.fillStyle=this.options.backgroundColor.toRGBString();
+_221.fillRect(0,0,this.width,this.height);
+_221.restore();
+};
+PlotKit.CanvasRenderer.prototype.clear=function(){
+if(this.isIE){
+try{
+if(this.clearDelay){
+this.clearDelay.cancel();
+this.clearDelay=null;
+}
+var _222=this.element.getContext("2d");
+}
+catch(e){
+this.isFirstRender=false;
+this.clearDelay=MochiKit.Async.wait(this.IEDelay);
+this.clearDelay.addCallback(bind(this.clear,this));
+return;
+}
+}
+var _222=this.element.getContext("2d");
+_222.clearRect(0,0,this.width,this.height);
+MochiKit.Iter.forEach(this.xlabels,MochiKit.DOM.removeElement);
+MochiKit.Iter.forEach(this.ylabels,MochiKit.DOM.removeElement);
+this.xlabels=new Array();
+this.ylabels=new Array();
+};
+PlotKit.CanvasRenderer.prototype._initialiseEvents=function(){
+var _223=MochiKit.Signal.connect;
+var bind=MochiKit.Base.bind;
+_223(this.element,"onclick",bind(this.onclick,this));
+};
+PlotKit.CanvasRenderer.prototype._resolveObject=function(e){
+var x=(e.mouse().page.x-PlotKit.Base.findPosX(this.element)-this.area.x)/this.area.w;
+var y=(e.mouse().page.y-PlotKit.Base.findPosY(this.element)-this.area.y)/this.area.h;
+var _225=this.layout.hitTest(x,y);
+if(_225){
+return _225;
+}
+return null;
+};
+PlotKit.CanvasRenderer.prototype._createEventObject=function(_226,e){
+if(_226==null){
+return null;
+}
+e.chart=_226;
+return e;
+};
+PlotKit.CanvasRenderer.prototype.onclick=function(e){
+var _227=this._resolveObject(e);
+var _228=this._createEventObject(_227,e);
+if(_228!=null){
+MochiKit.Signal.signal(this,"onclick",_228);
+}
+};
+PlotKit.CanvasRenderer.prototype.onmouseover=function(e){
+var _229=this._resolveObject(e);
+var _230=this._createEventObject(_229,e);
+if(_230!=null){
+signal(this,"onmouseover",_230);
+}
+};
+PlotKit.CanvasRenderer.prototype.onmouseout=function(e){
+var _231=this._resolveObject(e);
+var _232=this._createEventObject(_231,e);
+if(_232==null){
+signal(this,"onmouseout",e);
+}else{
+signal(this,"onmouseout",_232);
+}
+};
+PlotKit.CanvasRenderer.prototype.onmousemove=function(e){
+var _233=this._resolveObject(e);
+var _234=this._createEventObject(_233,e);
+if((_233==null)&&(this.event_isinside==null)){
+return;
+}
+if((_233!=null)&&(this.event_isinside==null)){
+signal(this,"onmouseover",_234);
+}
+if((_233==null)&&(this.event_isinside!=null)){
+signal(this,"onmouseout",_234);
+}
+if((_233!=null)&&(this.event_isinside!=null)){
+signal(this,"onmousemove",_234);
+}
+this.event_isinside=_233;
+};
+PlotKit.CanvasRenderer.isSupported=function(_235){
+var _236=null;
+try{
+if(MochiKit.Base.isUndefinedOrNull(_235)){
+_236=MochiKit.DOM.CANVAS({});
+}else{
+_236=MochiKit.DOM.getElement(_235);
+}
+var _237=_236.getContext("2d");
+}
+catch(e){
+var ie=navigator.appVersion.match(/MSIE (\d\.\d)/);
+var _239=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1);
+if((!ie)||(ie[1]<6)||(_239)){
+return false;
+}
+return true;
+}
+return true;
+};
+PlotKit.Canvas={};
+PlotKit.Canvas.CanvasRenderer=PlotKit.CanvasRenderer;
+PlotKit.Canvas.EXPORT=["CanvasRenderer"];
+PlotKit.Canvas.EXPORT_OK=["CanvasRenderer"];
+PlotKit.Canvas.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.Canvas.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.Canvas);
+try{
+if(typeof (PlotKit.Layout)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout";
+}
+PlotKit.SVGRenderer=function(_240,_241,_242){
+if(arguments.length>0){
+this.__init__(_240,_241,_242);
+}
+};
+PlotKit.SVGRenderer.NAME="PlotKit.SVGRenderer";
+PlotKit.SVGRenderer.VERSION=PlotKit.VERSION;
+PlotKit.SVGRenderer.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.SVGRenderer.toString=function(){
+return this.__repr__();
+};
+PlotKit.SVGRenderer.SVGNS="http://www.w3.org/2000/svg";
+PlotKit.SVGRenderer.prototype.__init__=function(_243,_244,_245){
+var _246=MochiKit.Base.isUndefinedOrNull;
+this.options={"drawBackground":true,"backgroundColor":Color.whiteColor(),"padding":{left:30,right:30,top:5,bottom:10},"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),"strokeColor":Color.whiteColor(),"strokeColorTransform":"asStrokeColor","strokeWidth":0.5,"shouldFill":true,"shouldStroke":true,"drawXAxis":true,"drawYAxis":true,"axisLineColor":Color.blackColor(),"axisLineWidth":0.5,"axisTickSize":3,"axisLabelColor":Color.blackColor(),"axisLabelFont":"Arial","axisLabelFontSize":9,"axisLabelWidth":50,"axisLabelUseDiv":true,"pieRadius":0.4,"enableEvents":true};
+MochiKit.Base.update(this.options,_245?_245:{});
+this.layout=_244;
+this.element=MochiKit.DOM.getElement(_243);
+this.container=this.element.parentNode;
+this.height=parseInt(this.element.getAttribute("height"));
+this.width=parseInt(this.element.getAttribute("width"));
+this.document=document;
+this.root=this.element;
+try{
+this.document=this.element.getSVGDocument();
+this.root=_246(this.document.documentElement)?this.element:this.document.documentElement;
+}
+catch(e){
+}
+this.element.style.zIndex=1;
+if(_246(this.element)){
+throw "SVGRenderer() - passed SVG object is not found";
+}
+if(_246(this.container)||this.container.nodeName.toLowerCase()!="div"){
+throw "SVGRenderer() - No DIV's around the SVG.";
+}
+this.xlabels=new Array();
+this.ylabels=new Array();
+this.defs=this.createSVGElement("defs");
+this.area={x:this.options.padding.left,y:this.options.padding.top,w:this.width-this.options.padding.left-this.options.padding.right,h:this.height-this.options.padding.top-this.options.padding.bottom};
+MochiKit.DOM.updateNodeAttributes(this.container,{"style":{"position":"relative","width":this.width+"px"}});
+};
+PlotKit.SVGRenderer.prototype.render=function(){
+if(this.options.drawBackground){
+this._renderBackground();
+}
+if(this.layout.style=="bar"){
+this._renderBarChart();
+this._renderBarAxis();
+}else{
+if(this.layout.style=="pie"){
+this._renderPieChart();
+this._renderPieAxis();
+}else{
+if(this.layout.style=="line"){
+this._renderLineChart();
+this._renderLineAxis();
+}
+}
+}
+};
+PlotKit.SVGRenderer.prototype._renderBarOrLine=function(data,_247,_248,_249){
+var _250=this.options.colorScheme.length;
+var _251=this.options.colorScheme;
+var _252=MochiKit.Base.keys(this.layout.datasets);
+var _253=_252.length;
+for(var i=0;i<_253;i++){
+var _254=_252[i];
+var _255=new Array();
+var _256=_251[i%_250];
+if(this.options.shouldFill){
+_255["fill"]=_256.toRGBString();
+}else{
+_255["fill"]="none";
+}
+if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){
+if(this.options.strokeColor){
+_255["stroke"]=this.options.strokeColor.toRGBString();
+}else{
+if(this.options.strokeColorTransform){
+_255["stroke"]=_256[this.options.strokeColorTransform]().toRGBString();
+}
+}
+_255["strokeWidth"]=this.options.strokeWidth;
+}
+if(_248){
+_248(_255);
+}
+var _257=function(obj){
+if(obj.name==_254){
+_247(_255,obj);
+}
+};
+MochiKit.Iter.forEach(data,bind(_257,this));
+if(_249){
+_249(_255);
+}
+}
+};
+PlotKit.SVGRenderer.prototype._renderBarChart=function(){
+var bind=MochiKit.Base.bind;
+var _258=function(_259,bar){
+var x=this.area.w*bar.x+this.area.x;
+var y=this.area.h*bar.y+this.area.y;
+var w=this.area.w*bar.w;
+var h=this.area.h*bar.h;
+this._drawRect(x,y,w,h,_259);
+};
+this._renderBarOrLine(this.layout.bars,bind(_258,this));
+};
+PlotKit.SVGRenderer.prototype._renderLineChart=function(){
+var bind=MochiKit.Base.bind;
+var _260=function(_261,_262){
+this._tempPointsBuffer+=(this.area.w*_262.x+this.area.x)+","+(this.area.h*_262.y+this.area.y)+" ";
+};
+var _263=function(_264){
+this._tempPointsBuffer="";
+this._tempPointsBuffer+=(this.area.x)+","+(this.area.y+this.area.h)+" ";
+};
+var _265=function(_266){
+this._tempPointsBuffer+=(this.area.w+this.area.x)+","+(this.area.h+this.area.y);
+_266["points"]=this._tempPointsBuffer;
+var elem=this.createSVGElement("polygon",_266);
+this.root.appendChild(elem);
+};
+this._renderBarOrLine(this.layout.points,bind(_260,this),bind(_263,this),bind(_265,this));
+};
+PlotKit.SVGRenderer.prototype._renderPieChart=function(){
+var _268=this.options.colorScheme.length;
+var _269=this.layout.slices;
+var _270=this.area.x+this.area.w*0.5;
+var _271=this.area.y+this.area.h*0.5;
+var _272=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius);
+if(_269.length==1&&(Math.abs(_269[0].startAngle)-Math.abs(_269[0].endAngle)<0.1)){
+var _273={"cx":_270,"cy":_271,"r":_272};
+var _274=this.options.colorScheme[0];
+if(this.options.shouldFill){
+_273["fill"]=_274.toRGBString();
+}else{
+_273["fill"]="none";
+}
+if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){
+if(this.options.strokeColor){
+_273["stroke"]=this.options.strokeColor.toRGBString();
+}else{
+if(this.options.strokeColorTransform){
+_273["stroke"]=_274[this.options.strokeColorTransform]().toRGBString();
+}
+}
+_273["style"]="stroke-width: "+this.options.strokeWidth;
+}
+this.root.appendChild(this.createSVGElement("circle",_273));
+return;
+}
+for(var i=0;i<_269.length;i++){
+var _273=new Array();
+var _274=this.options.colorScheme[i%_268];
+if(this.options.shouldFill){
+_273["fill"]=_274.toRGBString();
+}else{
+_273["fill"]="none";
+}
+if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){
+if(this.options.strokeColor){
+_273["stroke"]=this.options.strokeColor.toRGBString();
+}else{
+if(this.options.strokeColorTransform){
+_273["stroke"]=_274[this.options.strokeColorTransform]().toRGBString();
+}
+}
+_273["style"]="stroke-width:"+this.options.strokeWidth;
+}
+var _275=0;
+if(Math.abs(_269[i].endAngle-_269[i].startAngle)>Math.PI){
+_275=1;
+}
+var x1=Math.cos(_269[i].startAngle-Math.PI/2)*_272;
+var y1=Math.sin(_269[i].startAngle-Math.PI/2)*_272;
+var x2=Math.cos(_269[i].endAngle-Math.PI/2)*_272;
+var y2=Math.sin(_269[i].endAngle-Math.PI/2)*_272;
+var rx=x2-x1;
+var ry=y2-y1;
+var _282="M"+_270+","+_271+" ";
+_282+="l"+x1+","+y1+" ";
+_282+="a"+_272+","+_272+" 0 "+_275+",1 "+rx+","+ry+" z";
+_273["d"]=_282;
+var elem=this.createSVGElement("path",_273);
+this.root.appendChild(elem);
+}
+};
+PlotKit.SVGRenderer.prototype._renderBarAxis=function(){
+this._renderAxis();
+};
+PlotKit.SVGRenderer.prototype._renderLineAxis=function(){
+this._renderAxis();
+};
+PlotKit.SVGRenderer.prototype._renderAxis=function(){
+if(!this.options.drawXAxis&&!this.options.drawYAxis){
+return;
+}
+var _283={"style":{"position":"absolute","textAlign":"center","fontSize":this.options.axisLabelFontSize+"px","zIndex":10,"color":this.options.axisLabelColor.toRGBString(),"width":this.options.axisLabelWidth+"px","overflow":"hidden"}};
+var _284={"stroke":this.options.axisLineColor.toRGBString(),"strokeWidth":this.options.axisLineWidth};
+if(this.options.drawYAxis){
+if(this.layout.yticks){
+var _285=function(tick){
+var x=this.area.x;
+var y=this.area.y+tick[0]*this.area.h;
+this._drawLine(x,y,x-3,y,_284);
+if(this.options.axisLabelUseDiv){
+var _286=DIV(_283,tick[1]);
+_286.style.top=(y-this.options.axisLabelFontSize)+"px";
+_286.style.left=(x-this.options.padding.left+this.options.axisTickSize)+"px";
+_286.style.textAlign="left";
+_286.style.width=(this.options.padding.left-3)+"px";
+MochiKit.DOM.appendChildNodes(this.container,_286);
+this.ylabels.push(_286);
+}else{
+var _287={y:y+3,x:(x-this.options.padding.left+3),width:(this.options.padding.left-this.options.axisTickSize)+"px",height:(this.options.axisLabelFontSize+3)+"px",fontFamily:"Arial",fontSize:this.options.axisLabelFontSize+"px",fill:this.options.axisLabelColor.toRGBString()};
+var _286=this.createSVGElement("text",_287);
+_286.appendChild(this.document.createTextNode(tick[1]));
+this.root.appendChild(_286);
+}
+};
+MochiKit.Iter.forEach(this.layout.yticks,bind(_285,this));
+}
+this._drawLine(this.area.x,this.area.y,this.area.x,this.area.y+this.area.h,_284);
+}
+if(this.options.drawXAxis){
+if(this.layout.xticks){
+var _285=function(tick){
+var x=this.area.x+tick[0]*this.area.w;
+var y=this.area.y+this.area.h;
+this._drawLine(x,y,x,y+this.options.axisTickSize,_284);
+if(this.options.axisLabelUseDiv){
+var _288=DIV(_283,tick[1]);
+_288.style.top=(y+this.options.axisTickSize)+"px";
+_288.style.left=(x-this.options.axisLabelWidth/2)+"px";
+_288.style.textAlign="center";
+_288.style.width=this.options.axisLabelWidth+"px";
+MochiKit.DOM.appendChildNodes(this.container,_288);
+this.xlabels.push(_288);
+}else{
+var _289={y:(y+this.options.axisTickSize+this.options.axisLabelFontSize),x:x-3,width:this.options.axisLabelWidth+"px",height:(this.options.axisLabelFontSize+3)+"px",fontFamily:"Arial",fontSize:this.options.axisLabelFontSize+"px",fill:this.options.axisLabelColor.toRGBString(),textAnchor:"middle"};
+var _288=this.createSVGElement("text",_289);
+_288.appendChild(this.document.createTextNode(tick[1]));
+this.root.appendChild(_288);
+}
+};
+MochiKit.Iter.forEach(this.layout.xticks,bind(_285,this));
+}
+this._drawLine(this.area.x,this.area.y+this.area.h,this.area.x+this.area.w,this.area.y+this.area.h,_284);
+}
+};
+PlotKit.SVGRenderer.prototype._renderPieAxis=function(){
+if(this.layout.xticks){
+var _290=new Array();
+for(var i=0;i<this.layout.slices.length;i++){
+_290[this.layout.slices[i].xval]=this.layout.slices[i];
+}
+var _291=this.area.x+this.area.w*0.5;
+var _292=this.area.y+this.area.h*0.5;
+var _293=Math.min(this.area.w*this.options.pieRadius+10,this.area.h*this.options.pieRadius+10);
+var _294=this.options.axisLabelWidth;
+for(var i=0;i<this.layout.xticks.length;i++){
+var _295=_290[this.layout.xticks[i][0]];
+if(MochiKit.Base.isUndefinedOrNull(_295)){
+continue;
+}
+var _296=(_295.startAngle+_295.endAngle)/2;
+var _297=_296;
+if(_297>Math.PI*2){
+_297=_297-Math.PI*2;
+}else{
+if(_297<0){
+_297=_297+Math.PI*2;
+}
+}
+var _298=_291+Math.sin(_297)*(_293+10);
+var _299=_292-Math.cos(_297)*(_293+10);
+var _300={"position":"absolute","zIndex":11,"width":_294+"px","fontSize":this.options.axisLabelFontSize+"px","overflow":"hidden","color":this.options.axisLabelColor.toHexString()};
+var _301={"width":_294+"px","fontSize":this.options.axisLabelFontSize+"px","height":(this.options.axisLabelFontSize+3)+"px","fill":this.options.axisLabelColor.toRGBString()};
+if(_297<=Math.PI*0.5){
+MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"top","left":_298+"px","top":(_299-this.options.axisLabelFontSize)+"px"});
+MochiKit.Base.update(_301,{"x":_298,"y":(_299-this.options.axisLabelFontSize),"textAnchor":"left"});
+}else{
+if((_297>Math.PI*0.5)&&(_297<=Math.PI)){
+MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"bottom","left":_298+"px","top":_299+"px"});
+MochiKit.Base.update(_301,{"textAnchor":"left","x":_298,"y":_299});
+}else{
+if((_297>Math.PI)&&(_297<=Math.PI*1.5)){
+MochiKit.Base.update(_300,{"textAlign":"right","verticalAlign":"bottom","left":_298+"px","top":_299+"px"});
+MochiKit.Base.update(_301,{"textAnchor":"right","x":_298-_294,"y":_299});
+}else{
+MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"bottom","left":_298+"px","top":_299+"px"});
+MochiKit.Base.update(_301,{"textAnchor":"left","x":_298-_294,"y":_299-this.options.axisLabelFontSize});
+}
+}
+}
+if(this.options.axisLabelUseDiv){
+var _302=DIV({"style":_300},this.layout.xticks[i][1]);
+this.xlabels.push(_302);
+MochiKit.DOM.appendChildNodes(this.container,_302);
+}else{
+var _302=this.createSVGElement("text",_301);
+_302.appendChild(this.document.createTextNode(this.layout.xticks[i][1]));
+this.root.appendChild(_302);
+}
+}
+}
+};
+PlotKit.SVGRenderer.prototype._renderBackground=function(){
+var opts={"stroke":"none","fill":this.options.backgroundColor.toRGBString()};
+this._drawRect(0,0,this.width,this.height,opts);
+};
+PlotKit.SVGRenderer.prototype._drawRect=function(x,y,w,h,_304){
+var _305={x:x+"px",y:y+"px",width:w+"px",height:h+"px"};
+if(_304){
+MochiKit.Base.update(_305,_304);
+}
+var elem=this.createSVGElement("rect",_305);
+this.root.appendChild(elem);
+};
+PlotKit.SVGRenderer.prototype._drawLine=function(x1,y1,x2,y2,_306){
+var _307={x1:x1+"px",y1:y1+"px",x2:x2+"px",y2:y2+"px"};
+if(_306){
+MochiKit.Base.update(_307,_306);
+}
+var elem=this.createSVGElement("line",_307);
+this.root.appendChild(elem);
+};
+PlotKit.SVGRenderer.prototype.clear=function(){
+while(this.element.firstChild){
+this.element.removeChild(this.element.firstChild);
+}
+if(this.options.axisLabelUseDiv){
+for(var i=0;i<this.xlabels.length;i++){
+MochiKit.DOM.removeElement(this.xlabels[i]);
+}
+for(var i=0;i<this.ylabels.length;i++){
+MochiKit.DOM.removeElement(this.ylabels[i]);
+}
+}
+this.xlabels=new Array();
+this.ylabels=new Array();
+};
+PlotKit.SVGRenderer.prototype.createSVGElement=function(name,_309){
+var _310=MochiKit.Base.isUndefinedOrNull;
+var elem;
+var doc=_310(this.document)?document:this.document;
+try{
+elem=doc.createElementNS(PlotKit.SVGRenderer.SVGNS,name);
+}
+catch(e){
+elem=doc.createElement(name);
+elem.setAttribute("xmlns",PlotKit.SVGRenderer.SVGNS);
+}
+if(_309){
+MochiKit.DOM.updateNodeAttributes(elem,_309);
+}
+return elem;
+};
+PlotKit.SVGRenderer.SVG=function(_312){
+var ie=navigator.appVersion.match(/MSIE (\d\.\d)/);
+var _313=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1);
+if(ie&&(ie[1]>=6)&&(!_313)){
+var _314=_312["width"]?_312["width"]:"100";
+var _315=_312["height"]?_312["height"]:"100";
+var eid=_312["id"]?_312["id"]:"notunique";
+var html="<svg:svg width=\""+_314+"\" height=\""+_315+"\" ";
+html+="id=\""+eid+"\" version=\"1.1\" baseProfile=\"full\" />";
+var _318=document.createElement(html);
+var _319=_318.getSVGDocument().createElementNS(PlotKit.SVGRenderer.SVGNS,"svg");
+_319.setAttribute("width",_314);
+_319.setAttribute("height",_315);
+_318.getSVGDocument().appendChild(_319);
+return _318;
+}else{
+return PlotKit.SVGRenderer.prototype.createSVGElement("svg",_312);
+}
+};
+PlotKit.SVGRenderer.isSupported=function(){
+var _320=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1);
+var _321=navigator.appVersion.match(/MSIE (\d\.\d)/);
+var _322=navigator.userAgent.match(/AppleWebKit\/(\d+)/);
+var _323=navigator.userAgent.match(/Opera\/(\d*\.\d*)/);
+var _324=navigator.userAgent.match(/rv:(\d*\.\d*).*Gecko/);
+var _325="http://www.w3.org/TR/SVG11/feature#SVG";
+if(_321&&(_321[1]>=6)&&!_320){
+return document.implementation.hasFeature(_325,"1.1");
+}
+if(_323&&(_323[1]>8.9)){
+return true;
+}
+if(_324&&(_324>1.7)){
+return true;
+}
+return false;
+};
+PlotKit.SVG={};
+PlotKit.SVG.SVGRenderer=PlotKit.SVGRenderer;
+PlotKit.SVG.EXPORT=["SVGRenderer"];
+PlotKit.SVG.EXPORT_OK=["SVGRenderer"];
+PlotKit.SVG.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.SVG.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.SVG);
+try{
+if(typeof (PlotKit.CanvasRenderer)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "SweetCanvas depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, Canvas}";
+}
+if(typeof (PlotKit.SweetCanvasRenderer)=="undefined"){
+PlotKit.SweetCanvasRenderer={};
+}
+PlotKit.SweetCanvasRenderer=function(_326,_327,_328){
+if(arguments.length>0){
+this.__init__(_326,_327,_328);
+}
+};
+PlotKit.SweetCanvasRenderer.NAME="PlotKit.SweetCanvasRenderer";
+PlotKit.SweetCanvasRenderer.VERSION=PlotKit.VERSION;
+PlotKit.SweetCanvasRenderer.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.SweetCanvasRenderer.toString=function(){
+return this.__repr__();
+};
+PlotKit.SweetCanvasRenderer.prototype=new PlotKit.CanvasRenderer();
+PlotKit.SweetCanvasRenderer.prototype.constructor=PlotKit.SweetCanvasRenderer;
+PlotKit.SweetCanvasRenderer.__super__=PlotKit.CanvasRenderer.prototype;
+PlotKit.SweetCanvasRenderer.prototype.__init__=function(el,_330,opts){
+var _331=PlotKit.Base.officeBlue();
+MochiKit.Base.update(_331,opts);
+PlotKit.SweetCanvasRenderer.__super__.__init__.call(this,el,_330,_331);
+};
+PlotKit.SweetCanvasRenderer.prototype._renderBarChart=function(){
+var bind=MochiKit.Base.bind;
+var _332=Color.blackColor().colorWithAlpha(0.1).toRGBString();
+var _333=function(_334,x,y,w,h){
+_334.fillStyle=_332;
+_334.fillRect(x-2,y-2,w+4,h+2);
+_334.fillStyle=_332;
+_334.fillRect(x-1,y-1,w+2,h+1);
+};
+var _335=this.options.colorScheme.length;
+var _336=this.options.colorScheme;
+var _337=PlotKit.Base.keys(this.layout.datasets);
+var _338=_337.length;
+var _339=function(name){
+for(var i=0;i<_338;i++){
+if(name==_337[i]){
+return _336[i%_335];
+}
+}
+return _336[0];
+};
+var _340=function(_341,bar){
+var x=this.area.w*bar.x+this.area.x;
+var y=this.area.h*bar.y+this.area.y;
+var w=this.area.w*bar.w;
+var h=this.area.h*bar.h;
+if((w<1)||(h<1)){
+return;
+}
+_341.save();
+_341.shadowBlur=5;
+_341.shadowColor=Color.fromHexString("#888888").toRGBString();
+if(this.isIE){
+_341.save();
+_341.fillStyle="#cccccc";
+_341.fillRect(x-2,y-2,w+4,h+2);
+_341.restore();
+}else{
+_333(_341,x,y,w,h);
+}
+if(this.options.shouldFill){
+_341.fillStyle=_339(bar.name).toRGBString();
+_341.fillRect(x,y,w,h);
+}
+_341.shadowBlur=0;
+_341.strokeStyle=Color.whiteColor().toRGBString();
+_341.lineWidth=2;
+if(this.options.shouldStroke){
+_341.strokeRect(x,y,w,h);
+}
+_341.restore();
+};
+this._renderBarChartWrap(this.layout.bars,bind(_340,this));
+};
+PlotKit.SweetCanvasRenderer.prototype._renderLineChart=function(){
+var _342=this.element.getContext("2d");
+var _343=this.options.colorScheme.length;
+var _344=this.options.colorScheme;
+var _345=PlotKit.Base.keys(this.layout.datasets);
+var _346=_345.length;
+var bind=MochiKit.Base.bind;
+for(var i=0;i<_346;i++){
+var _347=_345[i];
+var _348=_344[i%_343];
+var _349=this.options.strokeColorTransform;
+_342.save();
+var _350=function(ctx){
+ctx.beginPath();
+ctx.moveTo(this.area.x,this.area.y+this.area.h);
+var _351=function(ctx_,_352){
+if(_352.name==_347){
+ctx_.lineTo(this.area.w*_352.x+this.area.x,this.area.h*_352.y+this.area.y);
+}
+};
+MochiKit.Iter.forEach(this.layout.points,partial(_351,ctx),this);
+ctx.lineTo(this.area.w+this.area.x,this.area.h+this.area.y);
+ctx.lineTo(this.area.x,this.area.y+this.area.h);
+ctx.closePath();
+};
+if(this.options.shouldFill){
+_342.save();
+if(this.isIE){
+_342.fillStyle="#cccccc";
+}else{
+_342.fillStyle=Color.blackColor().colorWithAlpha(0.2).toRGBString();
+}
+_342.translate(-1,-2);
+bind(_350,this)(_342);
+if(this.options.shouldFill){
+_342.fill();
+}
+_342.restore();
+}
+_342.shadowBlur=5;
+_342.shadowColor=Color.fromHexString("#888888").toRGBString();
+_342.fillStyle=_348.toRGBString();
+_342.lineWidth=2;
+_342.strokeStyle=Color.whiteColor().toRGBString();
+if(this.options.shouldFill){
+bind(_350,this)(_342);
+_342.fill();
+}
+if(this.options.shouldStroke){
+bind(_350,this)(_342);
+_342.stroke();
+}
+_342.restore();
+}
+};
+PlotKit.SweetCanvasRenderer.prototype._renderPieChart=function(){
+var _353=this.element.getContext("2d");
+var _354=this.options.colorScheme.length;
+var _355=this.layout.slices;
+var _356=this.area.x+this.area.w*0.5;
+var _357=this.area.y+this.area.h*0.5;
+var _358=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius);
+if(this.isIE){
+_356=parseInt(_356);
+_357=parseInt(_357);
+_358=parseInt(_358);
+}
+if(!this.isIE){
+_353.save();
+var _359=Color.blackColor().colorWithAlpha(0.2);
+_353.fillStyle=_359.toRGBString();
+_353.shadowBlur=5;
+_353.shadowColor=Color.fromHexString("#888888").toRGBString();
+_353.translate(1,1);
+_353.beginPath();
+_353.moveTo(_356,_357);
+_353.arc(_356,_357,_358+2,0,Math.PI*2,false);
+_353.closePath();
+_353.fill();
+_353.restore();
+}
+_353.save();
+_353.strokeStyle=Color.whiteColor().toRGBString();
+_353.lineWidth=2;
+for(var i=0;i<_355.length;i++){
+var _360=this.options.colorScheme[i%_354];
+_353.fillStyle=_360.toRGBString();
+var _361=function(){
+_353.beginPath();
+_353.moveTo(_356,_357);
+_353.arc(_356,_357,_358,_355[i].startAngle-Math.PI/2,_355[i].endAngle-Math.PI/2,false);
+_353.lineTo(_356,_357);
+_353.closePath();
+};
+if(Math.abs(_355[i].startAngle-_355[i].endAngle)>0.0001){
+if(this.options.shouldFill){
+_361();
+_353.fill();
+}
+if(this.options.shouldStroke){
+_361();
+_353.stroke();
+}
+}
+}
+_353.restore();
+};
+PlotKit.SweetCanvasRenderer.prototype._renderBackground=function(){
+var _362=this.element.getContext("2d");
+if(this.layout.style=="bar"||this.layout.style=="line"){
+_362.save();
+_362.fillStyle=this.options.backgroundColor.toRGBString();
+_362.fillRect(this.area.x,this.area.y,this.area.w,this.area.h);
+_362.strokeStyle=this.options.axisLineColor.toRGBString();
+_362.lineWidth=1;
+var _363=this.layout.yticks;
+var _364=false;
+if(this.layout.style=="bar"&&this.layout.options.barOrientation=="horizontal"){
+_363=this.layout.xticks;
+_364=true;
+}
+for(var i=0;i<_363.length;i++){
+var x1=0;
+var y1=0;
+var x2=0;
+var y2=0;
+if(_364){
+x1=_363[i][0]*this.area.w+this.area.x;
+y1=this.area.y;
+x2=x1;
+y2=y1+this.area.h;
+}else{
+x1=this.area.x;
+y1=_363[i][0]*this.area.h+this.area.y;
+x2=x1+this.area.w;
+y2=y1;
+}
+_362.beginPath();
+_362.moveTo(x1,y1);
+_362.lineTo(x2,y2);
+_362.closePath();
+_362.stroke();
+}
+_362.restore();
+}else{
+PlotKit.SweetCanvasRenderer.__super__._renderBackground.call(this);
+}
+};
+PlotKit.SweetCanvas={};
+PlotKit.SweetCanvas.SweetCanvasRenderer=PlotKit.SweetCanvasRenderer;
+PlotKit.SweetCanvas.EXPORT=["SweetCanvasRenderer"];
+PlotKit.SweetCanvas.EXPORT_OK=["SweetCanvasRenderer"];
+PlotKit.SweetCanvas.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.SweetCanvas.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.SweetCanvas);
+try{
+if(typeof (PlotKit.SVGRenderer)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "SweetSVG depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, SVG}";
+}
+if(typeof (PlotKit.SweetSVGRenderer)=="undefined"){
+PlotKit.SweetSVGRenderer={};
+}
+PlotKit.SweetSVGRenderer=function(_365,_366,_367){
+if(arguments.length>0){
+this.__init__(_365,_366,_367);
+}
+};
+PlotKit.SweetSVGRenderer.NAME="PlotKit.SweetSVGRenderer";
+PlotKit.SweetSVGRenderer.VERSION=PlotKit.VERSION;
+PlotKit.SweetSVGRenderer.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.SweetSVGRenderer.toString=function(){
+return this.__repr__();
+};
+PlotKit.SweetSVGRenderer.prototype=new PlotKit.SVGRenderer();
+PlotKit.SweetSVGRenderer.prototype.constructor=PlotKit.SweetSVGRenderer;
+PlotKit.SweetSVGRenderer.__super__=PlotKit.SVGRenderer.prototype;
+PlotKit.SweetSVGRenderer.prototype.__init__=function(_368,_369,_370){
+var _371=PlotKit.Base.officeBlue();
+MochiKit.Base.update(_371,_370);
+PlotKit.SweetSVGRenderer.__super__.__init__.call(this,_368,_369,_371);
+};
+PlotKit.SweetSVGRenderer.prototype._addDropShadowFilter=function(){
+var _372=this.createSVGElement("filter",{x:0,y:0,"id":"dropShadow"});
+var _373=this.createSVGElement("feOffset",{"in":"SourceGraphic","dx":0,"dy":0,"result":"topCopy"});
+var blur=this.createSVGElement("feGaussianBlur",{"in":"SourceAlpha","StdDeviation":2,"result":"shadow"});
+var _375=this.createSVGElement("feOffset",{"in":"shadow","dx":-1,"dy":-2,"result":"movedShadow"});
+var _376=this.createSVGElement("feMerge");
+var _377=this.createSVGElement("feMergeNode",{"in":"topCopy"});
+var _378=this.createSVGElement("feMergeNode",{"in":"movedShadow"});
+_376.appendChild(_377);
+_376.appendChild(_378);
+_372.appendChild(_373);
+_372.appendChild(blur);
+_372.appendChild(_375);
+_372.appendChild(_376);
+this.defs.appendChild(_372);
+};
+PlotKit.SweetSVGRenderer.prototype._renderBarChart=function(){
+var bind=MochiKit.Base.bind;
+var _379=Color.blackColor().toRGBString();
+var _380="fill:"+_379+";fill-opacity:0.15";
+var _381="stroke-width: 2.0; stroke:"+Color.whiteColor().toRGBString();
+var _382=function(_383,bar){
+var x=this.area.w*bar.x+this.area.x;
+var y=this.area.h*bar.y+this.area.y;
+var w=this.area.w*bar.w;
+var h=this.area.h*bar.h;
+if((w<1)||(h<1)){
+return;
+}
+_383["style"]=_381;
+this._drawRect(x-2,y-1,w+4,h+2,{"style":_380});
+this._drawRect(x,y,w,h,_383);
+};
+this._renderBarOrLine(this.layout.bars,bind(_382,this));
+};
+PlotKit.SweetSVGRenderer.prototype._renderLineChart=function(){
+var bind=MochiKit.Base.bind;
+var _384=Color.blackColor().toRGBString();
+var _385="fill:"+_384+";fill-opacity:0.15";
+var _386="stroke-width: 2.0; stroke:"+Color.whiteColor().toRGBString();
+var _387=function(_388,_389){
+this._tempPointsBuffer+=(this.area.w*_389.x+this.area.x)+","+(this.area.h*_389.y+this.area.y)+" ";
+};
+var _390=function(_391){
+this._tempPointsBuffer="";
+this._tempPointsBuffer+=(this.area.x)+","+(this.area.y+this.area.h)+" ";
+};
+var _392=function(_393){
+this._tempPointsBuffer+=(this.area.w+this.area.x)+","+(this.area.h+this.area.y);
+_393["points"]=this._tempPointsBuffer;
+_393["stroke"]="none";
+_393["transform"]="translate(-2, -1)";
+_393["style"]=_385;
+var _394=this.createSVGElement("polygon",_393);
+this.root.appendChild(_394);
+_393["transform"]="";
+_393["style"]=_386;
+var elem=this.createSVGElement("polygon",_393);
+this.root.appendChild(elem);
+};
+this._renderBarOrLine(this.layout.points,bind(_387,this),bind(_390,this),bind(_392,this));
+};
+PlotKit.SweetSVGRenderer.prototype._renderPieChart=function(){
+var _395=this.area.x+this.area.w*0.5;
+var _396=this.area.y+this.area.h*0.5;
+var _397=Color.blackColor().toRGBString();
+var _398=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius);
+var _399="fill:"+_397+";fill-opacity:0.15";
+var _400=this.createSVGElement("circle",{"style":_399,"cx":_395+1,"cy":_396+1,"r":_398+1});
+this.root.appendChild(_400);
+PlotKit.SweetSVGRenderer.__super__._renderPieChart.call(this);
+};
+PlotKit.SweetSVGRenderer.prototype._renderBackground=function(){
+var _401={"fill":this.options.backgroundColor.toRGBString(),"stroke":"none"};
+if(this.layout.style=="bar"||this.layout.style=="line"){
+this._drawRect(this.area.x,this.area.y,this.area.w,this.area.h,_401);
+var _402=this.layout.yticks;
+var _403=false;
+if(this.layout.style=="bar"&&this.layout.options.barOrientation=="horizontal"){
+_402=this.layout.xticks;
+_403=true;
+}
+for(var i=0;i<_402.length;i++){
+var x=0;
+var y=0;
+var w=0;
+var h=0;
+if(_403){
+x=_402[i][0]*this.area.w+this.area.x;
+y=this.area.y;
+w=1;
+h=this.area.w;
+}else{
+x=this.area.x;
+y=_402[i][0]*this.area.h+this.area.y;
+w=this.area.w;
+h=1;
+}
+this._drawRect(x,y,w,h,{"fill":this.options.axisLineColor.toRGBString()});
+}
+}else{
+PlotKit.SweetSVGRenderer.__super__._renderBackground.call(this);
+}
+};
+PlotKit.SweetSVG={};
+PlotKit.SweetSVG.SweetSVGRenderer=PlotKit.SweetSVGRenderer;
+PlotKit.SweetSVG.EXPORT=["SweetSVGRenderer"];
+PlotKit.SweetSVG.EXPORT_OK=["SweetSVGRenderer"];
+PlotKit.SweetSVG.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.SweetSVG.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.SweetSVG);
+try{
+if(typeof (PlotKit.CanvasRenderer)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit.EasyPlot depends on all of PlotKit's components";
+}
+if(typeof (PlotKit.EasyPlot)=="undefined"){
+PlotKit.EasyPlot={};
+}
+PlotKit.EasyPlot.NAME="PlotKit.EasyPlot";
+PlotKit.EasyPlot.VERSION=PlotKit.VERSION;
+PlotKit.EasyPlot.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.EasyPlot.toString=function(){
+return this.__repr__();
+};
+PlotKit.EasyPlot=function(_404,_405,_406,_407){
+this.layout=new Layout(_404,_405);
+this.divElem=_406;
+this.width=parseInt(_406.getAttribute("width"));
+this.height=parseInt(_406.getAttribute("height"));
+this.deferredCount=0;
+if(this.width<1){
+this.width=this.divElem.width?this.divElem.width:300;
+}
+if(this.height<1){
+this.height=this.divElem.height?this.divElem.height:300;
+}
+if(isArrayLike(_407)){
+for(var i=0;i<_407.length;i++){
+if(typeof (_407[i])=="string"){
+this.deferredCount++;
+var d=MochiKit.Async.doSimpleXMLHttpRequest(_407[i]);
+d.addCallback(MochiKit.Base.bind(PlotKit.EasyPlot.onDataLoaded,this));
+}else{
+if(isArrayLike(_407[i])){
+this.layout.addDataset("data-"+i,_407[i]);
+}
+}
+}
+}else{
+if(!isUndefinedOrNull(_407)){
+throw "Passed datasources are not Array like";
+}
+}
+if(CanvasRenderer.isSupported()){
+this.element=CANVAS({"id":this.divElem.getAttribute("id")+"-canvas","width":this.width,"height":this.height},"");
+this.divElem.appendChild(this.element);
+this.renderer=new SweetCanvasRenderer(this.element,this.layout,_405);
+}else{
+if(SVGRenderer.isSupported()){
+this.element=SVGRenderer.SVG({"id":this.divElem.getAttribute("id")+"-svg","width":this.width,"height":this.height,"version":"1.1","baseProfile":"full"},"");
+this.divElem.appendChild(this.element);
+this.renderer=new SweetSVGRenderer(this.element,this.layout,_405);
+}
+}
+if((this.deferredCount==0)&&(PlotKit.Base.keys(this.layout.datasets).length>0)){
+this.layout.evaluate();
+this.renderer.clear();
+this.renderer.render();
+}
+};
+PlotKit.EasyPlot.onDataLoaded=function(_409){
+var _410=new Array();
+var _411=_409.responseText.split("\n");
+for(var i=0;i<_411.length;i++){
+var _412=MochiKit.Format.strip(_411[i]);
+if((_412.length>1)&&(_412.charAt(0)!="#")){
+_410.push(_412.split(","));
+}
+}
+this.layout.addDataset("data-ajax-"+this.deferredCount,_410);
+this.deferredCount--;
+if((this.deferredCount==0)&&(PlotKit.Base.keys(this.layout.datasets).length>0)){
+this.layout.evaluate();
+this.renderer.clear();
+this.renderer.render();
+}
+};
+PlotKit.EasyPlot.prototype.reload=function(){
+this.layout.evaluate();
+this.renderer.clear();
+this.renderer.render();
+};
+PlotKit.EasyPlotModule={};
+PlotKit.EasyPlotModule.EasyPlot=PlotKit.EasyPlot;
+PlotKit.EasyPlotModule.EXPORT=["EasyPlot"];
+PlotKit.EasyPlotModule.EXPORT_OK=[];
+PlotKit.EasyPlotModule.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.EasyPlotModule.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.EasyPlotModule);
+
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SVG.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SVG.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,705 @@
+/*
+    PlotKit SVG
+    ===========
+    SVG Renderer for PlotKit
+
+    Copyright
+    ---------
+    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
+    For use under the BSD license. <http://www.liquidx.net/plotkit>
+*/
+
+// -------------------------------------------------------------------------
+// NOTES: - If you use XHTML1.1 strict, then you must include each MochiKit
+//          file individuall.
+//        - For IE support, you must include the AdobeSVG object hack.
+//          See tests/svg.html for details.
+// -------------------------------------------------------------------------
+// -------------------------------------------------------------------------
+// Check required components
+// -------------------------------------------------------------------------
+
+try {    
+    if (typeof(PlotKit.Layout) == 'undefined')
+    {
+        throw "";    
+    }
+} 
+catch (e) {    
+    throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout"
+}
+
+
+// ---------------------------------------------------------------------------
+//  SVG Renderer
+// ---------------------------------------------------------------------------
+
+PlotKit.SVGRenderer = function(element, layout, options) {
+    if (arguments.length > 0) 
+        this.__init__(element, layout, options);
+};
+
+PlotKit.SVGRenderer.NAME = "PlotKit.SVGRenderer";
+PlotKit.SVGRenderer.VERSION = PlotKit.VERSION;
+
+PlotKit.SVGRenderer.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.SVGRenderer.toString = function() {
+    return this.__repr__();
+}
+
+PlotKit.SVGRenderer.SVGNS = 'http://www.w3.org/2000/svg';
+
+PlotKit.SVGRenderer.prototype.__init__ = function(element, layout, options) {
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+
+    // default options
+    this.options = {
+        "drawBackground": true,
+        "backgroundColor": Color.whiteColor(),
+        "padding": {left: 30, right: 30, top: 5, bottom: 10},
+        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),
+        "strokeColor": Color.whiteColor(),
+        "strokeColorTransform": "asStrokeColor",
+        "strokeWidth": 0.5,
+        "shouldFill": true,
+        "shouldStroke": true,
+        "drawXAxis": true,
+        "drawYAxis": true,
+        "axisLineColor": Color.blackColor(),
+        "axisLineWidth": 0.5,
+        "axisTickSize": 3,
+        "axisLabelColor": Color.blackColor(),
+        "axisLabelFont": "Arial",
+        "axisLabelFontSize": 9,
+        "axisLabelWidth": 50,
+        "axisLabelUseDiv": true,
+        "pieRadius": 0.4,
+        "enableEvents": true
+    };
+
+    MochiKit.Base.update(this.options, options ? options : {});
+    this.layout = layout;
+    this.element = MochiKit.DOM.getElement(element);
+    this.container = this.element.parentNode;
+    this.height = parseInt(this.element.getAttribute("height"));
+    this.width = parseInt(this.element.getAttribute("width"));
+    this.document = document;
+    this.root = this.element;
+
+    // Adobe SVG Support:
+    // - if an exception is thrown, then no Adobe SVG Plugin support.
+    try {
+        this.document = this.element.getSVGDocument();
+        this.root = isNil(this.document.documentElement) ? this.element : this.document.documentElement;
+    }
+    catch (e) {
+    }
+
+    this.element.style.zIndex = 1;
+
+    if (isNil(this.element))
+        throw "SVGRenderer() - passed SVG object is not found";
+
+    if (isNil(this.container) || this.container.nodeName.toLowerCase() != "div")
+        throw "SVGRenderer() - No DIV's around the SVG.";
+
+    // internal state
+    this.xlabels = new Array();
+    this.ylabels = new Array();
+
+    // initialise some meta structures in SVG
+    this.defs = this.createSVGElement("defs");
+
+    this.area = {
+        x: this.options.padding.left,
+        y: this.options.padding.top,
+        w: this.width - this.options.padding.left - this.options.padding.right,
+        h: this.height - this.options.padding.top - this.options.padding.bottom
+    };
+
+    MochiKit.DOM.updateNodeAttributes(this.container, 
+    {"style":{ "position": "relative", "width": this.width + "px"}});
+
+    
+};
+
+
+PlotKit.SVGRenderer.prototype.render = function() {
+    if (this.options.drawBackground)
+        this._renderBackground();
+
+    if (this.layout.style == "bar") {
+        this._renderBarChart();
+        this._renderBarAxis();
+    }
+    else if (this.layout.style == "pie") {
+        this._renderPieChart();
+        this._renderPieAxis();
+    }
+    else if (this.layout.style == "line") {
+        this._renderLineChart();
+        this._renderLineAxis();
+    }
+};
+
+PlotKit.SVGRenderer.prototype._renderBarOrLine = function(data, plotFunc, startFunc, endFunc) {
+    
+    var colorCount = this.options.colorScheme.length;
+    var colorScheme = this.options.colorScheme;
+    var setNames = MochiKit.Base.keys(this.layout.datasets);
+    var setCount = setNames.length;
+
+    for (var i = 0; i < setCount; i++) {
+        var setName = setNames[i];
+        var attrs = new Array();
+        var color = colorScheme[i%colorCount];
+
+        if (this.options.shouldFill)
+            attrs["fill"] = color.toRGBString();
+        else
+            attrs["fill"] = "none";
+
+        if (this.options.shouldStroke && 
+            (this.options.strokeColor || this.options.strokeColorTransform)) {
+            if (this.options.strokeColor)
+                attrs["stroke"] = this.options.strokeColor.toRGBString();
+            else if (this.options.strokeColorTransform)
+                attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString();
+            attrs["strokeWidth"] = this.options.strokeWidth;
+        }
+
+        if (startFunc)
+            startFunc(attrs);
+
+        var forEachFunc = function(obj) {
+            if (obj.name == setName)
+                plotFunc(attrs, obj);
+        };                
+
+        MochiKit.Iter.forEach(data, bind(forEachFunc, this));
+        if (endFunc)
+            endFunc(attrs);
+    }
+};
+
+PlotKit.SVGRenderer.prototype._renderBarChart = function() {
+    var bind = MochiKit.Base.bind;
+
+    var drawRect = function(attrs, bar) {
+        var x = this.area.w * bar.x + this.area.x;
+        var y = this.area.h * bar.y + this.area.y;
+        var w = this.area.w * bar.w;
+        var h = this.area.h * bar.h;
+        this._drawRect(x, y, w, h, attrs);
+    };
+    this._renderBarOrLine(this.layout.bars, bind(drawRect, this));
+};
+
+PlotKit.SVGRenderer.prototype._renderLineChart = function() {
+    var bind = MochiKit.Base.bind;
+
+    var addPoint = function(attrs, point) {
+        this._tempPointsBuffer += (this.area.w * point.x + this.area.x) + "," +
+                                 (this.area.h * point.y + this.area.y) + " ";
+    };
+
+    var startLine = function(attrs) {
+        this._tempPointsBuffer = "";
+        this._tempPointsBuffer += (this.area.x) + "," + (this.area.y+this.area.h) + " ";
+    };
+
+    var endLine = function(attrs) {
+        this._tempPointsBuffer += (this.area.w + this.area.x) + ","  +(this.area.h + this.area.y);
+        attrs["points"] = this._tempPointsBuffer;
+        var elem = this.createSVGElement("polygon", attrs);
+        this.root.appendChild(elem);
+    };
+
+    this._renderBarOrLine(this.layout.points, 
+                          bind(addPoint, this), 
+                          bind(startLine, this), 
+                          bind(endLine, this));
+};
+
+
+PlotKit.SVGRenderer.prototype._renderPieChart = function() {
+    var colorCount = this.options.colorScheme.length;
+    var slices = this.layout.slices;
+
+    var centerx = this.area.x + this.area.w * 0.5;
+    var centery = this.area.y + this.area.h * 0.5;
+    var radius = Math.min(this.area.w * this.options.pieRadius, 
+                          this.area.h * this.options.pieRadius);
+
+    // NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1
+    // so we have to subtract 90 degrees to make it start at y = 1, x = 0
+
+	// workaround if we only have 1 slice of 100%
+	if (slices.length == 1 && (Math.abs(slices[0].startAngle) - Math.abs(slices[0].endAngle) < 0.1)) {
+        var attrs = {"cx": centerx , "cy": centery , "r": radius };
+        var color = this.options.colorScheme[0];
+        if (this.options.shouldFill)
+            attrs["fill"] = color.toRGBString();
+        else
+            attrs["fill"] = "none";
+
+        if (this.options.shouldStroke && 
+            (this.options.strokeColor || this.options.strokeColorTransform)) {
+            if (this.options.strokeColor)
+                attrs["stroke"] = this.options.strokeColor.toRGBString();
+            else if (this.options.strokeColorTransform)
+                attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString();
+            attrs["style"] = "stroke-width: " + this.options.strokeWidth;
+        }
+
+        this.root.appendChild(this.createSVGElement("circle", attrs));
+        return;
+	}
+
+    for (var i = 0; i < slices.length; i++) {
+        var attrs = new Array();
+        var color = this.options.colorScheme[i%colorCount];
+        if (this.options.shouldFill)
+            attrs["fill"] = color.toRGBString();
+        else
+            attrs["fill"] = "none";
+
+        if (this.options.shouldStroke &&
+            (this.options.strokeColor || this.options.strokeColorTransform)) {
+            if (this.options.strokeColor)
+                attrs["stroke"] = this.options.strokeColor.toRGBString();
+            else if (this.options.strokeColorTransform)
+                attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString();
+            attrs["style"] = "stroke-width:" + this.options.strokeWidth;
+        }
+
+        var largearc = 0;
+        if (Math.abs(slices[i].endAngle - slices[i].startAngle) > Math.PI)
+            largearc = 1;
+        var x1 = Math.cos(slices[i].startAngle - Math.PI/2) * radius;
+        var y1 = Math.sin(slices[i].startAngle - Math.PI/2) * radius;
+        var x2 = Math.cos(slices[i].endAngle - Math.PI/2) * radius;
+        var y2 = Math.sin(slices[i].endAngle - Math.PI/2) * radius;
+        var rx = x2 - x1;
+        var ry = y2 - y1;
+
+        var pathString = "M" + centerx + "," + centery + " ";       
+        pathString += "l" + x1 + "," + y1 + " ";
+        pathString += "a" + radius + "," + radius + " 0 " + largearc + ",1 " + rx + "," + ry + " z";
+
+        attrs["d"] = pathString;
+
+        var elem = this.createSVGElement("path", attrs);
+        this.root.appendChild(elem);
+    }
+};
+
+PlotKit.SVGRenderer.prototype._renderBarAxis = function() {
+    this._renderAxis();
+}
+
+PlotKit.SVGRenderer.prototype._renderLineAxis = function() {
+    this._renderAxis();
+};
+
+
+PlotKit.SVGRenderer.prototype._renderAxis = function() {
+
+    if (!this.options.drawXAxis && !this.options.drawYAxis)
+        return;
+
+    var labelStyle = {"style":
+         {"position": "absolute",
+          "textAlign": "center",
+          "fontSize": this.options.axisLabelFontSize + "px",
+          "zIndex": 10,
+          "color": this.options.axisLabelColor.toRGBString(),
+          "width": this.options.axisLabelWidth + "px",
+          "overflow": "hidden"
+         }
+    };
+
+    // axis lines
+    var lineAttrs = {
+        "stroke": this.options.axisLineColor.toRGBString(),
+        "strokeWidth": this.options.axisLineWidth
+    };
+    
+
+    if (this.options.drawYAxis) {
+        if (this.layout.yticks) {
+            var drawTick = function(tick) {
+                var x = this.area.x;
+                var y = this.area.y + tick[0] * this.area.h;
+                this._drawLine(x, y, x - 3, y, lineAttrs);
+                
+                if (this.options.axisLabelUseDiv) {
+                    var label = DIV(labelStyle, tick[1]);
+                    label.style.top = (y - this.options.axisLabelFontSize) + "px";
+                    label.style.left = (x - this.options.padding.left + this.options.axisTickSize) + "px";
+                    label.style.textAlign = "left";
+                    label.style.width = (this.options.padding.left - 3) + "px";
+                    MochiKit.DOM.appendChildNodes(this.container, label);
+                    this.ylabels.push(label);
+                }
+                else {
+                    var attrs = {
+                        y: y + 3,
+                        x: (x - this.options.padding.left + 3),
+                        width: (this.options.padding.left - this.options.axisTickSize) + "px",
+                        height: (this.options.axisLabelFontSize + 3) + "px",
+                        fontFamily: "Arial",
+                        fontSize: this.options.axisLabelFontSize + "px",
+                        fill: this.options.axisLabelColor.toRGBString()
+                    };
+                    
+                    /* we can do clipping just like DIVs
+                    http://www.xml.com/pub/a/2004/06/02/svgtype.html */
+                    /*
+                    var mask = this.createSVGElement("mask", {id: "mask" + tick[0]});
+                    var maskShape = this.createSVGElement("rect",
+                        {y: y + 3,
+                         x: (x - this.options.padding.left + 3),
+                         width: (this.options.padding.left - this.options.axisTickSize) + "px",
+                         height: (this.options.axisLabelFontSize + 3) + "px",
+                         style: {"fill": "#ffffff", "stroke": "#000000"}});
+                    mask.appendChild(maskShape);
+                    this.defs.appendChild(mask);
+                    
+                    attrs["filter"] = "url(#mask" + tick[0] + ")";
+                    */
+                    
+                    var label = this.createSVGElement("text", attrs);
+                    label.appendChild(this.document.createTextNode(tick[1]));
+                    this.root.appendChild(label);
+                }
+            };
+            
+            MochiKit.Iter.forEach(this.layout.yticks, bind(drawTick, this));
+        }
+
+        this._drawLine(this.area.x, this.area.y, this.area.x, this.area.y + this.area.h, lineAttrs);
+    }
+
+    if (this.options.drawXAxis) {
+        if (this.layout.xticks) {
+            var drawTick = function(tick) {
+                var x = this.area.x + tick[0] * this.area.w;
+                var y = this.area.y + this.area.h;
+                this._drawLine(x, y, x, y + this.options.axisTickSize, lineAttrs);
+
+                if (this.options.axisLabelUseDiv) {
+                    var label = DIV(labelStyle, tick[1]);
+                    label.style.top = (y + this.options.axisTickSize) + "px";
+                    label.style.left = (x - this.options.axisLabelWidth/2) + "px";
+                    label.style.textAlign = "center";
+                    label.style.width = this.options.axisLabelWidth + "px";
+                    MochiKit.DOM.appendChildNodes(this.container, label);
+                    this.xlabels.push(label);
+                }
+                else {
+                    var attrs = {
+                        y: (y + this.options.axisTickSize + this.options.axisLabelFontSize),
+                        x: x - 3,
+                        width: this.options.axisLabelWidth + "px",
+                        height: (this.options.axisLabelFontSize + 3) + "px",
+                        fontFamily: "Arial",
+                        fontSize: this.options.axisLabelFontSize + "px",
+                        fill: this.options.axisLabelColor.toRGBString(),
+                        textAnchor: "middle"
+                    };
+                    var label = this.createSVGElement("text", attrs);
+                    label.appendChild(this.document.createTextNode(tick[1]));
+                    this.root.appendChild(label);
+                }
+            };
+            
+            MochiKit.Iter.forEach(this.layout.xticks, bind(drawTick, this));
+        }
+
+        this._drawLine(this.area.x, this.area.y + this.area.h, this.area.x + this.area.w, this.area.y + this.area.h, lineAttrs)
+    }
+};
+
+PlotKit.SVGRenderer.prototype._renderPieAxis = function() {
+
+    if (this.layout.xticks) {
+        // make a lookup dict for x->slice values
+        var lookup = new Array();
+        for (var i = 0; i < this.layout.slices.length; i++) {
+            lookup[this.layout.slices[i].xval] = this.layout.slices[i];
+        }
+        
+        var centerx = this.area.x + this.area.w * 0.5;
+        var centery = this.area.y + this.area.h * 0.5;
+        var radius = Math.min(this.area.w * this.options.pieRadius + 10, 
+                              this.area.h * this.options.pieRadius + 10);
+        var labelWidth = this.options.axisLabelWidth;
+        
+        for (var i = 0; i < this.layout.xticks.length; i++) {
+            var slice = lookup[this.layout.xticks[i][0]];
+            if (MochiKit.Base.isUndefinedOrNull(slice))
+                continue;
+                
+                
+            var angle = (slice.startAngle + slice.endAngle)/2;
+            // normalize the angle
+            var normalisedAngle = angle;
+            if (normalisedAngle > Math.PI * 2)
+                normalisedAngle = normalisedAngle - Math.PI * 2;
+            else if (normalisedAngle < 0)
+                normalisedAngle = normalisedAngle + Math.PI * 2;
+                
+            var labelx = centerx + Math.sin(normalisedAngle) * (radius + 10);
+            var labely = centery - Math.cos(normalisedAngle) * (radius + 10);
+
+            var attrib = {
+                "position": "absolute",
+                 "zIndex": 11,
+                "width": labelWidth + "px",
+                "fontSize": this.options.axisLabelFontSize + "px",
+                "overflow": "hidden",
+                "color": this.options.axisLabelColor.toHexString()
+            };
+
+            var svgattrib = {
+                "width": labelWidth + "px",
+                "fontSize": this.options.axisLabelFontSize + "px",
+                "height": (this.options.axisLabelFontSize + 3) + "px",
+                "fill": this.options.axisLabelColor.toRGBString()
+            };
+
+            if (normalisedAngle <= Math.PI * 0.5) {
+                // text on top and align left
+                MochiKit.Base.update(attrib, {
+                    'textAlign': 'left', 'verticalAlign': 'top',
+                    'left': labelx + 'px',
+                    'top':  (labely - this.options.axisLabelFontSize) + "px"
+                });
+                MochiKit.Base.update(svgattrib, {
+                    "x": labelx,
+                    "y" :(labely - this.options.axisLabelFontSize),
+                    "textAnchor": "left"
+                        });
+            }
+            else if ((normalisedAngle > Math.PI * 0.5) && (normalisedAngle <= Math.PI)) {
+                // text on bottom and align left
+                MochiKit.Base.update(attrib, {
+                    'textAlign': 'left', 'verticalAlign': 'bottom',
+                    'left': labelx + 'px',
+                    'top':  labely + "px"
+                });
+                MochiKit.Base.update(svgattrib, {
+                    'textAnchor': 'left',
+                    'x': labelx,
+                    'y':  labely
+                });
+            }
+            else if ((normalisedAngle > Math.PI) && (normalisedAngle <= Math.PI*1.5)) {
+                // text on bottom and align right
+                MochiKit.Base.update(attrib, {
+                    'textAlign': 'right', 'verticalAlign': 'bottom',
+                    'left': labelx + 'px',
+                    'top':  labely + "px"
+                });
+                MochiKit.Base.update(svgattrib, {
+                    'textAnchor': 'right',
+                    'x': labelx - labelWidth,
+                    'y':  labely
+                });
+            }
+            else {
+                // text on top and align right
+                MochiKit.Base.update(attrib, {
+                    'textAlign': 'left', 'verticalAlign': 'bottom',
+                    'left': labelx + 'px',
+                    'top':  labely + "px"
+                });
+                MochiKit.Base.update(svgattrib, {
+                    'textAnchor': 'left',
+                    'x': labelx - labelWidth,
+                    'y':  labely - this.options.axisLabelFontSize
+                });
+            }
+
+            if (this.options.axisLabelUseDiv) {
+                var label = DIV({'style': attrib}, this.layout.xticks[i][1]);
+                this.xlabels.push(label);
+                MochiKit.DOM.appendChildNodes(this.container, label);
+            }
+            else {
+                var label = this.createSVGElement("text", svgattrib);
+                label.appendChild(this.document.createTextNode(this.layout.xticks[i][1]))
+                this.root.appendChild(label);
+            }
+      }
+        
+    }
+};
+
+PlotKit.SVGRenderer.prototype._renderBackground = function() {
+    var opts = {"stroke": "none",
+                  "fill": this.options.backgroundColor.toRGBString()
+    };
+    this._drawRect(0, 0, this.width, this.height, opts);
+};
+
+PlotKit.SVGRenderer.prototype._drawRect = function(x, y, w, h, moreattrs) {
+    var attrs = {x: x + "px", y: y + "px", width: w + "px", height: h + "px"};
+    if (moreattrs)
+        MochiKit.Base.update(attrs, moreattrs);
+
+    var elem = this.createSVGElement("rect", attrs);
+    this.root.appendChild(elem);
+};
+
+PlotKit.SVGRenderer.prototype._drawLine = function(x1, y1, x2, y2, moreattrs) {
+    var attrs = {x1: x1 + "px", y1: y1 + "px", x2: x2 + "px", y2: y2 + "px"};
+    if (moreattrs)
+        MochiKit.Base.update(attrs, moreattrs);
+
+    var elem = this.createSVGElement("line", attrs);
+    this.root.appendChild(elem);
+}
+
+PlotKit.SVGRenderer.prototype.clear = function() {
+    while(this.element.firstChild) {
+        this.element.removeChild(this.element.firstChild);
+    }
+    
+    if (this.options.axisLabelUseDiv) {
+        for (var i = 0; i < this.xlabels.length; i++) {
+            MochiKit.DOM.removeElement(this.xlabels[i]);
+        }        
+        for (var i = 0; i < this.ylabels.length; i++) {
+            MochiKit.DOM.removeElement(this.ylabels[i]);
+        }            
+    }
+    this.xlabels = new Array();
+    this.ylabels = new Array();
+};
+
+
+PlotKit.SVGRenderer.prototype.createSVGElement = function(name, attrs) {
+    var isNil = MochiKit.Base.isUndefinedOrNull;
+    var elem;
+    var doc = isNil(this.document) ? document : this.document;
+
+    try {
+        elem = doc.createElementNS(PlotKit.SVGRenderer.SVGNS, name);
+    }
+    catch (e) {
+        elem = doc.createElement(name);
+        elem.setAttribute("xmlns", PlotKit.SVGRenderer.SVGNS);
+    }
+
+    if (attrs)
+        MochiKit.DOM.updateNodeAttributes(elem, attrs);
+
+    // TODO: we don't completely emulate the MochiKit.DOM.createElement
+    //       as we don't care about nodes contained. We really should though.
+
+    return elem;
+
+};
+
+
+PlotKit.SVGRenderer.SVG = function(attrs) {
+    // we have to do things differently for IE+AdobeSVG.
+    // My guess this works (via trial and error) is that we need to
+    // have an SVG object in order to use SVGDocument.createElementNS
+    // but IE doesn't allow us to that.
+
+    var ie = navigator.appVersion.match(/MSIE (\d\.\d)/);
+    var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
+    if (ie && (ie[1] >= 6) && (!opera)) {
+        var width = attrs["width"] ? attrs["width"] : "100";
+        var height = attrs["height"] ? attrs["height"] : "100";
+        var eid = attrs["id"] ? attrs["id"] : "notunique";
+        
+        var html = '<svg:svg width="' + width + '" height="' + height + '" ';
+        html += 'id="' + eid + '" version="1.1" baseProfile="full" />';
+
+        var canvas = document.createElement(html);
+
+        // create embedded SVG inside SVG.
+        var group = canvas.getSVGDocument().createElementNS(PlotKit.SVGRenderer.SVGNS, "svg");
+        group.setAttribute("width", width);
+        group.setAttribute("height", height);
+        canvas.getSVGDocument().appendChild(group);
+
+        return canvas;
+    }
+    else {
+        return PlotKit.SVGRenderer.prototype.createSVGElement("svg", attrs);
+    }
+};
+
+PlotKit.SVGRenderer.isSupported = function() {
+    var isOpera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
+    var ieVersion = navigator.appVersion.match(/MSIE (\d\.\d)/);
+    var safariVersion = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
+    var operaVersion = navigator.userAgent.match(/Opera\/(\d*\.\d*)/);
+    var mozillaVersion = navigator.userAgent.match(/rv:(\d*\.\d*).*Gecko/);
+    var svgFeature = "http://www.w3.org/TR/SVG11/feature#SVG";
+
+    if (ieVersion && (ieVersion[1] >= 6) && !isOpera) {
+        return document.implementation.hasFeature(svgFeature,"1.1");
+        /*
+        var dummysvg = document.createElement('<svg:svg width="1" height="1" baseProfile="full" version="1.1" id="dummy">');
+        try {
+            dummysvg.getSVGDocument();
+            dummysvg = null;
+            return true;
+        }
+        catch (e) {
+            return false;
+        }
+        */
+        
+    }
+    
+    /* support not really there yet. no text and paths are buggy
+    if (safariVersion && (safariVersion[1] > 419))
+        return true;
+    */
+
+    if (operaVersion && (operaVersion[1] > 8.9))
+        return true
+    
+    if (mozillaVersion && (mozillaVersion > 1.7))
+        return true;
+    
+    return false;
+};
+
+// Namespace Iniitialisation
+
+PlotKit.SVG = {}
+PlotKit.SVG.SVGRenderer = PlotKit.SVGRenderer;
+
+PlotKit.SVG.EXPORT = [
+    "SVGRenderer"
+];
+
+PlotKit.SVG.EXPORT_OK = [
+    "SVGRenderer"
+];
+
+PlotKit.SVG.__new__ = function() {
+    var m = MochiKit.Base;
+    
+    m.nameFunctions(this);
+    
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+PlotKit.SVG.__new__();
+MochiKit.Base._exportSymbols(this, PlotKit.SVG);
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SweetCanvas.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SweetCanvas.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,348 @@
+/*
+    PlotKit Sweet Canvas Renderer
+    =============================
+    Canvas Renderer for PlotKit which looks pretty!
+
+    Copyright
+    ---------
+    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
+    For use under the BSD license. <http://www.liquidx.net/plotkit>
+*/
+
+// -------------------------------------------------------------------------
+// Check required components
+// -------------------------------------------------------------------------
+
+try {    
+    if (typeof(PlotKit.CanvasRenderer) == 'undefined')
+    {
+        throw "";    
+    }
+} 
+catch (e) {    
+    throw "SweetCanvas depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, Canvas}"
+}
+
+
+if (typeof(PlotKit.SweetCanvasRenderer) == 'undefined') {
+    PlotKit.SweetCanvasRenderer = {};
+}
+
+PlotKit.SweetCanvasRenderer = function(element, layout, options) {
+    if (arguments.length > 0) {
+        this.__init__(element, layout, options);
+    }
+};
+
+PlotKit.SweetCanvasRenderer.NAME = "PlotKit.SweetCanvasRenderer";
+PlotKit.SweetCanvasRenderer.VERSION = PlotKit.VERSION;
+
+PlotKit.SweetCanvasRenderer.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.SweetCanvasRenderer.toString = function() {
+    return this.__repr__();
+};
+
+// ---------------------------------------------------------------------
+// Subclassing Magic
+// ---------------------------------------------------------------------
+
+PlotKit.SweetCanvasRenderer.prototype = new PlotKit.CanvasRenderer();
+PlotKit.SweetCanvasRenderer.prototype.constructor = PlotKit.SweetCanvasRenderer;
+PlotKit.SweetCanvasRenderer.__super__ = PlotKit.CanvasRenderer.prototype;
+
+// ---------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------
+
+PlotKit.SweetCanvasRenderer.prototype.__init__ = function(el, layout, opts) { 
+    var moreOpts = PlotKit.Base.officeBlue();
+    MochiKit.Base.update(moreOpts, opts);
+    PlotKit.SweetCanvasRenderer.__super__.__init__.call(this, el, layout, moreOpts);
+};
+
+// ---------------------------------------------------------------------
+// Extended Plotting Functions
+// ---------------------------------------------------------------------
+
+PlotKit.SweetCanvasRenderer.prototype._renderBarChart = function() {
+    var bind = MochiKit.Base.bind;
+    var shadowColor = Color.blackColor().colorWithAlpha(0.1).toRGBString();
+
+    var prepareFakeShadow = function(context, x, y, w, h) {
+        context.fillStyle = shadowColor;
+        context.fillRect(x-2, y-2, w+4, h+2); 
+        context.fillStyle = shadowColor;
+        context.fillRect(x-1, y-1, w+2, h+1); 
+    };
+
+    var colorCount = this.options.colorScheme.length;
+    var colorScheme =  this.options.colorScheme;
+    var setNames = PlotKit.Base.keys(this.layout.datasets);
+    var setCount = setNames.length;
+
+    var chooseColor = function(name) {
+        for (var i = 0; i < setCount; i++) {
+            if (name == setNames[i])
+                return colorScheme[i%colorCount];
+        }
+        return colorScheme[0];
+    };
+
+    var drawRect = function(context, bar) {
+        var x = this.area.w * bar.x + this.area.x;
+        var y = this.area.h * bar.y + this.area.y;
+        var w = this.area.w * bar.w;
+        var h = this.area.h * bar.h;
+
+        if ((w < 1) || (h < 1))
+            return;        
+
+        context.save();
+
+        context.shadowBlur = 5.0;
+        context.shadowColor = Color.fromHexString("#888888").toRGBString();
+
+        if (this.isIE) {
+            context.save();
+            context.fillStyle = "#cccccc";
+            context.fillRect(x-2, y-2, w+4, h+2); 
+            context.restore();
+        }
+        else {
+            prepareFakeShadow(context, x, y, w, h);
+        }
+
+        if (this.options.shouldFill) {
+            context.fillStyle = chooseColor(bar.name).toRGBString();
+            context.fillRect(x, y, w, h);
+        }
+
+        context.shadowBlur = 0;
+        context.strokeStyle = Color.whiteColor().toRGBString();
+        context.lineWidth = 2.0;
+        
+        if (this.options.shouldStroke) {
+            context.strokeRect(x, y, w, h);                
+        }
+
+        context.restore();
+
+    };
+    this._renderBarChartWrap(this.layout.bars, bind(drawRect, this));
+};
+
+PlotKit.SweetCanvasRenderer.prototype._renderLineChart = function() {
+    var context = this.element.getContext("2d");
+    var colorCount = this.options.colorScheme.length;
+    var colorScheme = this.options.colorScheme;
+    var setNames = PlotKit.Base.keys(this.layout.datasets);
+    var setCount = setNames.length;
+    var bind = MochiKit.Base.bind;
+
+
+    for (var i = 0; i < setCount; i++) {
+        var setName = setNames[i];
+        var color = colorScheme[i%colorCount];
+        var strokeX = this.options.strokeColorTransform;
+
+        // setup graphics context
+        context.save();
+        
+        // create paths
+        var makePath = function(ctx) {
+            ctx.beginPath();
+            ctx.moveTo(this.area.x, this.area.y + this.area.h);
+            var addPoint = function(ctx_, point) {
+            if (point.name == setName)
+                ctx_.lineTo(this.area.w * point.x + this.area.x,
+                            this.area.h * point.y + this.area.y);
+            };
+            MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
+            ctx.lineTo(this.area.w + this.area.x,
+                           this.area.h + this.area.y);
+            ctx.lineTo(this.area.x, this.area.y + this.area.h);
+            ctx.closePath();
+        };
+
+        // faux shadow for firefox
+        if (this.options.shouldFill) {
+            context.save();
+            if (this.isIE) {
+                context.fillStyle = "#cccccc";
+            }
+            else {
+                context.fillStyle = Color.blackColor().colorWithAlpha(0.2).toRGBString();
+            }
+            context.translate(-1, -2);
+            bind(makePath, this)(context);
+            if (this.options.shouldFill) {
+                context.fill();
+            }
+            context.restore();
+        }
+
+        context.shadowBlur = 5.0;
+        context.shadowColor = Color.fromHexString("#888888").toRGBString();
+        context.fillStyle = color.toRGBString();
+        context.lineWidth = 2.0;
+        context.strokeStyle = Color.whiteColor().toRGBString();
+
+        if (this.options.shouldFill) {
+            bind(makePath, this)(context);
+            context.fill();
+        }
+        if (this.options.shouldStroke) {
+            bind(makePath, this)(context);
+            context.stroke();
+        }
+        context.restore();
+    }
+};
+
+PlotKit.SweetCanvasRenderer.prototype._renderPieChart = function() {
+    var context = this.element.getContext("2d");
+
+    var colorCount = this.options.colorScheme.length;
+    var slices = this.layout.slices;
+
+    var centerx = this.area.x + this.area.w * 0.5;
+    var centery = this.area.y + this.area.h * 0.5;
+    var radius = Math.min(this.area.w * this.options.pieRadius, 
+                          this.area.h * this.options.pieRadius);
+
+    if (this.isIE) {
+        centerx = parseInt(centerx);
+        centery = parseInt(centery);
+        radius = parseInt(radius);
+    }
+
+	// NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1
+	// so we have to subtract 90 degrees to make it start at y = 1, x = 0
+
+    if (!this.isIE) {
+        context.save();
+        var shadowColor = Color.blackColor().colorWithAlpha(0.2);
+        context.fillStyle = shadowColor.toRGBString();
+        context.shadowBlur = 5.0;
+        context.shadowColor = Color.fromHexString("#888888").toRGBString();
+        context.translate(1, 1);
+        context.beginPath();
+        context.moveTo(centerx, centery);
+        context.arc(centerx, centery, radius + 2, 0, Math.PI*2, false);
+        context.closePath();
+        context.fill();
+        context.restore();
+    }
+
+    context.save();
+    context.strokeStyle = Color.whiteColor().toRGBString();
+    context.lineWidth = 2.0;    
+    for (var i = 0; i < slices.length; i++) {
+        var color = this.options.colorScheme[i%colorCount];
+        context.fillStyle = color.toRGBString();
+
+        var makePath = function() {
+            context.beginPath();
+            context.moveTo(centerx, centery);
+            context.arc(centerx, centery, radius, 
+                        slices[i].startAngle - Math.PI/2,
+                        slices[i].endAngle - Math.PI/2,
+                        false);
+            context.lineTo(centerx, centery);
+            context.closePath();
+        };
+
+        if (Math.abs(slices[i].startAngle - slices[i].endAngle) > 0.0001) {
+            if (this.options.shouldFill) {
+                makePath();
+                context.fill();
+            }
+            if (this.options.shouldStroke) {
+                makePath();
+                context.stroke();
+            }
+        }
+    }
+    context.restore();
+};
+
+PlotKit.SweetCanvasRenderer.prototype._renderBackground = function() {
+    var context = this.element.getContext("2d");
+   
+    if (this.layout.style == "bar" || this.layout.style == "line") {
+        context.save();
+        context.fillStyle = this.options.backgroundColor.toRGBString();
+        context.fillRect(this.area.x, this.area.y, this.area.w, this.area.h);
+        context.strokeStyle = this.options.axisLineColor.toRGBString();
+        context.lineWidth = 1.0;
+        
+        var ticks = this.layout.yticks;
+        var horiz = false;
+        if (this.layout.style == "bar" && 
+            this.layout.options.barOrientation == "horizontal") {
+                ticks = this.layout.xticks;
+                horiz = true;
+        }
+        
+        for (var i = 0; i < ticks.length; i++) {
+            var x1 = 0;
+            var y1 = 0;
+            var x2 = 0;
+            var y2 = 0;
+            
+            if (horiz) {
+                x1 = ticks[i][0] * this.area.w + this.area.x;
+                y1 = this.area.y;
+                x2 = x1;
+                y2 = y1 + this.area.h;
+            }
+            else {
+                x1 = this.area.x;
+                y1 = ticks[i][0] * this.area.h + this.area.y;
+                x2 = x1 + this.area.w;
+                y2 = y1;
+            }
+            
+            context.beginPath();
+            context.moveTo(x1, y1);
+            context.lineTo(x2, y2);
+            context.closePath();
+            context.stroke();
+        }
+        context.restore();
+    }
+    else {
+        PlotKit.SweetCanvasRenderer.__super__._renderBackground.call(this);
+    }
+};
+
+// Namespace Iniitialisation
+
+PlotKit.SweetCanvas = {}
+PlotKit.SweetCanvas.SweetCanvasRenderer = PlotKit.SweetCanvasRenderer;
+
+PlotKit.SweetCanvas.EXPORT = [
+    "SweetCanvasRenderer"
+];
+
+PlotKit.SweetCanvas.EXPORT_OK = [
+    "SweetCanvasRenderer"
+];
+
+PlotKit.SweetCanvas.__new__ = function() {
+    var m = MochiKit.Base;
+    
+    m.nameFunctions(this);
+    
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+PlotKit.SweetCanvas.__new__();
+MochiKit.Base._exportSymbols(this, PlotKit.SweetCanvas);
+

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SweetSVG.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/SweetSVG.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,247 @@
+/*
+    PlotKit Sweet SVG Renderer
+    ==========================
+    SVG Renderer for PlotKit which looks pretty!
+
+    Copyright
+    ---------
+    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
+    For use under the BSD license. <http://www.liquidx.net/plotkit>
+*/
+
+
+// -------------------------------------------------------------------------
+// Check required components
+// -------------------------------------------------------------------------
+
+try {    
+    if (typeof(PlotKit.SVGRenderer) == 'undefined')
+    {
+        throw "";    
+    }
+} 
+catch (e) {    
+    throw "SweetSVG depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, SVG}"
+}
+
+
+if (typeof(PlotKit.SweetSVGRenderer) == 'undefined') {
+    PlotKit.SweetSVGRenderer = {};
+}
+
+PlotKit.SweetSVGRenderer = function(element, layout, options) {
+    if (arguments.length > 0) {
+        this.__init__(element, layout, options);
+    }
+};
+
+PlotKit.SweetSVGRenderer.NAME = "PlotKit.SweetSVGRenderer";
+PlotKit.SweetSVGRenderer.VERSION = PlotKit.VERSION;
+
+PlotKit.SweetSVGRenderer.__repr__ = function() {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+PlotKit.SweetSVGRenderer.toString = function() {
+    return this.__repr__();
+};
+
+// ---------------------------------------------------------------------
+// Subclassing Magic
+// ---------------------------------------------------------------------
+
+PlotKit.SweetSVGRenderer.prototype = new PlotKit.SVGRenderer();
+PlotKit.SweetSVGRenderer.prototype.constructor = PlotKit.SweetSVGRenderer;
+PlotKit.SweetSVGRenderer.__super__ = PlotKit.SVGRenderer.prototype;
+
+// ---------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------
+
+PlotKit.SweetSVGRenderer.prototype.__init__ = function(element, layout, options) { 
+    var moreOpts = PlotKit.Base.officeBlue();
+    MochiKit.Base.update(moreOpts, options);
+    PlotKit.SweetSVGRenderer.__super__.__init__.call(this, element, layout, moreOpts);
+    //this._addDropShadowFilter();
+};
+
+PlotKit.SweetSVGRenderer.prototype._addDropShadowFilter = function() {
+    var filter = this.createSVGElement("filter", {x: 0, y: 0, "id":"dropShadow"});
+    var goffset = this.createSVGElement("feOffset",
+        {"in": "SourceGraphic", "dx": 0, "dy": 0, "result": "topCopy"});
+    var blur = this.createSVGElement("feGaussianBlur",
+        {"in": "SourceAlpha", "StdDeviation": 2, "result": "shadow"});
+    var soffset = this.createSVGElement("feOffset",
+        {"in": "shadow", "dx": -1, "dy": -2, "result":"movedShadow"});
+    var merge = this.createSVGElement("feMerge");
+    var gmerge = this.createSVGElement("feMergeNode", {"in":"topCopy"});
+    var smerge = this.createSVGElement("feMergeNode", {"in":"movedShadow"});
+    
+    merge.appendChild(gmerge);
+    merge.appendChild(smerge);
+    filter.appendChild(goffset);
+    filter.appendChild(blur);
+    filter.appendChild(soffset);
+    filter.appendChild(merge);
+    this.defs.appendChild(filter);
+};
+
+// ---------------------------------------------------------------------
+// Extended Plotting Functions
+// ---------------------------------------------------------------------
+
+PlotKit.SweetSVGRenderer.prototype._renderBarChart = function() {
+    var bind = MochiKit.Base.bind;
+    var shadowColor = Color.blackColor().toRGBString();
+    var shadowStyle = "fill:" + shadowColor + ";fill-opacity:0.15";
+    var strokeStyle = "stroke-width: 2.0; stroke:" + Color.whiteColor().toRGBString();
+    
+    var drawRect = function(attrs, bar) {
+        var x = this.area.w * bar.x + this.area.x;
+        var y = this.area.h * bar.y + this.area.y;
+        var w = this.area.w * bar.w;
+        var h = this.area.h * bar.h;
+
+        if ((w < 1) || (h < 1))
+            return;        
+
+        //attrs["filter"] = "url(#dropShadow)";
+        attrs["style"] = strokeStyle;
+        this._drawRect(x - 2, y - 1, w+4, h+2, {"style":shadowStyle});
+        this._drawRect(x, y, w, h, attrs);
+    };
+    this._renderBarOrLine(this.layout.bars, bind(drawRect, this));
+
+};
+
+PlotKit.SweetSVGRenderer.prototype._renderLineChart = function() {
+    var bind = MochiKit.Base.bind;
+    var shadowColor = Color.blackColor().toRGBString();
+    var shadowStyle = "fill:" + shadowColor + ";fill-opacity:0.15";
+    var strokeStyle = "stroke-width: 2.0; stroke:" + Color.whiteColor().toRGBString();
+
+    var addPoint = function(attrs, point) {
+        this._tempPointsBuffer += (this.area.w * point.x + this.area.x) + "," +
+                                 (this.area.h * point.y + this.area.y) + " ";
+    };
+
+    var startLine = function(attrs) {
+        this._tempPointsBuffer = "";
+        this._tempPointsBuffer += (this.area.x) + "," + (this.area.y+this.area.h) + " ";
+    };
+
+    var endLine = function(attrs) {
+        this._tempPointsBuffer += (this.area.w + this.area.x) + ","  +(this.area.h + this.area.y);
+        attrs["points"] = this._tempPointsBuffer;    
+            
+        attrs["stroke"] = "none";
+        attrs["transform"] = "translate(-2, -1)";
+        attrs["style"] = shadowStyle;
+        var shadow = this.createSVGElement("polygon", attrs);
+        this.root.appendChild(shadow);
+        
+        attrs["transform"] = "";
+        attrs["style"] = strokeStyle;
+        var elem = this.createSVGElement("polygon", attrs);
+        this.root.appendChild(elem);
+        
+       
+    };
+
+    this._renderBarOrLine(this.layout.points, 
+                             bind(addPoint, this), 
+                             bind(startLine, this), 
+                             bind(endLine, this));
+};
+
+PlotKit.SweetSVGRenderer.prototype._renderPieChart = function() {
+    var centerx = this.area.x + this.area.w * 0.5;
+    var centery = this.area.y + this.area.h * 0.5;
+    var shadowColor = Color.blackColor().toRGBString();
+    var radius = Math.min(this.area.w * this.options.pieRadius, 
+                          this.area.h * this.options.pieRadius);
+    var shadowStyle = "fill:" + shadowColor + ";fill-opacity:0.15";
+    
+    var shadow = this.createSVGElement("circle", 
+        {"style": shadowStyle, "cx": centerx + 1, "cy": centery + 1, "r": radius + 1});
+    this.root.appendChild(shadow);
+                             
+    PlotKit.SweetSVGRenderer.__super__._renderPieChart.call(this);
+};
+    
+
+PlotKit.SweetSVGRenderer.prototype._renderBackground = function() {
+    var attrs = {
+        "fill": this.options.backgroundColor.toRGBString(),
+        "stroke": "none"
+    };
+    
+
+    if (this.layout.style == "bar" || this.layout.style == "line") {
+        this._drawRect(this.area.x, this.area.y, 
+                       this.area.w, this.area.h, attrs);
+                       
+        var ticks = this.layout.yticks;
+        var horiz = false;
+        if (this.layout.style == "bar" && 
+            this.layout.options.barOrientation == "horizontal") {
+                ticks = this.layout.xticks;
+                horiz = true;
+        }
+        
+        for (var i = 0; i < ticks.length; i++) {
+            var x = 0;
+            var y = 0;
+            var w = 0;
+            var h = 0;
+            
+            if (horiz) {
+                x = ticks[i][0] * this.area.w + this.area.x;
+                y = this.area.y;
+                w = 1;
+                h = this.area.w;
+            }
+            else {
+                x = this.area.x;
+                y = ticks[i][0] * this.area.h + this.area.y;
+                w = this.area.w;
+                h = 1;
+            }
+            
+            this._drawRect(x, y, w, h,
+                           {"fill": this.options.axisLineColor.toRGBString()});
+        }
+    }
+    else {
+        PlotKit.SweetSVGRenderer.__super__._renderBackground.call(this);
+        
+    }
+    
+};
+
+// Namespace Iniitialisation
+
+PlotKit.SweetSVG = {}
+PlotKit.SweetSVG.SweetSVGRenderer = PlotKit.SweetSVGRenderer;
+
+PlotKit.SweetSVG.EXPORT = [
+    "SweetSVGRenderer"
+];
+
+PlotKit.SweetSVG.EXPORT_OK = [
+    "SweetSVGRenderer"
+];
+
+PlotKit.SweetSVG.__new__ = function() {
+    var m = MochiKit.Base;
+    
+    m.nameFunctions(this);
+    
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+PlotKit.SweetSVG.__new__();
+MochiKit.Base._exportSymbols(this, PlotKit.SweetSVG);

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/dummy.svg
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/dummy.svg	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink">
+</svg>

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/excanvas.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/PlotKit/excanvas.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,723 @@
+// Copyright 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// TODO: Patterns
+// TODO: Radial gradient
+// TODO: Clipping paths
+// TODO: Coordsize (still need to support stretching)
+// TODO: Painting mode
+// TODO: Optimize
+// TODO: canvas width/height sets content size in moz, border size in ie
+
+// only add this code if we do not already have a canvas implementation
+if (!window.CanvasRenderingContext2D) {
+
+(function () {
+
+  // alias some functions to make (compiled) code shorter
+  var m = Math;
+  var mr = m.round;
+  var ms = m.sin;
+  var mc = m.cos;
+
+  var G_vmlCanvasManager_ = {
+    init: function (opt_doc) {
+      var doc = opt_doc || document;
+      if (/MSIE/.test(navigator.userAgent) && !window.opera) {
+        var self = this;
+        doc.attachEvent("onreadystatechange", function () {
+          self.init_(doc);
+        });
+      }
+    },
+
+    init_: function (doc, e) {
+      if (doc.readyState == "complete") {
+        // create xmlns
+        if (!doc.namespaces["g_vml_"]) {
+          doc.namespaces.add("g_vml_", "urn:schemas-microsoft-com:vml");
+        }
+
+        // setup default css
+        var ss = doc.createStyleSheet();
+        ss.cssText = "canvas{display:inline-block;overflow:hidden;" +
+            "text-align:left;}" +
+            "g_vml_\\:*{behavior:url(#default#VML)}";
+
+        // find all canvas elements
+        var els = doc.getElementsByTagName("canvas");
+        for (var i = 0; i < els.length; i++) {
+          if (!els[i].getContext) {
+            this.initElement(els[i]);
+          }
+        }
+      }
+    },
+
+    fixElement_: function (el) {
+      // in IE before version 5.5 we would need to add HTML: to the tag name
+      // but we do not care about IE before version 6
+      var outerHTML = el.outerHTML;
+      var newEl = document.createElement(outerHTML);
+      // if the tag is still open IE has created the children as siblings and
+      // it has also created a tag with the name "/FOO"
+      if (outerHTML.slice(-2) != "/>") {
+        var tagName = "/" + el.tagName;
+        var ns;
+        // remove content
+        while ((ns = el.nextSibling) && ns.tagName != tagName) {
+          ns.removeNode();
+        }
+        // remove the incorrect closing tag
+        if (ns) {
+          ns.removeNode();
+        }
+      }
+      el.parentNode.replaceChild(newEl, el);
+      return newEl;
+    },
+
+    /**
+     * Public initializes a canvas element so that it can be used as canvas
+     * element from now on. This is called automatically before the page is
+     * loaded but if you are creating elements using createElement you need to
+     * make sure this is called on the element.
+     * @param {HTMLElement} el The canvas element to initialize.
+     * @return {HTMLElement} the element that was created.
+     */
+    initElement: function (el) {
+      el = this.fixElement_(el);
+      el.getContext = function () {
+        if (this.context_) {
+          return this.context_;
+        }
+        return this.context_ = new CanvasRenderingContext2D_(this);
+      };
+
+      // do not use inline function because that will leak memory
+      // el.attachEvent('onpropertychange', onPropertyChange)
+      el.attachEvent('onresize', onResize);
+
+      var attrs = el.attributes;
+      if (attrs.width && attrs.width.specified) {
+        // TODO: use runtimeStyle and coordsize
+        // el.getContext().setWidth_(attrs.width.nodeValue);
+        el.style.width = attrs.width.nodeValue + "px";
+      }
+      if (attrs.height && attrs.height.specified) {
+        // TODO: use runtimeStyle and coordsize
+        // el.getContext().setHeight_(attrs.height.nodeValue);
+        el.style.height = attrs.height.nodeValue + "px";
+      }
+      //el.getContext().setCoordsize_()
+      return el;
+    }
+  };
+
+  function onPropertyChange(e) {
+    // we need to watch changes to width and height
+    switch (e.propertyName) {
+      case 'width':
+      case 'height':
+        // TODO: coordsize and size
+        break;
+    }
+  }
+
+  function onResize(e) {
+    var el = e.srcElement;
+    if (el.firstChild) {
+      el.firstChild.style.width =  el.clientWidth + 'px';
+      el.firstChild.style.height = el.clientHeight + 'px';
+    }
+  }
+
+  G_vmlCanvasManager_.init();
+
+  // precompute "00" to "FF"
+  var dec2hex = [];
+  for (var i = 0; i < 16; i++) {
+    for (var j = 0; j < 16; j++) {
+      dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
+    }
+  }
+
+  function createMatrixIdentity() {
+    return [
+      [1, 0, 0],
+      [0, 1, 0],
+      [0, 0, 1]
+    ];
+  }
+
+  function matrixMultiply(m1, m2) {
+    var result = createMatrixIdentity();
+
+    for (var x = 0; x < 3; x++) {
+      for (var y = 0; y < 3; y++) {
+        var sum = 0;
+
+        for (var z = 0; z < 3; z++) {
+          sum += m1[x][z] * m2[z][y];
+        }
+
+        result[x][y] = sum;
+      }
+    }
+    return result;
+  }
+
+  function copyState(o1, o2) {
+    o2.fillStyle     = o1.fillStyle;
+    o2.lineCap       = o1.lineCap;
+    o2.lineJoin      = o1.lineJoin;
+    o2.lineWidth     = o1.lineWidth;
+    o2.miterLimit    = o1.miterLimit;
+    o2.shadowBlur    = o1.shadowBlur;
+    o2.shadowColor   = o1.shadowColor;
+    o2.shadowOffsetX = o1.shadowOffsetX;
+    o2.shadowOffsetY = o1.shadowOffsetY;
+    o2.strokeStyle   = o1.strokeStyle;
+  }
+
+  function processStyle(styleString) {
+    var str, alpha = 1;
+
+    styleString = String(styleString);
+    if (styleString.substring(0, 3) == "rgb") {
+      var start = styleString.indexOf("(", 3);
+      var end = styleString.indexOf(")", start + 1);
+      var guts = styleString.substring(start + 1, end).split(",");
+
+      str = "#";
+      for (var i = 0; i < 3; i++) {
+        str += dec2hex[parseInt(guts[i])];
+      }
+
+      if ((guts.length == 4) && (styleString.substr(3, 1) == "a")) {
+        alpha = guts[3];
+      }
+    } else {
+      str = styleString;
+    }
+
+    return [str, alpha];
+  }
+
+  function processLineCap(lineCap) {
+    switch (lineCap) {
+      case "butt":
+        return "flat";
+      case "round":
+        return "round";
+      case "square":
+      default:
+        return "square";
+    }
+  }
+
+  /**
+   * This class implements CanvasRenderingContext2D interface as described by
+   * the WHATWG.
+   * @param {HTMLElement} surfaceElement The element that the 2D context should
+   * be associated with
+   */
+   function CanvasRenderingContext2D_(surfaceElement) {
+    this.m_ = createMatrixIdentity();
+
+    this.mStack_ = [];
+    this.aStack_ = [];
+    this.currentPath_ = [];
+
+    // Canvas context properties
+    this.strokeStyle = "#000";
+    this.fillStyle = "#ccc";
+
+    this.lineWidth = 1;
+    this.lineJoin = "miter";
+    this.lineCap = "butt";
+    this.miterLimit = 10;
+    this.globalAlpha = 1;
+
+    var el = document.createElement('div');
+    el.style.width =  surfaceElement.clientWidth + 'px';
+    el.style.height = surfaceElement.clientHeight + 'px';
+    el.style.overflow = 'hidden';
+    el.style.position = 'absolute';
+    surfaceElement.appendChild(el);
+
+    this.element_ = el;
+    this.arcScaleX_ = 1;
+    this.arcScaleY_ = 1;
+  };
+
+  var contextPrototype = CanvasRenderingContext2D_.prototype;
+  contextPrototype.clearRect = function() {
+    this.element_.innerHTML = "";
+    this.currentPath_ = [];
+  };
+
+  contextPrototype.beginPath = function() {
+    // TODO: Branch current matrix so that save/restore has no effect
+    //       as per safari docs.
+
+    this.currentPath_ = [];
+  };
+
+  contextPrototype.moveTo = function(aX, aY) {
+    this.currentPath_.push({type: "moveTo", x: aX, y: aY});
+  };
+
+  contextPrototype.lineTo = function(aX, aY) {
+    this.currentPath_.push({type: "lineTo", x: aX, y: aY});
+  };
+
+  contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
+                                            aCP2x, aCP2y,
+                                            aX, aY) {
+    this.currentPath_.push({type: "bezierCurveTo",
+                           cp1x: aCP1x,
+                           cp1y: aCP1y,
+                           cp2x: aCP2x,
+                           cp2y: aCP2y,
+                           x: aX,
+                           y: aY});
+  };
+
+  contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
+    // VML's qb produces different output to Firefox's
+    // FF's behaviour seems to have changed in 1.5.0.1, check this
+    this.bezierCurveTo(aCPx, aCPy, aCPx, aCPy, aX, aY);
+  };
+
+  contextPrototype.arc = function(aX, aY, aRadius,
+                                  aStartAngle, aEndAngle, aClockwise) {
+    aRadius *= 10;
+    var arcType = aClockwise ? "at" : "wa";
+
+    var xStart = aX + (mc(aStartAngle) * aRadius) - 5;
+    var yStart = aY + (ms(aStartAngle) * aRadius) - 5;
+
+    var xEnd = aX + (mc(aEndAngle) * aRadius) - 5;
+    var yEnd = aY + (ms(aEndAngle) * aRadius) - 5;
+
+    this.currentPath_.push({type: arcType,
+                           x: aX,
+                           y: aY,
+                           radius: aRadius,
+                           xStart: xStart,
+                           yStart: yStart,
+                           xEnd: xEnd,
+                           yEnd: yEnd});
+
+  };
+
+  contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
+    this.moveTo(aX, aY);
+    this.lineTo(aX + aWidth, aY);
+    this.lineTo(aX + aWidth, aY + aHeight);
+    this.lineTo(aX, aY + aHeight);
+    this.closePath();
+  };
+
+  contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
+    // Will destroy any existing path (same as FF behaviour)
+    this.beginPath();
+    this.moveTo(aX, aY);
+    this.lineTo(aX + aWidth, aY);
+    this.lineTo(aX + aWidth, aY + aHeight);
+    this.lineTo(aX, aY + aHeight);
+    this.closePath();
+    this.stroke();
+  };
+
+  contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
+    // Will destroy any existing path (same as FF behaviour)
+    this.beginPath();
+    this.moveTo(aX, aY);
+    this.lineTo(aX + aWidth, aY);
+    this.lineTo(aX + aWidth, aY + aHeight);
+    this.lineTo(aX, aY + aHeight);
+    this.closePath();
+    this.fill();
+  };
+
+  contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
+    var gradient = new CanvasGradient_("gradient");
+    return gradient;
+  };
+
+  contextPrototype.createRadialGradient = function(aX0, aY0,
+                                                   aR0, aX1,
+                                                   aY1, aR1) {
+    var gradient = new CanvasGradient_("gradientradial");
+    gradient.radius1_ = aR0;
+    gradient.radius2_ = aR1;
+    gradient.focus_.x = aX0;
+    gradient.focus_.y = aY0;
+    return gradient;
+  };
+
+  contextPrototype.drawImage = function (image, var_args) {
+    var dx, dy, dw, dh, sx, sy, sw, sh;
+    var w = image.width;
+    var h = image.height;
+
+    if (arguments.length == 3) {
+      dx = arguments[1];
+      dy = arguments[2];
+      sx = sy = 0;
+      sw = dw = w;
+      sh = dh = h;
+    } else if (arguments.length == 5) {
+      dx = arguments[1];
+      dy = arguments[2];
+      dw = arguments[3];
+      dh = arguments[4];
+      sx = sy = 0;
+      sw = w;
+      sh = h;
+    } else if (arguments.length == 9) {
+      sx = arguments[1];
+      sy = arguments[2];
+      sw = arguments[3];
+      sh = arguments[4];
+      dx = arguments[5];
+      dy = arguments[6];
+      dw = arguments[7];
+      dh = arguments[8];
+    } else {
+      throw "Invalid number of arguments";
+    }
+
+    var d = this.getCoords_(dx, dy);
+
+    var w2 = (sw / 2);
+    var h2 = (sh / 2);
+
+    var vmlStr = [];
+
+    // For some reason that I've now forgotten, using divs didn't work
+    vmlStr.push(' <g_vml_:group',
+                ' coordsize="1000,1000"',
+                ' coordorigin="0, 0"' ,
+                ' style="width:100px;height:100px;position:absolute;');
+
+    // If filters are necessary (rotation exists), create them
+    // filters are bog-slow, so only create them if abbsolutely necessary
+    // The following check doesn't account for skews (which don't exist
+    // in the canvas spec (yet) anyway.
+
+    if (this.m_[0][0] != 1 || this.m_[0][1]) {
+      var filter = [];
+
+      // Note the 12/21 reversal
+      filter.push("M11='", this.m_[0][0], "',",
+                  "M12='", this.m_[1][0], "',",
+                  "M21='", this.m_[0][1], "',",
+                  "M22='", this.m_[1][1], "',",
+                  "Dx='", d.x, "',",
+                  "Dy='", d.y, "'");
+
+      // Bounding box calculation (need to minimize displayed area so that
+      // filters don't waste time on unused pixels.
+      var max = d;
+      var c2 = this.getCoords_(dx+dw, dy);
+      var c3 = this.getCoords_(dx, dy+dh);
+      var c4 = this.getCoords_(dx+dw, dy+dh);
+
+      max.x = Math.max(max.x, c2.x, c3.x, c4.x);
+      max.y = Math.max(max.y, c2.y, c3.y, c4.y);
+
+      vmlStr.push(" padding:0 ", mr(max.x), "px ", mr(max.y),
+                  "px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",
+                  filter.join(""), ", sizingmethod='clip');")
+    } else {
+      vmlStr.push(" top:", d.y, "px;left:", d.x, "px;")
+    }
+
+    vmlStr.push(' ">' ,
+                '<g_vml_:image src="', image.src, '"',
+                ' style="width:', dw, ';',
+                ' height:', dh, ';"',
+                ' cropleft="', sx / w, '"',
+                ' croptop="', sy / h, '"',
+                ' cropright="', (w - sx - sw) / w, '"',
+                ' cropbottom="', (h - sy - sh) / h, '"',
+                ' />',
+                '</g_vml_:group>');
+
+    this.element_.insertAdjacentHTML("BeforeEnd",
+                                    vmlStr.join(""));
+  };
+
+  contextPrototype.stroke = function(aFill) {
+    var lineStr = [];
+    var lineOpen = false;
+    var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
+    var color = a[0];
+    var opacity = a[1] * this.globalAlpha;
+
+    lineStr.push('<g_vml_:shape',
+                 ' fillcolor="', color, '"',
+                 ' filled="', Boolean(aFill), '"',
+                 ' style="position:absolute;width:10;height:10;"',
+                 ' coordorigin="0 0" coordsize="100 100"',
+                 ' stroked="', !aFill, '"',
+                 ' strokeweight="', this.lineWidth, '"',
+                 ' strokecolor="', color, '"',
+                 ' path="');
+
+    var newSeq = false;
+    var min = {x: null, y: null};
+    var max = {x: null, y: null};
+
+    for (var i = 0; i < this.currentPath_.length; i++) {
+      var p = this.currentPath_[i];
+
+      if (p.type == "moveTo") {
+        lineStr.push(" m ");
+        var c = this.getCoords_(p.x, p.y);
+        lineStr.push(mr(c.x), ",", mr(c.y));
+      } else if (p.type == "lineTo") {
+        lineStr.push(" l ");
+        var c = this.getCoords_(p.x, p.y);
+        lineStr.push(mr(c.x), ",", mr(c.y));
+      } else if (p.type == "close") {
+        lineStr.push(" x ");
+      } else if (p.type == "bezierCurveTo") {
+        lineStr.push(" c ");
+        var c = this.getCoords_(p.x, p.y);
+        var c1 = this.getCoords_(p.cp1x, p.cp1y);
+        var c2 = this.getCoords_(p.cp2x, p.cp2y);
+        lineStr.push(mr(c1.x), ",", mr(c1.y), ",",
+                     mr(c2.x), ",", mr(c2.y), ",",
+                     mr(c.x), ",", mr(c.y));
+      } else if (p.type == "at" || p.type == "wa") {
+        lineStr.push(" ", p.type, " ");
+        var c  = this.getCoords_(p.x, p.y);
+        var cStart = this.getCoords_(p.xStart, p.yStart);
+        var cEnd = this.getCoords_(p.xEnd, p.yEnd);
+
+        lineStr.push(mr(c.x - this.arcScaleX_ * p.radius), ",",
+                     mr(c.y - this.arcScaleY_ * p.radius), " ",
+                     mr(c.x + this.arcScaleX_ * p.radius), ",",
+                     mr(c.y + this.arcScaleY_ * p.radius), " ",
+                     mr(cStart.x), ",", mr(cStart.y), " ",
+                     mr(cEnd.x), ",", mr(cEnd.y));
+      }
+
+
+      // TODO: Following is broken for curves due to
+      //       move to proper paths.
+
+      // Figure out dimensions so we can do gradient fills
+      // properly
+      if(c) {
+        if (min.x == null || c.x < min.x) {
+          min.x = c.x;
+        }
+        if (max.x == null || c.x > max.x) {
+          max.x = c.x;
+        }
+        if (min.y == null || c.y < min.y) {
+          min.y = c.y;
+        }
+        if (max.y == null || c.y > max.y) {
+          max.y = c.y;
+        }
+      }
+    }
+    lineStr.push(' ">');
+
+    if (typeof this.fillStyle == "object") {
+      var focus = {x: "50%", y: "50%"};
+      var width = (max.x - min.x);
+      var height = (max.y - min.y);
+      var dimension = (width > height) ? width : height;
+
+      focus.x = mr((this.fillStyle.focus_.x / width) * 100 + 50) + "%";
+      focus.y = mr((this.fillStyle.focus_.y / height) * 100 + 50) + "%";
+
+      var colors = [];
+
+      // inside radius (%)
+      if (this.fillStyle.type_ == "gradientradial") {
+        var inside = (this.fillStyle.radius1_ / dimension * 100);
+
+        // percentage that outside radius exceeds inside radius
+        var expansion = (this.fillStyle.radius2_ / dimension * 100) - inside;
+      } else {
+        var inside = 0;
+        var expansion = 100;
+      }
+
+      var insidecolor = {offset: null, color: null};
+      var outsidecolor = {offset: null, color: null};
+
+      // We need to sort 'colors' by percentage, from 0 > 100 otherwise ie
+      // won't interpret it correctly
+      this.fillStyle.colors_.sort(function (cs1, cs2) {
+        return cs1.offset - cs2.offset;
+      });
+
+      for (var i = 0; i < this.fillStyle.colors_.length; i++) {
+        var fs = this.fillStyle.colors_[i];
+
+        colors.push( (fs.offset * expansion) + inside, "% ", fs.color, ",");
+
+        if (fs.offset > insidecolor.offset || insidecolor.offset == null) {
+          insidecolor.offset = fs.offset;
+          insidecolor.color = fs.color;
+        }
+
+        if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) {
+          outsidecolor.offset = fs.offset;
+          outsidecolor.color = fs.color;
+        }
+      }
+      colors.pop();
+
+      lineStr.push('<g_vml_:fill',
+                   ' color="', outsidecolor.color, '"',
+                   ' color2="', insidecolor.color, '"',
+                   ' type="', this.fillStyle.type_, '"',
+                   ' focusposition="', focus.x, ', ', focus.y, '"',
+                   ' colors="', colors.join(""), '"',
+                   ' opacity="', opacity, '" />');
+    } else if (aFill) {
+      lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, '" />');
+    } else {
+      lineStr.push(
+        '<g_vml_:stroke',
+        ' opacity="', opacity,'"',
+        ' joinstyle="', this.lineJoin, '"',
+        ' miterlimit="', this.miterLimit, '"',
+        ' endcap="', processLineCap(this.lineCap) ,'"',
+        ' weight="', this.lineWidth, 'px"',
+        ' color="', color,'" />'
+      );
+    }
+
+    lineStr.push("</g_vml_:shape>");
+
+    this.element_.insertAdjacentHTML("beforeEnd", lineStr.join(""));
+
+    this.currentPath_ = [];
+  };
+
+  contextPrototype.fill = function() {
+    this.stroke(true);
+  }
+
+  contextPrototype.closePath = function() {
+    this.currentPath_.push({type: "close"});
+  };
+
+  /**
+   * @private
+   */
+  contextPrototype.getCoords_ = function(aX, aY) {
+    return {
+      x: 10 * (aX * this.m_[0][0] + aY * this.m_[1][0] + this.m_[2][0]) - 5,
+      y: 10 * (aX * this.m_[0][1] + aY * this.m_[1][1] + this.m_[2][1]) - 5
+    }
+  };
+
+  contextPrototype.save = function() {
+    var o = {};
+    copyState(this, o);
+    this.aStack_.push(o);
+    this.mStack_.push(this.m_);
+    this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
+  };
+
+  contextPrototype.restore = function() {
+    copyState(this.aStack_.pop(), this);
+    this.m_ = this.mStack_.pop();
+  };
+
+  contextPrototype.translate = function(aX, aY) {
+    var m1 = [
+      [1,  0,  0],
+      [0,  1,  0],
+      [aX, aY, 1]
+    ];
+
+    this.m_ = matrixMultiply(m1, this.m_);
+  };
+
+  contextPrototype.rotate = function(aRot) {
+    var c = mc(aRot);
+    var s = ms(aRot);
+
+    var m1 = [
+      [c,  s, 0],
+      [-s, c, 0],
+      [0,  0, 1]
+    ];
+
+    this.m_ = matrixMultiply(m1, this.m_);
+  };
+
+  contextPrototype.scale = function(aX, aY) {
+    this.arcScaleX_ *= aX;
+    this.arcScaleY_ *= aY;
+    var m1 = [
+      [aX, 0,  0],
+      [0,  aY, 0],
+      [0,  0,  1]
+    ];
+
+    this.m_ = matrixMultiply(m1, this.m_);
+  };
+
+  /******** STUBS ********/
+  contextPrototype.clip = function() {
+    // TODO: Implement
+  };
+
+  contextPrototype.arcTo = function() {
+    // TODO: Implement
+  };
+
+  contextPrototype.createPattern = function() {
+    return new CanvasPattern_;
+  };
+
+  // Gradient / Pattern Stubs
+  function CanvasGradient_(aType) {
+    this.type_ = aType;
+    this.radius1_ = 0;
+    this.radius2_ = 0;
+    this.colors_ = [];
+    this.focus_ = {x: 0, y: 0};
+  }
+
+  CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
+    aColor = processStyle(aColor);
+    this.colors_.push({offset: 1-aOffset, color: aColor});
+  };
+
+  function CanvasPattern_() {}
+
+  // set up externs
+  G_vmlCanvasManager = G_vmlCanvasManager_;
+  CanvasRenderingContext2D = CanvasRenderingContext2D_;
+  CanvasGradient = CanvasGradient_;
+  CanvasPattern = CanvasPattern_;
+
+})();
+
+} // if

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/mochikit.noexport.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/Chart/web/static/js/mochikit.noexport.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1 @@
+MochiKit = {__export__: false};

Modified: jifty/branches/autoversioning/share/web/static/js/jifty.js
==============================================================================
--- jifty/branches/autoversioning/share/web/static/js/jifty.js	(original)
+++ jifty/branches/autoversioning/share/web/static/js/jifty.js	Thu Aug  2 11:50:22 2007
@@ -1,6 +1,97 @@
 /* An empty class so we can create things inside it */
 var Jifty = Class.create();
 
+Jifty.Web = Class.create();
+Jifty.Web.current_actions = new Array;
+Jifty.Web.new_action = function() {
+    var args = _get_named_args(arguments);
+    var a;
+    Jifty.Web.current_actions.each(function(x) { if (x.moniker == args.moniker) a = x });
+    if (!a) throw "hate";
+    
+    return a;
+};
+
+Jifty.web = function() { return Jifty.Web };
+
+function _get_named_args(args) {
+    var result = {};
+    for (var i = 0; i < args.length; i+=2) {
+	result[args[i]] = args[i+1];
+    }
+    return result;
+
+}
+
+function _get_onclick(action_hash, name, args, path) {
+    var onclick = 'if(event.ctrlKey||event.metaKey||event.altKey||event.shiftKey) return true; return update('
+    + JSON.stringify({'continuation': {},
+		      'actions': action_hash,
+		      'fragments': [{'mode': 'Replace', 'args': args, 'region': name, 'path': path}]})
+    +', this)';
+    onclick = onclick.replace(/"/g, "'"); //"' )# grr emacs!
+	return onclick;
+}
+// XXX
+var hyperlink  = function() {
+    var args = _get_named_args(arguments);
+    var current_region = Jifty.Web.current_region;
+    var onclick = _get_onclick({}, current_region.name, current_region.args, args.onclick[0].replace_with);
+    outs( a(function() { attr(function()
+			      {return ['onclick', onclick, 'href', '#']});
+	    return args.label
+		}));
+}
+
+var render_param = function(a, field) { outs(a.render_param(field)) };
+var form_return  = function() {
+    var args = _get_named_args(arguments);
+    var action_hash = {};
+    action_hash[args.submit.moniker] = 1;
+    // XXX: fix the fabricated refresh-self
+    // XXX: implicit onclick only for now
+
+    // $self->_push_onclick($args, { refresh_self => 1, submit => $args->{submit} });
+    // @args{qw/mode path region/} = ('Replace', Jifty->web->current_region->path, Jifty->web->current_region);
+
+    var current_region = Jifty.Web.current_region;
+    var onclick = _get_onclick(action_hash, current_region.name, current_region.args, current_region.path);
+    outs(
+	 div(function() {
+		 attr(function() { return ['class', 'submit_button'] });
+		 return input(function() { attr(function()
+						{return ['type', 'submit',
+							 'onclick', onclick,
+							 'class', 'widget button',
+							 'id', 'S' + (++SERIAL + SERIAL_postfix),
+							 'value', args.label,
+							 'name', 'J:V-region-__page-signup_widget=_signup|J:ACTIONS=signupnow'] })});
+		     }));
+
+};
+
+function register_action(a) {
+    outs(div(function() {
+		attr(function() { return ['class', 'hidden'] });
+		return input(function() { attr(function() {
+				return ['type', 'hidden',
+					'name', a.register_name(),
+					'id', a.register_name(),
+					'value', a.actionClass] }) } ) } ));
+    /* XXX: fallback values */
+}
+
+function apply_cached_for_action(code, actions) {
+    Jifty.Web.current_actions = actions;
+    this['out_buf'] = '';
+    this['outs'] = function(text) { this.out_buf += text };
+    actions.each(register_action);
+    var foo = code();
+    return foo;
+    alert(foo);
+    throw 'not yet';
+}
+
 /* Actions */
 var Action = Class.create();
 Action.prototype = {
@@ -235,10 +326,145 @@
         var enable = function() { arguments[0].disabled = false; };
         this.fields().each( enable );
         this.buttons().each( enable );
-    }
+    },
+
+
+    /* client side logic extracted from Jifty::Action */
+    _action_spec: function() {
+	if (!this.s_a) {
+	    /* XXX: make REST client accessible */
+	    var Todo = new AsynapseRecord('todo');
+	    this.s_a = $H(Todo.eval_ajax_get('/=/action/'+this.actionClass+'.js'));
+	}
+	
+	return this.s_a
+    },
+    argument_names: function() {
+	return this._action_spec().keys();
+    },
+
+    render_param: function(field) {
+	var a_s = this._action_spec();
+	var type = 'text';
+	var f = new ActionField(field, a_s[field], this);
+	return f.render();
+    },
+    register_name: function() { return this.register.id }
+
 };
 
+var SERIAL_postfix = Math.ceil(10000*Math.random());
+var SERIAL = 0;
+ActionField = Class.create();
+ActionField.prototype = {
+ initialize: function(name, args, action) {
+	this.name = name;
+	this.label = args.label;
+	this.hints = args.hints;
+	this.mandatory = args.mandatory;
+	this.ajax_validates = args.ajax_validates;
+	this.current_value = action.data_structure().fields[name].value;
+        this.error = action.result.field_error[name];
+	this.action = action;
+	if (!this.render_mode) this.render_mode = 'update';
+	this.type = 'text';
+    },
+
+ render: function() {
+	if (this.render_mode == 'read')
+	    return this.render_wrapper
+		(this.render_preamble,
+		 this.render_label,
+		 this.render_value);
+	else
+	    return this.render_wrapper
+	    (this.render_preamble,
+	     this.render_label,
+	     this.render_widget,
+	     this.render_autocomplete_div,
+	     this.render_inline_javascript,
+	     this.render_hints,
+	     this.render_errors,
+	     this.render_warnings,
+	     this.render_canonicalization_notes);
+    },
+ render_wrapper: function () {
+	var classes = ['form_field'];
+	if (this.mandatory) classes.push('mandatory');
+	if (this.name) classes.push('argument-'+this.name);
+	var args = arguments;
+	var tthis = this;
+	return div(function() {
+		attr(function(){return ['class', classes.join(' ')]});
+		var buf = new Array;
+		for (var i = 0; i < args.length; ++i) {
+		    buf.push(typeof(args[i]) == 'function' ? args[i].apply(tthis) : args[i]);
+		}
+		return buf.join('');
+	    });
+    },
+    render_preamble: function() {
+	var tthis = this;
+	return span(function(){attr(function(){return ['class', "preamble"]});
+		return tthis.preamble });
+    },
+
+    render_label: function() {
+	var tthis = this;
+	if(this.render_mode == 'update')
+	    return label(function(){attr(function(){return['class', "label", 'for', tthis.element_id()]});
+		    return tthis.label });
+	else
+	    return span(function(){attr(function(){return['class', "label" ]});
+		    return tthis.label });
+    },
+ input_name: function() {
+	return ['J:A:F', this.name, this.action.moniker].join('-');
+    },
+ render_hints: function() {
+	var tthis = this;
+	return span(function(){attr(function(){return ['class', "hints"]});
+		return tthis.hints });
+    },
+
+ render_errors: function() {
+	if (!this.action) return '';
+	var tthis = this;
+	// XXX: post-request handler needs to extract field error messages
+	return span(function(){attr(function(){return ['class', "error", 'id', 'errors-'+tthis.input_name()]});
+		return tthis.error });
+    },
+
+ render_widget: function () {
+	var tthis = this;
+	return input(function(){
+		    attr(function(){
+			    var fields = ['type', tthis.type];
+			    if (tthis.input_name) fields.push('name', tthis.input_name());
+			    fields.push('id', tthis.element_id());
+			    if (tthis.current_value) fields.push('value', tthis.current_value);
+			    fields.push('class', tthis._widget_class().join(' '));
+			    if (tthis.max_length) fields.push('size', tthis.max_length, 'maxlength', tthis.max_length);
+			    if (tthis.disable_autocomplete) fields.push('autocomplete', "off");
+			    //" " .$self->other_widget_properties;
+			    return fields;
+			})});
+    },
+ _widget_class: function() {
+	var classes = ['form_field'];
+	if (this.mandatory)      classes.push('mandatory');
+	if (this.name)           classes.push('argument-'+this.name);
+	if (this.ajax_validates) classes.push('ajaxvalidation');
+	return classes;
+    },
+
+ element_id: function() { if(!this._element_id) this._element_id = this.input_name() + '-S' + (++SERIAL + SERIAL_postfix);
+			  return this._element_id; },
+ __noSuchMethod__: function(name) {
+	return '<!-- '+name+' not implemented yet -->';
+    }
 
+};
 
 /* Forms */
 Object.extend(Form, {
@@ -249,7 +475,7 @@
 
         for (var i = 0; i < possible.length; i++) {
             if (Form.Element.getType(possible[i]) == "registration")
-                elements.push(new Action(Form.Element.getMoniker(possible[i])));
+                elements.push(Form.Element.getAction(possible[i]));
         }
         
         return elements;
@@ -264,6 +490,7 @@
 });
 
 
+var current_actions = $H();
 
 /* Fields */
 Object.extend(Form.Element, {
@@ -287,9 +514,10 @@
     // Takes an element or an element id
     getAction: function (element) {
         element = $(element);    
-
         var moniker = Form.Element.getMoniker(element);
-        return new Action(moniker);
+	if (!current_actions[moniker])
+	    current_actions[moniker] = new Action(moniker);
+	return current_actions[moniker];
     },
 
     // Returns the name of the field
@@ -652,6 +880,42 @@
 
     return f;    
 }
+
+var CACHE = {};
+
+
+var walk_node = function(node, table) {
+    for (var child = node.firstChild;
+         child != null;
+         child = child.nextSibling) {
+        var name = child.nodeName.toLowerCase();
+        if (table[name])
+	    table[name](child);
+    }
+}
+
+var extract_cacheable = function(fragment, f) {
+    walk_node(fragment,
+    { cacheable: function(fragment_bit) {
+            var c_type = fragment_bit.getAttribute("type");
+            var textContent = '';
+            if (fragment_bit.textContent) {
+                textContent = fragment_bit.textContent;
+            } else if (fragment_bit.firstChild) {
+                textContent = fragment_bit.firstChild.nodeValue;
+            } 
+	    try {
+		var cache_func = eval(textContent);
+		CACHE[f['path']] = { 'type': c_type, 'content': cache_func };
+	    }
+	    catch(e) { 
+		alert(e);
+		alert(textContent);
+	    }
+        }
+    });
+};
+
 // applying updates from a fragment
 //   - fragment: the fragment from the server
 //   - f: fragment spec
@@ -659,11 +923,10 @@
     // We found the right fragment
     var dom_fragment = fragments[f['region']];
     var new_dom_args = $H();
+
     var element = f['element'];
-    for (var fragment_bit = fragment.firstChild;
-	 fragment_bit != null;
-	 fragment_bit = fragment_bit.nextSibling) {
-	if (fragment_bit.nodeName == 'argument') {
+    walk_node(fragment,
+    { argument: function(fragment_bit) {
 	    // First, update the fragment's arguments
 	    // with what the server actually used --
 	    // this is needed in case there was
@@ -675,7 +938,8 @@
 		textContent = fragment_bit.firstChild.nodeValue;
 	    }
 	    new_dom_args[fragment_bit.getAttribute("name")] = textContent;
-	} else if (fragment_bit.nodeName.toLowerCase() == 'content') {
+	},
+      content: function(fragment_bit) {
 	    var textContent = '';
 	    if (fragment_bit.textContent) {
 		textContent = fragment_bit.textContent;
@@ -697,7 +961,7 @@
         });
         Behaviour.apply(element);
 	}
-    }
+    });
     dom_fragment.setArgs(new_dom_args);
 
     // Also, set us up the effect
@@ -733,7 +997,6 @@
         window.event.returnValue = false;
     }
 
-    show_wait_message();
     var named_args = arguments[0];
     var trigger    = arguments[1];
 
@@ -760,15 +1023,17 @@
     if (form && form['J:CALL']) 
 	optional_fragments = [ prepare_element_for_update({'mode':'Replace','args':{},'region':'__page','path': null}) ];
     // Build actions structure
+    var has_request = 0;
     request['actions'] = $H();
     for (var moniker in named_args['actions']) {
         var disable = named_args['actions'][moniker];
         var a = new Action(moniker, button_args);
+	current_actions[moniker] = a; // XXX: how do i make this bloody singleton?
         // Special case for Redirect, allow optional, implicit __page
         // from the response to be used.
         if (a.actionClass == 'Jifty::Action::Redirect')
             optional_fragments = [ prepare_element_for_update({'mode':'Replace','args':{},'region':'__page','path': a.fields().last().value}) ];
-
+        a.result = {}; a.result.field_error = {};
         if (a.register) {
             if (a.hasUpload())
                 return true;
@@ -776,15 +1041,71 @@
                 a.disable_input_fields();
             }
             request['actions'][moniker] = a.data_structure();
+            ++has_request;
         }
+
     }
 
     request['fragments'] = $H();
+    var update_from_cache = new Array;
+
     // Build fragments structure
     for (var i = 0; i < named_args['fragments'].length; i++) {
         var f = named_args['fragments'][i];
         f = prepare_element_for_update(f);
         if (!f) continue;
+
+        var cached = CACHE[f['path']];
+        if (cached && cached['type'] == 'static') {
+            var my_fragment = document.createElement('fragment');
+            var content_node = document.createElement('content');
+	    var cached_result;
+
+	    Jifty.Web.current_region = fragments[f['region']];
+	    try { cached_result = apply_cached_for_action(cached['content'], []) }
+	    catch (e) { alert(e) }
+
+            content_node.textContent = cached_result;
+            my_fragment.appendChild(content_node);
+            my_fragment.setAttribute('id', f['region']);
+
+            update_from_cache.push(function(){ apply_fragment_updates(my_fragment, f);
+ } );
+            continue;
+        }
+	else if (cached && cached['type'] == 'action') {
+            var my_fragment = document.createElement('fragment');
+            var content_node = document.createElement('content');
+
+            my_fragment.appendChild(content_node);
+            my_fragment.setAttribute('id', f['region']);
+            update_from_cache.push(function(){
+		    var cached_result;
+		    Jifty.Web.current_region = fragments[f['region']];
+		    try {
+			cached_result = apply_cached_for_action(cached['content'], Form.getActions(form));
+		    }
+		    catch (e) { alert(e); throw e }
+		    content_node.textContent = cached_result;
+		    apply_fragment_updates(my_fragment, f);
+ } );
+            continue;
+	}
+        else if (cached && cached['type'] == 'crudview') {
+	    try { // XXX: get model class etc as metadata in cache 
+		// XXX: kill dup code
+	    var Todo = new AsynapseRecord('todo');
+	    var record = Todo.find(f['args']['id']);
+            var my_fragment = document.createElement('fragment');
+            var content_node = document.createElement('content');
+            content_node.textContent = cached['content'](record);
+            my_fragment.appendChild(content_node);
+            my_fragment.setAttribute('id', f['region']);
+            update_from_cache.push(function(){ apply_fragment_updates(my_fragment, f); } );
+	    } catch (e) { alert(e) };
+	    continue;
+	}
+
         // Update with all new values
         var name = f['region'];
         var fragment_request = fragments[name].data_structure(f['path'], f['args']);
@@ -795,49 +1116,71 @@
 
         // Push it onto the request stack
         request['fragments'][name] = fragment_request;
+        ++has_request;
+    }
+
+    if (!has_request) {
+        for (var i = 0; i < update_from_cache.length; i++)
+            update_from_cache[i]();
+        return false;
     }
 
+    show_wait_message();
+
     // And when we get the result back..
     var onSuccess = function(transport, object) {
         // Grab the XML response
         var response = transport.responseXML.documentElement;
+
+	// Get action results
+        walk_node(response,
+	{ result: function(result) {
+		var moniker = result.getAttribute("moniker");
+		walk_node(result,
+			  { field: function(field) {
+				  var error = field.getElementsByTagName('error')[0];
+				  if (error) {
+				      var text = error.textContent
+					  ? error.textContent
+					  : (error.firstChild ? error.firstChild.nodeValue : '');
+				      var action = current_actions[moniker];
+				      action.result.field_error[field.getAttribute("name")] = text;
+				      }
+			      }});
+	    }});
+	// empty known action. XXX: we should only need to discard actions being submitted
+
         // Loop through the result looking for it
         var expected_fragments = optional_fragments ? optional_fragments : named_args['fragments'];
         for (var response_fragment = response.firstChild;
              response_fragment != null && response_fragment.nodeName == 'fragment';
              response_fragment = response_fragment.nextSibling) {
 
-            var f; 
-            for (var i = 0; i < expected_fragments.length; i++) {
-                f = expected_fragments[i];
-                if (response_fragment.getAttribute("id") == f['region'])
-                    break;
-            }
-            if (response_fragment.getAttribute("id") != f['region'])
+            var exp_id = response_fragment.getAttribute("id");
+            var f = expected_fragments.find(function(f) { return exp_id == f['region'] });
+            if (!f)
                 continue;
 
-	    try {
-            apply_fragment_updates(response_fragment, f);
-	    }catch (e) { alert(e) }
+            try {
+                apply_fragment_updates(response_fragment, f);
+            }catch (e) { alert(e) }
+            extract_cacheable(response_fragment, f);
         }
-        for (var result = response.firstChild;
-             result != null;
-             result = result.nextSibling) {
-            if (result.nodeName == 'result') {
+
+	update_from_cache.each(function(x) { x() });
+
+        walk_node(response,
+	{ result: function(result) {
                 for (var key = result.firstChild;
                      key != null;
                      key = key.nextSibling) {
                     show_action_result(result.getAttribute("moniker"),key);
                 }
-            }
-        }
-        for (var redirect = response.firstChild;
-             redirect != null;
-             redirect = redirect.nextSibling) {
-            if (redirect.nodeName == 'redirect') {
+            },
+	  redirect: function(redirect) {
                 document.location =  redirect.firstChild.firstChild.nodeValue;
-            }
-        }
+	}});
+	current_actions = $H();
     };
     var onFailure = function(transport, object) {
         hide_wait_message_now();

Added: jifty/branches/autoversioning/share/web/static/js/template_declare.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/web/static/js/template_declare.js	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,53 @@
+// FIXME: try not to pollute the namespace!
+var tags = ['div', 'h2', 'dl', 'dt', 'dd', 'span', 'label', 'input', 'a'];
+for (var i in tags) {
+    this[tags[i]] = _mk_tag_wrapper(tags[i]);
+}
+this['form'] = _mk_tag_wrapper('form', function(attr) {
+	return '<form method="post" enctype="multipart/form-data" >'; // XXX action: & friends
+    }, null, 1);
+var _ = function(str) { return str };
+var attr = function() {};
+
+function _mk_tag_wrapper(name, pre, post, want_outbuf) {
+    return function() {
+	var buf = new Array;
+	var sp = this['attr'];
+	var attr = {};
+	this['attr'] = function(a) {
+	    var foo;
+	    a = a();
+	    while(foo = a.splice(0, 2)) {
+		if (foo.length == 0)
+		    break;
+		attr[foo[0]] = foo[1];
+	    }
+	};
+
+	var flushed = '';
+	if (this.out_buf) {
+	    flushed = this.out_buf;
+	    this.out_buf = '';
+	}
+
+	for (var i = 0; i < arguments.length; ++i) {
+	    buf.push(typeof(arguments[i]) == 'function' ? arguments[i]() : arguments[i]);
+	}
+	var _mk_attr = function() {
+	    var foo = ' ';
+	    for (var k in attr) {
+		if (k == 'extend') continue;
+		foo += k + '="' + attr[k] + '"';
+	    }
+	    return foo;
+	};
+	var first = buf.splice(0, 1);
+	var _pre = pre ? pre(attr) : '<'+name+_mk_attr(attr)+'>';
+	var _post = post ? post(attr) : '</'+name+'>';
+	if (want_outbuf && this.out_buf) {
+	    first += this.out_buf;
+	    this.out_buf = '';
+	}
+	return flushed + _pre + first + _post + buf.join('');
+    }
+};

Modified: jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml
==============================================================================
--- jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml	(original)
+++ jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml	Thu Aug  2 11:50:22 2007
@@ -52,6 +52,9 @@
     $writer->startTag( "fragment", id => Jifty->web->current_region->qualified_name );
     my %args = %{ Jifty->web->current_region->arguments };
     $writer->dataElement( "argument", $args{$_}, name => $_) for sort keys %args;
+    if (Jifty->config->framework('ClientTemplate') && Jifty->web->current_region->client_cacheable) {
+        $writer->cdataElement( "cacheable", Jifty->web->current_region->client_cache_content, type => Jifty->web->current_region->client_cacheable );
+    }
     $writer->cdataElement( "content", Jifty->web->current_region->as_string );
     $writer->endTag();
 

Added: jifty/branches/autoversioning/t/13-sessions.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/13-sessions.t	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,65 @@
+use strict;
+use warnings;
+
+=head1 DESCRIPTION
+
+Tests Jifty::Web::Session
+
+=cut
+
+use Jifty::Test tests => 18;
+
+my ($first_id, $second_id, $third_id);
+
+{
+    my $session = Jifty::Web::Session->new();
+    $session->load_by_kv(user => 'first');
+    ok($session->id, "got a session");
+    $first_id = $session->id;
+
+    $session->set(hello => 'world');
+    $session->set(number => '1st');
+
+    is($session->get('hello'),  'world', "immediate 'get' works");
+    is($session->get('number'), '1st',   "immediate 'get' works");
+
+    $session->load_by_kv(user => 'first');
+    is($session->id, $first_id, "same session as before");
+    is($session->get('hello'),  'world', "'get' before destroy works");
+    is($session->get('number'), '1st',   "'get' before destroy works");
+}
+
+{
+    my $session = Jifty::Web::Session->new();
+    $session->load_by_kv(user => 'first');
+    ok($session->id, "got a session");
+    is($session->id, $first_id, "same session as before");
+
+    is($session->get('hello'),  'world', "'set', destroy, 'get' works");
+    is($session->get('number'), '1st',   "'set', destroy, 'get' works");
+}
+
+{
+    my $session = Jifty::Web::Session->new();
+    $session->load_by_kv(user => 'second');
+    ok($session->id, "got a session");
+    isnt($session->id, $first_id, "NOT same session as before");
+    $second_id = $session->id;
+
+    is($session->get('hello'),  undef, "different value gives different session");
+    is($session->get('number'), undef, "different value gives different session");
+
+    $session->set(hello => 'world');
+    $session->set(number => '2nd');
+}
+
+{
+    my $session = Jifty::Web::Session->new();
+    $session->load_by_kv(user => 'first');
+    ok($session->id, "got a session");
+    is($session->id, $first_id, "first session again");
+
+    is($session->get('hello'), 'world');
+    is($session->get('number'), '1st', "even though the two sessions have some overlapping keys, the one that matters doesn't overlap");
+}
+

Added: jifty/branches/autoversioning/t/TestApp-Plugin-Chart/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-Chart/Makefile.PL	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,7 @@
+use inc::Module::Install;
+
+name        'TestApp::Plugin::Chart';
+version     '0.01';
+requires    'Jifty' => '0.70129';
+
+WriteAll;

Added: jifty/branches/autoversioning/t/TestApp-Plugin-Chart/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-Chart/bin/jifty	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,11 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+use Jifty;
+use Jifty::Script;
+
+local $SIG{INT} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/autoversioning/t/TestApp-Plugin-Chart/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-Chart/etc/config.yml	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,54 @@
+--- 
+framework: 
+  AdminMode: 1
+  ApplicationClass: TestApp::Plugin::Chart
+  ApplicationName: TestApp-Plugin-Chart
+  ApplicationUUID: D16D885C-3E10-11DC-ABE9-A583E6FF98E1
+  ConfigFileVersion: 2
+  Database: 
+    CheckSchema: 1
+    Database: testapp_plugin_chart
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    RecordUUIDs: active
+    User: ''
+    Version: 0.0.1
+  DevelMode: 1
+  L10N: 
+    PoDir: share/po
+  LogLevel: INFO
+  Mailer: Sendmail
+  MailerArgs: []
+
+  Plugins: 
+    - LetMe: {}
+    - SkeletonApp: {}
+    - REST: {}
+    - Halo: {}
+    - ErrorTemplates: {}
+    - OnlineDocs: {}
+    - CompressedCSSandJS: {}
+    - AdminUI: {}
+    - Chart: {}
+
+  PubSub: 
+    Backend: Memcached
+    Enable: ~
+  SkipAccessControl: 0
+  TemplateClass: TestApp::Plugin::Chart::View
+  Web: 
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+
+    MasonConfig: 
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates

Added: jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-Chart/lib/TestApp/Plugin/Chart/View.pm	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,21 @@
+use strict;
+use warnings;
+
+package TestApp::Plugin::Chart::View;
+use Jifty::View::Declare -base;
+
+template '/graphit' => page {
+    Jifty->web->chart(
+        type   => 'Pie',
+        width  => 400,
+        height => 300,
+        data   => sub {
+            [
+                [ 2004, 2005, 2006, 2007 ],
+                [ 26, 37, 12, 42 ]
+            ];
+        },
+    );
+};
+
+1;

Added: jifty/branches/autoversioning/t/TestApp-Plugin-Chart/t/chart.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-Chart/t/chart.t	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,58 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use lib 't/lib';
+
+# XXX FIXME This is here to prevent a segfault on my machine during testing.
+#   -- sterling
+use GD;
+
+use Jifty::SubTest;
+use Jifty::Test;
+use Jifty::Test::WWW::Mechanize;
+
+eval "use Chart::Pie";
+if ($@) {
+    plan skip_all => 'Chart is not installed.';
+}
+else {
+    plan tests => 9;
+}
+
+use Jifty::Plugin::Chart::Renderer::Chart;
+
+(Jifty->find_plugin('Jifty::Plugin::Chart'))[0]
+    ->renderer('Jifty::Plugin::Chart::Renderer::Chart');
+
+my $server = Jifty::Test->make_server;
+ok($server, 'got a server');
+
+my $url = $server->started_ok;
+
+my $mech = Jifty::Test::WWW::Mechanize->new;
+
+$mech->get_ok($url . '/graphit', 'try getting /graphit');
+my $img_match = qr{<img src="(/chart/chart/S\d+)" width="400" height="300"/>};
+$mech->content_like($img_match, 'has an img tag');
+my ($chart_path) = $mech->content =~ $img_match;
+
+$mech->get_ok($url . $chart_path, 'try getting ' . $chart_path);
+
+my $response = $mech->response;
+is($response->header('Content-type'), 'image/png', 'content type set to png');
+
+SKIP: {
+    eval "use Image::Info qw/ image_info /";
+    skip "Image::Info is not installed", 3 if $@;
+
+    my $imgdata = $mech->content;
+    my $info = image_info(\$imgdata);
+
+    diag($info->{error}) if $info->{error};
+
+    is($info->{file_ext}, 'png', 'it is a png file');
+    is($info->{width}, 400, 'it is 400 pixels wide');
+    is($info->{height}, 300, 'it is 300 pixels tall');
+};
+

Added: jifty/branches/autoversioning/t/TestApp-Plugin-Chart/t/gd_graph.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-Chart/t/gd_graph.t	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,58 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use lib 't/lib';
+
+# XXX FIXME This is here to prevent a segfault on my machine during testing.
+#   -- sterling
+use GD;
+
+use Jifty::SubTest;
+use Jifty::Test;
+use Jifty::Test::WWW::Mechanize;
+
+eval "use GD::Graph::pie";
+if ($@) {
+    plan skip_all => 'GD::Graph is not installed.';
+}
+else {
+    plan tests => 9;
+}
+
+use Jifty::Plugin::Chart::Renderer::GD::Graph;
+
+(Jifty->find_plugin('Jifty::Plugin::Chart'))[0]
+    ->renderer('Jifty::Plugin::Chart::Renderer::GD::Graph');
+
+my $server = Jifty::Test->make_server;
+ok($server, 'got a server');
+
+my $url = $server->started_ok;
+
+my $mech = Jifty::Test::WWW::Mechanize->new;
+
+$mech->get_ok($url . '/graphit', 'try getting /graphit');
+my $img_match = qr{<img src="(/chart/gd_graph/S\d+)" width="400" height="300"/>};
+$mech->content_like($img_match, 'has an img tag');
+my ($chart_path) = $mech->content =~ $img_match;
+
+$mech->get_ok($url . $chart_path, 'try getting ' . $chart_path);
+
+my $response = $mech->response;
+is($response->header('Content-type'), 'image/png', 'content type set to png');
+
+SKIP: {
+    eval "use Image::Info qw/ image_info /";
+    skip "Image::Info is not installed", 3 if $@;
+
+    my $imgdata = $mech->content;
+    my $info = image_info(\$imgdata);
+
+    diag($info->{error}) if $info->{error};
+
+    is($info->{file_ext}, 'png', 'it is a png file');
+    is($info->{width}, 400, 'it is 400 pixels wide');
+    is($info->{height}, 300, 'it is 300 pixels tall');
+};
+

Modified: jifty/branches/autoversioning/t/TestApp/lib/TestApp/Model/User.pm
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/lib/TestApp/Model/User.pm	(original)
+++ jifty/branches/autoversioning/t/TestApp/lib/TestApp/Model/User.pm	Thu Aug  2 11:50:22 2007
@@ -34,6 +34,7 @@
   is immutable,
   default is defer { DateTime->now },
   filters are 'Jifty::DBI::Filter::DateTime';
+column 'uuid' => is UUID;
 };
 
 

Modified: jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t	(original)
+++ jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t	Thu Aug  2 11:50:22 2007
@@ -4,7 +4,7 @@
 
 use lib 't/lib';
 use Jifty::SubTest;
-use Jifty::Test tests => 9;
+use Jifty::Test tests => 8;
 use Jifty::Test::WWW::Mechanize;
 use Test::Log4perl;
 
@@ -16,7 +16,7 @@
 my $mech    = Jifty::Test::WWW::Mechanize->new();
 
 {
-    my $log = Test::Log4perl->expect(['', warn => qr/You can't call a 'show' rule in a 'before' or 'after' block in the dispatcher/ ]);
+#    my $log = Test::Log4perl->expect(['', warn => qr/You can't call a 'show' rule in a 'before' or 'after' block in the dispatcher/ ]);
 $mech->get("$URL/before_stage_show", "Got /before_stage_show");
 $mech->content_lacks("This is content");
 is( $mech->status , '404');

Modified: jifty/branches/autoversioning/t/TestApp/t/05-editactions-Record.t
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/t/05-editactions-Record.t	(original)
+++ jifty/branches/autoversioning/t/TestApp/t/05-editactions-Record.t	Thu Aug  2 11:50:22 2007
@@ -7,12 +7,12 @@
 use Jifty::SubTest;
 BEGIN { $ENV{'JIFTY_CONFIG'} = 't/config-Record' }
 
-use Jifty::Test tests => 10;
+use Jifty::Test tests => 11;
 use Jifty::Test::WWW::Mechanize;
-
 # Make sure we can load the model
 use_ok('TestApp::Model::User');
 
+Jifty->new();
 # Grab a system use
 my $system_user = TestApp::CurrentUser->superuser;
 ok($system_user, "Found a system user");
@@ -38,8 +38,9 @@
 $o->load($id);
 ok($id, "Load returned success");
 
+
 is($o->email, 'newemail at example.com', "Email was updated by form");
 is($o->tasty, 1, "User is still tasty (was not updated since immutable)");
-
+ok($o->uuid,  "The user has a uuid ". $o->uuid);
 1;
 

Modified: jifty/branches/autoversioning/t/TestApp/t/config-Record
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/t/config-Record	(original)
+++ jifty/branches/autoversioning/t/TestApp/t/config-Record	Thu Aug  2 11:50:22 2007
@@ -2,3 +2,5 @@
 framework:
   Database:
     RecordBaseClass: Jifty::DBI::Record
+  Plugins:
+    - UUID: {}

Added: jifty/branches/autoversioning/t/clientside/td.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/clientside/td.t	Thu Aug  2 11:50:22 2007
@@ -0,0 +1,104 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Jifty;
+
+package Foo;
+use Jifty::View::Declare -base;
+
+template _faq => \&_faq;
+
+sub _faq {
+    div {
+        attr { id => "faq" };
+        h2 { 'Using Yada' }
+        dl {
+            dt { 'Yada Yada Yada!'}
+            dd {
+                span {
+                    'are we nearly there yet?'
+                }
+	    }
+	};
+    }
+};
+
+template _faq2 => \&_faq2;
+
+sub _faq2 {
+    div {
+        attr { id => "faq" };
+        h2 { 'Using Yada' }
+        dl {
+            dt { 'Yada Yada Yada!'};
+            dd {
+                span {
+                    'are we nearly there yet?'
+                }
+	    }
+	};
+    }
+};
+
+package main;
+
+use Test::More;
+use IPC::Run3;
+eval 'use Jifty::View::Declare::Compile; 1'
+    or plan skip_all => "Can't load Jifty::View::Declare::Compile";
+
+my $jsbin = can_run('js')
+    or plan skip_all => "Can't find spidermonkey js binary";
+
+Template::Declare->init( roots => ['Foo']);
+
+plan tests => 2;
+
+is_compatible('_faq');
+TODO: {
+local $TODO = 'buf handling (non-katamari version) not yet';
+is_compatible('_faq2');
+
+};
+
+
+
+sub is_compatible {
+    my $template = shift;
+    my $js = js_output( js_code( Foo->can($template) ) );
+    my $td = Template::Declare->show($template);
+    $js =~ s/\s*//g;
+    $td =~ s/\s*//g;
+    unshift @_, $js, $td;
+    goto \&is;
+}
+
+sub js_code {
+    my $code = shift;
+    return '(function() '.Jifty::View::Declare::Compile->new->coderef2text($code) . ')()';
+}
+
+sub js_output {
+    my $code = shift;
+    my ($out, $err);
+    run3 [$jsbin],
+	['load("share/web/static/js/template_declare.js");', "print($code);"],
+	    \$out, \$err;
+    diag $err if $err;
+    return $out;
+
+}
+
+use File::Spec::Functions 'catfile';
+sub can_run {
+    my ($_cmd, @path) = @_;
+
+    return $_cmd if -x $_cmd;
+
+    for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), @path, '.') {
+        my $abs = catfile($dir, $_[0]);
+        return $abs if -x $abs;
+    }
+
+    return;
+}


More information about the Jifty-commit mailing list