Initial check-in
authorDan Vanderkam <danvdk@gmail.com>
Tue, 18 Aug 2009 23:35:08 +0000 (23:35 +0000)
committerDan Vanderkam <danvdk@gmail.com>
Tue, 18 Aug 2009 23:35:08 +0000 (23:35 +0000)
270 files changed:
data.js [new file with mode: 0644]
dygraph-canvas.js [new file with mode: 0644]
dygraph-combined.js [new file with mode: 0644]
dygraph.js [new file with mode: 0644]
generate-combined.sh [new file with mode: 0755]
mochikit_v14/LICENSE.txt [new file with mode: 0644]
mochikit_v14/MochiKit/Async.js [new file with mode: 0644]
mochikit_v14/MochiKit/Base.js [new file with mode: 0644]
mochikit_v14/MochiKit/Color.js [new file with mode: 0644]
mochikit_v14/MochiKit/Controls.js [new file with mode: 0644]
mochikit_v14/MochiKit/DOM.js [new file with mode: 0644]
mochikit_v14/MochiKit/DateTime.js [new file with mode: 0644]
mochikit_v14/MochiKit/DragAndDrop.js [new file with mode: 0644]
mochikit_v14/MochiKit/Format.js [new file with mode: 0644]
mochikit_v14/MochiKit/Iter.js [new file with mode: 0644]
mochikit_v14/MochiKit/Logging.js [new file with mode: 0644]
mochikit_v14/MochiKit/LoggingPane.js [new file with mode: 0644]
mochikit_v14/MochiKit/MochiKit.js [new file with mode: 0644]
mochikit_v14/MochiKit/MockDOM.js [new file with mode: 0644]
mochikit_v14/MochiKit/Position.js [new file with mode: 0644]
mochikit_v14/MochiKit/Selector.js [new file with mode: 0644]
mochikit_v14/MochiKit/Signal.js [new file with mode: 0644]
mochikit_v14/MochiKit/Sortable.js [new file with mode: 0644]
mochikit_v14/MochiKit/Style.js [new file with mode: 0644]
mochikit_v14/MochiKit/Test.js [new file with mode: 0644]
mochikit_v14/MochiKit/Visual.js [new file with mode: 0644]
mochikit_v14/MochiKit/__package__.js [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Async.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Base.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Color.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/DOM.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/DateTime.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/DragAndDrop.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Format.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Iter.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Logging.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/LoggingPane.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Position.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Selector.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Signal.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Sortable.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Style.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/VersionHistory.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/Visual.html [new file with mode: 0644]
mochikit_v14/doc/html/MochiKit/index.html [new file with mode: 0644]
mochikit_v14/doc/js/toc.js [new file with mode: 0644]
mochikit_v14/doc/rst/MochiKit/Async.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Base.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Color.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/DOM.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/DateTime.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/DragAndDrop.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Format.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Iter.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Logging.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/LoggingPane.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Position.rst [new file with mode: 0644]
mochikit_v14/doc/rst/MochiKit/Selector.rst [new file with mode: 0644]
mochikit_v14/doc/rst/MochiKit/Signal.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Sortable.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Style.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/VersionHistory.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/Visual.rst [new file with mode: 0755]
mochikit_v14/doc/rst/MochiKit/index.rst [new file with mode: 0755]
mochikit_v14/examples/ajax_tables/ajax_tables.css [new file with mode: 0755]
mochikit_v14/examples/ajax_tables/ajax_tables.js [new file with mode: 0644]
mochikit_v14/examples/ajax_tables/domains.json [new file with mode: 0755]
mochikit_v14/examples/ajax_tables/domains.xml [new file with mode: 0755]
mochikit_v14/examples/ajax_tables/index.html [new file with mode: 0644]
mochikit_v14/examples/color_wheel/color_wheel.css [new file with mode: 0755]
mochikit_v14/examples/color_wheel/color_wheel.js [new file with mode: 0644]
mochikit_v14/examples/color_wheel/index.html [new file with mode: 0644]
mochikit_v14/examples/dnd_sortable/dnd_sortable.css [new file with mode: 0755]
mochikit_v14/examples/dnd_sortable/dropmarker.png [new file with mode: 0755]
mochikit_v14/examples/dnd_sortable/icon.png [new file with mode: 0755]
mochikit_v14/examples/dnd_sortable/index.html [new file with mode: 0644]
mochikit_v14/examples/dnd_sortable/sortable2_test.html [new file with mode: 0644]
mochikit_v14/examples/dnd_sortable/sortable3_test.html [new file with mode: 0644]
mochikit_v14/examples/dnd_sortable/sortable4_test.html [new file with mode: 0644]
mochikit_v14/examples/dnd_sortable/sortable5_test.html [new file with mode: 0644]
mochikit_v14/examples/dnd_sortable/sortable_test.html [new file with mode: 0644]
mochikit_v14/examples/dnd_sortable/sortable_tree_test.html [new file with mode: 0644]
mochikit_v14/examples/draggable/draggable.css [new file with mode: 0755]
mochikit_v14/examples/draggable/draggable.js [new file with mode: 0644]
mochikit_v14/examples/draggable/index.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_bigslide.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_blind.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_blindslide.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_combi.css [new file with mode: 0755]
mochikit_v14/examples/effects/effects_fadeappear.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_grow_shrink.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_onload.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_queue.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_queue_limit.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_scroll.html [new file with mode: 0644]
mochikit_v14/examples/effects/effects_slide.html [new file with mode: 0644]
mochikit_v14/examples/effects/full.html [new file with mode: 0644]
mochikit_v14/examples/effects/icon.png [new file with mode: 0755]
mochikit_v14/examples/effects/index.html [new file with mode: 0644]
mochikit_v14/examples/interpreter/index.html [new file with mode: 0644]
mochikit_v14/examples/interpreter/interpreter.css [new file with mode: 0755]
mochikit_v14/examples/interpreter/interpreter.js [new file with mode: 0644]
mochikit_v14/examples/key_events/index.html [new file with mode: 0644]
mochikit_v14/examples/key_events/key_events.css [new file with mode: 0755]
mochikit_v14/examples/key_events/key_events.js [new file with mode: 0644]
mochikit_v14/examples/logging_pane/index.html [new file with mode: 0644]
mochikit_v14/examples/logging_pane/logging_pane.css [new file with mode: 0755]
mochikit_v14/examples/logging_pane/logging_pane.js [new file with mode: 0644]
mochikit_v14/examples/mochiregexp/index.html [new file with mode: 0644]
mochikit_v14/examples/mochiregexp/mochiregexp.css [new file with mode: 0755]
mochikit_v14/examples/mochiregexp/mochiregexp.js [new file with mode: 0644]
mochikit_v14/examples/rounded_corners/index.html [new file with mode: 0644]
mochikit_v14/examples/rounded_corners/rounded_corners.css [new file with mode: 0755]
mochikit_v14/examples/rounded_corners/rounded_corners.js [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/dnd_boxes.html [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/dnd_full.html [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/dnd_ghost.html [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/dnd_hoverclass.html [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/dnd_scroll.html [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/dnd_snap.html [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/index.html [new file with mode: 0644]
mochikit_v14/examples/simple_dnd/simple_dnd.css [new file with mode: 0755]
mochikit_v14/examples/sortable_tables/index.html [new file with mode: 0644]
mochikit_v14/examples/sortable_tables/sortable_tables.css [new file with mode: 0755]
mochikit_v14/examples/sortable_tables/sortable_tables.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css [new file with mode: 0755]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/Tests.html [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushDelphi.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushJScript.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushPython.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushSql.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushVb.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushXml.js [new file with mode: 0644]
mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shCore.js [new file with mode: 0644]
mochikit_v14/examples/view-source/view-source.css [new file with mode: 0755]
mochikit_v14/examples/view-source/view-source.html [new file with mode: 0644]
mochikit_v14/examples/view-source/view-source.js [new file with mode: 0644]
mochikit_v14/include/_img/bg_docheader.gif [new file with mode: 0755]
mochikit_v14/include/_img/g_bullet.gif [new file with mode: 0755]
mochikit_v14/include/_img/g_logo_doc.gif [new file with mode: 0755]
mochikit_v14/include/css/documentation.css [new file with mode: 0755]
mochikit_v14/include/css/general.css [new file with mode: 0755]
mochikit_v14/packed/MochiKit/MochiKit.js [new file with mode: 0644]
mochikit_v14/packed/MochiKit/__package__.js [new file with mode: 0644]
mochikit_v14/scripts/build.py [new file with mode: 0755]
mochikit_v14/scripts/custom_rhino.jar [new file with mode: 0755]
mochikit_v14/scripts/js.jar [new file with mode: 0755]
mochikit_v14/scripts/jscriptmochi.js [new file with mode: 0644]
mochikit_v14/scripts/make_docs.py [new file with mode: 0755]
mochikit_v14/scripts/pack.py [new file with mode: 0755]
mochikit_v14/scripts/rhinomochi.js [new file with mode: 0644]
mochikit_v14/scripts/spidermochi.js [new file with mode: 0644]
mochikit_v14/tests/FakeJSAN.js [new file with mode: 0644]
mochikit_v14/tests/SimpleTest/SimpleTest.js [new file with mode: 0644]
mochikit_v14/tests/SimpleTest/TestRunner.js [new file with mode: 0644]
mochikit_v14/tests/SimpleTest/test.css [new file with mode: 0755]
mochikit_v14/tests/cli.js [new file with mode: 0644]
mochikit_v14/tests/index.html [new file with mode: 0644]
mochikit_v14/tests/standalone.js [new file with mode: 0644]
mochikit_v14/tests/test_Base.js [new file with mode: 0644]
mochikit_v14/tests/test_Color.js [new file with mode: 0644]
mochikit_v14/tests/test_DateTime.js [new file with mode: 0644]
mochikit_v14/tests/test_DragAndDrop.js [new file with mode: 0644]
mochikit_v14/tests/test_Format.js [new file with mode: 0644]
mochikit_v14/tests/test_Iter.js [new file with mode: 0644]
mochikit_v14/tests/test_Logging.js [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Async.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Async.json [new file with mode: 0755]
mochikit_v14/tests/test_MochiKit-Base.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Color.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-DOM-Safari.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-DOM.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-DateTime.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-DragAndDrop.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Format.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Iter.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-JSAN.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Logging.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-MochiKit.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Selector.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Signal.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Style.html [new file with mode: 0644]
mochikit_v14/tests/test_MochiKit-Visual.html [new file with mode: 0644]
mochikit_v14/tests/test_Signal.js [new file with mode: 0644]
plotkit_v091/COPYING [new file with mode: 0644]
plotkit_v091/PlotKit/Base.js [new file with mode: 0644]
plotkit_v091/PlotKit/Canvas.js [new file with mode: 0644]
plotkit_v091/PlotKit/EasyPlot.js [new file with mode: 0644]
plotkit_v091/PlotKit/Layout.js [new file with mode: 0644]
plotkit_v091/PlotKit/PlotKit.js [new file with mode: 0644]
plotkit_v091/PlotKit/PlotKit_Packed.js [new file with mode: 0644]
plotkit_v091/PlotKit/SVG.js [new file with mode: 0644]
plotkit_v091/PlotKit/SweetCanvas.js [new file with mode: 0644]
plotkit_v091/PlotKit/SweetSVG.js [new file with mode: 0644]
plotkit_v091/PlotKit/dummy.svg [new file with mode: 0644]
plotkit_v091/PlotKit/excanvas.js [new file with mode: 0644]
plotkit_v091/README [new file with mode: 0644]
plotkit_v091/doc/MochiKitAdditions.html [new file with mode: 0644]
plotkit_v091/doc/MochiKitAdditions.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Base.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Base.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Canvas.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Canvas.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.EasyPlot.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.EasyPlot.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Layout.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Layout.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.QuickStart.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.QuickStart.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Renderer.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.Renderer.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.SVG.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.SVG.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.SweetCanvas.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.SweetCanvas.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.SweetSVG.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.SweetSVG.txt [new file with mode: 0644]
plotkit_v091/doc/PlotKit.html [new file with mode: 0644]
plotkit_v091/doc/PlotKit.txt [new file with mode: 0644]
plotkit_v091/doc/SVGCanvasCompat.html [new file with mode: 0644]
plotkit_v091/doc/SVGCanvasCompat.txt [new file with mode: 0644]
plotkit_v091/doc/barsample.png [new file with mode: 0644]
plotkit_v091/doc/black.png [new file with mode: 0644]
plotkit_v091/doc/blue.png [new file with mode: 0644]
plotkit_v091/doc/cyan.png [new file with mode: 0644]
plotkit_v091/doc/doc.css [new file with mode: 0644]
plotkit_v091/doc/generate.py [new file with mode: 0755]
plotkit_v091/doc/green.png [new file with mode: 0644]
plotkit_v091/doc/orange.png [new file with mode: 0644]
plotkit_v091/doc/piesample.png [new file with mode: 0644]
plotkit_v091/doc/purple.png [new file with mode: 0644]
plotkit_v091/doc/red.png [new file with mode: 0644]
plotkit_v091/scripts/custom_rhino.jar [new file with mode: 0644]
plotkit_v091/scripts/pack.py [new file with mode: 0755]
plotkit_v091/tests/axis.html [new file with mode: 0644]
plotkit_v091/tests/basic.html [new file with mode: 0644]
plotkit_v091/tests/basic.js [new file with mode: 0644]
plotkit_v091/tests/debug.html [new file with mode: 0644]
plotkit_v091/tests/demo-svg.html [new file with mode: 0644]
plotkit_v091/tests/demo-svg.js [new file with mode: 0644]
plotkit_v091/tests/demo.html [new file with mode: 0644]
plotkit_v091/tests/demo.js [new file with mode: 0644]
plotkit_v091/tests/dynamic.html [new file with mode: 0644]
plotkit_v091/tests/img/firefox.png [new file with mode: 0644]
plotkit_v091/tests/img/konqueror.png [new file with mode: 0644]
plotkit_v091/tests/img/mozilla.ico [new file with mode: 0644]
plotkit_v091/tests/img/msie.gif [new file with mode: 0644]
plotkit_v091/tests/img/opera.ico [new file with mode: 0644]
plotkit_v091/tests/img/safari.gif [new file with mode: 0644]
plotkit_v091/tests/labels-img.html [new file with mode: 0644]
plotkit_v091/tests/labels.html [new file with mode: 0644]
plotkit_v091/tests/prototype_compat.html [new file with mode: 0644]
plotkit_v091/tests/quickstart-easy.html [new file with mode: 0644]
plotkit_v091/tests/quickstart-horiz.html [new file with mode: 0644]
plotkit_v091/tests/quickstart-neg.html [new file with mode: 0644]
plotkit_v091/tests/quickstart-svg.html [new file with mode: 0644]
plotkit_v091/tests/quickstart.html [new file with mode: 0644]
plotkit_v091/tests/sample.txt [new file with mode: 0644]
plotkit_v091/tests/svg-sweet.html [new file with mode: 0644]
plotkit_v091/tests/svg-sweet.js [new file with mode: 0644]
plotkit_v091/tests/svg.html [new file with mode: 0644]
plotkit_v091/tests/svg.js [new file with mode: 0644]
plotkit_v091/tests/sweet.html [new file with mode: 0644]
plotkit_v091/tests/sweet.js [new file with mode: 0644]
plotkit_v091/tests/tests.css [new file with mode: 0644]
plotkit_v091/tests/testsvg.html [new file with mode: 0644]
plotkit_v091/tests/testsvg.js [new file with mode: 0644]
test.html [new file with mode: 0644]

diff --git a/data.js b/data.js
new file mode 100644 (file)
index 0000000..d92a633
--- /dev/null
+++ b/data.js
@@ -0,0 +1,63 @@
+function StubbedData() {
+return "" +
+"Date,A,B\n" +
+"20061001,3.01953818828,0.7212041046,2.18487394958,0.599318549691\n" +
+"20061002,3.63321799308,0.778297234566,1.69491525424,0.531417655826\n" +
+"20061003,2.44328097731,0.644967734352,2.51256281407,0.640539070386\n" +
+"20061004,3.52733686067,0.774700921683,2.68456375839,0.66207105053\n" +
+"20061005,3.28719723183,0.741636245748,2.35294117647,0.621407707226\n" +
+"20061006,1.58450704225,0.523967868159,3.78657487091,0.791868460623\n" +
+"20061007,5.32859680284,0.946589405904,4.0404040404,0.807910739509\n" +
+"20061008,2.64084507042,0.672799548916,2.37288135593,0.626609885481\n" +
+"20061009,2.26480836237,0.620990945917,3.5413153457,0.75897176848\n" +
+"20061010,3.29289428076,0.74289969528,2.02702702703,0.579191340004\n" +
+"20061011,2.7633851468,0.681234043829,1.1744966443,0.4413034044\n" +
+"20061012,3.28719723183,0.741636245748,3.37268128162,0.741327769578\n" +
+"20061013,1.77304964539,0.55569466381,1.85810810811,0.555011329732\n" +
+"20061014,3.39892665474,0.7664008338,1.67224080268,0.524368852929\n" +
+"20061015,2.65017667845,0.675144574777,3.35570469799,0.737661045752\n" +
+"20061016,3.63951473137,0.779620631266,2.34899328859,0.620377617453\n" +
+"20061017,2.25694444444,0.618859623032,1.68067226891,0.526990133716\n" +
+"20061018,4.47504302926,0.857766274964,2.51677852349,0.641599927369\n" +
+"20061019,2.44755244755,0.646081155692,1.68067226891,0.526990133716\n" +
+"20061020,3.67775831874,0.787656442774,3.066439523,0.711598843969\n" +
+"20061021,3.94265232975,0.823839169829,3.85906040268,0.788990618726\n" +
+"20061022,2.59067357513,0.660187558973,3.71621621622,0.777438794254\n" +
+"20061023,4.33275563258,0.847570482324,3.85906040268,0.788990618726\n" +
+"20061024,3.10344827586,0.720049610821,2.84280936455,0.679611549697\n" +
+"20061025,1.40350877193,0.492720767725,2.7027027027,0.666482380968\n" +
+"20061026,1.95035460993,0.582291234145,2.36486486486,0.624518599275\n" +
+"20061027,2.30905861456,0.632980642182,2.03045685279,0.580161203819\n" +
+"20061028,4.09252669039,0.835706590809,2.87648054146,0.68754192469\n" +
+"20061029,2.66903914591,0.679883997626,2.02360876897,0.578224712918\n" +
+"20061030,4.74516695958,0.89127787497,4.36241610738,0.836670992529\n" +
+"20061031,2.78260869565,0.685905251933,3.20945945946,0.724388507178\n" +
+"20061101,1.5873015873,0.524884521441,1.51260504202,0.500373860545\n" +
+"20061102,2.78745644599,0.687083077461,2.0202020202,0.57726130639\n" +
+"20061103,5.11463844797,0.925157232782,2.68907563025,0.663168401088\n" +
+"20061104,4.9001814882,0.919644816432,3.07692307692,0.713993047527\n" +
+"20061105,5.13274336283,0.928343545136,3.55329949239,0.761492892041\n" +
+"20061106,1.92644483363,0.575222935029,2.35294117647,0.621407707226\n" +
+"20061107,2.46478873239,0.650573541306,1.52027027027,0.502889967904\n" +
+"20061108,2.13523131673,0.609772022763,2.6981450253,0.665374048085\n" +
+"20061109,3.88007054674,0.811026422222,2.72572402044,0.672079879106\n" +
+"20061110,2.63620386643,0.671633132526,3.71621621622,0.777438794254\n" +
+"20061111,3.69718309859,0.791736755355,3.0303030303,0.703344064467\n" +
+"20061112,3.83944153578,0.802703592906,4.05405405405,0.81058250986\n" +
+"20061113,2.47787610619,0.653984033555,2.20338983051,0.604340313133\n" +
+"20061114,1.77304964539,0.55569466381,2.22222222222,0.60944692682\n" +
+"20061115,2.30088495575,0.630766388737,0.843170320405,0.375484163785\n" +
+"20061116,1.57894736842,0.522144132232,2.19594594595,0.602321544724\n" +
+"20061118,2.45183887916,0.647198426991,1.69491525424,0.531417655826\n" +
+"20061119,3.52733686067,0.774700921683,1.85185185185,0.55316023504\n" +
+"20061120,2.97723292469,0.711254751484,2.6981450253,0.665374048085\n" +
+"20061121,2.29681978799,0.629665059963,2.01680672269,0.576301104352\n" +
+"20061122,3.01418439716,0.719945245328,2.5466893039,0.649125445325\n" +
+"20061123,3.78378378378,0.809917534069,2.6936026936,0.664269394219\n" +
+"20061124,3.18584070796,0.738851643987,2.01005025126,0.57439025002\n" +
+"20061125,2.83185840708,0.697868332879,3.066439523,0.711598843969\n" +
+"20061126,3.01953818828,0.7212041046,2.53378378378,0.645878720149\n" +
+"20061127,2.81195079086,0.693033387099,1.51006711409,0.499540743312\n" +
+"20061128,2.97723292469,0.711254751484,2.54237288136,0.648039583782\n" +
+"20061129,1.41093474427,0.495309102312,3.02013422819,0.701020603129";
+}
diff --git a/dygraph-canvas.js b/dygraph-canvas.js
new file mode 100644 (file)
index 0000000..04e1eb1
--- /dev/null
@@ -0,0 +1,230 @@
+// Copyright 2006 Dan Vanderkam (danvdk@gmail.com)
+// All Rights Reserved.
+
+/**
+ * @fileoverview Subclasses various parts of PlotKit to meet the additional
+ * needs of DateGraph: grid overlays and error bars
+ */
+
+// Subclass PlotKit.Layout to add:
+// 1. Sigma/errorBars properties
+// 2. Copy error terms for PlotKit.CanvasRenderer._renderLineChart
+
+/**
+ * Creates a new DateGraphLayout object. Options are the same as those allowed
+ * by the PlotKit.Layout constructor.
+ * @param {Object} options Options for PlotKit.Layout
+ * @return {Object} The DateGraphLayout object
+ */
+DateGraphLayout = function(options) {
+  PlotKit.Layout.call(this, "line", options);
+};
+DateGraphLayout.prototype = new PlotKit.Layout();
+
+/**
+ * Behaves the same way as PlotKit.Layout, but also copies the errors
+ * @private
+ */
+DateGraphLayout.prototype.evaluateWithError = function() {
+  this.evaluate();
+  if (!this.options.errorBars) return;
+
+  // Copy over the error terms
+  var i = 0; // index in this.points
+  for (var setName in this.datasets) {
+    var j = 0;
+    var dataset = this.datasets[setName];
+    if (PlotKit.Base.isFuncLike(dataset)) continue;
+    for (var j = 0; j < dataset.length; j++, i++) {
+      var item = dataset[j];
+      var xv = parseFloat(item[0]);
+      var yv = parseFloat(item[1]);
+
+      if (xv == this.points[i].xval &&
+          yv == this.points[i].yval) {
+        this.points[i].errorMinus = parseFloat(item[2]);
+        this.points[i].errorPlus = parseFloat(item[3]);
+      }
+    }
+  }
+};
+
+/**
+ * Convenience function to remove all the data sets from a graph
+ */
+DateGraphLayout.prototype.removeAllDatasets = function() {
+  delete this.datasets;
+  this.datasets = new Array();
+};
+
+/**
+ * Change the values of various layout options
+ * @param {Object} new_options an associative array of new properties
+ */
+DateGraphLayout.prototype.updateOptions = function(new_options) {
+  MochiKit.Base.update(this.options, new_options ? new_options : {});
+};
+
+// Subclass PlotKit.CanvasRenderer to add:
+// 1. X/Y grid overlay
+// 2. Ability to draw error bars (if required)
+
+/**
+ * Sets some PlotKit.CanvasRenderer options
+ * @param {Object} element The canvas to attach to
+ * @param {Layout} layout The DateGraphLayout object for this graph.
+ * @param {Object} options Options to pass on to CanvasRenderer
+ */
+DateGraphCanvasRenderer = function(element, layout, options) {
+  PlotKit.CanvasRenderer.call(this, element, layout, options);
+  this.options.shouldFill = false;
+  this.options.shouldStroke = true;
+  this.options.drawYGrid = true;
+  this.options.drawXGrid = true;
+  this.options.gridLineColor = MochiKit.Color.Color.grayColor();
+  MochiKit.Base.update(this.options, options);
+
+  // TODO(danvk) This shouldn't be necessary: effects should be overlaid
+  this.options.drawBackground = false;
+};
+DateGraphCanvasRenderer.prototype = new PlotKit.CanvasRenderer();
+
+/**
+ * Draw an X/Y grid on top of the existing plot
+ */
+DateGraphCanvasRenderer.prototype.render = function() {
+  // Do the ordinary rendering, as before
+  // TODO(danvk) Call super.render()
+  this._renderLineChart();
+  this._renderLineAxis();
+
+  // Draw the new X/Y grid
+  var ctx = this.element.getContext("2d");
+  if (this.options.drawYGrid) {
+    var ticks = this.layout.yticks;
+    ctx.save();
+    ctx.strokeStyle = this.options.gridLineColor.toRGBString();
+    ctx.lineWidth = this.options.axisLineWidth;
+    for (var i = 0; i < ticks.length; i++) {
+      var x = this.area.x;
+      var y = this.area.y + ticks[i][0] * this.area.h;
+      ctx.beginPath();
+      ctx.moveTo(x, y);
+      ctx.lineTo(x + this.area.w, y);
+      ctx.closePath();
+      ctx.stroke();
+    }
+  }
+
+  if (this.options.drawXGrid) {
+    var ticks = this.layout.xticks;
+    ctx.save();
+    ctx.strokeStyle = this.options.gridLineColor.toRGBString();
+    ctx.lineWidth = this.options.axisLineWidth;
+    for (var i=0; i<ticks.length; i++) {
+      var x = this.area.x + ticks[i][0] * this.area.w;
+      var y = this.area.y + this.area.h;
+      ctx.beginPath();
+      ctx.moveTo(x, y);
+      ctx.lineTo(x, this.area.y);
+      ctx.closePath();
+      ctx.stroke();
+    }
+  }
+};
+
+/**
+ * Overrides the CanvasRenderer method to draw error bars
+ */
+DateGraphCanvasRenderer.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 errorBars = this.layout.options.errorBars;
+  var setCount = setNames.length;
+  var bind = MochiKit.Base.bind;
+  var partial = MochiKit.Base.partial;
+
+  //Update Points
+  var updatePoint = function(point) {
+    point.canvasx = this.area.w * point.x + this.area.x;
+    point.canvasy = this.area.h * point.y + this.area.y;
+  }
+  MochiKit.Iter.forEach(this.layout.points, updatePoint, this);
+
+  // create paths
+  var makePath = function(ctx) {
+    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.strokeStyle = color.toRGBString();
+      context.lineWidth = this.options.strokeWidth;
+      ctx.beginPath();
+      var point = this.layout.points[0];
+      var first_point = true;
+      var addPoint = function(ctx_, point) {
+        if (point.name == setName) {
+          if (first_point)
+            ctx_.moveTo(point.canvasx, point.canvasy);
+          else
+            ctx_.lineTo(point.canvasx, point.canvasy);
+          first_point = false;
+        }
+      };
+      MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
+      ctx.stroke();
+    }
+  };
+
+  var makeErrorBars = function(ctx) {
+    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.strokeStyle = color.toRGBString();
+      context.lineWidth = this.options.strokeWidth;
+      var prevX = -1;
+      var prevYs = [-1, -1];
+      var count = 0;
+      var yscale = this.layout.yscale;
+      var errorTrapezoid = function(ctx_,point) {
+        count++;
+        if (point.name == setName) {
+          var newYs = [ point.y - point.errorPlus * yscale,
+                        point.y + point.errorMinus * yscale ];
+          newYs[0] = this.area.h * newYs[0] + this.area.y;
+          newYs[1] = this.area.h * newYs[1] + this.area.y;
+          if (prevX >= 0) {
+            ctx_.moveTo(prevX, prevYs[0]);
+            ctx_.lineTo(point.canvasx, newYs[0]);
+            ctx_.lineTo(point.canvasx, newYs[1]);
+            ctx_.lineTo(prevX, prevYs[1]);
+            ctx_.closePath();
+          }
+          prevYs[0] = newYs[0];
+          prevYs[1] = newYs[1];
+          prevX = point.canvasx;
+        }
+      };
+      // should be same color as the lines
+      var err_color = color.colorWithAlpha(0.15);
+      ctx.fillStyle = err_color.toRGBString();
+      ctx.beginPath();
+      MochiKit.Iter.forEach(this.layout.points, partial(errorTrapezoid, ctx), this);
+      ctx.fill();
+    }
+  };
+
+  if (errorBars)
+    bind(makeErrorBars, this)(context);
+  bind(makePath, this)(context);
+  context.restore();
+};
diff --git a/dygraph-combined.js b/dygraph-combined.js
new file mode 100644 (file)
index 0000000..d0c243a
--- /dev/null
@@ -0,0 +1,10375 @@
+/***
+
+    MochiKit.MochiKit 1.4 : 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={};
+}
+if(typeof (MochiKit.__export__)=="undefined"){
+MochiKit.__export__=(MochiKit.__compat__||(typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined"));
+}
+MochiKit.Base.VERSION="1.4";
+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__();
+},camelize:function(_6){
+var _7=_6.split("-");
+var cc=_7[0];
+for(var i=1;i<_7.length;i++){
+cc+=_7[i].charAt(0).toUpperCase()+_7[i].substring(1);
+}
+return cc;
+},counter:function(n){
+if(arguments.length===0){
+n=1;
+}
+return function(){
+return n++;
+};
+},clone:function(_b){
+var me=arguments.callee;
+if(arguments.length==1){
+me.prototype=_b;
+return new me();
+}
+},_flattenArray:function(_d,_e){
+for(var i=0;i<_e.length;i++){
+var o=_e[i];
+if(o instanceof Array){
+arguments.callee(_d,o);
+}else{
+_d.push(o);
+}
+}
+return _d;
+},flattenArray:function(lst){
+return MochiKit.Base._flattenArray([],lst);
+},flattenArguments:function(lst){
+var res=[];
+var m=MochiKit.Base;
+var _15=m.extend(null,arguments);
+while(_15.length){
+var o=_15.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+for(var i=o.length-1;i>=0;i--){
+_15.unshift(o[i]);
+}
+}else{
+res.push(o);
+}
+}
+return res;
+},extend:function(_18,obj,_1a){
+if(!_1a){
+_1a=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(!_18){
+_18=[];
+}
+for(var i=_1a;i<l;i++){
+_18.push(obj[i]);
+}
+}
+return _18;
+},updatetree:function(_1d,obj){
+if(_1d===null){
+_1d={};
+}
+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 (_1d[k])=="object"&&typeof (v)=="object"){
+arguments.callee(_1d[k],v);
+}else{
+_1d[k]=v;
+}
+}
+}
+}
+return _1d;
+},setdefault:function(_23,obj){
+if(_23===null){
+_23={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+for(var k in o){
+if(!(k in _23)){
+_23[k]=o[k];
+}
+}
+}
+return _23;
+},keys:function(obj){
+var _29=[];
+for(var _2a in obj){
+_29.push(_2a);
+}
+return _29;
+},values:function(obj){
+var _2c=[];
+for(var _2d in obj){
+_2c.push(obj[_2d]);
+}
+return _2c;
+},items:function(obj){
+var _2f=[];
+var e;
+for(var _31 in obj){
+var v;
+try{
+v=obj[_31];
+}
+catch(e){
+continue;
+}
+_2f.push([_31,v]);
+}
+return _2f;
+},_newNamedError:function(_33,_34,_35){
+_35.prototype=new MochiKit.Base.NamedError(_33.NAME+"."+_34);
+_33[_34]=_35;
+},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;
+},seq:function(a,b){
+return a===b;
+},sne: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(_73){
+return function(){
+return this[_73].apply(this,arguments);
+};
+},itemgetter:function(_74){
+return function(arg){
+return arg[_74];
+};
+},typeMatcher:function(){
+var _76={};
+for(var i=0;i<arguments.length;i++){
+var typ=arguments[i];
+_76[typ]=typ;
+}
+return function(){
+for(var i=0;i<arguments.length;i++){
+if(!(typeof (arguments[i]) in _76)){
+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"||o.nodeType===3){
+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 _87=[];
+for(var i=1;i<arguments.length;i++){
+_87.push(fn(arguments[i]));
+}
+return _87;
+},map:function(fn,lst){
+var m=MochiKit.Base;
+var itr=MochiKit.Iter;
+var _8d=m.isArrayLike;
+if(arguments.length<=2){
+if(!_8d(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 _8e=[];
+for(var i=0;i<lst.length;i++){
+_8e.push(fn(lst[i]));
+}
+return _8e;
+}else{
+if(fn===null){
+fn=Array;
+}
+var _90=null;
+for(i=1;i<arguments.length;i++){
+if(!_8d(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(_90===null||_90>l){
+_90=l;
+}
+}
+_8e=[];
+for(i=0;i<_90;i++){
+var _92=[];
+for(var j=1;j<arguments.length;j++){
+_92.push(arguments[j][i]);
+}
+_8e.push(fn.apply(this,_92));
+}
+return _8e;
+}
+},xfilter:function(fn){
+var _95=[];
+if(fn===null){
+fn=MochiKit.Base.operator.truth;
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(fn(o)){
+_95.push(o);
+}
+}
+return _95;
+},filter:function(fn,lst,_9a){
+var _9b=[];
+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,_9a);
+}else{
+if(typeof (_9a)=="undefined"||_9a===null){
+for(var i=0;i<lst.length;i++){
+var o=lst[i];
+if(fn(o)){
+_9b.push(o);
+}
+}
+}else{
+for(i=0;i<lst.length;i++){
+o=lst[i];
+if(fn.call(_9a,o)){
+_9b.push(o);
+}
+}
+}
+}
+return _9b;
+},_wrapDumbFunction:function(_9f){
+return function(){
+switch(arguments.length){
+case 0:
+return _9f();
+case 1:
+return _9f(arguments[0]);
+case 2:
+return _9f(arguments[0],arguments[1]);
+case 3:
+return _9f(arguments[0],arguments[1],arguments[2]);
+}
+var _a0=[];
+for(var i=0;i<arguments.length;i++){
+_a0.push("arguments["+i+"]");
+}
+return eval("(func("+_a0.join(",")+"))");
+};
+},methodcaller:function(_a2){
+var _a3=MochiKit.Base.extend(null,arguments,1);
+if(typeof (_a2)=="function"){
+return function(obj){
+return _a2.apply(obj,_a3);
+};
+}else{
+return function(obj){
+return obj[_a2].apply(obj,_a3);
+};
+}
+},method:function(_a6,_a7){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([_a7,_a6],arguments,2));
+},compose:function(f1,f2){
+var _ab=[];
+var m=MochiKit.Base;
+if(arguments.length===0){
+throw new TypeError("compose() requires at least one argument");
+}
+for(var i=0;i<arguments.length;i++){
+var fn=arguments[i];
+if(typeof (fn)!="function"){
+throw new TypeError(m.repr(fn)+" is not a function");
+}
+_ab.push(fn);
+}
+return function(){
+var _af=arguments;
+for(var i=_ab.length-1;i>=0;i--){
+_af=[_ab[i].apply(this,_af)];
+}
+return _af[0];
+};
+},bind:function(_b1,_b2){
+if(typeof (_b1)=="string"){
+_b1=_b2[_b1];
+}
+var _b3=_b1.im_func;
+var _b4=_b1.im_preargs;
+var _b5=_b1.im_self;
+var m=MochiKit.Base;
+if(typeof (_b1)=="function"&&typeof (_b1.apply)=="undefined"){
+_b1=m._wrapDumbFunction(_b1);
+}
+if(typeof (_b3)!="function"){
+_b3=_b1;
+}
+if(typeof (_b2)!="undefined"){
+_b5=_b2;
+}
+if(typeof (_b4)=="undefined"){
+_b4=[];
+}else{
+_b4=_b4.slice();
+}
+m.extend(_b4,arguments,2);
+var _b7=function(){
+var _b8=arguments;
+var me=arguments.callee;
+if(me.im_preargs.length>0){
+_b8=m.concat(me.im_preargs,_b8);
+}
+var _ba=me.im_self;
+if(!_ba){
+_ba=this;
+}
+return me.im_func.apply(_ba,_b8);
+};
+_b7.im_self=_b5;
+_b7.im_func=_b3;
+_b7.im_preargs=_b4;
+return _b7;
+},bindMethods:function(_bb){
+var _bc=MochiKit.Base.bind;
+for(var k in _bb){
+var _be=_bb[k];
+if(typeof (_be)=="function"){
+_bb[k]=_bc(_be,_bb);
+}
+}
+},registerComparator:function(_bf,_c0,_c1,_c2){
+MochiKit.Base.comparatorRegistry.register(_bf,_c0,_c1,_c2);
+},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){
+if(a==b){
+return 0;
+}
+var _c5=(typeof (a)=="undefined"||a===null);
+var _c6=(typeof (b)=="undefined"||b===null);
+if(_c5&&_c6){
+return 0;
+}else{
+if(_c5){
+return -1;
+}else{
+if(_c6){
+return 1;
+}
+}
+}
+var m=MochiKit.Base;
+var _c8=m._primitives;
+if(!(typeof (a) in _c8&&typeof (b) in _c8)){
+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 _c9=m.repr;
+throw new TypeError(_c9(a)+" and "+_c9(b)+" can not be compared");
+},compareDateLike:function(a,b){
+return MochiKit.Base.compare(a.getTime(),b.getTime());
+},compareArrayLike:function(a,b){
+var _ce=MochiKit.Base.compare;
+var _cf=a.length;
+var _d0=0;
+if(_cf>b.length){
+_d0=1;
+_cf=b.length;
+}else{
+if(_cf<b.length){
+_d0=-1;
+}
+}
+for(var i=0;i<_cf;i++){
+var cmp=_ce(a[i],b[i]);
+if(cmp){
+return cmp;
+}
+}
+return _d0;
+},registerRepr:function(_d3,_d4,_d5,_d6){
+MochiKit.Base.reprRegistry.register(_d3,_d4,_d5,_d6);
+},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 _d8=(o+"");
+}
+catch(e){
+return "["+typeof (o)+"]";
+}
+if(typeof (o)=="function"){
+o=_d8.replace(/^\s+/,"");
+var idx=o.indexOf("{");
+if(idx!=-1){
+o=o.substr(0,idx)+"{...}";
+}
+}
+return _d8;
+},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(_de,_df,_e0,_e1){
+MochiKit.Base.jsonRegistry.register(_de,_df,_e0,_e1);
+},evalJSON:function(){
+return eval("("+arguments[0]+")");
+},serializeJSON:function(o){
+var _e3=typeof (o);
+if(_e3=="number"||_e3=="boolean"){
+return o+"";
+}else{
+if(o===null){
+return "null";
+}
+}
+var m=MochiKit.Base;
+var _e5=m.reprString;
+if(_e3=="string"){
+return _e5(o);
+}
+var me=arguments.callee;
+var _e7;
+if(typeof (o.__json__)=="function"){
+_e7=o.__json__();
+if(o!==_e7){
+return me(_e7);
+}
+}
+if(typeof (o.json)=="function"){
+_e7=o.json();
+if(o!==_e7){
+return me(_e7);
+}
+}
+if(_e3!="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{
+_e7=m.jsonRegistry.match(o);
+if(o!==_e7){
+return me(_e7);
+}
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+if(_e3=="undefined"){
+throw new TypeError("undefined can not be serialized as JSON");
+}
+if(_e3=="function"){
+return null;
+}
+res=[];
+for(var k in o){
+var _ec;
+if(typeof (k)=="number"){
+_ec="\""+k+"\"";
+}else{
+if(typeof (k)=="string"){
+_ec=_e5(k);
+}else{
+continue;
+}
+}
+val=me(o[k]);
+if(typeof (val)!="string"){
+continue;
+}
+res.push(_ec+":"+val);
+}
+return "{"+res.join(", ")+"}";
+},objEqual:function(a,b){
+return (MochiKit.Base.compare(a,b)===0);
+},arrayEqual:function(_ef,arr){
+if(_ef.length!=arr.length){
+return false;
+}
+return (MochiKit.Base.compare(_ef,arr)===0);
+},concat:function(){
+var _f1=[];
+var _f2=MochiKit.Base.extend;
+for(var i=0;i<arguments.length;i++){
+_f2(_f1,arguments[i]);
+}
+return _f1;
+},keyComparator:function(key){
+var m=MochiKit.Base;
+var _f6=m.compare;
+if(arguments.length==1){
+return function(a,b){
+return _f6(a[key],b[key]);
+};
+}
+var _f9=m.extend(null,arguments);
+return function(a,b){
+var _fc=0;
+for(var i=0;(_fc===0)&&(i<_f9.length);i++){
+var key=_f9[i];
+_fc=_f6(a[key],b[key]);
+}
+return _fc;
+};
+},reverseKeyComparator:function(key){
+var _100=MochiKit.Base.keyComparator.apply(this,arguments);
+return function(a,b){
+return _100(b,a);
+};
+},partial:function(func){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([func,undefined],arguments,1));
+},listMinMax:function(_105,lst){
+if(lst.length===0){
+return null;
+}
+var cur=lst[0];
+var _108=MochiKit.Base.compare;
+for(var i=1;i<lst.length;i++){
+var o=lst[i];
+if(_108(o,cur)==_105){
+cur=o;
+}
+}
+return cur;
+},objMax:function(){
+return MochiKit.Base.listMinMax(1,arguments);
+},objMin:function(){
+return MochiKit.Base.listMinMax(-1,arguments);
+},findIdentical:function(lst,_10c,_10d,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_10d)=="undefined"||_10d===null){
+_10d=0;
+}
+for(var i=_10d;i<end;i++){
+if(lst[i]===_10c){
+return i;
+}
+}
+return -1;
+},mean:function(){
+var sum=0;
+var m=MochiKit.Base;
+var args=m.extend(null,arguments);
+var _113=args.length;
+while(args.length){
+var o=args.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+_113+=o.length-1;
+for(var i=o.length-1;i>=0;i--){
+sum+=o[i];
+}
+}else{
+sum+=o;
+}
+}
+if(_113<=0){
+throw new TypeError("mean() requires at least one argument");
+}
+return sum/_113;
+},median:function(){
+var data=MochiKit.Base.flattenArguments(arguments);
+if(data.length===0){
+throw new TypeError("median() requires at least one argument");
+}
+data.sort(compare);
+if(data.length%2==0){
+var _117=data.length/2;
+return (data[_117]+data[_117-1])/2;
+}else{
+return data[(data.length-1)/2];
+}
+},findValue:function(lst,_119,_11a,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_11a)=="undefined"||_11a===null){
+_11a=0;
+}
+var cmp=MochiKit.Base.compare;
+for(var i=_11a;i<end;i++){
+if(cmp(lst[i],_119)===0){
+return i;
+}
+}
+return -1;
+},nodeWalk:function(node,_11f){
+var _120=[node];
+var _121=MochiKit.Base.extend;
+while(_120.length){
+var res=_11f(_120.shift());
+if(res){
+_121(_120,res);
+}
+}
+},nameFunctions:function(_123){
+var base=_123.NAME;
+if(typeof (base)=="undefined"){
+base="";
+}else{
+base=base+".";
+}
+for(var name in _123){
+var o=_123[name];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+name;
+}
+catch(e){
+}
+}
+}
+},queryString:function(_127,_128){
+if(typeof (MochiKit.DOM)!="undefined"&&arguments.length==1&&(typeof (_127)=="string"||(typeof (_127.nodeType)!="undefined"&&_127.nodeType>0))){
+var kv=MochiKit.DOM.formContents(_127);
+_127=kv[0];
+_128=kv[1];
+}else{
+if(arguments.length==1){
+if(typeof (_127.length)=="number"&&_127.length==2){
+return arguments.callee(_127[0],_127[1]);
+}
+var o=_127;
+_127=[];
+_128=[];
+for(var k in o){
+var v=o[k];
+if(typeof (v)=="function"){
+continue;
+}else{
+if(typeof (v)!="string"&&typeof (v.length)=="number"){
+for(var i=0;i<v.length;i++){
+_127.push(k);
+_128.push(v[i]);
+}
+}else{
+_127.push(k);
+_128.push(v);
+}
+}
+}
+}
+}
+var rval=[];
+var len=Math.min(_127.length,_128.length);
+var _130=MochiKit.Base.urlEncode;
+for(var i=0;i<len;i++){
+v=_128[i];
+if(typeof (v)!="undefined"&&v!==null){
+rval.push(_130(_127[i])+"="+_130(v));
+}
+}
+return rval.join("&");
+},parseQueryString:function(_131,_132){
+var qstr=(_131.charAt(0)=="?")?_131.substring(1):_131;
+var _134=qstr.replace(/\+/g,"%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
+var o={};
+var _136;
+if(typeof (decodeURIComponent)!="undefined"){
+_136=decodeURIComponent;
+}else{
+_136=unescape;
+}
+if(_132){
+for(var i=0;i<_134.length;i++){
+var pair=_134[i].split("=");
+var name=_136(pair.shift());
+if(!name){
+continue;
+}
+var arr=o[name];
+if(!(arr instanceof Array)){
+arr=[];
+o[name]=arr;
+}
+arr.push(_136(pair.join("=")));
+}
+}else{
+for(i=0;i<_134.length;i++){
+pair=_134[i].split("=");
+var name=pair.shift();
+if(!name){
+continue;
+}
+o[_136(name)]=_136(pair.join("="));
+}
+}
+return o;
+}});
+MochiKit.Base.AdapterRegistry=function(){
+this.pairs=[];
+};
+MochiKit.Base.AdapterRegistry.prototype={register:function(name,_13c,wrap,_13e){
+if(_13e){
+this.pairs.unshift([name,_13c,wrap]);
+}else{
+this.pairs.push([name,_13c,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=["flattenArray","noop","camelize","counter","clone","extend","update","updatetree","setdefault","keys","values","items","NamedError","operator","forwardCall","itemgetter","typeMatcher","isCallable","isUndefined","isUndefinedOrNull","isNull","isEmpty","isNotEmpty","isArrayLike","isDateLike","xmap","map","xfilter","filter","methodcaller","compose","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","average","mean","median"];
+MochiKit.Base.EXPORT_OK=["nameFunctions","comparatorRegistry","reprRegistry","jsonRegistry","compareDateLike","compareArrayLike","reprArrayLike","reprString","reprNumber"];
+MochiKit.Base._exportSymbols=function(_144,_145){
+if(!MochiKit.__export__){
+return;
+}
+var all=_145.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_144[all[i]]=_145[all[i]];
+}
+};
+MochiKit.Base.__new__=function(){
+var m=this;
+m.noop=m.operator.identity;
+m.forward=m.forwardCall;
+m.find=m.findValue;
+if(typeof (encodeURIComponent)!="undefined"){
+m.urlEncode=function(_149){
+return encodeURIComponent(_149).replace(/\'/g,"%27");
+};
+}else{
+m.urlEncode=function(_14a){
+return escape(_14a).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.average=m.mean;
+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.__export__){
+compare=MochiKit.Base.compare;
+compose=MochiKit.Base.compose;
+serializeJSON=MochiKit.Base.serializeJSON;
+}
+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.4";
+MochiKit.Base.update(MochiKit.Iter,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},registerIteratorFactory:function(name,_14e,_14f,_150){
+MochiKit.Iter.iteratorRegistry.register(name,_14e,_14f,_150);
+},iter:function(_151,_152){
+var self=MochiKit.Iter;
+if(arguments.length==2){
+return self.takewhile(function(a){
+return a!=_152;
+},_151);
+}
+if(typeof (_151.next)=="function"){
+return _151;
+}else{
+if(typeof (_151.iter)=="function"){
+return _151.iter();
+}
+}
+try{
+return self.iteratorRegistry.match(_151);
+}
+catch(e){
+var m=MochiKit.Base;
+if(e==m.NotFound){
+e=new TypeError(typeof (_151)+": "+m.repr(_151)+" 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 _15c=self.iter(p);
+return {repr:function(){
+return "cycle(...)";
+},toString:m.forwardCall("repr"),next:function(){
+try{
+var rval=_15c.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(_162){
+return _162.next();
+},izip:function(p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var next=self.next;
+var _168=m.map(self.iter,arguments);
+return {repr:function(){
+return "izip(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return m.map(next,_168);
+}};
+},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 _174=0;
+var stop=0;
+var step=1;
+var i=-1;
+if(arguments.length==2){
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_174=arguments[1];
+stop=arguments[2];
+}else{
+_174=arguments[1];
+stop=arguments[2];
+step=arguments[3];
+}
+}
+return {repr:function(){
+return "islice("+["...",_174,stop,step].join(", ")+")";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+while(i<_174){
+rval=seq.next();
+i++;
+}
+if(_174>=stop){
+throw self.StopIteration;
+}
+_174+=step;
+return rval;
+}};
+},imap:function(fun,p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var _17e=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,_17e));
+}};
+},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 _189=m.map(self.iter,arguments);
+return {repr:function(){
+return "chain(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(_189.length>1){
+try{
+return _189[0].next();
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+_189.shift();
+}
+}
+if(_189.length==1){
+var arg=_189.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(_194,sync,_196){
+sync.pos[_194]=-1;
+var m=MochiKit.Base;
+var _198=m.listMin;
+return {repr:function(){
+return "tee("+_194+", ...)";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+var i=sync.pos[_194];
+if(i==sync.max){
+rval=_196.next();
+sync.deque.push(rval);
+sync.max+=1;
+sync.pos[_194]+=1;
+}else{
+rval=sync.deque[i-sync.min];
+sync.pos[_194]+=1;
+if(i==sync.min&&_198(sync.pos)!=sync.min){
+sync.min+=1;
+sync.deque.shift();
+}
+}
+return rval;
+}};
+},tee:function(_19b,n){
+var rval=[];
+var sync={"pos":[],"deque":[],"max":-1,"min":-1};
+if(arguments.length==1||typeof (n)=="undefined"||n===null){
+n=2;
+}
+var self=MochiKit.Iter;
+_19b=self.iter(_19b);
+var _tee=self._tee;
+for(var i=0;i<n;i++){
+rval.push(_tee(i,sync,_19b));
+}
+return rval;
+},list:function(_1a2){
+var rval;
+if(_1a2 instanceof Array){
+return _1a2.slice();
+}
+if(typeof (_1a2)=="function"&&!(_1a2 instanceof Function)&&typeof (_1a2.length)=="number"){
+rval=[];
+for(var i=0;i<_1a2.length;i++){
+rval.push(_1a2[i]);
+}
+return rval;
+}
+var self=MochiKit.Iter;
+_1a2=self.iter(_1a2);
+var rval=[];
+try{
+while(true){
+rval.push(_1a2.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return rval;
+}
+return undefined;
+},reduce:function(fn,_1a7,_1a8){
+var i=0;
+var x=_1a8;
+var self=MochiKit.Iter;
+_1a7=self.iter(_1a7);
+if(arguments.length<3){
+try{
+x=_1a7.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,_1a7.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},range:function(){
+var _1ac=0;
+var stop=0;
+var step=1;
+if(arguments.length==1){
+stop=arguments[0];
+}else{
+if(arguments.length==2){
+_1ac=arguments[0];
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_1ac=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&&_1ac>=stop)||(step<0&&_1ac<=stop)){
+throw MochiKit.Iter.StopIteration;
+}
+var rval=_1ac;
+_1ac+=step;
+return rval;
+},repr:function(){
+return "range("+[_1ac,stop,step].join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+},sum:function(_1b0,_1b1){
+if(typeof (_1b1)=="undefined"||_1b1===null){
+_1b1=0;
+}
+var x=_1b1;
+var self=MochiKit.Iter;
+_1b0=self.iter(_1b0);
+try{
+while(true){
+x+=_1b0.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},exhaust:function(_1b4){
+var self=MochiKit.Iter;
+_1b4=self.iter(_1b4);
+try{
+while(true){
+_1b4.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+},forEach:function(_1b6,func,self){
+var m=MochiKit.Base;
+if(arguments.length>2){
+func=m.bind(func,self);
+}
+if(m.isArrayLike(_1b6)){
+try{
+for(var i=0;i<_1b6.length;i++){
+func(_1b6[i]);
+}
+}
+catch(e){
+if(e!=MochiKit.Iter.StopIteration){
+throw e;
+}
+}
+}else{
+self=MochiKit.Iter;
+self.exhaust(self.imap(func,_1b6));
+}
+},every:function(_1bb,func){
+var self=MochiKit.Iter;
+try{
+self.ifilterfalse(func,_1bb).next();
+return false;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return true;
+}
+},sorted:function(_1be,cmp){
+var rval=MochiKit.Iter.list(_1be);
+if(arguments.length==1){
+cmp=MochiKit.Base.compare;
+}
+rval.sort(cmp);
+return rval;
+},reversed:function(_1c1){
+var rval=MochiKit.Iter.list(_1c1);
+rval.reverse();
+return rval;
+},some:function(_1c3,func){
+var self=MochiKit.Iter;
+try{
+self.ifilter(func,_1c3).next();
+return true;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return false;
+}
+},iextend:function(lst,_1c7){
+if(MochiKit.Base.isArrayLike(_1c7)){
+for(var i=0;i<_1c7.length;i++){
+lst.push(_1c7[i]);
+}
+}else{
+var self=MochiKit.Iter;
+_1c7=self.iter(_1c7);
+try{
+while(true){
+lst.push(_1c7.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+}
+return lst;
+},groupby:function(_1ca,_1cb){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_1cb=m.operator.identity;
+}
+_1ca=self.iter(_1ca);
+var pk=undefined;
+var k=undefined;
+var v;
+function fetch(){
+v=_1ca.next();
+k=_1cb(v);
+}
+function eat(){
+var ret=v;
+v=undefined;
+return ret;
+}
+var _1d2=true;
+var _1d3=m.compare;
+return {repr:function(){
+return "groupby(...)";
+},next:function(){
+while(_1d3(k,pk)===0){
+fetch();
+if(_1d2){
+_1d2=false;
+break;
+}
+}
+pk=k;
+return [k,{next:function(){
+if(v==undefined){
+fetch();
+}
+if(_1d3(k,pk)!==0){
+throw self.StopIteration;
+}
+return eat();
+}}];
+}};
+},groupby_as_array:function(_1d4,_1d5){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_1d5=m.operator.identity;
+}
+_1d4=self.iter(_1d4);
+var _1d8=[];
+var _1d9=true;
+var _1da;
+var _1db=m.compare;
+while(true){
+try{
+var _1dc=_1d4.next();
+var key=_1d5(_1dc);
+}
+catch(e){
+if(e==self.StopIteration){
+break;
+}
+throw e;
+}
+if(_1d9||_1db(key,_1da)!==0){
+var _1de=[];
+_1d8.push([key,_1de]);
+}
+_1de.push(_1dc);
+_1d9=false;
+_1da=key;
+}
+return _1d8;
+},arrayLikeIter:function(_1df){
+var i=0;
+return {repr:function(){
+return "arrayLikeIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+if(i>=_1df.length){
+throw MochiKit.Iter.StopIteration;
+}
+return _1df[i++];
+}};
+},hasIterateNext:function(_1e1){
+return (_1e1&&typeof (_1e1.iterateNext)=="function");
+},iterateNextIter:function(_1e2){
+return {repr:function(){
+return "iterateNextIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=_1e2.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;
+if(typeof (StopIteration)!="undefined"){
+this.StopIteration=StopIteration;
+}else{
+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.__export__){
+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.4";
+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,_1e6,info){
+this.num=num;
+this.level=_1e6;
+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(_1e9){
+var self=MochiKit.Logging;
+if(typeof (_1e9)=="string"){
+_1e9=self.LogLevel[_1e9];
+}
+return function(msg){
+var _1ec=msg.level;
+if(typeof (_1ec)=="string"){
+_1ec=self.LogLevel[_1ec];
+}
+return _1ec>=_1e9;
+};
+},isLogMessage:function(){
+var _1ed=MochiKit.Logging.LogMessage;
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof _1ed)){
+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(_1f2){
+this.counter=0;
+if(typeof (_1f2)=="undefined"||_1f2===null){
+_1f2=-1;
+}
+this.maxSize=_1f2;
+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.replace(/%/g,"\uff05"));
+}else{
+if(typeof (opera)!="undefined"&&opera.postError){
+opera.postError(msg);
+}else{
+if(typeof (printfire)=="function"){
+printfire(msg);
+}else{
+if(typeof (Debug)!="undefined"&&Debug.writeln){
+Debug.writeln(msg);
+}else{
+if(typeof (debug)!="undefined"&&debug.trace){
+debug.trace(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(_1f7,_1f8,_1f9){
+if(typeof (_1f8)=="string"){
+_1f8=MochiKit.Logging.logLevelAtLeast(_1f8);
+}
+var _1fa=[_1f8,_1f9];
+_1fa.ident=_1f7;
+this.listeners[_1f7]=_1fa;
+},removeListener:function(_1fb){
+delete this.listeners[_1fb];
+},baseLog:function(_1fc,_1fd){
+var msg=new MochiKit.Logging.LogMessage(this.counter,_1fc,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(_1ff){
+var _200=0;
+if(!(typeof (_1ff)=="undefined"||_1ff===null)){
+_200=Math.max(0,this._messages.length-_1ff);
+}
+return this._messages.slice(_200);
+},getMessageText:function(_201){
+if(typeof (_201)=="undefined"||_201===null){
+_201=30;
+}
+var _202=this.getMessages(_201);
+if(_202.length){
+var lst=map(function(m){
+return "\n  ["+m.num+"] "+m.level+": "+m.info.join(" ");
+},_202);
+lst.unshift("LAST "+_202.length+" MESSAGES:");
+return lst.join("");
+}
+return "";
+},debuggingBookmarklet:function(_205){
+if(typeof (MochiKit.LoggingPane)=="undefined"){
+alert(this.getMessageText());
+}else{
+MochiKit.LoggingPane.createLoggingPane(_205||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 _207=m.partial;
+var _208=this.Logger;
+var _209=_208.prototype.baseLog;
+m.update(this.Logger.prototype,{debug:_207(_209,"DEBUG"),log:_207(_209,"INFO"),error:_207(_209,"ERROR"),fatal:_207(_209,"FATAL"),warning:_207(_209,"WARNING")});
+var self=this;
+var _20b=function(name){
+return function(){
+self.logger[name].apply(self.logger,arguments);
+};
+};
+this.log=_20b("log");
+this.logError=_20b("error");
+this.logDebug=_20b("debug");
+this.logFatal=_20b("fatal");
+this.logWarning=_20b("warning");
+this.logger=new _208();
+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.4";
+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,_213,day,hour,min,sec,msec;
+year=parseInt(res[1],10);
+if(typeof (res[2])=="undefined"||res[2]===""){
+return new Date(year);
+}
+_213=parseInt(res[2],10)-1;
+day=parseInt(res[3],10);
+if(typeof (res[4])=="undefined"||res[4]===""){
+return new Date(year,_213,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,_213,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,_213,day,hour,min,sec,msec)-ofs);
+};
+MochiKit.DateTime.toISOTime=function(date,_21b){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var hh=date.getHours();
+var mm=date.getMinutes();
+var ss=date.getSeconds();
+var lst=[((_21b&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];
+return lst.join(":");
+};
+MochiKit.DateTime.toISOTimestamp=function(date,_221){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var sep=_221?"T":" ";
+var foot=_221?"Z":"";
+if(_221){
+date=new Date(date.getTime()+(date.getTimezoneOffset()*60000));
+}
+return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_221)+foot;
+};
+MochiKit.DateTime.toISODate=function(date){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var _225=MochiKit.DateTime._padTwo;
+return [date.getFullYear(),_225(date.getMonth()+1),_225(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 _22a=MochiKit.DateTime._padTwo;
+return [_22a(d.getMonth()+1),_22a(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(_22f,_230){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_230.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_22f[all[i]]=_230[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.4";
+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,_23a,_23b){
+return function(num){
+num=parseFloat(num);
+if(typeof (num)=="undefined"||num===null||isNaN(num)){
+return _233;
+}
+var _23d=_234;
+var _23e=_235;
+if(num<0){
+num=-num;
+}else{
+_23d=_23d.replace(/-/,"");
+}
+var me=arguments.callee;
+var fmt=MochiKit.Format.formatLocale(_236);
+if(_237){
+num=num*100;
+_23e=fmt.percent+_23e;
+}
+num=MochiKit.Format.roundToFixed(num,_238);
+var _241=num.split(/\./);
+var _242=_241[0];
+var frac=(_241.length==1)?"":_241[1];
+var res="";
+while(_242.length<_239){
+_242="0"+_242;
+}
+if(_23a){
+while(_242.length>_23a){
+var i=_242.length-_23a;
+res=fmt.separator+_242.substring(i,_242.length)+res;
+_242=_242.substring(0,i);
+}
+}
+res=_242+res;
+if(_238>0){
+while(frac.length<_23b){
+frac=frac+"0";
+}
+res=res+fmt.decimal+frac;
+}
+return _23d+res+_23e;
+};
+};
+MochiKit.Format.numberFormatter=function(_246,_247,_248){
+if(typeof (_247)=="undefined"){
+_247="";
+}
+var _249=_246.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
+if(!_249){
+throw TypeError("Invalid pattern");
+}
+var _24a=_246.substr(0,_249.index);
+var _24b=_246.substr(_249.index+_249[0].length);
+if(_24a.search(/-/)==-1){
+_24a=_24a+"-";
+}
+var _24c=_249[1];
+var frac=(typeof (_249[2])=="string"&&_249[2]!="")?_249[2]:"";
+var _24e=(typeof (_249[3])=="string"&&_249[3]!="");
+var tmp=_24c.split(/,/);
+var _250;
+if(typeof (_248)=="undefined"){
+_248="default";
+}
+if(tmp.length==1){
+_250=null;
+}else{
+_250=tmp[1].length;
+}
+var _251=_24c.length-_24c.replace(/0/g,"").length;
+var _252=frac.length-frac.replace(/0/g,"").length;
+var _253=frac.length;
+var rval=MochiKit.Format._numberFormatter(_247,_24a,_24b,_248,_24e,_253,_251,_250,_252);
+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(_258){
+if(typeof (_258)=="undefined"||_258===null){
+_258="default";
+}
+if(typeof (_258)=="string"){
+var rval=MochiKit.Format.LOCALE[_258];
+if(typeof (rval)=="string"){
+rval=arguments.callee(rval);
+MochiKit.Format.LOCALE[_258]=rval;
+}
+return rval;
+}else{
+return _258;
+}
+};
+MochiKit.Format.twoDigitAverage=function(_25a,_25b){
+if(_25b){
+var res=_25a/_25b;
+if(!isNaN(res)){
+return MochiKit.Format.twoDigitFloat(_25a/_25b);
+}
+}
+return "0";
+};
+MochiKit.Format.twoDigitFloat=function(_25d){
+var sign=(_25d<0?"-":"");
+var s=Math.floor(Math.abs(_25d)*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,_263){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_263){
+return str.replace(/^\s+/,"");
+}else{
+return str.replace(new RegExp("^["+_263+"]+"),"");
+}
+};
+MochiKit.Format.rstrip=function(str,_265){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_265){
+return str.replace(/\s+$/,"");
+}else{
+return str.replace(new RegExp("["+_265+"]+$"),"");
+}
+};
+MochiKit.Format.strip=function(str,_267){
+var self=MochiKit.Format;
+return self.rstrip(self.lstrip(str,_267),_267);
+};
+MochiKit.Format.truncToFixed=function(_269,_26a){
+_269=Math.floor(_269*Math.pow(10,_26a));
+var res=(_269*Math.pow(10,-_26a)).toFixed(_26a);
+if(res.charAt(0)=="."){
+res="0"+res;
+}
+return res;
+};
+MochiKit.Format.roundToFixed=function(_26c,_26d){
+return MochiKit.Format.truncToFixed(_26c+0.5*Math.pow(10,-_26d),_26d);
+};
+MochiKit.Format.percentFormat=function(_26e){
+return MochiKit.Format.twoDigitFloat(100*_26e)+"%";
+};
+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(_273,_274){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_274.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_273[all[i]]=_274[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.4";
+MochiKit.Async.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Async.toString=function(){
+return this.__repr__();
+};
+MochiKit.Async.Deferred=function(_277){
+this.chain=[];
+this.id=this._nextId();
+this.fired=-1;
+this.paused=0;
+this.results=[null,null];
+this.canceller=_277;
+this.silentlyCancelled=false;
+this.chained=false;
+};
+MochiKit.Async.Deferred.prototype={repr:function(){
+var _278;
+if(this.fired==-1){
+_278="unfired";
+}else{
+if(this.fired===0){
+_278="success";
+}else{
+_278="error";
+}
+}
+return "Deferred("+this.id+", "+_278+")";
+},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();
+}
+}
+},_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 _283=this.chain;
+var _284=this.fired;
+var res=this.results[_284];
+var self=this;
+var cb=null;
+while(_283.length>0&&this.paused===0){
+var pair=_283.shift();
+var f=pair[_284];
+if(f===null){
+continue;
+}
+try{
+res=f(res);
+_284=((res instanceof Error)?1:0);
+if(res instanceof MochiKit.Async.Deferred){
+cb=function(res){
+self._resback(res);
+self.paused--;
+if((self.paused===0)&&(self.fired>=0)){
+self._fire();
+}
+};
+this.paused++;
+}
+}
+catch(err){
+_284=1;
+if(!(err instanceof Error)){
+err=new MochiKit.Async.GenericError(err);
+}
+res=err;
+}
+}
+this.fired=_284;
+this.results[_284]=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(_28b){
+var d=new MochiKit.Async.Deferred();
+d.callback.apply(d,arguments);
+return d;
+},fail:function(_28d){
+var d=new MochiKit.Async.Deferred();
+d.errback.apply(d,arguments);
+return d;
+},getXMLHttpRequest:function(){
+var self=arguments.callee;
+if(!self.XMLHttpRequest){
+var _290=[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<_290.length;i++){
+var func=_290[i];
+try{
+self.XMLHttpRequest=func;
+return func();
+}
+catch(e){
+}
+}
+}
+return self.XMLHttpRequest();
+},_xhr_onreadystatechange:function(d){
+var m=MochiKit.Base;
+if(this.readyState==4){
+try{
+this.onreadystatechange=null;
+}
+catch(e){
+try{
+this.onreadystatechange=m.noop;
+}
+catch(e){
+}
+}
+var _295=null;
+try{
+_295=this.status;
+if(!_295&&m.isNotEmpty(this.responseText)){
+_295=304;
+}
+}
+catch(e){
+}
+if(_295==200||_295==201||_295==204||_295==304||_295==1223){
+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.Base.noop;
+}
+catch(e){
+}
+}
+req.abort();
+},sendXMLHttpRequest:function(req,_299){
+if(typeof (_299)=="undefined"||_299===null){
+_299="";
+}
+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(_299);
+}
+catch(e){
+try{
+req.onreadystatechange=null;
+}
+catch(ignore){
+}
+d.errback(e);
+}
+return d;
+},doXHR:function(url,opts){
+var self=MochiKit.Async;
+return self.callLater(0,self._doXHR,url,opts);
+},_doXHR:function(url,opts){
+var m=MochiKit.Base;
+opts=m.update({method:"GET",sendContent:""},opts);
+var self=MochiKit.Async;
+var req=self.getXMLHttpRequest();
+if(opts.queryString){
+var qs=m.queryString(opts.queryString);
+if(qs){
+url+="?"+qs;
+}
+}
+if("username" in opts){
+req.open(opts.method,url,true,opts.username,opts.password);
+}else{
+req.open(opts.method,url,true);
+}
+if(req.overrideMimeType&&opts.mimeType){
+req.overrideMimeType(opts.mimeType);
+}
+if(opts.headers){
+var _2a6=opts.headers;
+if(!m.isArrayLike(_2a6)){
+_2a6=m.items(_2a6);
+}
+for(var i=0;i<_2a6.length;i++){
+var _2a8=_2a6[i];
+var name=_2a8[0];
+var _2aa=_2a8[1];
+req.setRequestHeader(name,_2aa);
+}
+}
+return self.sendXMLHttpRequest(req,opts.sendContent);
+},_buildURL:function(url){
+if(arguments.length>1){
+var m=MochiKit.Base;
+var qs=m.queryString.apply(null,m.extend(null,arguments,1));
+if(qs){
+return url+"?"+qs;
+}
+}
+return url;
+},doSimpleXMLHttpRequest:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+return self.doXHR(url);
+},loadJSONDoc:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+var d=self.doXHR(url,{"mimeType":"text/plain","headers":[["Accept","application/json"]]});
+d=d.addCallback(self.evalJSONRequest);
+return d;
+},wait:function(_2b3,_2b4){
+var d=new MochiKit.Async.Deferred();
+var m=MochiKit.Base;
+if(typeof (_2b4)!="undefined"){
+d.addCallback(function(){
+return _2b4;
+});
+}
+var _2b7=setTimeout(m.bind("callback",d),Math.floor(_2b3*1000));
+d.canceller=function(){
+try{
+clearTimeout(_2b7);
+}
+catch(e){
+}
+};
+return d;
+},callLater:function(_2b8,func){
+var m=MochiKit.Base;
+var _2bb=m.partial.apply(m,m.extend(null,arguments,1));
+return MochiKit.Async.wait(_2b8).addCallback(function(res){
+return _2bb();
+});
+}});
+MochiKit.Async.DeferredLock=function(){
+this.waiting=[];
+this.locked=false;
+this.id=this._nextId();
+};
+MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){
+var 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 _2be;
+if(this.locked){
+_2be="locked, "+this.waiting.length+" waiting";
+}else{
+_2be="unlocked";
+}
+return "DeferredLock("+this.id+", "+_2be+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Async.DeferredList=function(list,_2c0,_2c1,_2c2,_2c3){
+MochiKit.Async.Deferred.apply(this,[_2c3]);
+this.list=list;
+var _2c4=[];
+this.resultList=_2c4;
+this.finishedCount=0;
+this.fireOnOneCallback=_2c0;
+this.fireOnOneErrback=_2c1;
+this.consumeErrors=_2c2;
+var cb=MochiKit.Base.bind(this._cbDeferred,this);
+for(var i=0;i<list.length;i++){
+var d=list[i];
+_2c4.push(undefined);
+d.addCallback(cb,i,true);
+d.addErrback(cb,i,false);
+}
+if(list.length===0&&!_2c0){
+this.callback(this.resultList);
+}
+};
+MochiKit.Async.DeferredList.prototype=new MochiKit.Async.Deferred();
+MochiKit.Async.DeferredList.prototype._cbDeferred=function(_2c8,_2c9,_2ca){
+this.resultList[_2c8]=[_2c9,_2ca];
+this.finishedCount+=1;
+if(this.fired==-1){
+if(_2c9&&this.fireOnOneCallback){
+this.callback([_2c8,_2ca]);
+}else{
+if(!_2c9&&this.fireOnOneErrback){
+this.errback(_2ca);
+}else{
+if(this.finishedCount==this.list.length){
+this.callback(this.resultList);
+}
+}
+}
+}
+if(!_2c9&&this.consumeErrors){
+_2ca=null;
+}
+return _2ca;
+};
+MochiKit.Async.gatherResults=function(_2cb){
+var d=new MochiKit.Async.DeferredList(_2cb,false,true,false);
+d.addCallback(function(_2cd){
+var ret=[];
+for(var i=0;i<_2cd.length;i++){
+ret.push(_2cd[i][1]);
+}
+return ret;
+});
+return d;
+};
+MochiKit.Async.maybeDeferred=function(func){
+var self=MochiKit.Async;
+var _2d2;
+try{
+var r=func.apply(null,MochiKit.Base.extend([],arguments,1));
+if(r instanceof self.Deferred){
+_2d2=r;
+}else{
+if(r instanceof Error){
+_2d2=self.fail(r);
+}else{
+_2d2=self.succeed(r);
+}
+}
+}
+catch(e){
+_2d2=self.fail(e);
+}
+return _2d2;
+};
+MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred","doXHR"];
+MochiKit.Async.EXPORT_OK=["evalJSONRequest"];
+MochiKit.Async.__new__=function(){
+var m=MochiKit.Base;
+var ne=m.partial(m._newNamedError,this);
+ne("AlreadyCalledError",function(_2d6){
+this.deferred=_2d6;
+});
+ne("CancelledError",function(_2d7){
+this.deferred=_2d7;
+});
+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.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.DOM depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.DOM)=="undefined"){
+MochiKit.DOM={};
+}
+MochiKit.DOM.NAME="MochiKit.DOM";
+MochiKit.DOM.VERSION="1.4";
+MochiKit.DOM.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DOM.toString=function(){
+return this.__repr__();
+};
+MochiKit.DOM.EXPORT=["removeEmptyTextNodes","formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","isChildNode","getNodeAttribute","removeNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","insertSiblingNodesAfter","insertSiblingNodesBefore","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","$","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","escapeHTML","toHTML","emitHTML","scrapeText","isParent","getFirstParentByTagAndClassName","makeClipping","undoClipping","makePositioned","undoPositioned","getFirstElementByTagAndClassName"];
+MochiKit.DOM.EXPORT_OK=["domConverters"];
+MochiKit.DOM.DEPRECATED=[["computedStyle","MochiKit.Style.getStyle","1.4"],["elementDimensions","MochiKit.Style.getElementDimensions","1.4"],["elementPosition","MochiKit.Style.getElementPosition","1.4"],["hideElement","MochiKit.Style.hideElement","1.4"],["setElementDimensions","MochiKit.Style.setElementDimensions","1.4"],["setElementPosition","MochiKit.Style.setElementPosition","1.4"],["setDisplayForElement","MochiKit.Style.setDisplayForElement","1.4"],["setOpacity","MochiKit.Style.setOpacity","1.4"],["showElement","MochiKit.Style.showElement","1.4"],["Coordinates","MochiKit.Style.Coordinates","1.4"],["Dimensions","MochiKit.Style.Dimensions","1.4"]];
+MochiKit.DOM.getViewportDimensions=new Function(""+"if (!MochiKit[\"Style\"]) {"+"    throw new Error(\"This function has been deprecated and depends on MochiKit.Style.\");"+"}"+"return MochiKit.Style.getViewportDimensions.apply(this, arguments);");
+MochiKit.Base.update(MochiKit.DOM,{currentWindow:function(){
+return MochiKit.DOM._window;
+},currentDocument:function(){
+return MochiKit.DOM._document;
+},withWindow:function(win,func){
+var self=MochiKit.DOM;
+var _2df=self._document;
+var _2e0=self._window;
+var rval;
+try{
+self._window=win;
+self._document=win.document;
+rval=func();
+}
+catch(e){
+self._window=_2e0;
+self._document=_2df;
+throw e;
+}
+self._window=_2e0;
+self._document=_2df;
+return rval;
+},formContents:function(elem){
+var _2e3=[];
+var _2e4=[];
+var m=MochiKit.Base;
+var self=MochiKit.DOM;
+if(typeof (elem)=="undefined"||elem===null){
+elem=self._document.body;
+}else{
+elem=self.getElement(elem);
+}
+m.nodeWalk(elem,function(elem){
+var name=elem.name;
+if(m.isNotEmpty(name)){
+var _2e9=elem.tagName.toUpperCase();
+if(_2e9==="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){
+return null;
+}
+if(_2e9==="SELECT"){
+if(elem.type=="select-one"){
+if(elem.selectedIndex>=0){
+var opt=elem.options[elem.selectedIndex];
+var v=opt.value;
+if(!v){
+var h=opt.outerHTML;
+if(h&&!h.match(/^[^>]+\svalue\s*=/i)){
+v=opt.text;
+}
+}
+_2e3.push(name);
+_2e4.push(v);
+return null;
+}
+_2e3.push(name);
+_2e4.push("");
+return null;
+}else{
+var opts=elem.options;
+if(!opts.length){
+_2e3.push(name);
+_2e4.push("");
+return null;
+}
+for(var i=0;i<opts.length;i++){
+var opt=opts[i];
+if(!opt.selected){
+continue;
+}
+var v=opt.value;
+if(!v){
+var h=opt.outerHTML;
+if(h&&!h.match(/^[^>]+\svalue\s*=/i)){
+v=opt.text;
+}
+}
+_2e3.push(name);
+_2e4.push(v);
+}
+return null;
+}
+}
+if(_2e9==="FORM"||_2e9==="P"||_2e9==="SPAN"||_2e9==="DIV"){
+return elem.childNodes;
+}
+_2e3.push(name);
+_2e4.push(elem.value||"");
+return null;
+}
+return elem.childNodes;
+});
+return [_2e3,_2e4];
+},withDocument:function(doc,func){
+var self=MochiKit.DOM;
+var _2f2=self._document;
+var rval;
+try{
+self._document=doc;
+rval=func();
+}
+catch(e){
+self._document=_2f2;
+throw e;
+}
+self._document=_2f2;
+return rval;
+},registerDOMConverter:function(name,_2f5,wrap,_2f7){
+MochiKit.DOM.domConverters.register(name,_2f5,wrap,_2f7);
+},coerceToDOM:function(node,ctx){
+var m=MochiKit.Base;
+var im=MochiKit.Iter;
+var self=MochiKit.DOM;
+if(im){
+var iter=im.iter;
+var _2fe=im.repeat;
+var map=m.map;
+}
+var _300=self.domConverters;
+var _301=arguments.callee;
+var _302=m.NotFound;
+while(true){
+if(typeof (node)=="undefined"||node===null){
+return null;
+}
+if(typeof (node)=="function"&&typeof (node.length)=="number"&&!(node instanceof Function)){
+node=im.list(node);
+}
+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.__dom__)=="function"){
+node=node.__dom__(ctx);
+continue;
+}
+if(typeof (node.dom)=="function"){
+node=node.dom(ctx);
+continue;
+}
+if(typeof (node)=="function"){
+node=node.apply(ctx,[ctx]);
+continue;
+}
+if(im){
+var _303=null;
+try{
+_303=iter(node);
+}
+catch(e){
+}
+if(_303){
+return map(_301,_303,_2fe(ctx));
+}
+}
+try{
+node=_300.match(node,ctx);
+continue;
+}
+catch(e){
+if(e!=_302){
+throw e;
+}
+}
+return self._document.createTextNode(node.toString());
+}
+return undefined;
+},isChildNode:function(node,_305){
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+node=self.getElement(node);
+}
+if(typeof (_305)=="string"){
+_305=self.getElement(_305);
+}
+if(node===_305){
+return true;
+}
+while(node&&node.tagName.toUpperCase()!="BODY"){
+node=node.parentNode;
+if(node===_305){
+return true;
+}
+}
+return false;
+},setNodeAttribute:function(node,attr,_309){
+var o={};
+o[attr]=_309;
+try{
+return MochiKit.DOM.updateNodeAttributes(node,o);
+}
+catch(e){
+}
+return null;
+},getNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _30e=self.attributeArray.renames[attr];
+node=self.getElement(node);
+try{
+if(_30e){
+return node[_30e];
+}
+return node.getAttribute(attr);
+}
+catch(e){
+}
+return null;
+},removeNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _312=self.attributeArray.renames[attr];
+node=self.getElement(node);
+try{
+if(_312){
+return node[_312];
+}
+return node.removeAttribute(attr);
+}
+catch(e){
+}
+return null;
+},updateNodeAttributes:function(node,_314){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+if(_314){
+var _317=MochiKit.Base.updatetree;
+if(self.attributeArray.compliant){
+for(var k in _314){
+var v=_314[k];
+if(typeof (v)=="object"&&typeof (elem[k])=="object"){
+if(k=="style"&&MochiKit.Style){
+MochiKit.Style.setStyle(elem,v);
+}else{
+_317(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 _31a=self.attributeArray.renames;
+for(var k in _314){
+v=_314[k];
+var _31b=_31a[k];
+if(k=="style"&&typeof (v)=="string"){
+elem.style.cssText=v;
+}else{
+if(typeof (_31b)=="string"){
+elem[_31b]=v;
+}else{
+if(typeof (elem[k])=="object"&&typeof (v)=="object"){
+if(k=="style"&&MochiKit.Style){
+MochiKit.Style.setStyle(elem,v);
+}else{
+_317(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 _31f=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _320=MochiKit.Base.concat;
+while(_31f.length){
+var n=_31f.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+elem.appendChild(n);
+}else{
+_31f=_320(n,_31f);
+}
+}
+}
+return elem;
+},insertSiblingNodesBefore:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _325=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _326=elem.parentNode;
+var _327=MochiKit.Base.concat;
+while(_325.length){
+var n=_325.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+_326.insertBefore(n,elem);
+}else{
+_325=_327(n,_325);
+}
+}
+}
+return _326;
+},insertSiblingNodesAfter:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _32c=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+if(elem.nextSibling){
+return self.insertSiblingNodesBefore(elem.nextSibling,_32c);
+}else{
+return self.appendChildNodes(elem.parentNode,_32c);
+}
+},replaceChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+arguments[0]=elem;
+}
+var _330;
+while((_330=elem.firstChild)){
+elem.removeChild(_330);
+}
+if(arguments.length<2){
+return elem;
+}else{
+return self.appendChildNodes.apply(this,arguments);
+}
+},createDOM:function(name,_332){
+var elem;
+var self=MochiKit.DOM;
+var m=MochiKit.Base;
+if(typeof (_332)=="string"||typeof (_332)=="number"){
+var args=m.extend([name,null],arguments,1);
+return arguments.callee.apply(this,args);
+}
+if(typeof (name)=="string"){
+var _337=self._xhtml;
+if(_332&&!self.attributeArray.compliant){
+var _338="";
+if("name" in _332){
+_338+=" name=\""+self.escapeHTML(_332.name)+"\"";
+}
+if(name=="input"&&"type" in _332){
+_338+=" type=\""+self.escapeHTML(_332.type)+"\"";
+}
+if(_338){
+name="<"+name+_338+">";
+_337=false;
+}
+}
+var d=self._document;
+if(_337&&d===document){
+elem=d.createElementNS("http://www.w3.org/1999/xhtml",name);
+}else{
+elem=d.createElement(name);
+}
+}else{
+elem=name;
+}
+if(_332){
+self.updateNodeAttributes(elem,_332);
+}
+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));
+},removeElement:function(elem){
+var e=MochiKit.DOM.getElement(elem);
+e.parentNode.removeChild(e);
+return e;
+},swapDOM:function(dest,src){
+var self=MochiKit.DOM;
+dest=self.getElement(dest);
+var _340=dest.parentNode;
+if(src){
+src=self.getElement(src);
+_340.replaceChild(src,dest);
+}else{
+_340.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);
+}
+},getElementsByTagAndClassName:function(_343,_344,_345){
+var self=MochiKit.DOM;
+if(typeof (_343)=="undefined"||_343===null){
+_343="*";
+}
+if(typeof (_345)=="undefined"||_345===null){
+_345=self._document;
+}
+_345=self.getElement(_345);
+var _347=(_345.getElementsByTagName(_343)||self._document.all);
+if(typeof (_344)=="undefined"||_344===null){
+return MochiKit.Base.extend(null,_347);
+}
+var _348=[];
+for(var i=0;i<_347.length;i++){
+var _34a=_347[i];
+var cls=_34a.className;
+if(!cls){
+continue;
+}
+var _34c=cls.split(" ");
+for(var j=0;j<_34c.length;j++){
+if(_34c[j]==_344){
+_348.push(_34a);
+break;
+}
+}
+}
+return _348;
+},_newCallStack:function(path,once){
+var rval=function(){
+var _351=arguments.callee.callStack;
+for(var i=0;i<_351.length;i++){
+if(_351[i].apply(this,arguments)===false){
+break;
+}
+}
+if(once){
+try{
+this[path]=null;
+}
+catch(e){
+}
+}
+};
+rval.callStack=[];
+return rval;
+},addToCallStack:function(_353,path,func,once){
+var self=MochiKit.DOM;
+var _358=_353[path];
+var _359=_358;
+if(!(typeof (_358)=="function"&&typeof (_358.callStack)=="object"&&_358.callStack!==null)){
+_359=self._newCallStack(path,once);
+if(typeof (_358)=="function"){
+_359.callStack.push(_358);
+}
+_353[path]=_359;
+}
+_359.callStack.push(func);
+},addLoadEvent:function(func){
+var self=MochiKit.DOM;
+self.addToCallStack(self._window,"onload",func,true);
+},focusOnLoad:function(_35c){
+var self=MochiKit.DOM;
+self.addLoadEvent(function(){
+_35c=self.getElement(_35c);
+if(_35c){
+_35c.focus();
+}
+});
+},setElementClass:function(_35e,_35f){
+var self=MochiKit.DOM;
+var obj=self.getElement(_35e);
+if(self.attributeArray.compliant){
+obj.setAttribute("class",_35f);
+}else{
+obj.setAttribute("className",_35f);
+}
+},toggleElementClass:function(_362){
+var self=MochiKit.DOM;
+for(var i=1;i<arguments.length;i++){
+var obj=self.getElement(arguments[i]);
+if(!self.addElementClass(obj,_362)){
+self.removeElementClass(obj,_362);
+}
+}
+},addElementClass:function(_366,_367){
+var self=MochiKit.DOM;
+var obj=self.getElement(_366);
+var cls=obj.className;
+if(cls==undefined||cls.length===0){
+self.setElementClass(obj,_367);
+return true;
+}
+if(cls==_367){
+return false;
+}
+var _36b=cls.split(" ");
+for(var i=0;i<_36b.length;i++){
+if(_36b[i]==_367){
+return false;
+}
+}
+self.setElementClass(obj,cls+" "+_367);
+return true;
+},removeElementClass:function(_36d,_36e){
+var self=MochiKit.DOM;
+var obj=self.getElement(_36d);
+var cls=obj.className;
+if(cls==undefined||cls.length===0){
+return false;
+}
+if(cls==_36e){
+self.setElementClass(obj,"");
+return true;
+}
+var _372=cls.split(" ");
+for(var i=0;i<_372.length;i++){
+if(_372[i]==_36e){
+_372.splice(i,1);
+self.setElementClass(obj,_372.join(" "));
+return true;
+}
+}
+return false;
+},swapElementClass:function(_374,_375,_376){
+var obj=MochiKit.DOM.getElement(_374);
+var res=MochiKit.DOM.removeElementClass(obj,_375);
+if(res){
+MochiKit.DOM.addElementClass(obj,_376);
+}
+return res;
+},hasElementClass:function(_379,_37a){
+var obj=MochiKit.DOM.getElement(_379);
+var cls=obj.className;
+if(!cls){
+return false;
+}
+var _37d=cls.split(" ");
+for(var i=1;i<arguments.length;i++){
+var good=false;
+for(var j=0;j<_37d.length;j++){
+if(_37d[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 _385=[dom];
+var self=MochiKit.DOM;
+var _387=self.escapeHTML;
+var _388=self.attributeArray;
+while(_385.length){
+dom=_385.pop();
+if(typeof (dom)=="string"){
+lst.push(dom);
+}else{
+if(dom.nodeType==1){
+lst.push("<"+dom.tagName.toLowerCase());
+var _389=[];
+var _38a=_388(dom);
+for(var i=0;i<_38a.length;i++){
+var a=_38a[i];
+_389.push([" ",a.name,"=\"",_387(a.value),"\""]);
+}
+_389.sort();
+for(i=0;i<_389.length;i++){
+var _38d=_389[i];
+for(var j=0;j<_38d.length;j++){
+lst.push(_38d[j]);
+}
+}
+if(dom.hasChildNodes()){
+lst.push(">");
+_385.push("</"+dom.tagName.toLowerCase()+">");
+var _38f=dom.childNodes;
+for(i=_38f.length-1;i>=0;i--){
+_385.push(_38f[i]);
+}
+}else{
+lst.push("/>");
+}
+}else{
+if(dom.nodeType==3){
+lst.push(_387(dom.nodeValue));
+}
+}
+}
+}
+return lst;
+},scrapeText:function(node,_391){
+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 _396=node.nodeValue;
+if(typeof (_396)=="string"){
+rval.push(_396);
+}
+})(MochiKit.DOM.getElement(node));
+if(_391){
+return rval;
+}else{
+return rval.join("");
+}
+},removeEmptyTextNodes:function(_397){
+_397=MochiKit.DOM.getElement(_397);
+for(var i=0;i<_397.childNodes.length;i++){
+var node=_397.childNodes[i];
+if(node.nodeType==3&&!/\S/.test(node.nodeValue)){
+node.parentNode.removeChild(node);
+}
+}
+},makeClipping:function(_39a){
+_39a=MochiKit.DOM.getElement(_39a);
+var _39b=_39a.style.overflow;
+if((MochiKit.Style.getStyle(_39a,"overflow")||"visible")!="hidden"){
+_39a.style.overflow="hidden";
+}
+return _39b;
+},undoClipping:function(_39c,_39d){
+_39c=MochiKit.DOM.getElement(_39c);
+if(!_39d){
+return;
+}
+_39c.style.overflow=_39d;
+},makePositioned:function(_39e){
+_39e=MochiKit.DOM.getElement(_39e);
+var pos=MochiKit.Style.getStyle(_39e,"position");
+if(pos=="static"||!pos){
+_39e.style.position="relative";
+if(/Opera/.test(navigator.userAgent)){
+_39e.style.top=0;
+_39e.style.left=0;
+}
+}
+},undoPositioned:function(_3a0){
+_3a0=MochiKit.DOM.getElement(_3a0);
+if(_3a0.style.position=="relative"){
+_3a0.style.position=_3a0.style.top=_3a0.style.left=_3a0.style.bottom=_3a0.style.right="";
+}
+},getFirstElementByTagAndClassName:function(_3a1,_3a2,_3a3){
+var self=MochiKit.DOM;
+if(typeof (_3a1)=="undefined"||_3a1===null){
+_3a1="*";
+}
+if(typeof (_3a3)=="undefined"||_3a3===null){
+_3a3=self._document;
+}
+_3a3=self.getElement(_3a3);
+var _3a5=(_3a3.getElementsByTagName(_3a1)||self._document.all);
+if(typeof (_3a2)=="undefined"||_3a2===null){
+return _3a5[0];
+}
+for(var i=0;i<_3a5.length;i++){
+var _3a7=_3a5[i];
+var _3a8=_3a7.className.split(" ");
+for(var j=0;j<_3a8.length;j++){
+if(_3a8[j]==_3a2){
+return _3a7;
+}
+}
+}
+},getFirstParentByTagAndClassName:function(elem,_3ab,_3ac){
+var self=MochiKit.DOM;
+elem=self.getElement(elem);
+if(typeof (_3ab)=="undefined"||_3ab===null){
+_3ab="*";
+}else{
+_3ab=_3ab.toUpperCase();
+}
+if(typeof (_3ac)=="undefined"||_3ac===null){
+_3ac=null;
+}
+var _3ae="";
+var _3af="";
+while(elem&&elem.tagName){
+elem=elem.parentNode;
+if(_3ab=="*"&&_3ac===null){
+return elem;
+}
+_3ae=elem.className.split(" ");
+_3af=elem.tagName.toUpperCase();
+if(_3ac===null&&_3ab==_3af){
+return elem;
+}else{
+if(_3ac!==null){
+for(var i=0;i<_3ae.length;i++){
+if(_3ab=="*"&&_3ae[i]==_3ac){
+return elem;
+}else{
+if(_3ab==_3af&&_3ae[i]==_3ac){
+return elem;
+}
+}
+}
+}
+}
+}
+return elem;
+},isParent:function(_3b1,_3b2){
+if(!_3b1.parentNode||_3b1==_3b2){
+return false;
+}
+if(_3b1.parentNode==_3b2){
+return true;
+}
+return MochiKit.DOM.isParent(_3b1.parentNode,_3b2);
+},__new__:function(win){
+var m=MochiKit.Base;
+if(typeof (document)!="undefined"){
+this._document=document;
+var _3b5="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+this._xhtml=(document.documentElement&&document.createElementNS&&document.documentElement.namespaceURI===_3b5);
+}else{
+if(MochiKit.MockDOM){
+this._document=MochiKit.MockDOM.document;
+}
+}
+this._window=win;
+this.domConverters=new m.AdapterRegistry();
+var _3b6=this._document.createElement("span");
+var _3b7;
+if(_3b6&&_3b6.attributes&&_3b6.attributes.length>0){
+var _3b8=m.filter;
+_3b7=function(node){
+return _3b8(_3b7.ignoreAttrFilter,node.attributes);
+};
+_3b7.ignoreAttr={};
+var _3ba=_3b6.attributes;
+var _3bb=_3b7.ignoreAttr;
+for(var i=0;i<_3ba.length;i++){
+var a=_3ba[i];
+_3bb[a.name]=a.value;
+}
+_3b7.ignoreAttrFilter=function(a){
+return (_3b7.ignoreAttr[a.name]!=a.value);
+};
+_3b7.compliant=false;
+_3b7.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor","readonly":"readOnly","colspan":"colSpan","bgcolor":"bgColor","cellspacing":"cellSpacing","cellpadding":"cellPadding"};
+}else{
+_3b7=function(node){
+return node.attributes;
+};
+_3b7.compliant=true;
+_3b7.renames={};
+}
+this.attributeArray=_3b7;
+var _3c0=function(_3c1,arr){
+var _3c3=arr[1].split(".");
+var str="";
+var obj={};
+str+="if (!MochiKit."+_3c3[1]+") { throw new Error(\"";
+str+="This function has been deprecated and depends on MochiKit.";
+str+=_3c3[1]+".\");}";
+str+="return MochiKit."+_3c3[1]+"."+arr[0];
+str+=".apply(this, arguments);";
+obj[_3c3[2]]=new Function(str);
+MochiKit.Base.update(MochiKit[_3c1],obj);
+};
+for(var i;i<MochiKit.DOM.DEPRECATED.length;i++){
+_3c0("DOM",MochiKit.DOM.DEPRECATED[i]);
+}
+var _3c6=this.createDOMFunc;
+this.UL=_3c6("ul");
+this.OL=_3c6("ol");
+this.LI=_3c6("li");
+this.TD=_3c6("td");
+this.TR=_3c6("tr");
+this.TBODY=_3c6("tbody");
+this.THEAD=_3c6("thead");
+this.TFOOT=_3c6("tfoot");
+this.TABLE=_3c6("table");
+this.TH=_3c6("th");
+this.INPUT=_3c6("input");
+this.SPAN=_3c6("span");
+this.A=_3c6("a");
+this.DIV=_3c6("div");
+this.IMG=_3c6("img");
+this.BUTTON=_3c6("button");
+this.TT=_3c6("tt");
+this.PRE=_3c6("pre");
+this.H1=_3c6("h1");
+this.H2=_3c6("h2");
+this.H3=_3c6("h3");
+this.BR=_3c6("br");
+this.HR=_3c6("hr");
+this.LABEL=_3c6("label");
+this.TEXTAREA=_3c6("textarea");
+this.FORM=_3c6("form");
+this.P=_3c6("p");
+this.SELECT=_3c6("select");
+this.OPTION=_3c6("option");
+this.OPTGROUP=_3c6("optgroup");
+this.LEGEND=_3c6("legend");
+this.FIELDSET=_3c6("fieldset");
+this.STRONG=_3c6("strong");
+this.CANVAS=_3c6("canvas");
+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.__export__){
+withWindow=MochiKit.DOM.withWindow;
+withDocument=MochiKit.DOM.withDocument;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.DOM);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Selector");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Iter");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Iter",[]);
+}
+try{
+if(typeof (MochiKit.Base)==="undefined"||typeof (MochiKit.DOM)==="undefined"||typeof (MochiKit.Iter)==="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Selector depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
+}
+if(typeof (MochiKit.Selector)=="undefined"){
+MochiKit.Selector={};
+}
+MochiKit.Selector.NAME="MochiKit.Selector";
+MochiKit.Selector.VERSION="1.4";
+MochiKit.Selector.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Selector.toString=function(){
+return this.__repr__();
+};
+MochiKit.Selector.EXPORT=["Selector","findChildElements","findDocElements","$$"];
+MochiKit.Selector.EXPORT_OK=[];
+MochiKit.Selector.Selector=function(_3c7){
+this.params={classNames:[],pseudoClassNames:[]};
+this.expression=_3c7.toString().replace(/(^\s+|\s+$)/g,"");
+this.parseExpression();
+this.compileMatcher();
+};
+MochiKit.Selector.Selector.prototype={__class__:MochiKit.Selector.Selector,parseExpression:function(){
+function abort(_3c8){
+throw "Parse error in selector: "+_3c8;
+}
+if(this.expression==""){
+abort("empty expression");
+}
+var repr=MochiKit.Base.repr;
+var _3ca=this.params;
+var expr=this.expression;
+var _3cc,_3cd,_3ce,rest;
+while(_3cc=expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)){
+_3ca.attributes=_3ca.attributes||[];
+_3ca.attributes.push({name:_3cc[2],operator:_3cc[3],value:_3cc[4]||_3cc[5]||""});
+expr=_3cc[1];
+}
+if(expr=="*"){
+return this.params.wildcard=true;
+}
+while(_3cc=expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)){
+_3cd=_3cc[1];
+_3ce=_3cc[2];
+rest=_3cc[3];
+switch(_3cd){
+case "#":
+_3ca.id=_3ce;
+break;
+case ".":
+_3ca.classNames.push(_3ce);
+break;
+case ":":
+_3ca.pseudoClassNames.push(_3ce);
+break;
+case "":
+case undefined:
+_3ca.tagName=_3ce.toUpperCase();
+break;
+default:
+abort(repr(expr));
+}
+expr=rest;
+}
+if(expr.length>0){
+abort(repr(expr));
+}
+},buildMatchExpression:function(){
+var repr=MochiKit.Base.repr;
+var _3d1=this.params;
+var _3d2=[];
+var _3d3,i;
+function childElements(_3d5){
+return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, "+_3d5+".childNodes)";
+}
+if(_3d1.wildcard){
+_3d2.push("true");
+}
+if(_3d3=_3d1.id){
+_3d2.push("element.id == "+repr(_3d3));
+}
+if(_3d3=_3d1.tagName){
+_3d2.push("element.tagName.toUpperCase() == "+repr(_3d3));
+}
+if((_3d3=_3d1.classNames).length>0){
+for(i=0;i<_3d3.length;i++){
+_3d2.push("MochiKit.DOM.hasElementClass(element, "+repr(_3d3[i])+")");
+}
+}
+if((_3d3=_3d1.pseudoClassNames).length>0){
+for(i=0;i<_3d3.length;i++){
+var _3d6=_3d3[i].match(/^([^(]+)(?:\((.*)\))?$/);
+var _3d7=_3d6[1];
+var _3d8=_3d6[2];
+switch(_3d7){
+case "root":
+_3d2.push("element.nodeType == 9 || element === element.ownerDocument.documentElement");
+break;
+case "nth-child":
+case "nth-last-child":
+case "nth-of-type":
+case "nth-last-of-type":
+_3d6=_3d8.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
+if(!_3d6){
+throw "Invalid argument to pseudo element nth-child: "+_3d8;
+}
+var a,b;
+if(_3d6[0]=="odd"){
+a=2;
+b=1;
+}else{
+if(_3d6[0]=="even"){
+a=2;
+b=0;
+}else{
+a=_3d6[2]&&parseInt(_3d6)||null;
+b=parseInt(_3d6[3]);
+}
+}
+_3d2.push("this.nthChild(element,"+a+","+b+","+!!_3d7.match("^nth-last")+","+!!_3d7.match("of-type$")+")");
+break;
+case "first-child":
+_3d2.push("this.nthChild(element, null, 1)");
+break;
+case "last-child":
+_3d2.push("this.nthChild(element, null, 1, true)");
+break;
+case "first-of-type":
+_3d2.push("this.nthChild(element, null, 1, false, true)");
+break;
+case "last-of-type":
+_3d2.push("this.nthChild(element, null, 1, true, true)");
+break;
+case "only-child":
+_3d2.push(childElements("element.parentNode")+".length == 1");
+break;
+case "only-of-type":
+_3d2.push("MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, "+childElements("element.parentNode")+").length == 1");
+break;
+case "empty":
+_3d2.push("element.childNodes.length == 0");
+break;
+case "enabled":
+_3d2.push("(this.isUIElement(element) && element.disabled === false)");
+break;
+case "disabled":
+_3d2.push("(this.isUIElement(element) && element.disabled === true)");
+break;
+case "checked":
+_3d2.push("(this.isUIElement(element) && element.checked === true)");
+break;
+case "not":
+var _3db=new MochiKit.Selector.Selector(_3d8);
+_3d2.push("!( "+_3db.buildMatchExpression()+")");
+break;
+}
+}
+}
+if(_3d3=_3d1.attributes){
+MochiKit.Base.map(function(_3dc){
+var _3dd="MochiKit.DOM.getNodeAttribute(element, "+repr(_3dc.name)+")";
+var _3de=function(_3df){
+return _3dd+".split("+repr(_3df)+")";
+};
+switch(_3dc.operator){
+case "=":
+_3d2.push(_3dd+" == "+repr(_3dc.value));
+break;
+case "~=":
+_3d2.push(_3dd+" && MochiKit.Base.findValue("+_3de(" ")+", "+repr(_3dc.value)+") > -1");
+break;
+case "^=":
+_3d2.push(_3dd+".substring(0, "+_3dc.value.length+") == "+repr(_3dc.value));
+break;
+case "$=":
+_3d2.push(_3dd+".substring("+_3dd+".length - "+_3dc.value.length+") == "+repr(_3dc.value));
+break;
+case "*=":
+_3d2.push(_3dd+".match("+repr(_3dc.value)+")");
+break;
+case "|=":
+_3d2.push(_3dd+" && "+_3de("-")+"[0].toUpperCase() == "+repr(_3dc.value.toUpperCase()));
+break;
+case "!=":
+_3d2.push(_3dd+" != "+repr(_3dc.value));
+break;
+case "":
+case undefined:
+_3d2.push(_3dd+" != null");
+break;
+default:
+throw "Unknown operator "+_3dc.operator+" in selector";
+}
+},_3d3);
+}
+return _3d2.join(" && ");
+},compileMatcher:function(){
+this.match=new Function("element","if (!element.tagName) return false;                 return "+this.buildMatchExpression());
+},nthChild:function(_3e0,a,b,_3e3,_3e4){
+var _3e5=MochiKit.Base.filter(function(node){
+return node.nodeType==1;
+},_3e0.parentNode.childNodes);
+if(_3e4){
+_3e5=MochiKit.Base.filter(function(node){
+return node.tagName==_3e0.tagName;
+},_3e5);
+}
+if(_3e3){
+_3e5=MochiKit.Iter.reversed(_3e5);
+}
+if(a){
+var _3e8=MochiKit.Base.findIdentical(_3e5,_3e0);
+return ((_3e8+1-b)/a)%1==0;
+}else{
+return b==MochiKit.Base.findIdentical(_3e5,_3e0)+1;
+}
+},isUIElement:function(_3e9){
+return MochiKit.Base.findValue(["input","button","select","option","textarea","object"],_3e9.tagName.toLowerCase())>-1;
+},findElements:function(_3ea,axis){
+var _3ec;
+if(axis==undefined){
+axis="";
+}
+function inScope(_3ed,_3ee){
+if(axis==""){
+return MochiKit.DOM.isChildNode(_3ed,_3ee);
+}else{
+if(axis==">"){
+return _3ed.parentNode==_3ee;
+}else{
+if(axis=="+"){
+return _3ed==nextSiblingElement(_3ee);
+}else{
+if(axis=="~"){
+var _3ef=_3ee;
+while(_3ef=nextSiblingElement(_3ef)){
+if(_3ed==_3ef){
+return true;
+}
+}
+return false;
+}else{
+throw "Invalid axis: "+axis;
+}
+}
+}
+}
+}
+if(_3ec=MochiKit.DOM.getElement(this.params.id)){
+if(this.match(_3ec)){
+if(!_3ea||inScope(_3ec,_3ea)){
+return [_3ec];
+}
+}
+}
+function nextSiblingElement(node){
+node=node.nextSibling;
+while(node&&node.nodeType!=1){
+node=node.nextSibling;
+}
+return node;
+}
+if(axis==""){
+_3ea=(_3ea||MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName||"*");
+}else{
+if(axis==">"){
+if(!_3ea){
+throw "> combinator not allowed without preceeding expression";
+}
+_3ea=MochiKit.Base.filter(function(node){
+return node.nodeType==1;
+},_3ea.childNodes);
+}else{
+if(axis=="+"){
+if(!_3ea){
+throw "+ combinator not allowed without preceeding expression";
+}
+_3ea=nextSiblingElement(_3ea)&&[nextSiblingElement(_3ea)];
+}else{
+if(axis=="~"){
+if(!_3ea){
+throw "~ combinator not allowed without preceeding expression";
+}
+var _3f2=[];
+while(nextSiblingElement(_3ea)){
+_3ea=nextSiblingElement(_3ea);
+_3f2.push(_3ea);
+}
+_3ea=_3f2;
+}
+}
+}
+}
+if(!_3ea){
+return [];
+}
+var _3f3=MochiKit.Base.filter(MochiKit.Base.bind(function(_3f4){
+return this.match(_3f4);
+},this),_3ea);
+return _3f3;
+},repr:function(){
+return "Selector("+this.expression+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Base.update(MochiKit.Selector,{findChildElements:function(_3f5,_3f6){
+return MochiKit.Base.flattenArray(MochiKit.Base.map(function(_3f7){
+var _3f8="";
+return MochiKit.Iter.reduce(function(_3f9,expr){
+if(match=expr.match(/^[>+~]$/)){
+_3f8=match[0];
+return _3f9;
+}else{
+var _3fb=new MochiKit.Selector.Selector(expr);
+var _3fc=MochiKit.Iter.reduce(function(_3fd,_3fe){
+return MochiKit.Base.extend(_3fd,_3fb.findElements(_3fe||_3f5,_3f8));
+},_3f9,[]);
+_3f8="";
+return _3fc;
+}
+},_3f7.replace(/(^\s+|\s+$)/g,"").split(/\s+/),[null]);
+},_3f6));
+},findDocElements:function(){
+return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(),arguments);
+},__new__:function(){
+var m=MochiKit.Base;
+this.$$=this.findDocElements;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.Selector.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Selector);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Style");
+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.Style depends on MochiKit.Base!";
+}
+try{
+if(typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Style depends on MochiKit.DOM!";
+}
+if(typeof (MochiKit.Style)=="undefined"){
+MochiKit.Style={};
+}
+MochiKit.Style.NAME="MochiKit.Style";
+MochiKit.Style.VERSION="1.4";
+MochiKit.Style.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Style.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.EXPORT_OK=[];
+MochiKit.Style.EXPORT=["setStyle","setOpacity","getStyle","getElementDimensions","elementDimensions","setElementDimensions","getElementPosition","elementPosition","setElementPosition","setDisplayForElement","hideElement","showElement","getViewportDimensions","getViewportPosition","Dimensions","Coordinates"];
+MochiKit.Style.Dimensions=function(w,h){
+this.w=w;
+this.h=h;
+};
+MochiKit.Style.Dimensions.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}";
+};
+MochiKit.Style.Dimensions.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.Coordinates=function(x,y){
+this.x=x;
+this.y=y;
+};
+MochiKit.Style.Coordinates.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}";
+};
+MochiKit.Style.Coordinates.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Base.update(MochiKit.Style,{getStyle:function(elem,_407){
+var dom=MochiKit.DOM;
+var d=dom._document;
+elem=dom.getElement(elem);
+_407=MochiKit.Base.camelize(_407);
+if(!elem||elem==d){
+return undefined;
+}
+if(_407=="opacity"&&elem.filters){
+var _40a=(MochiKit.Style.getStyle(elem,"filter")||"").match(/alpha\(opacity=(.*)\)/);
+if(_40a&&_40a[1]){
+return parseFloat(_40a[1])/100;
+}
+return 1;
+}
+var _40b=elem.style?elem.style[_407]:null;
+if(!_40b){
+if(d.defaultView&&d.defaultView.getComputedStyle){
+var css=d.defaultView.getComputedStyle(elem,null);
+_407=_407.replace(/([A-Z])/g,"-$1").toLowerCase();
+_40b=css?css.getPropertyValue(_407):null;
+}else{
+if(elem.currentStyle){
+_40b=elem.currentStyle[_407];
+}
+}
+}
+if(_407=="opacity"){
+_40b=parseFloat(_40b);
+}
+if(/Opera/.test(navigator.userAgent)&&(MochiKit.Base.find(["left","top","right","bottom"],_407)!=-1)){
+if(MochiKit.Style.getStyle(elem,"position")=="static"){
+_40b="auto";
+}
+}
+return _40b=="auto"?null:_40b;
+},setStyle:function(elem,_40e){
+elem=MochiKit.DOM.getElement(elem);
+for(var name in _40e){
+if(name=="opacity"){
+MochiKit.Style.setOpacity(elem,_40e[name]);
+}else{
+elem.style[MochiKit.Base.camelize(name)]=_40e[name];
+}
+}
+},setOpacity:function(elem,o){
+elem=MochiKit.DOM.getElement(elem);
+var self=MochiKit.Style;
+if(o==1){
+var _413=/Gecko/.test(navigator.userAgent)&&!(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
+elem.style["opacity"]=_413?0.999999:1;
+if(/MSIE/.test(navigator.userAgent)){
+elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"");
+}
+}else{
+if(o<0.00001){
+o=0;
+}
+elem.style["opacity"]=o;
+if(/MSIE/.test(navigator.userAgent)){
+elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"")+"alpha(opacity="+o*100+")";
+}
+}
+},getElementPosition:function(elem,_415){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+elem=dom.getElement(elem);
+if(!elem||(!(elem.x&&elem.y)&&(!elem.parentNode===null||self.getStyle(elem,"display")=="none"))){
+return undefined;
+}
+var c=new self.Coordinates(0,0);
+var box=null;
+var _41a=null;
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var b=d.body;
+if(!elem.parentNode&&elem.x&&elem.y){
+c.x+=elem.x||0;
+c.y+=elem.y||0;
+}else{
+if(elem.getBoundingClientRect){
+box=elem.getBoundingClientRect();
+c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
+c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}else{
+if(elem.offsetParent){
+c.x+=elem.offsetLeft;
+c.y+=elem.offsetTop;
+_41a=elem.offsetParent;
+if(_41a!=elem){
+while(_41a){
+c.x+=_41a.offsetLeft;
+c.y+=_41a.offsetTop;
+_41a=_41a.offsetParent;
+}
+}
+var ua=navigator.userAgent.toLowerCase();
+if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("AppleWebKit")!=-1&&self.getStyle(elem,"position")=="absolute")){
+c.x-=b.offsetLeft;
+c.y-=b.offsetTop;
+}
+}
+}
+}
+if(typeof (_415)!="undefined"){
+_415=arguments.callee(_415);
+if(_415){
+c.x-=(_415.x||0);
+c.y-=(_415.y||0);
+}
+}
+if(elem.parentNode){
+_41a=elem.parentNode;
+}else{
+_41a=null;
+}
+while(_41a){
+var _41f=_41a.tagName.toUpperCase();
+if(_41f==="BODY"||_41f==="HTML"){
+break;
+}
+var disp=self.getStyle(_41a,"display");
+if(disp!="inline"&&disp!="table-row"){
+c.x-=_41a.scrollLeft;
+c.y-=_41a.scrollTop;
+}
+if(_41a.parentNode){
+_41a=_41a.parentNode;
+}else{
+_41a=null;
+}
+}
+return c;
+},setElementPosition:function(elem,_422,_423){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_423)=="undefined"){
+_423="px";
+}
+var _424={};
+var _425=MochiKit.Base.isUndefinedOrNull;
+if(!_425(_422.x)){
+_424["left"]=_422.x+_423;
+}
+if(!_425(_422.y)){
+_424["top"]=_422.y+_423;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_424});
+},getElementDimensions:function(elem){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){
+return new self.Dimensions(elem.w||0,elem.h||0);
+}
+elem=dom.getElement(elem);
+if(!elem){
+return undefined;
+}
+var disp=self.getStyle(elem,"display");
+if(disp!="none"&&disp!==""&&typeof (disp)!="undefined"){
+return new self.Dimensions(elem.offsetWidth||0,elem.offsetHeight||0);
+}
+var s=elem.style;
+var _42b=s.visibility;
+var _42c=s.position;
+s.visibility="hidden";
+s.position="absolute";
+s.display="";
+var _42d=elem.offsetWidth;
+var _42e=elem.offsetHeight;
+s.display="none";
+s.position=_42c;
+s.visibility=_42b;
+return new self.Dimensions(_42d,_42e);
+},setElementDimensions:function(elem,_430,_431){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_431)=="undefined"){
+_431="px";
+}
+var _432={};
+var _433=MochiKit.Base.isUndefinedOrNull;
+if(!_433(_430.w)){
+_432["width"]=_430.w+_431;
+}
+if(!_433(_430.h)){
+_432["height"]=_430.h+_431;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_432});
+},setDisplayForElement:function(_434,_435){
+var _436=MochiKit.Base.extend(null,arguments,1);
+var _437=MochiKit.DOM.getElement;
+for(var i=0;i<_436.length;i++){
+_435=_437(_436[i]);
+if(_435){
+_435.style.display=_434;
+}
+}
+},getViewportDimensions:function(){
+var d=new MochiKit.Style.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;
+},getViewportPosition:function(){
+var c=new MochiKit.Style.Coordinates(0,0);
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var db=d.body;
+if(de&&(de.scrollTop||de.scrollLeft)){
+c.x=de.scrollLeft;
+c.y=de.scrollTop;
+}else{
+if(db){
+c.x=db.scrollLeft;
+c.y=db.scrollTop;
+}
+}
+return c;
+},__new__:function(){
+var m=MochiKit.Base;
+this.elementPosition=this.getElementPosition;
+this.elementDimensions=this.getElementDimensions;
+this.hideElement=m.partial(this.setDisplayForElement,"none");
+this.showElement=m.partial(this.setDisplayForElement,"block");
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.Style.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Style);
+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.4";
+MochiKit.LoggingPane.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.LoggingPane.toString=function(){
+return this.__repr__();
+};
+MochiKit.LoggingPane.createLoggingPane=function(_441){
+var m=MochiKit.LoggingPane;
+_441=!(!_441);
+if(m._loggingPane&&m._loggingPane.inline!=_441){
+m._loggingPane.closePane();
+m._loggingPane=null;
+}
+if(!m._loggingPane||m._loggingPane.closed){
+m._loggingPane=new m.LoggingPane(_441,MochiKit.Logging.logger);
+}
+return m._loggingPane;
+};
+MochiKit.LoggingPane.LoggingPane=function(_443,_444){
+if(typeof (_444)=="undefined"||_444===null){
+_444=MochiKit.Logging.logger;
+}
+this.logger=_444;
+var _445=MochiKit.Base.update;
+var _446=MochiKit.Base.updatetree;
+var bind=MochiKit.Base.bind;
+var _448=MochiKit.Base.clone;
+var win=window;
+var uid="_MochiKit_LoggingPane";
+if(typeof (MochiKit.DOM)!="undefined"){
+win=MochiKit.DOM.currentWindow();
+}
+if(!_443){
+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 _44f=doc.getElementById(uid);
+var _450=!!_44f;
+if(_44f&&typeof (_44f.loggingPane)!="undefined"){
+_44f.loggingPane.logger=this.logger;
+_44f.loggingPane.buildAndApplyFilter();
+return _44f.loggingPane;
+}
+if(_450){
+var _451;
+while((_451=_44f.firstChild)){
+_44f.removeChild(_451);
+}
+}else{
+_44f=doc.createElement("div");
+_44f.id=uid;
+}
+_44f.loggingPane=this;
+var _452=doc.createElement("input");
+var _453=doc.createElement("input");
+var _454=doc.createElement("button");
+var _455=doc.createElement("button");
+var _456=doc.createElement("button");
+var _457=doc.createElement("button");
+var _458=doc.createElement("div");
+var _459=doc.createElement("div");
+var _45a=uid+"_Listener";
+this.colorTable=_448(this.colorTable);
+var _45b=[];
+var _45c=null;
+var _45d=function(msg){
+var _45f=msg.level;
+if(typeof (_45f)=="number"){
+_45f=MochiKit.Logging.LogLevel[_45f];
+}
+return _45f;
+};
+var _460=function(msg){
+return msg.info.join(" ");
+};
+var _462=bind(function(msg){
+var _464=_45d(msg);
+var text=_460(msg);
+var c=this.colorTable[_464];
+var p=doc.createElement("span");
+p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_464;
+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(_464+": "+text));
+_459.appendChild(p);
+_459.appendChild(doc.createElement("br"));
+if(_458.offsetHeight>_458.scrollHeight){
+_458.scrollTop=0;
+}else{
+_458.scrollTop=_458.scrollHeight;
+}
+},this);
+var _468=function(msg){
+_45b[_45b.length]=msg;
+_462(msg);
+};
+var _46a=function(){
+var _46b,_46c;
+try{
+_46b=new RegExp(_452.value);
+_46c=new RegExp(_453.value);
+}
+catch(e){
+logDebug("Error in filter regex: "+e.message);
+return null;
+}
+return function(msg){
+return (_46b.test(_45d(msg))&&_46c.test(_460(msg)));
+};
+};
+var _46e=function(){
+while(_459.firstChild){
+_459.removeChild(_459.firstChild);
+}
+};
+var _46f=function(){
+_45b=[];
+_46e();
+};
+var _470=bind(function(){
+if(this.closed){
+return;
+}
+this.closed=true;
+if(MochiKit.LoggingPane._loggingPane==this){
+MochiKit.LoggingPane._loggingPane=null;
+}
+this.logger.removeListener(_45a);
+try{
+try{
+_44f.loggingPane=null;
+}
+catch(e){
+logFatal("Bookmarklet was closed incorrectly.");
+}
+if(_443){
+_44f.parentNode.removeChild(_44f);
+}else{
+this.win.close();
+}
+}
+catch(e){
+}
+},this);
+var _471=function(){
+_46e();
+for(var i=0;i<_45b.length;i++){
+var msg=_45b[i];
+if(_45c===null||_45c(msg)){
+_462(msg);
+}
+}
+};
+this.buildAndApplyFilter=function(){
+_45c=_46a();
+_471();
+this.logger.removeListener(_45a);
+this.logger.addListener(_45a,_45c,_468);
+};
+var _474=bind(function(){
+_45b=this.logger.getMessages();
+_471();
+},this);
+var _475=bind(function(_476){
+_476=_476||window.event;
+key=_476.which||_476.keyCode;
+if(key==13){
+this.buildAndApplyFilter();
+}
+},this);
+var _477="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont;
+if(_443){
+_477+="; height: 10em; border-top: 2px solid black";
+}else{
+_477+="; height: 100%;";
+}
+_44f.style.cssText=_477;
+if(!_450){
+doc.body.appendChild(_44f);
+}
+_477={"cssText":"width: 33%; display: inline; font: "+this.logFont};
+_446(_452,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_475,"style":_477});
+_44f.appendChild(_452);
+_446(_453,{"value":".*","onkeypress":_475,"style":_477});
+_44f.appendChild(_453);
+_477="width: 8%; display:inline; font: "+this.logFont;
+_454.appendChild(doc.createTextNode("Filter"));
+_454.onclick=bind("buildAndApplyFilter",this);
+_454.style.cssText=_477;
+_44f.appendChild(_454);
+_455.appendChild(doc.createTextNode("Load"));
+_455.onclick=_474;
+_455.style.cssText=_477;
+_44f.appendChild(_455);
+_456.appendChild(doc.createTextNode("Clear"));
+_456.onclick=_46f;
+_456.style.cssText=_477;
+_44f.appendChild(_456);
+_457.appendChild(doc.createTextNode("Close"));
+_457.onclick=_470;
+_457.style.cssText=_477;
+_44f.appendChild(_457);
+_458.style.cssText="overflow: auto; width: 100%";
+_459.style.cssText="width: 100%; height: "+(_443?"8em":"100%");
+_458.appendChild(_459);
+_44f.appendChild(_458);
+this.buildAndApplyFilter();
+_474();
+if(_443){
+this.win=undefined;
+}else{
+this.win=win;
+}
+this.inline=_443;
+this.closePane=_470;
+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");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.Base";
+}
+try{
+if(typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.DOM";
+}
+try{
+if(typeof (MochiKit.Style)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.Style";
+}
+if(typeof (MochiKit.Color)=="undefined"){
+MochiKit.Color={};
+}
+MochiKit.Color.NAME="MochiKit.Color";
+MochiKit.Color.VERSION="1.4";
+MochiKit.Color.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Color.toString=function(){
+return this.__repr__();
+};
+MochiKit.Color.Color=function(red,_479,blue,_47b){
+if(typeof (_47b)=="undefined"||_47b===null){
+_47b=1;
+}
+this.rgb={r:red,g:_479,b:blue,a:_47b};
+};
+MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_47c){
+var rgb=this.rgb;
+var m=MochiKit.Color;
+return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_47c);
+},colorWithHue:function(hue){
+var hsl=this.asHSL();
+hsl.h=hue;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithSaturation:function(_482){
+var hsl=this.asHSL();
+hsl.s=_482;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithLightness:function(_485){
+var hsl=this.asHSL();
+hsl.l=_485;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},darkerColorWithLevel:function(_488){
+var hsl=this.asHSL();
+hsl.l=Math.max(hsl.l-_488,0);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},lighterColorWithLevel:function(_48b){
+var hsl=this.asHSL();
+hsl.l=Math.min(hsl.l+_48b,1);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},blendedColor:function(_48e,_48f){
+if(typeof (_48f)=="undefined"||_48f===null){
+_48f=0.5;
+}
+var sf=1-_48f;
+var s=this.rgb;
+var d=_48e.rgb;
+var df=_48f;
+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(_494){
+var a=this.asRGB();
+var b=_494.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,_4ab,blue,_4ad){
+var _4ae=MochiKit.Color.Color;
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_4ab=rgb.g;
+blue=rgb.b;
+if(typeof (rgb.a)=="undefined"){
+_4ad=undefined;
+}else{
+_4ad=rgb.a;
+}
+}
+return new _4ae(red,_4ab,blue,_4ad);
+},fromHSL:function(hue,_4b1,_4b2,_4b3){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hslToRGB.apply(m,arguments));
+},fromHSV:function(hue,_4b6,_4b7,_4b8){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments));
+},fromName:function(name){
+var _4bb=MochiKit.Color.Color;
+if(name.charAt(0)=="\""){
+name=name.substr(1,name.length-2);
+}
+var _4bc=_4bb._namedColors[name.toLowerCase()];
+if(typeof (_4bc)=="string"){
+return _4bb.fromHexString(_4bc);
+}else{
+if(name=="transparent"){
+return _4bb.transparentColor();
+}
+}
+return null;
+},fromString:function(_4bd){
+var self=MochiKit.Color.Color;
+var _4bf=_4bd.substr(0,3);
+if(_4bf=="rgb"){
+return self.fromRGBString(_4bd);
+}else{
+if(_4bf=="hsl"){
+return self.fromHSLString(_4bd);
+}else{
+if(_4bd.charAt(0)=="#"){
+return self.fromHexString(_4bd);
+}
+}
+}
+return self.fromName(_4bd);
+},fromHexString:function(_4c0){
+if(_4c0.charAt(0)=="#"){
+_4c0=_4c0.substring(1);
+}
+var _4c1=[];
+var i,hex;
+if(_4c0.length==3){
+for(i=0;i<3;i++){
+hex=_4c0.substr(i,1);
+_4c1.push(parseInt(hex+hex,16)/255);
+}
+}else{
+for(i=0;i<6;i+=2){
+hex=_4c0.substr(i,2);
+_4c1.push(parseInt(hex,16)/255);
+}
+}
+var _4c4=MochiKit.Color.Color;
+return _4c4.fromRGB.apply(_4c4,_4c1);
+},_fromColorString:function(pre,_4c6,_4c7,_4c8){
+if(_4c8.indexOf(pre)===0){
+_4c8=_4c8.substring(_4c8.indexOf("(",3)+1,_4c8.length-1);
+}
+var _4c9=_4c8.split(/\s*,\s*/);
+var _4ca=[];
+for(var i=0;i<_4c9.length;i++){
+var c=_4c9[i];
+var val;
+var _4ce=c.substring(c.length-3);
+if(c.charAt(c.length-1)=="%"){
+val=0.01*parseFloat(c.substring(0,c.length-1));
+}else{
+if(_4ce=="deg"){
+val=parseFloat(c)/360;
+}else{
+if(_4ce=="rad"){
+val=parseFloat(c)/(Math.PI*2);
+}else{
+val=_4c7[i]*parseFloat(c);
+}
+}
+}
+_4ca.push(val);
+}
+return this[_4c6].apply(this,_4ca);
+},fromComputedStyle:function(elem,_4d0){
+var d=MochiKit.DOM;
+var cls=MochiKit.Color.Color;
+for(elem=d.getElement(elem);elem;elem=elem.parentNode){
+var _4d3=MochiKit.Style.getStyle.apply(d,arguments);
+if(!_4d3){
+continue;
+}
+var _4d4=cls.fromString(_4d3);
+if(!_4d4){
+break;
+}
+if(_4d4.asRGB().a>0){
+return _4d4;
+}
+}
+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,_4da){
+v*=_4da;
+if(v<0){
+return 0;
+}else{
+if(v>_4da){
+return _4da;
+}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,_4e0,_4e1,_4e2){
+if(arguments.length==1){
+var hsv=hue;
+hue=hsv.h;
+_4e0=hsv.s;
+_4e1=hsv.v;
+_4e2=hsv.a;
+}
+var red;
+var _4e5;
+var blue;
+if(_4e0===0){
+red=_4e1;
+_4e5=_4e1;
+blue=_4e1;
+}else{
+var i=Math.floor(hue*6);
+var f=(hue*6)-i;
+var p=_4e1*(1-_4e0);
+var q=_4e1*(1-(_4e0*f));
+var t=_4e1*(1-(_4e0*(1-f)));
+switch(i){
+case 1:
+red=q;
+_4e5=_4e1;
+blue=p;
+break;
+case 2:
+red=p;
+_4e5=_4e1;
+blue=t;
+break;
+case 3:
+red=p;
+_4e5=q;
+blue=_4e1;
+break;
+case 4:
+red=t;
+_4e5=p;
+blue=_4e1;
+break;
+case 5:
+red=_4e1;
+_4e5=p;
+blue=q;
+break;
+case 6:
+case 0:
+red=_4e1;
+_4e5=t;
+blue=p;
+break;
+}
+}
+return {r:red,g:_4e5,b:blue,a:_4e2};
+},hslToRGB:function(hue,_4ed,_4ee,_4ef){
+if(arguments.length==1){
+var hsl=hue;
+hue=hsl.h;
+_4ed=hsl.s;
+_4ee=hsl.l;
+_4ef=hsl.a;
+}
+var red;
+var _4f2;
+var blue;
+if(_4ed===0){
+red=_4ee;
+_4f2=_4ee;
+blue=_4ee;
+}else{
+var m2;
+if(_4ee<=0.5){
+m2=_4ee*(1+_4ed);
+}else{
+m2=_4ee+_4ed-(_4ee*_4ed);
+}
+var m1=(2*_4ee)-m2;
+var f=MochiKit.Color._hslValue;
+var h6=hue*6;
+red=f(m1,m2,h6+2);
+_4f2=f(m1,m2,h6);
+blue=f(m1,m2,h6-2);
+}
+return {r:red,g:_4f2,b:blue,a:_4ef};
+},rgbToHSV:function(red,_4f9,blue,_4fb){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_4f9=rgb.g;
+blue=rgb.b;
+_4fb=rgb.a;
+}
+var max=Math.max(Math.max(red,_4f9),blue);
+var min=Math.min(Math.min(red,_4f9),blue);
+var hue;
+var _500;
+var _501=max;
+if(min==max){
+hue=0;
+_500=0;
+}else{
+var _502=(max-min);
+_500=_502/max;
+if(red==max){
+hue=(_4f9-blue)/_502;
+}else{
+if(_4f9==max){
+hue=2+((blue-red)/_502);
+}else{
+hue=4+((red-_4f9)/_502);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_500,v:_501,a:_4fb};
+},rgbToHSL:function(red,_504,blue,_506){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_504=rgb.g;
+blue=rgb.b;
+_506=rgb.a;
+}
+var max=Math.max(red,Math.max(_504,blue));
+var min=Math.min(red,Math.min(_504,blue));
+var hue;
+var _50b;
+var _50c=(max+min)/2;
+var _50d=max-min;
+if(_50d===0){
+hue=0;
+_50b=0;
+}else{
+if(_50c<=0.5){
+_50b=_50d/(max+min);
+}else{
+_50b=_50d/(2-max-min);
+}
+if(red==max){
+hue=(_504-blue)/_50d;
+}else{
+if(_504==max){
+hue=2+((blue-red)/_50d);
+}else{
+hue=4+((red-_504)/_50d);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_50b,l:_50c,a:_506};
+},toColorPart:function(num){
+num=Math.round(num);
+var _50f=num.toString(16);
+if(num<16){
+return "0"+_50f;
+}
+return _50f;
+},__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 _511=1/3;
+var _512={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_511,_511,_511],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_511,2*_511,2*_511],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 _513=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 _512){
+var name=k+"Color";
+var _51c=m.concat([_513,this.Color,name],_512[k]);
+this.Color[name]=m.bind.apply(null,_51c);
+}
+var _51d=function(){
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof Color)){
+return false;
+}
+}
+return true;
+};
+var _51f=function(a,b){
+return a.compareRGB(b);
+};
+m.nameFunctions(this);
+m.registerComparator(this.Color.NAME,_51d,_51f);
+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");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+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!";
+}
+try{
+if(typeof (MochiKit.Style)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Signal depends on MochiKit.Style!";
+}
+if(typeof (MochiKit.Signal)=="undefined"){
+MochiKit.Signal={};
+}
+MochiKit.Signal.NAME="MochiKit.Signal";
+MochiKit.Signal.VERSION="1.4";
+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());
+if(this.type()&&this.type().indexOf("key")===0||this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu"){
+str+=", 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:null,relatedTarget:function(){
+if(this._relatedTarget!==null){
+return this._relatedTarget;
+}
+var elem=null;
+if(this.type()=="mouseover"){
+elem=(this._event.relatedTarget||this._event.fromElement);
+}else{
+if(this.type()=="mouseout"){
+elem=(this._event.relatedTarget||this._event.toElement);
+}
+}
+if(elem!==null){
+this._relatedTarget=elem;
+return elem;
+}
+return undefined;
+},_modifier:null,modifier:function(){
+if(this._modifier!==null){
+return this._modifier;
+}
+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;
+this._modifier=m;
+return m;
+},_key:null,key:function(){
+if(this._key!==null){
+return this._key;
+}
+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");
+this._key=k;
+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);
+}
+}
+this._key=k;
+return k;
+}
+}
+}
+return undefined;
+},_mouse:null,mouse:function(){
+if(this._mouse!==null){
+return this._mouse;
+}
+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.Style.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.Style.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||0);
+m.page.y=e.clientY+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}
+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);
+}
+}
+this._mouse=m;
+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{
+if(this._confirmUnload===null){
+this._event.returnValue=false;
+}
+}
+},_confirmUnload:null,confirmUnload:function(msg){
+if(this.type()=="beforeunload"){
+this._confirmUnload=msg;
+this._event.returnValue=msg;
+}
+}});
+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"};
+(function(){
+var _52e=MochiKit.Signal._specialMacKeys;
+for(i=63236;i<=63242;i++){
+_52e[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"};
+(function(){
+var _52f=MochiKit.Signal._specialKeys;
+for(var i=48;i<=57;i++){
+_52f[i]="KEY_"+(i-48);
+}
+for(i=65;i<=90;i++){
+_52f[i]="KEY_"+String.fromCharCode(i);
+}
+for(i=96;i<=105;i++){
+_52f[i]="KEY_NUM_PAD_"+(i-96);
+}
+for(i=112;i<=123;i++){
+_52f[i]="KEY_F"+(i-112+1);
+}
+})();
+MochiKit.Signal.Ident=function(_531){
+this.source=_531.source;
+this.signal=_531.signal;
+this.listener=_531.listener;
+this.isDOM=_531.isDOM;
+this.objOrFunc=_531.objOrFunc;
+this.funcOrStr=_531.funcOrStr;
+this.connected=_531.connected;
+};
+MochiKit.Signal.Ident.prototype={};
+MochiKit.Base.update(MochiKit.Signal,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},_unloadCache:function(){
+var self=MochiKit.Signal;
+var _533=self._observers;
+for(var i=0;i<_533.length;i++){
+if(_533[i].signal!=="onload"&&_533[i].signal!=="onunload"){
+self._disconnect(_533[i]);
+}
+}
+},_listener:function(src,sig,func,obj,_539){
+var self=MochiKit.Signal;
+var E=self.Event;
+if(!_539){
+return MochiKit.Base.bind(func,obj);
+}
+obj=obj||src;
+if(typeof (func)=="string"){
+if(sig==="onload"||sig==="onunload"){
+return function(_53c){
+obj[func].apply(obj,[new E(src,_53c)]);
+var _53d=new MochiKit.Signal.Ident({source:src,signal:sig,objOrFunc:obj,funcOrStr:func});
+MochiKit.Signal._disconnect(_53d);
+};
+}else{
+return function(_53e){
+obj[func].apply(obj,[new E(src,_53e)]);
+};
+}
+}else{
+if(sig==="onload"||sig==="onunload"){
+return function(_53f){
+func.apply(obj,[new E(src,_53f)]);
+MochiKit.Signal.disconnect(src,sig,func);
+var _540=new MochiKit.Signal.Ident({source:src,signal:sig,objOrFunc:func});
+MochiKit.Signal._disconnect(_540);
+};
+}else{
+return function(_541){
+func.apply(obj,[new E(src,_541)]);
+};
+}
+}
+},_browserAlreadyHasMouseEnterAndLeave:function(){
+return /MSIE/.test(navigator.userAgent);
+},_mouseEnterListener:function(src,sig,func,obj){
+var E=MochiKit.Signal.Event;
+return function(_547){
+var e=new E(src,_547);
+try{
+e.relatedTarget().nodeName;
+}
+catch(err){
+return;
+}
+e.stop();
+if(MochiKit.DOM.isChildNode(e.relatedTarget(),src)){
+return;
+}
+e.type=function(){
+return sig;
+};
+if(typeof (func)=="string"){
+return obj[func].apply(obj,[e]);
+}else{
+return func.apply(obj,[e]);
+}
+};
+},_getDestPair:function(_549,_54a){
+var obj=null;
+var func=null;
+if(typeof (_54a)!="undefined"){
+obj=_549;
+func=_54a;
+if(typeof (_54a)=="string"){
+if(typeof (_549[_54a])!="function"){
+throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
+}
+}else{
+if(typeof (_54a)!="function"){
+throw new Error("'funcOrStr' must be a function or string");
+}
+}
+}else{
+if(typeof (_549)!="function"){
+throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
+}else{
+func=_549;
+}
+}
+return [obj,func];
+},connect:function(src,sig,_54f,_550){
+src=MochiKit.DOM.getElement(src);
+var self=MochiKit.Signal;
+if(typeof (sig)!="string"){
+throw new Error("'sig' must be a string");
+}
+var _552=self._getDestPair(_54f,_550);
+var obj=_552[0];
+var func=_552[1];
+if(typeof (obj)=="undefined"||obj===null){
+obj=src;
+}
+var _555=!!(src.addEventListener||src.attachEvent);
+if(_555&&(sig==="onmouseenter"||sig==="onmouseleave")&&!self._browserAlreadyHasMouseEnterAndLeave()){
+var _556=self._mouseEnterListener(src,sig.substr(2),func,obj);
+if(sig==="onmouseenter"){
+sig="onmouseover";
+}else{
+sig="onmouseout";
+}
+}else{
+var _556=self._listener(src,sig,func,obj,_555);
+}
+if(src.addEventListener){
+src.addEventListener(sig.substr(2),_556,false);
+}else{
+if(src.attachEvent){
+src.attachEvent(sig,_556);
+}
+}
+var _557=new MochiKit.Signal.Ident({source:src,signal:sig,listener:_556,isDOM:_555,objOrFunc:_54f,funcOrStr:_550,connected:true});
+self._observers.push(_557);
+if(!_555&&typeof (src.__connect__)=="function"){
+var args=MochiKit.Base.extend([_557],arguments,1);
+src.__connect__.apply(src,args);
+}
+return _557;
+},_disconnect:function(_559){
+if(!_559.connected){
+return;
+}
+_559.connected=false;
+if(!_559.isDOM){
+return;
+}
+var src=_559.source;
+var sig=_559.signal;
+var _55c=_559.listener;
+if(src.removeEventListener){
+src.removeEventListener(sig.substr(2),_55c,false);
+}else{
+if(src.detachEvent){
+src.detachEvent(sig,_55c);
+}else{
+throw new Error("'src' must be a DOM element");
+}
+}
+},disconnect:function(_55d){
+var self=MochiKit.Signal;
+var _55f=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=_55f.length-1;i>=0;i--){
+var o=_55f[i];
+if(o.source===src&&o.signal===sig&&o.objOrFunc===obj&&o.funcOrStr===func){
+self._disconnect(o);
+if(!self._lock){
+_55f.splice(i,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+}else{
+var idx=m.findIdentical(_55f,_55d);
+if(idx>=0){
+self._disconnect(_55d);
+if(!self._lock){
+_55f.splice(idx,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+return false;
+},disconnectAllTo:function(_568,_569){
+var self=MochiKit.Signal;
+var _56b=self._observers;
+var _56c=self._disconnect;
+var _56d=self._lock;
+var _56e=self._dirty;
+if(typeof (_569)==="undefined"){
+_569=null;
+}
+for(var i=_56b.length-1;i>=0;i--){
+var _570=_56b[i];
+if(_570.objOrFunc===_568&&(_569===null||_570.funcOrStr===_569)){
+_56c(_570);
+if(_56d){
+_56e=true;
+}else{
+_56b.splice(i,1);
+}
+}
+}
+self._dirty=_56e;
+},disconnectAll:function(src,sig){
+src=MochiKit.DOM.getElement(src);
+var m=MochiKit.Base;
+var _574=m.flattenArguments(m.extend(null,arguments,1));
+var self=MochiKit.Signal;
+var _576=self._disconnect;
+var _577=self._observers;
+var i,_579;
+var _57a=self._lock;
+var _57b=self._dirty;
+if(_574.length===0){
+for(i=_577.length-1;i>=0;i--){
+_579=_577[i];
+if(_579.source===src){
+_576(_579);
+if(!_57a){
+_577.splice(i,1);
+}else{
+_57b=true;
+}
+}
+}
+}else{
+var sigs={};
+for(i=0;i<_574.length;i++){
+sigs[_574[i]]=true;
+}
+for(i=_577.length-1;i>=0;i--){
+_579=_577[i];
+if(_579.source===src&&_579.signal in sigs){
+_576(_579);
+if(!_57a){
+_577.splice(i,1);
+}else{
+_57b=true;
+}
+}
+}
+}
+self._dirty=_57b;
+},signal:function(src,sig){
+var self=MochiKit.Signal;
+var _580=self._observers;
+src=MochiKit.DOM.getElement(src);
+var args=MochiKit.Base.extend(null,arguments,2);
+var _582=[];
+self._lock=true;
+for(var i=0;i<_580.length;i++){
+var _584=_580[i];
+if(_584.source===src&&_584.signal===sig){
+try{
+_584.listener.apply(src,args);
+}
+catch(e){
+_582.push(e);
+}
+}
+}
+self._lock=false;
+if(self._dirty){
+self._dirty=false;
+for(var i=_580.length-1;i>=0;i--){
+if(!_580[i].connected){
+_580.splice(i,1);
+}
+}
+}
+if(_582.length==1){
+throw _582[0];
+}else{
+if(_582.length>1){
+var e=new Error("Multiple errors thrown in handling 'sig', see errors property");
+e.errors=_582;
+throw e;
+}
+}
+}});
+MochiKit.Signal.EXPORT_OK=[];
+MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll","disconnectAllTo"];
+MochiKit.Signal.__new__=function(win){
+var m=MochiKit.Base;
+this._document=document;
+this._window=win;
+this._lock=false;
+this._dirty=false;
+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.__export__){
+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.Position");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.Style)=="undefined"||typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!";
+}
+if(typeof (MochiKit.Position)=="undefined"){
+MochiKit.Position={};
+}
+MochiKit.Position.NAME="MochiKit.Position";
+MochiKit.Position.VERSION="1.4";
+MochiKit.Position.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Position.toString=function(){
+return this.__repr__();
+};
+MochiKit.Position.EXPORT_OK=[];
+MochiKit.Position.EXPORT=[];
+MochiKit.Base.update(MochiKit.Position,{includeScrollOffsets:false,prepare:function(){
+var _588=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
+var _589=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;
+this.windowOffset=new MochiKit.Style.Coordinates(_588,_589);
+},cumulativeOffset:function(_58a){
+var _58b=0;
+var _58c=0;
+do{
+_58b+=_58a.offsetTop||0;
+_58c+=_58a.offsetLeft||0;
+_58a=_58a.offsetParent;
+}while(_58a);
+return new MochiKit.Style.Coordinates(_58c,_58b);
+},realOffset:function(_58d){
+var _58e=0;
+var _58f=0;
+do{
+_58e+=_58d.scrollTop||0;
+_58f+=_58d.scrollLeft||0;
+_58d=_58d.parentNode;
+}while(_58d);
+return new MochiKit.Style.Coordinates(_58f,_58e);
+},within:function(_590,x,y){
+if(this.includeScrollOffsets){
+return this.withinIncludingScrolloffsets(_590,x,y);
+}
+this.xcomp=x;
+this.ycomp=y;
+this.offset=this.cumulativeOffset(_590);
+if(_590.style.position=="fixed"){
+this.offset.x+=this.windowOffset.x;
+this.offset.y+=this.windowOffset.y;
+}
+return (y>=this.offset.y&&y<this.offset.y+_590.offsetHeight&&x>=this.offset.x&&x<this.offset.x+_590.offsetWidth);
+},withinIncludingScrolloffsets:function(_593,x,y){
+var _596=this.realOffset(_593);
+this.xcomp=x+_596.x-this.windowOffset.x;
+this.ycomp=y+_596.y-this.windowOffset.y;
+this.offset=this.cumulativeOffset(_593);
+return (this.ycomp>=this.offset.y&&this.ycomp<this.offset.y+_593.offsetHeight&&this.xcomp>=this.offset.x&&this.xcomp<this.offset.x+_593.offsetWidth);
+},overlap:function(mode,_598){
+if(!mode){
+return 0;
+}
+if(mode=="vertical"){
+return ((this.offset.y+_598.offsetHeight)-this.ycomp)/_598.offsetHeight;
+}
+if(mode=="horizontal"){
+return ((this.offset.x+_598.offsetWidth)-this.xcomp)/_598.offsetWidth;
+}
+},absolutize:function(_599){
+_599=MochiKit.DOM.getElement(_599);
+if(_599.style.position=="absolute"){
+return;
+}
+MochiKit.Position.prepare();
+var _59a=MochiKit.Position.positionedOffset(_599);
+var _59b=_599.clientWidth;
+var _59c=_599.clientHeight;
+var _59d={"position":_599.style.position,"left":_59a.x-parseFloat(_599.style.left||0),"top":_59a.y-parseFloat(_599.style.top||0),"width":_599.style.width,"height":_599.style.height};
+_599.style.position="absolute";
+_599.style.top=_59a.y+"px";
+_599.style.left=_59a.x+"px";
+_599.style.width=_59b+"px";
+_599.style.height=_59c+"px";
+return _59d;
+},positionedOffset:function(_59e){
+var _59f=0,_5a0=0;
+do{
+_59f+=_59e.offsetTop||0;
+_5a0+=_59e.offsetLeft||0;
+_59e=_59e.offsetParent;
+if(_59e){
+p=MochiKit.Style.getStyle(_59e,"position");
+if(p=="relative"||p=="absolute"){
+break;
+}
+}
+}while(_59e);
+return new MochiKit.Style.Coordinates(_5a0,_59f);
+},relativize:function(_5a1,_5a2){
+_5a1=MochiKit.DOM.getElement(_5a1);
+if(_5a1.style.position=="relative"){
+return;
+}
+MochiKit.Position.prepare();
+var top=parseFloat(_5a1.style.top||0)-(_5a2["top"]||0);
+var left=parseFloat(_5a1.style.left||0)-(_5a2["left"]||0);
+_5a1.style.position=_5a2["position"];
+_5a1.style.top=top+"px";
+_5a1.style.left=left+"px";
+_5a1.style.width=_5a2["width"];
+_5a1.style.height=_5a2["height"];
+},clone:function(_5a5,_5a6){
+_5a5=MochiKit.DOM.getElement(_5a5);
+_5a6=MochiKit.DOM.getElement(_5a6);
+_5a6.style.position="absolute";
+var _5a7=this.cumulativeOffset(_5a5);
+_5a6.style.top=_5a7.y+"px";
+_5a6.style.left=_5a7.x+"px";
+_5a6.style.width=_5a5.offsetWidth+"px";
+_5a6.style.height=_5a5.offsetHeight+"px";
+},page:function(_5a8){
+var _5a9=0;
+var _5aa=0;
+var _5ab=_5a8;
+do{
+_5a9+=_5ab.offsetTop||0;
+_5aa+=_5ab.offsetLeft||0;
+if(_5ab.offsetParent==document.body&&MochiKit.Style.getStyle(_5ab,"position")=="absolute"){
+break;
+}
+}while(_5ab=_5ab.offsetParent);
+_5ab=_5a8;
+do{
+_5a9-=_5ab.scrollTop||0;
+_5aa-=_5ab.scrollLeft||0;
+}while(_5ab=_5ab.parentNode);
+return new MochiKit.Style.Coordinates(_5aa,_5a9);
+}});
+MochiKit.Position.__new__=function(win){
+var m=MochiKit.Base;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Position.__new__(this);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Visual");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+dojo.require("MochiKit.Color");
+dojo.require("MochiKit.Position");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+JSAN.use("MochiKit.Color",[]);
+JSAN.use("MochiKit.Position",[]);
+}
+try{
+if(typeof (MochiKit.Base)==="undefined"||typeof (MochiKit.DOM)==="undefined"||typeof (MochiKit.Style)==="undefined"||typeof (MochiKit.Position)==="undefined"||typeof (MochiKit.Color)==="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style, MochiKit.Position and MochiKit.Color!";
+}
+if(typeof (MochiKit.Visual)=="undefined"){
+MochiKit.Visual={};
+}
+MochiKit.Visual.NAME="MochiKit.Visual";
+MochiKit.Visual.VERSION="1.4";
+MochiKit.Visual.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Visual.toString=function(){
+return this.__repr__();
+};
+MochiKit.Visual._RoundCorners=function(e,_5af){
+e=MochiKit.DOM.getElement(e);
+this._setOptions(_5af);
+if(this.options.__unstable__wrapElement){
+e=this._doWrap(e);
+}
+var _5b0=this.options.color;
+var C=MochiKit.Color.Color;
+if(this.options.color==="fromElement"){
+_5b0=C.fromBackground(e);
+}else{
+if(!(_5b0 instanceof C)){
+_5b0=C.fromString(_5b0);
+}
+}
+this.isTransparent=(_5b0.asRGB().a<=0);
+var _5b2=this.options.bgColor;
+if(this.options.bgColor==="fromParent"){
+_5b2=C.fromBackground(e.offsetParent);
+}else{
+if(!(_5b2 instanceof C)){
+_5b2=C.fromString(_5b2);
+}
+}
+this._roundCornersImpl(e,_5b0,_5b2);
+};
+MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){
+var _5b4=e.parentNode;
+var doc=MochiKit.DOM.currentDocument();
+if(typeof (doc.defaultView)==="undefined"||doc.defaultView===null){
+return e;
+}
+var _5b6=doc.defaultView.getComputedStyle(e,null);
+if(typeof (_5b6)==="undefined"||_5b6===null){
+return e;
+}
+var _5b7=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_5b6.getPropertyValue("padding-top"),marginRight:_5b6.getPropertyValue("padding-right"),marginBottom:_5b6.getPropertyValue("padding-bottom"),marginLeft:_5b6.getPropertyValue("padding-left"),padding:"0px"}});
+_5b7.innerHTML=e.innerHTML;
+e.innerHTML="";
+e.appendChild(_5b7);
+return e;
+},_roundCornersImpl:function(e,_5b9,_5ba){
+if(this.options.border){
+this._renderBorder(e,_5ba);
+}
+if(this._isTopRounded()){
+this._roundTopCorners(e,_5b9,_5ba);
+}
+if(this._isBottomRounded()){
+this._roundBottomCorners(e,_5b9,_5ba);
+}
+},_renderBorder:function(el,_5bc){
+var _5bd="1px solid "+this._borderColor(_5bc);
+var _5be="border-left: "+_5bd;
+var _5bf="border-right: "+_5bd;
+var _5c0="style='"+_5be+";"+_5bf+"'";
+el.innerHTML="<div "+_5c0+">"+el.innerHTML+"</div>";
+},_roundTopCorners:function(el,_5c2,_5c3){
+var _5c4=this._createCorner(_5c3);
+for(var i=0;i<this.options.numSlices;i++){
+_5c4.appendChild(this._createCornerSlice(_5c2,_5c3,i,"top"));
+}
+el.style.paddingTop=0;
+el.insertBefore(_5c4,el.firstChild);
+},_roundBottomCorners:function(el,_5c7,_5c8){
+var _5c9=this._createCorner(_5c8);
+for(var i=(this.options.numSlices-1);i>=0;i--){
+_5c9.appendChild(this._createCornerSlice(_5c7,_5c8,i,"bottom"));
+}
+el.style.paddingBottom=0;
+el.appendChild(_5c9);
+},_createCorner:function(_5cb){
+var dom=MochiKit.DOM;
+return dom.DIV({style:{backgroundColor:_5cb.toString()}});
+},_createCornerSlice:function(_5cd,_5ce,n,_5d0){
+var _5d1=MochiKit.DOM.SPAN();
+var _5d2=_5d1.style;
+_5d2.backgroundColor=_5cd.toString();
+_5d2.display="block";
+_5d2.height="1px";
+_5d2.overflow="hidden";
+_5d2.fontSize="1px";
+var _5d3=this._borderColor(_5cd,_5ce);
+if(this.options.border&&n===0){
+_5d2.borderTopStyle="solid";
+_5d2.borderTopWidth="1px";
+_5d2.borderLeftWidth="0px";
+_5d2.borderRightWidth="0px";
+_5d2.borderBottomWidth="0px";
+_5d2.height="0px";
+_5d2.borderColor=_5d3.toString();
+}else{
+if(_5d3){
+_5d2.borderColor=_5d3.toString();
+_5d2.borderStyle="solid";
+_5d2.borderWidth="0px 1px";
+}
+}
+if(!this.options.compact&&(n==(this.options.numSlices-1))){
+_5d2.height="2px";
+}
+this._setMargin(_5d1,n,_5d0);
+this._setBorder(_5d1,n,_5d0);
+return _5d1;
+},_setOptions:function(_5d4){
+this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false};
+MochiKit.Base.update(this.options,_5d4);
+this.options.numSlices=(this.options.compact?2:4);
+},_whichSideTop:function(){
+var _5d5=this.options.corners;
+if(this._hasString(_5d5,"all","top")){
+return "";
+}
+var _5d6=(_5d5.indexOf("tl")!=-1);
+var _5d7=(_5d5.indexOf("tr")!=-1);
+if(_5d6&&_5d7){
+return "";
+}
+if(_5d6){
+return "left";
+}
+if(_5d7){
+return "right";
+}
+return "";
+},_whichSideBottom:function(){
+var _5d8=this.options.corners;
+if(this._hasString(_5d8,"all","bottom")){
+return "";
+}
+var _5d9=(_5d8.indexOf("bl")!=-1);
+var _5da=(_5d8.indexOf("br")!=-1);
+if(_5d9&&_5da){
+return "";
+}
+if(_5d9){
+return "left";
+}
+if(_5da){
+return "right";
+}
+return "";
+},_borderColor:function(_5db,_5dc){
+if(_5db=="transparent"){
+return _5dc;
+}else{
+if(this.options.border){
+return this.options.border;
+}else{
+if(this.options.blend){
+return _5dc.blendedColor(_5db);
+}
+}
+}
+return "";
+},_setMargin:function(el,n,_5df){
+var _5e0=this._marginSize(n)+"px";
+var _5e1=(_5df=="top"?this._whichSideTop():this._whichSideBottom());
+var _5e2=el.style;
+if(_5e1=="left"){
+_5e2.marginLeft=_5e0;
+_5e2.marginRight="0px";
+}else{
+if(_5e1=="right"){
+_5e2.marginRight=_5e0;
+_5e2.marginLeft="0px";
+}else{
+_5e2.marginLeft=_5e0;
+_5e2.marginRight=_5e0;
+}
+}
+},_setBorder:function(el,n,_5e5){
+var _5e6=this._borderSize(n)+"px";
+var _5e7=(_5e5=="top"?this._whichSideTop():this._whichSideBottom());
+var _5e8=el.style;
+if(_5e7=="left"){
+_5e8.borderLeftWidth=_5e6;
+_5e8.borderRightWidth="0px";
+}else{
+if(_5e7=="right"){
+_5e8.borderRightWidth=_5e6;
+_5e8.borderLeftWidth="0px";
+}else{
+_5e8.borderLeftWidth=_5e6;
+_5e8.borderRightWidth=_5e6;
+}
+}
+},_marginSize:function(n){
+if(this.isTransparent){
+return 0;
+}
+var o=this.options;
+if(o.compact&&o.blend){
+var _5eb=[1,0];
+return _5eb[n];
+}else{
+if(o.compact){
+var _5ec=[2,1];
+return _5ec[n];
+}else{
+if(o.blend){
+var _5ed=[3,2,1,0];
+return _5ed[n];
+}else{
+var _5ee=[5,3,2,1];
+return _5ee[n];
+}
+}
+}
+},_borderSize:function(n){
+var o=this.options;
+var _5f1;
+if(o.compact&&(o.blend||this.isTransparent)){
+return 1;
+}else{
+if(o.compact){
+_5f1=[1,0];
+}else{
+if(o.blend){
+_5f1=[2,1,1,1];
+}else{
+if(o.border){
+_5f1=[0,2,0,0];
+}else{
+if(this.isTransparent){
+_5f1=[5,3,2,1];
+}else{
+return 0;
+}
+}
+}
+}
+}
+return _5f1[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,_5f6){
+new MochiKit.Visual._RoundCorners(e,_5f6);
+};
+MochiKit.Visual.roundClass=function(_5f7,_5f8,_5f9){
+var _5fa=MochiKit.DOM.getElementsByTagAndClassName(_5f7,_5f8);
+for(var i=0;i<_5fa.length;i++){
+MochiKit.Visual.roundElement(_5fa[i],_5f9);
+}
+};
+MochiKit.Visual.tagifyText=function(_5fc,_5fd){
+_5fd=_5fd||"position:relative";
+if(/MSIE/.test(navigator.userAgent)){
+_5fd+=";zoom:1";
+}
+_5fc=MochiKit.DOM.getElement(_5fc);
+var ma=MochiKit.Base.map;
+ma(function(_5ff){
+if(_5ff.nodeType==3){
+ma(function(_600){
+_5fc.insertBefore(MochiKit.DOM.SPAN({style:_5fd},_600==" "?String.fromCharCode(160):_600),_5ff);
+},_5ff.nodeValue.split(""));
+MochiKit.DOM.removeElement(_5ff);
+}
+},_5fc.childNodes);
+};
+MochiKit.Visual.forceRerendering=function(_601){
+try{
+_601=MochiKit.DOM.getElement(_601);
+var n=document.createTextNode(" ");
+_601.appendChild(n);
+_601.removeChild(n);
+}
+catch(e){
+}
+};
+MochiKit.Visual.multiple=function(_603,_604,_605){
+_605=MochiKit.Base.update({speed:0.1,delay:0},_605||{});
+var _606=_605.delay;
+var _607=0;
+MochiKit.Base.map(function(_608){
+_605.delay=_607*_605.speed+_606;
+new _604(_608,_605);
+_607+=1;
+},_603);
+};
+MochiKit.Visual.PAIRS={"slide":["slideDown","slideUp"],"blind":["blindDown","blindUp"],"appear":["appear","fade"],"size":["grow","shrink"]};
+MochiKit.Visual.toggle=function(_609,_60a,_60b){
+_609=MochiKit.DOM.getElement(_609);
+_60a=(_60a||"appear").toLowerCase();
+_60b=MochiKit.Base.update({queue:{position:"end",scope:(_609.id||"global"),limit:1}},_60b||{});
+var v=MochiKit.Visual;
+v[_609.style.display!="none"?v.PAIRS[_60a][1]:v.PAIRS[_60a][0]](_609,_60b);
+};
+MochiKit.Visual.Transitions={};
+MochiKit.Visual.Transitions.linear=function(pos){
+return pos;
+};
+MochiKit.Visual.Transitions.sinoidal=function(pos){
+return (-Math.cos(pos*Math.PI)/2)+0.5;
+};
+MochiKit.Visual.Transitions.reverse=function(pos){
+return 1-pos;
+};
+MochiKit.Visual.Transitions.flicker=function(pos){
+return ((-Math.cos(pos*Math.PI)/4)+0.75)+Math.random()/4;
+};
+MochiKit.Visual.Transitions.wobble=function(pos){
+return (-Math.cos(pos*Math.PI*(9*pos))/2)+0.5;
+};
+MochiKit.Visual.Transitions.pulse=function(pos,_613){
+if(!_613){
+return (Math.floor(pos*10)%2===0?(pos*10-Math.floor(pos*10)):1-(pos*10-Math.floor(pos*10)));
+}
+return (Math.round((pos%(1/_613))*_613)==0?((pos*_613*2)-Math.floor(pos*_613*2)):1-((pos*_613*2)-Math.floor(pos*_613*2)));
+};
+MochiKit.Visual.Transitions.none=function(pos){
+return 0;
+};
+MochiKit.Visual.Transitions.full=function(pos){
+return 1;
+};
+MochiKit.Visual.ScopedQueue=function(){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls();
+}
+this.__init__();
+};
+MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype,{__init__:function(){
+this.effects=[];
+this.interval=null;
+},add:function(_617){
+var _618=new Date().getTime();
+var _619=(typeof (_617.options.queue)=="string")?_617.options.queue:_617.options.queue.position;
+var ma=MochiKit.Base.map;
+switch(_619){
+case "front":
+ma(function(e){
+if(e.state=="idle"){
+e.startOn+=_617.finishOn;
+e.finishOn+=_617.finishOn;
+}
+},this.effects);
+break;
+case "end":
+var _61c;
+ma(function(e){
+var i=e.finishOn;
+if(i>=(_61c||i)){
+_61c=i;
+}
+},this.effects);
+_618=_61c||_618;
+break;
+case "break":
+ma(function(e){
+e.finalize();
+},this.effects);
+break;
+}
+_617.startOn+=_618;
+_617.finishOn+=_618;
+if(!_617.options.queue.limit||this.effects.length<_617.options.queue.limit){
+this.effects.push(_617);
+}
+if(!this.interval){
+this.interval=this.startLoop(MochiKit.Base.bind(this.loop,this),40);
+}
+},startLoop:function(func,_621){
+return setInterval(func,_621);
+},remove:function(_622){
+this.effects=MochiKit.Base.filter(function(e){
+return e!=_622;
+},this.effects);
+if(!this.effects.length){
+this.stopLoop(this.interval);
+this.interval=null;
+}
+},stopLoop:function(_624){
+clearInterval(_624);
+},loop:function(){
+var _625=new Date().getTime();
+MochiKit.Base.map(function(_626){
+_626.loop(_625);
+},this.effects);
+}});
+MochiKit.Visual.Queues={instances:{},get:function(_627){
+if(typeof (_627)!="string"){
+return _627;
+}
+if(!this.instances[_627]){
+this.instances[_627]=new MochiKit.Visual.ScopedQueue();
+}
+return this.instances[_627];
+}};
+MochiKit.Visual.Queue=MochiKit.Visual.Queues.get("global");
+MochiKit.Visual.DefaultOptions={transition:MochiKit.Visual.Transitions.sinoidal,duration:1,fps:25,sync:false,from:0,to:1,delay:0,queue:"parallel"};
+MochiKit.Visual.Base=function(){
+};
+MochiKit.Visual.Base.prototype={__class__:MochiKit.Visual.Base,start:function(_628){
+var v=MochiKit.Visual;
+this.options=MochiKit.Base.setdefault(_628||{},v.DefaultOptions);
+this.currentFrame=0;
+this.state="idle";
+this.startOn=this.options.delay*1000;
+this.finishOn=this.startOn+(this.options.duration*1000);
+this.event("beforeStart");
+if(!this.options.sync){
+v.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).add(this);
+}
+},loop:function(_62a){
+if(_62a>=this.startOn){
+if(_62a>=this.finishOn){
+return this.finalize();
+}
+var pos=(_62a-this.startOn)/(this.finishOn-this.startOn);
+var _62c=Math.round(pos*this.options.fps*this.options.duration);
+if(_62c>this.currentFrame){
+this.render(pos);
+this.currentFrame=_62c;
+}
+}
+},render:function(pos){
+if(this.state=="idle"){
+this.state="running";
+this.event("beforeSetup");
+this.setup();
+this.event("afterSetup");
+}
+if(this.state=="running"){
+if(this.options.transition){
+pos=this.options.transition(pos);
+}
+pos*=(this.options.to-this.options.from);
+pos+=this.options.from;
+this.event("beforeUpdate");
+this.update(pos);
+this.event("afterUpdate");
+}
+},cancel:function(){
+if(!this.options.sync){
+MochiKit.Visual.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).remove(this);
+}
+this.state="finished";
+},finalize:function(){
+this.render(1);
+this.cancel();
+this.event("beforeFinish");
+this.finish();
+this.event("afterFinish");
+},setup:function(){
+},finish:function(){
+},update:function(_62e){
+},event:function(_62f){
+if(this.options[_62f+"Internal"]){
+this.options[_62f+"Internal"](this);
+}
+if(this.options[_62f]){
+this.options[_62f](this);
+}
+},repr:function(){
+return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]";
+}};
+MochiKit.Visual.Parallel=function(_630,_631){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_630,_631);
+}
+this.__init__(_630,_631);
+};
+MochiKit.Visual.Parallel.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,{__class__:MochiKit.Visual.Parallel,__init__:function(_633,_634){
+this.effects=_633||[];
+this.start(_634);
+},update:function(_635){
+MochiKit.Base.map(function(_636){
+_636.render(_635);
+},this.effects);
+},finish:function(){
+MochiKit.Base.map(function(_637){
+_637.finalize();
+},this.effects);
+}});
+MochiKit.Visual.Opacity=function(_638,_639){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_638,_639);
+}
+this.__init__(_638,_639);
+};
+MochiKit.Visual.Opacity.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Opacity.prototype,{__class__:MochiKit.Visual.Opacity,__init__:function(_63b,_63c){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+this.element=MochiKit.DOM.getElement(_63b);
+if(this.element.currentStyle&&(!this.element.currentStyle.hasLayout)){
+s.setStyle(this.element,{zoom:1});
+}
+_63c=b.update({from:s.getStyle(this.element,"opacity")||0,to:1},_63c||{});
+this.start(_63c);
+},update:function(_63f){
+MochiKit.Style.setStyle(this.element,{"opacity":_63f});
+}});
+MochiKit.Visual.Move=function(_640,_641){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_640,_641);
+}
+this.__init__(_640,_641);
+};
+MochiKit.Visual.Move.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Move.prototype,{__class__:MochiKit.Visual.Move,__init__:function(_643,_644){
+this.element=MochiKit.DOM.getElement(_643);
+_644=MochiKit.Base.update({x:0,y:0,mode:"relative"},_644||{});
+this.start(_644);
+},setup:function(){
+MochiKit.DOM.makePositioned(this.element);
+var s=this.element.style;
+var _646=s.visibility;
+var _647=s.display;
+if(_647=="none"){
+s.visibility="hidden";
+s.display="";
+}
+this.originalLeft=parseFloat(MochiKit.Style.getStyle(this.element,"left")||"0");
+this.originalTop=parseFloat(MochiKit.Style.getStyle(this.element,"top")||"0");
+if(this.options.mode=="absolute"){
+this.options.x-=this.originalLeft;
+this.options.y-=this.originalTop;
+}
+if(_647=="none"){
+s.visibility=_646;
+s.display=_647;
+}
+},update:function(_648){
+MochiKit.Style.setStyle(this.element,{left:Math.round(this.options.x*_648+this.originalLeft)+"px",top:Math.round(this.options.y*_648+this.originalTop)+"px"});
+}});
+MochiKit.Visual.Scale=function(_649,_64a,_64b){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_649,_64a,_64b);
+}
+this.__init__(_649,_64a,_64b);
+};
+MochiKit.Visual.Scale.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Scale.prototype,{__class__:MochiKit.Visual.Scale,__init__:function(_64d,_64e,_64f){
+this.element=MochiKit.DOM.getElement(_64d);
+_64f=MochiKit.Base.update({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:_64e},_64f||{});
+this.start(_64f);
+},setup:function(){
+this.restoreAfterFinish=this.options.restoreAfterFinish||false;
+this.elementPositioning=MochiKit.Style.getStyle(this.element,"position");
+var ma=MochiKit.Base.map;
+var b=MochiKit.Base.bind;
+this.originalStyle={};
+ma(b(function(k){
+this.originalStyle[k]=this.element.style[k];
+},this),["top","left","width","height","fontSize"]);
+this.originalTop=this.element.offsetTop;
+this.originalLeft=this.element.offsetLeft;
+var _653=MochiKit.Style.getStyle(this.element,"font-size")||"100%";
+ma(b(function(_654){
+if(_653.indexOf(_654)>0){
+this.fontSize=parseFloat(_653);
+this.fontSizeType=_654;
+}
+},this),["em","px","%"]);
+this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;
+if(/^content/.test(this.options.scaleMode)){
+this.dims=[this.element.scrollHeight,this.element.scrollWidth];
+}else{
+if(this.options.scaleMode=="box"){
+this.dims=[this.element.offsetHeight,this.element.offsetWidth];
+}else{
+this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth];
+}
+}
+},update:function(_655){
+var _656=(this.options.scaleFrom/100)+(this.factor*_655);
+if(this.options.scaleContent&&this.fontSize){
+MochiKit.Style.setStyle(this.element,{fontSize:this.fontSize*_656+this.fontSizeType});
+}
+this.setDimensions(this.dims[0]*_656,this.dims[1]*_656);
+},finish:function(){
+if(this.restoreAfterFinish){
+MochiKit.Style.setStyle(this.element,this.originalStyle);
+}
+},setDimensions:function(_657,_658){
+var d={};
+var r=Math.round;
+if(/MSIE/.test(navigator.userAgent)){
+r=Math.ceil;
+}
+if(this.options.scaleX){
+d.width=r(_658)+"px";
+}
+if(this.options.scaleY){
+d.height=r(_657)+"px";
+}
+if(this.options.scaleFromCenter){
+var topd=(_657-this.dims[0])/2;
+var _65c=(_658-this.dims[1])/2;
+if(this.elementPositioning=="absolute"){
+if(this.options.scaleY){
+d.top=this.originalTop-topd+"px";
+}
+if(this.options.scaleX){
+d.left=this.originalLeft-_65c+"px";
+}
+}else{
+if(this.options.scaleY){
+d.top=-topd+"px";
+}
+if(this.options.scaleX){
+d.left=-_65c+"px";
+}
+}
+}
+MochiKit.Style.setStyle(this.element,d);
+}});
+MochiKit.Visual.Highlight=function(_65d,_65e){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_65d,_65e);
+}
+this.__init__(_65d,_65e);
+};
+MochiKit.Visual.Highlight.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,{__class__:MochiKit.Visual.Highlight,__init__:function(_660,_661){
+this.element=MochiKit.DOM.getElement(_660);
+_661=MochiKit.Base.update({startcolor:"#ffff99"},_661||{});
+this.start(_661);
+},setup:function(){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+if(s.getStyle(this.element,"display")=="none"){
+this.cancel();
+return;
+}
+this.oldStyle={backgroundImage:s.getStyle(this.element,"background-image")};
+s.setStyle(this.element,{backgroundImage:"none"});
+if(!this.options.endcolor){
+this.options.endcolor=MochiKit.Color.Color.fromBackground(this.element).toHexString();
+}
+if(b.isUndefinedOrNull(this.options.restorecolor)){
+this.options.restorecolor=s.getStyle(this.element,"background-color");
+}
+this._base=b.map(b.bind(function(i){
+return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+this._delta=b.map(b.bind(function(i){
+return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i];
+},this),[0,1,2]);
+},update:function(_666){
+var m="#";
+MochiKit.Base.map(MochiKit.Base.bind(function(i){
+m+=MochiKit.Color.toColorPart(Math.round(this._base[i]+this._delta[i]*_666));
+},this),[0,1,2]);
+MochiKit.Style.setStyle(this.element,{backgroundColor:m});
+},finish:function(){
+MochiKit.Style.setStyle(this.element,MochiKit.Base.update(this.oldStyle,{backgroundColor:this.options.restorecolor}));
+}});
+MochiKit.Visual.ScrollTo=function(_669,_66a){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_669,_66a);
+}
+this.__init__(_669,_66a);
+};
+MochiKit.Visual.ScrollTo.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,{__class__:MochiKit.Visual.ScrollTo,__init__:function(_66c,_66d){
+this.element=MochiKit.DOM.getElement(_66c);
+this.start(_66d||{});
+},setup:function(){
+var p=MochiKit.Position;
+p.prepare();
+var _66f=p.cumulativeOffset(this.element);
+if(this.options.offset){
+_66f.y+=this.options.offset;
+}
+var max;
+if(window.innerHeight){
+max=window.innerHeight-window.height;
+}else{
+if(document.documentElement&&document.documentElement.clientHeight){
+max=document.documentElement.clientHeight-document.body.scrollHeight;
+}else{
+if(document.body){
+max=document.body.clientHeight-document.body.scrollHeight;
+}
+}
+}
+this.scrollStart=p.windowOffset.y;
+this.delta=(_66f.y>max?max:_66f.y)-this.scrollStart;
+},update:function(_671){
+var p=MochiKit.Position;
+p.prepare();
+window.scrollTo(p.windowOffset.x,this.scrollStart+(_671*this.delta));
+}});
+MochiKit.Visual.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+MochiKit.Visual.Morph=function(_673,_674){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_673,_674);
+}
+this.__init__(_673,_674);
+};
+MochiKit.Visual.Morph.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Morph.prototype,{__class__:MochiKit.Visual.Morph,__init__:function(_676,_677){
+this.element=MochiKit.DOM.getElement(_676);
+this.start(_677||{});
+},setup:function(){
+var b=MochiKit.Base;
+var _679=this.options.style;
+this.styleStart={};
+this.styleEnd={};
+this.units={};
+var _67a,unit;
+for(var s in _679){
+_67a=_679[s];
+s=b.camelize(s);
+if(MochiKit.Visual.CSS_LENGTH.test(_67a)){
+var _67d=_67a.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+_67a=parseFloat(_67d[1]);
+unit=(_67d.length==3)?_67d[2]:null;
+this.styleEnd[s]=_67a;
+this.units[s]=unit;
+_67a=MochiKit.Style.getStyle(this.element,s);
+_67d=_67a.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+_67a=parseFloat(_67d[1]);
+this.styleStart[s]=_67a;
+}else{
+var c=MochiKit.Color.Color;
+_67a=c.fromString(_67a);
+if(_67a){
+this.units[s]="color";
+this.styleEnd[s]=_67a.toHexString();
+_67a=MochiKit.Style.getStyle(this.element,s);
+this.styleStart[s]=c.fromString(_67a).toHexString();
+this.styleStart[s]=b.map(b.bind(function(i){
+return parseInt(this.styleStart[s].slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+this.styleEnd[s]=b.map(b.bind(function(i){
+return parseInt(this.styleEnd[s].slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+}
+}
+}
+},update:function(_681){
+var _682;
+for(var s in this.styleStart){
+if(this.units[s]=="color"){
+var m="#";
+var _685=this.styleStart[s];
+var end=this.styleEnd[s];
+MochiKit.Base.map(MochiKit.Base.bind(function(i){
+m+=MochiKit.Color.toColorPart(Math.round(_685[i]+(end[i]-_685[i])*_681));
+},this),[0,1,2]);
+this.element.style[s]=m;
+}else{
+_682=this.styleStart[s]+Math.round((this.styleEnd[s]-this.styleStart[s])*_681*1000)/1000+this.units[s];
+this.element.style[s]=_682;
+}
+}
+}});
+MochiKit.Visual.fade=function(_688,_689){
+var s=MochiKit.Style;
+var _68b=s.getStyle(_688,"opacity");
+_689=MochiKit.Base.update({from:s.getStyle(_688,"opacity")||1,to:0,afterFinishInternal:function(_68c){
+if(_68c.options.to!==0){
+return;
+}
+s.hideElement(_68c.element);
+s.setStyle(_68c.element,{"opacity":_68b});
+}},_689||{});
+return new MochiKit.Visual.Opacity(_688,_689);
+};
+MochiKit.Visual.appear=function(_68d,_68e){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_68e=MochiKit.Base.update({from:(s.getStyle(_68d,"display")=="none"?0:s.getStyle(_68d,"opacity")||0),to:1,afterFinishInternal:function(_691){
+v.forceRerendering(_691.element);
+},beforeSetupInternal:function(_692){
+s.setStyle(_692.element,{"opacity":_692.options.from});
+s.showElement(_692.element);
+}},_68e||{});
+return new v.Opacity(_68d,_68e);
+};
+MochiKit.Visual.puff=function(_693,_694){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_693=MochiKit.DOM.getElement(_693);
+var _697={position:s.getStyle(_693,"position"),top:_693.style.top,left:_693.style.left,width:_693.style.width,height:_693.style.height,opacity:s.getStyle(_693,"opacity")};
+_694=MochiKit.Base.update({beforeSetupInternal:function(_698){
+MochiKit.Position.absolutize(_698.effects[0].element);
+},afterFinishInternal:function(_699){
+s.hideElement(_699.effects[0].element);
+s.setStyle(_699.effects[0].element,_697);
+},scaleContent:true,scaleFromCenter:true},_694||{});
+return new v.Parallel([new v.Scale(_693,200,{sync:true,scaleFromCenter:_694.scaleFromCenter,scaleContent:_694.scaleContent,restoreAfterFinish:true}),new v.Opacity(_693,{sync:true,to:0})],_694);
+};
+MochiKit.Visual.blindUp=function(_69a,_69b){
+var d=MochiKit.DOM;
+_69a=d.getElement(_69a);
+var _69d=d.makeClipping(_69a);
+_69b=MochiKit.Base.update({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(_69e){
+MochiKit.Style.hideElement(_69e.element);
+d.undoClipping(_69e.element,_69d);
+}},_69b||{});
+return new MochiKit.Visual.Scale(_69a,0,_69b);
+};
+MochiKit.Visual.blindDown=function(_69f,_6a0){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_69f=d.getElement(_69f);
+var _6a3=s.getElementDimensions(_69f);
+var _6a4;
+_6a0=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_6a3.h,originalWidth:_6a3.w},restoreAfterFinish:true,afterSetupInternal:function(_6a5){
+_6a4=d.makeClipping(_6a5.element);
+s.setStyle(_6a5.element,{height:"0px"});
+s.showElement(_6a5.element);
+},afterFinishInternal:function(_6a6){
+d.undoClipping(_6a6.element,_6a4);
+}},_6a0||{});
+return new MochiKit.Visual.Scale(_69f,100,_6a0);
+};
+MochiKit.Visual.switchOff=function(_6a7,_6a8){
+var d=MochiKit.DOM;
+_6a7=d.getElement(_6a7);
+var _6aa=MochiKit.Style.getStyle(_6a7,"opacity");
+var _6ab;
+_6a8=MochiKit.Base.update({duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetupInternal:function(_6ac){
+d.makePositioned(_6ac.element);
+_6ab=d.makeClipping(_6ac.element);
+},afterFinishInternal:function(_6ad){
+MochiKit.Style.hideElement(_6ad.element);
+d.undoClipping(_6ad.element,_6ab);
+d.undoPositioned(_6ad.element);
+MochiKit.Style.setStyle(_6ad.element,{"opacity":_6aa});
+}},_6a8||{});
+var v=MochiKit.Visual;
+return new v.appear(_6a7,{duration:0.4,from:0,transition:v.Transitions.flicker,afterFinishInternal:function(_6af){
+new v.Scale(_6af.element,1,_6a8);
+}});
+};
+MochiKit.Visual.dropOut=function(_6b0,_6b1){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_6b0=d.getElement(_6b0);
+var _6b4={top:s.getStyle(_6b0,"top"),left:s.getStyle(_6b0,"left"),opacity:s.getStyle(_6b0,"opacity")};
+_6b1=MochiKit.Base.update({duration:0.5,distance:100,beforeSetupInternal:function(_6b5){
+d.makePositioned(_6b5.effects[0].element);
+},afterFinishInternal:function(_6b6){
+s.hideElement(_6b6.effects[0].element);
+d.undoPositioned(_6b6.effects[0].element);
+s.setStyle(_6b6.effects[0].element,_6b4);
+}},_6b1||{});
+var v=MochiKit.Visual;
+return new v.Parallel([new v.Move(_6b0,{x:0,y:_6b1.distance,sync:true}),new v.Opacity(_6b0,{sync:true,to:0})],_6b1);
+};
+MochiKit.Visual.shake=function(_6b8,_6b9){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_6b8=d.getElement(_6b8);
+_6b9=MochiKit.Base.update({x:-20,y:0,duration:0.05,afterFinishInternal:function(_6bd){
+d.undoPositioned(_6bd.element);
+s.setStyle(_6bd.element,_6be);
+}},_6b9||{});
+var _6be={top:s.getStyle(_6b8,"top"),left:s.getStyle(_6b8,"left")};
+return new v.Move(_6b8,{x:20,y:0,duration:0.05,afterFinishInternal:function(_6bf){
+new v.Move(_6bf.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_6c0){
+new v.Move(_6c0.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_6c1){
+new v.Move(_6c1.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_6c2){
+new v.Move(_6c2.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_6c3){
+new v.Move(_6c3.element,_6b9);
+}});
+}});
+}});
+}});
+}});
+};
+MochiKit.Visual.slideDown=function(_6c4,_6c5){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_6c4=d.getElement(_6c4);
+if(!_6c4.firstChild){
+throw "MochiKit.Visual.slideDown must be used on a element with a child";
+}
+d.removeEmptyTextNodes(_6c4);
+var _6c9=s.getStyle(_6c4.firstChild,"bottom")||0;
+var _6ca=s.getElementDimensions(_6c4);
+var _6cb;
+_6c5=b.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_6ca.h,originalWidth:_6ca.w},restoreAfterFinish:true,afterSetupInternal:function(_6cc){
+d.makePositioned(_6cc.element);
+d.makePositioned(_6cc.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_6cc.element,{top:""});
+}
+_6cb=d.makeClipping(_6cc.element);
+s.setStyle(_6cc.element,{height:"0px"});
+s.showElement(_6cc.element);
+},afterUpdateInternal:function(_6cd){
+s.setStyle(_6cd.element.firstChild,{bottom:(_6cd.dims[0]-_6cd.element.clientHeight)+"px"});
+},afterFinishInternal:function(_6ce){
+d.undoClipping(_6ce.element,_6cb);
+if(/MSIE/.test(navigator.userAgent)){
+d.undoPositioned(_6ce.element);
+d.undoPositioned(_6ce.element.firstChild);
+}else{
+d.undoPositioned(_6ce.element.firstChild);
+d.undoPositioned(_6ce.element);
+}
+s.setStyle(_6ce.element.firstChild,{bottom:_6c9});
+}},_6c5||{});
+return new MochiKit.Visual.Scale(_6c4,100,_6c5);
+};
+MochiKit.Visual.slideUp=function(_6cf,_6d0){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_6cf=d.getElement(_6cf);
+if(!_6cf.firstChild){
+throw "MochiKit.Visual.slideUp must be used on a element with a child";
+}
+d.removeEmptyTextNodes(_6cf);
+var _6d4=s.getStyle(_6cf.firstChild,"bottom");
+var _6d5;
+_6d0=b.update({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(_6d6){
+d.makePositioned(_6d6.element);
+d.makePositioned(_6d6.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_6d6.element,{top:""});
+}
+_6d5=d.makeClipping(_6d6.element);
+s.showElement(_6d6.element);
+},afterUpdateInternal:function(_6d7){
+s.setStyle(_6d7.element.firstChild,{bottom:(_6d7.dims[0]-_6d7.element.clientHeight)+"px"});
+},afterFinishInternal:function(_6d8){
+s.hideElement(_6d8.element);
+d.undoClipping(_6d8.element,_6d5);
+d.undoPositioned(_6d8.element.firstChild);
+d.undoPositioned(_6d8.element);
+s.setStyle(_6d8.element.firstChild,{bottom:_6d4});
+}},_6d0||{});
+return new MochiKit.Visual.Scale(_6cf,0,_6d0);
+};
+MochiKit.Visual.squish=function(_6d9,_6da){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var _6dd;
+_6da=b.update({restoreAfterFinish:true,beforeSetupInternal:function(_6de){
+_6dd=d.makeClipping(_6de.element);
+},afterFinishInternal:function(_6df){
+MochiKit.Style.hideElement(_6df.element);
+d.undoClipping(_6df.element,_6dd);
+}},_6da||{});
+return new MochiKit.Visual.Scale(_6d9,/Opera/.test(navigator.userAgent)?1:0,_6da);
+};
+MochiKit.Visual.grow=function(_6e0,_6e1){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_6e0=d.getElement(_6e0);
+_6e1=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.full,scaleContent:true,scaleFromCenter:false},_6e1||{});
+var _6e5={top:_6e0.style.top,left:_6e0.style.left,height:_6e0.style.height,width:_6e0.style.width,opacity:s.getStyle(_6e0,"opacity")};
+var dims=s.getElementDimensions(_6e0);
+var _6e7,_6e8;
+var _6e9,_6ea;
+switch(_6e1.direction){
+case "top-left":
+_6e7=_6e8=_6e9=_6ea=0;
+break;
+case "top-right":
+_6e7=dims.w;
+_6e8=_6ea=0;
+_6e9=-dims.w;
+break;
+case "bottom-left":
+_6e7=_6e9=0;
+_6e8=dims.h;
+_6ea=-dims.h;
+break;
+case "bottom-right":
+_6e7=dims.w;
+_6e8=dims.h;
+_6e9=-dims.w;
+_6ea=-dims.h;
+break;
+case "center":
+_6e7=dims.w/2;
+_6e8=dims.h/2;
+_6e9=-dims.w/2;
+_6ea=-dims.h/2;
+break;
+}
+var _6eb=MochiKit.Base.update({beforeSetupInternal:function(_6ec){
+s.setStyle(_6ec.effects[0].element,{height:"0px"});
+s.showElement(_6ec.effects[0].element);
+},afterFinishInternal:function(_6ed){
+d.undoClipping(_6ed.effects[0].element);
+d.undoPositioned(_6ed.effects[0].element);
+s.setStyle(_6ed.effects[0].element,_6e5);
+}},_6e1||{});
+return new v.Move(_6e0,{x:_6e7,y:_6e8,duration:0.01,beforeSetupInternal:function(_6ee){
+s.hideElement(_6ee.element);
+d.makeClipping(_6ee.element);
+d.makePositioned(_6ee.element);
+},afterFinishInternal:function(_6ef){
+new v.Parallel([new v.Opacity(_6ef.element,{sync:true,to:1,from:0,transition:_6e1.opacityTransition}),new v.Move(_6ef.element,{x:_6e9,y:_6ea,sync:true,transition:_6e1.moveTransition}),new v.Scale(_6ef.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:/Opera/.test(navigator.userAgent)?1:0,transition:_6e1.scaleTransition,scaleContent:_6e1.scaleContent,scaleFromCenter:_6e1.scaleFromCenter,restoreAfterFinish:true})],_6eb);
+}});
+};
+MochiKit.Visual.shrink=function(_6f0,_6f1){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_6f0=d.getElement(_6f0);
+_6f1=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none,scaleContent:true,scaleFromCenter:false},_6f1||{});
+var _6f5={top:_6f0.style.top,left:_6f0.style.left,height:_6f0.style.height,width:_6f0.style.width,opacity:s.getStyle(_6f0,"opacity")};
+var dims=s.getElementDimensions(_6f0);
+var _6f7,_6f8;
+switch(_6f1.direction){
+case "top-left":
+_6f7=_6f8=0;
+break;
+case "top-right":
+_6f7=dims.w;
+_6f8=0;
+break;
+case "bottom-left":
+_6f7=0;
+_6f8=dims.h;
+break;
+case "bottom-right":
+_6f7=dims.w;
+_6f8=dims.h;
+break;
+case "center":
+_6f7=dims.w/2;
+_6f8=dims.h/2;
+break;
+}
+var _6f9;
+var _6fa=MochiKit.Base.update({beforeStartInternal:function(_6fb){
+_6f9=d.makePositioned(_6fb.effects[0].element);
+d.makeClipping(_6fb.effects[0].element);
+},afterFinishInternal:function(_6fc){
+s.hideElement(_6fc.effects[0].element);
+d.undoClipping(_6fc.effects[0].element,_6f9);
+d.undoPositioned(_6fc.effects[0].element);
+s.setStyle(_6fc.effects[0].element,_6f5);
+}},_6f1||{});
+return new v.Parallel([new v.Opacity(_6f0,{sync:true,to:0,from:1,transition:_6f1.opacityTransition}),new v.Scale(_6f0,/Opera/.test(navigator.userAgent)?1:0,{sync:true,transition:_6f1.scaleTransition,scaleContent:_6f1.scaleContent,scaleFromCenter:_6f1.scaleFromCenter,restoreAfterFinish:true}),new v.Move(_6f0,{x:_6f7,y:_6f8,sync:true,transition:_6f1.moveTransition})],_6fa);
+};
+MochiKit.Visual.pulsate=function(_6fd,_6fe){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var b=MochiKit.Base;
+var _702=MochiKit.Style.getStyle(_6fd,"opacity");
+_6fe=b.update({duration:3,from:0,afterFinishInternal:function(_703){
+MochiKit.Style.setStyle(_703.element,{"opacity":_702});
+}},_6fe||{});
+var _704=_6fe.transition||v.Transitions.sinoidal;
+var _705=b.bind(function(pos){
+return _704(1-v.Transitions.pulse(pos,_6fe.pulses));
+},_704);
+b.bind(_705,_704);
+return new v.Opacity(_6fd,b.update({transition:_705},_6fe));
+};
+MochiKit.Visual.fold=function(_707,_708){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_707=d.getElement(_707);
+var _70c={top:_707.style.top,left:_707.style.left,width:_707.style.width,height:_707.style.height};
+var _70d=d.makeClipping(_707);
+_708=MochiKit.Base.update({scaleContent:false,scaleX:false,afterFinishInternal:function(_70e){
+new v.Scale(_707,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(_70f){
+s.hideElement(_70f.element);
+d.undoClipping(_70f.element,_70d);
+s.setStyle(_70f.element,_70c);
+}});
+}},_708||{});
+return new v.Scale(_707,5,_708);
+};
+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","tagifyText","multiple","toggle","Parallel","Opacity","Move","Scale","Highlight","ScrollTo","Morph","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"];
+MochiKit.Visual.EXPORT_OK=["Base","PAIRS"];
+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.4";
+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","Selector","Style","LoggingPane","Color","Signal","Position","Visual"];
+if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.MochiKit");
+dojo.require("MochiKit.*");
+}
+if(typeof (JSAN)!="undefined"){
+(function(lst){
+for(var i=0;i<lst.length;i++){
+JSAN.use("MochiKit."+lst[i],[]);
+}
+})(MochiKit.MochiKit.SUBMODULES);
+}
+(function(){
+var _713=MochiKit.Base.extend;
+var self=MochiKit.MochiKit;
+var _715=self.SUBMODULES;
+var _716=[];
+var _717=[];
+var _718={};
+var i,k,m,all;
+for(i=0;i<_715.length;i++){
+m=MochiKit[_715[i]];
+_713(_716,m.EXPORT);
+_713(_717,m.EXPORT_OK);
+for(k in m.EXPORT_TAGS){
+_718[k]=_713(_718[k],m.EXPORT_TAGS[k]);
+}
+all=m.EXPORT_TAGS[":all"];
+if(!all){
+all=_713(null,m.EXPORT,m.EXPORT_OK);
+}
+var j;
+for(j=0;j<all.length;j++){
+k=all[j];
+self[k]=m[k];
+}
+}
+self.EXPORT=_716;
+self.EXPORT_OK=_717;
+self.EXPORT_TAGS=_718;
+}());
+}else{
+if(typeof (MochiKit.__compat__)=="undefined"){
+MochiKit.__compat__=true;
+}
+(function(){
+if(typeof (document)=="undefined"){
+return;
+}
+var _71e=document.getElementsByTagName("script");
+var _71f="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+var base=null;
+var _721=null;
+var _722={};
+var i;
+for(i=0;i<_71e.length;i++){
+var src=_71e[i].getAttribute("src");
+if(!src){
+continue;
+}
+_722[src]=true;
+if(src.match(/MochiKit.js$/)){
+base=src.substring(0,src.lastIndexOf("MochiKit.js"));
+_721=_71e[i];
+}
+}
+if(base===null){
+return;
+}
+var _725=MochiKit.MochiKit.SUBMODULES;
+for(var i=0;i<_725.length;i++){
+if(MochiKit[_725[i]]){
+continue;
+}
+var uri=base+_725[i]+".js";
+if(uri in _722){
+continue;
+}
+if(document.documentElement&&document.documentElement.namespaceURI==_71f){
+var s=document.createElementNS(_71f,"script");
+s.setAttribute("id","MochiKit_"+base+_725[i]);
+s.setAttribute("src",uri);
+s.setAttribute("type","application/x-javascript");
+_721.parentNode.appendChild(s);
+}else{
+document.write("<script src=\""+uri+"\" type=\"text/javascript\"></script>");
+}
+}
+})();
+}
+
+
+/***
+
+    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);
+
+
+// Copyright 2006 Dan Vanderkam (danvdk@gmail.com)
+// All Rights Reserved.
+
+/**
+ * @fileoverview Subclasses various parts of PlotKit to meet the additional
+ * needs of DateGraph: grid overlays and error bars
+ */
+
+// Subclass PlotKit.Layout to add:
+// 1. Sigma/errorBars properties
+// 2. Copy error terms for PlotKit.CanvasRenderer._renderLineChart
+
+/**
+ * Creates a new DateGraphLayout object. Options are the same as those allowed
+ * by the PlotKit.Layout constructor.
+ * @param {Object} options Options for PlotKit.Layout
+ * @return {Object} The DateGraphLayout object
+ */
+DateGraphLayout = function(options) {
+  PlotKit.Layout.call(this, "line", options);
+};
+DateGraphLayout.prototype = new PlotKit.Layout();
+
+/**
+ * Behaves the same way as PlotKit.Layout, but also copies the errors
+ * @private
+ */
+DateGraphLayout.prototype.evaluateWithError = function() {
+  this.evaluate();
+  if (!this.options.errorBars) return;
+
+  // Copy over the error terms
+  var i = 0; // index in this.points
+  for (var setName in this.datasets) {
+    var j = 0;
+    var dataset = this.datasets[setName];
+    if (PlotKit.Base.isFuncLike(dataset)) continue;
+    for (var j = 0; j < dataset.length; j++, i++) {
+      var item = dataset[j];
+      var xv = parseFloat(item[0]);
+      var yv = parseFloat(item[1]);
+
+      if (xv == this.points[i].xval &&
+          yv == this.points[i].yval) {
+        this.points[i].errorMinus = parseFloat(item[2]);
+        this.points[i].errorPlus = parseFloat(item[3]);
+      }
+    }
+  }
+};
+
+/**
+ * Convenience function to remove all the data sets from a graph
+ */
+DateGraphLayout.prototype.removeAllDatasets = function() {
+  delete this.datasets;
+  this.datasets = new Array();
+};
+
+/**
+ * Change the values of various layout options
+ * @param {Object} new_options an associative array of new properties
+ */
+DateGraphLayout.prototype.updateOptions = function(new_options) {
+  MochiKit.Base.update(this.options, new_options ? new_options : {});
+};
+
+// Subclass PlotKit.CanvasRenderer to add:
+// 1. X/Y grid overlay
+// 2. Ability to draw error bars (if required)
+
+/**
+ * Sets some PlotKit.CanvasRenderer options
+ * @param {Object} element The canvas to attach to
+ * @param {Layout} layout The DateGraphLayout object for this graph.
+ * @param {Object} options Options to pass on to CanvasRenderer
+ */
+DateGraphCanvasRenderer = function(element, layout, options) {
+  PlotKit.CanvasRenderer.call(this, element, layout, options);
+  this.options.shouldFill = false;
+  this.options.shouldStroke = true;
+  this.options.drawYGrid = true;
+  this.options.drawXGrid = true;
+  this.options.gridLineColor = MochiKit.Color.Color.grayColor();
+  MochiKit.Base.update(this.options, options);
+
+  // TODO(danvk) This shouldn't be necessary: effects should be overlaid
+  this.options.drawBackground = false;
+};
+DateGraphCanvasRenderer.prototype = new PlotKit.CanvasRenderer();
+
+/**
+ * Draw an X/Y grid on top of the existing plot
+ */
+DateGraphCanvasRenderer.prototype.render = function() {
+  // Do the ordinary rendering, as before
+  // TODO(danvk) Call super.render()
+  this._renderLineChart();
+  this._renderLineAxis();
+
+  // Draw the new X/Y grid
+  var ctx = this.element.getContext("2d");
+  if (this.options.drawYGrid) {
+    var ticks = this.layout.yticks;
+    ctx.save();
+    ctx.strokeStyle = this.options.gridLineColor.toRGBString();
+    ctx.lineWidth = this.options.axisLineWidth;
+    for (var i = 0; i < ticks.length; i++) {
+      var x = this.area.x;
+      var y = this.area.y + ticks[i][0] * this.area.h;
+      ctx.beginPath();
+      ctx.moveTo(x, y);
+      ctx.lineTo(x + this.area.w, y);
+      ctx.closePath();
+      ctx.stroke();
+    }
+  }
+
+  if (this.options.drawXGrid) {
+    var ticks = this.layout.xticks;
+    ctx.save();
+    ctx.strokeStyle = this.options.gridLineColor.toRGBString();
+    ctx.lineWidth = this.options.axisLineWidth;
+    for (var i=0; i<ticks.length; i++) {
+      var x = this.area.x + ticks[i][0] * this.area.w;
+      var y = this.area.y + this.area.h;
+      ctx.beginPath();
+      ctx.moveTo(x, y);
+      ctx.lineTo(x, this.area.y);
+      ctx.closePath();
+      ctx.stroke();
+    }
+  }
+};
+
+/**
+ * Overrides the CanvasRenderer method to draw error bars
+ */
+DateGraphCanvasRenderer.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 errorBars = this.layout.options.errorBars;
+  var setCount = setNames.length;
+  var bind = MochiKit.Base.bind;
+  var partial = MochiKit.Base.partial;
+
+  //Update Points
+  var updatePoint = function(point) {
+    point.canvasx = this.area.w * point.x + this.area.x;
+    point.canvasy = this.area.h * point.y + this.area.y;
+  }
+  MochiKit.Iter.forEach(this.layout.points, updatePoint, this);
+
+  // create paths
+  var makePath = function(ctx) {
+    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.strokeStyle = color.toRGBString();
+      context.lineWidth = this.options.strokeWidth;
+      ctx.beginPath();
+      var point = this.layout.points[0];
+      var first_point = true;
+      var addPoint = function(ctx_, point) {
+        if (point.name == setName) {
+          if (first_point)
+            ctx_.moveTo(point.canvasx, point.canvasy);
+          else
+            ctx_.lineTo(point.canvasx, point.canvasy);
+          first_point = false;
+        }
+      };
+      MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
+      ctx.stroke();
+    }
+  };
+
+  var makeErrorBars = function(ctx) {
+    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.strokeStyle = color.toRGBString();
+      context.lineWidth = this.options.strokeWidth;
+      var prevX = -1;
+      var prevYs = [-1, -1];
+      var count = 0;
+      var yscale = this.layout.yscale;
+      var errorTrapezoid = function(ctx_,point) {
+        count++;
+        if (point.name == setName) {
+          var newYs = [ point.y - point.errorPlus * yscale,
+                        point.y + point.errorMinus * yscale ];
+          newYs[0] = this.area.h * newYs[0] + this.area.y;
+          newYs[1] = this.area.h * newYs[1] + this.area.y;
+          if (prevX >= 0) {
+            ctx_.moveTo(prevX, prevYs[0]);
+            ctx_.lineTo(point.canvasx, newYs[0]);
+            ctx_.lineTo(point.canvasx, newYs[1]);
+            ctx_.lineTo(prevX, prevYs[1]);
+            ctx_.closePath();
+          }
+          prevYs[0] = newYs[0];
+          prevYs[1] = newYs[1];
+          prevX = point.canvasx;
+        }
+      };
+      // should be same color as the lines
+      var err_color = color.colorWithAlpha(0.15);
+      ctx.fillStyle = err_color.toRGBString();
+      ctx.beginPath();
+      MochiKit.Iter.forEach(this.layout.points, partial(errorTrapezoid, ctx), this);
+      ctx.fill();
+    }
+  };
+
+  if (errorBars)
+    bind(makeErrorBars, this)(context);
+  bind(makePath, this)(context);
+  context.restore();
+};
+// Copyright 2006 Dan Vanderkam (danvdk@gmail.com)
+// All Rights Reserved.
+
+/**
+ * @fileoverview Creates an interactive, zoomable graph based on a CSV file or
+ * string. DateGraph can handle multiple series with or without error bars. The
+ * date/value ranges will be automatically set. DateGraph uses the
+ * &lt;canvas&gt; tag, so it only works in FF1.5+.
+ * @author danvdk@gmail.com (Dan Vanderkam)
+
+  Usage:
+   <div id="graphdiv" style="width:800px; height:500px;"></div>
+   <script type="text/javascript">
+     new DateGraph(document.getElementById("graphdiv"),
+                   "datafile.csv",
+                     ["Series 1", "Series 2"],
+                     { }); // options
+   </script>
+
+ The CSV file is of the form
+
+   YYYYMMDD,A1,B1,C1
+   YYYYMMDD,A2,B2,C2
+
+ If null is passed as the third parameter (series names), then the first line
+ of the CSV file is assumed to contain names for each series.
+
+ If the 'errorBars' option is set in the constructor, the input should be of
+ the form
+
+   YYYYMMDD,A1,sigmaA1,B1,sigmaB1,...
+   YYYYMMDD,A2,sigmaA2,B2,sigmaB2,...
+
+ If the 'fractions' option is set, the input should be of the form:
+
+   YYYYMMDD,A1/B1,A2/B2,...
+   YYYYMMDD,A1/B1,A2/B2,...
+
+ And error bars will be calculated automatically using a binomial distribution.
+
+ For further documentation and examples, see http://www/~danvk/dg/
+
+ */
+
+/**
+ * An interactive, zoomable graph
+ * @param {String | Function} file A file containing CSV data or a function that
+ * returns this data. The expected format for each line is
+ * YYYYMMDD,val1,val2,... or, if attrs.errorBars is set,
+ * YYYYMMDD,val1,stddev1,val2,stddev2,...
+ * @param {Array.<String>} labels Labels for the data series
+ * @param {Object} attrs Various other attributes, e.g. errorBars determines
+ * whether the input data contains error ranges.
+ */
+DateGraph = function(div, file, labels, attrs) {
+  if (arguments.length > 0)
+    this.__init__(div, file, labels, attrs);
+};
+
+DateGraph.NAME = "DateGraph";
+DateGraph.VERSION = "1.1";
+DateGraph.__repr__ = function() {
+  return "[" + this.NAME + " " + this.VERSION + "]";
+};
+DateGraph.toString = function() {
+  return this.__repr__();
+};
+
+// Various default values
+DateGraph.DEFAULT_ROLL_PERIOD = 1;
+DateGraph.DEFAULT_WIDTH = 480;
+DateGraph.DEFAULT_HEIGHT = 320;
+DateGraph.DEFAULT_STROKE_WIDTH = 1.0;
+DateGraph.AXIS_LINE_WIDTH = 0.3;
+
+/**
+ * Initializes the DateGraph. This creates a new DIV and constructs the PlotKit
+ * and interaction &lt;canvas&gt; inside of it. See the constructor for details
+ * on the parameters.
+ * @param {String | Function} file Source data
+ * @param {Array.<String>} labels Names of the data series
+ * @param {Object} attrs Miscellaneous other options
+ * @private
+ */
+DateGraph.prototype.__init__ = function(div, file, labels, attrs) {
+  // Copy the important bits into the object
+  this.maindiv_ = div;
+  this.labels_ = labels;
+  this.file_ = file;
+  this.rollPeriod_ = attrs.rollPeriod || DateGraph.DEFAULT_ROLL_PERIOD;
+  this.previousVerticalX_ = -1;
+  this.width_ = parseInt(div.style.width, 10);
+  this.height_ = parseInt(div.style.height, 10);
+  this.errorBars_ = attrs.errorBars || false;
+  this.fractions_ = attrs.fractions || false;
+  this.strokeWidth_ = attrs.strokeWidth || DateGraph.DEFAULT_STROKE_WIDTH;
+  this.dateWindow_ = attrs.dateWindow || null;
+  this.valueRange_ = attrs.valueRange || null;
+  this.labelsSeparateLines = attrs.labelsSeparateLines || false;
+  this.labelsDiv_ = attrs.labelsDiv || null;
+  this.labelsKMB_ = attrs.labelsKMB || false;
+  this.minTickSize_ = attrs.minTickSize || 0;
+  this.xValueParser_ = attrs.xValueParser || DateGraph.prototype.dateParser;
+  this.xValueFormatter_ = attrs.xValueFormatter ||
+      DateGraph.prototype.dateString_;
+  this.xTicker_ = attrs.xTicker || DateGraph.prototype.dateTicker;
+  this.sigma_ = attrs.sigma || 2.0;
+  this.wilsonInterval_ = attrs.wilsonInterval || true;
+  this.customBars_ = attrs.customBars || false;
+  this.attrs_ = attrs;
+
+  // Make a note of whether labels will be pulled from the CSV file.
+  this.labelsFromCSV_ = (this.labels_ == null);
+  if (this.labels_ == null)
+    this.labels_ = [];
+
+  // Prototype of the callback is "void clickCallback(event, date)"
+  this.clickCallback_ = attrs.clickCallback || null;
+
+  // Prototype of zoom callback is "void dragCallback(minDate, maxDate)"
+  this.zoomCallback_ = attrs.zoomCallback || null;
+
+  // Create the containing DIV and other interactive elements
+  this.createInterface_();
+
+  // Create the PlotKit grapher
+  this.layoutOptions_ = { 'errorBars': (this.errorBars_ || this.customBars_),
+                          'xOriginIsZero': false };
+  MochiKit.Base.update(this.layoutOptions_, attrs);
+  this.setColors_(attrs);
+
+  this.layout_ = new DateGraphLayout(this.layoutOptions_);
+
+  this.renderOptions_ = { colorScheme: this.colors_,
+                          strokeColor: null,
+                          strokeWidth: this.strokeWidth_,
+                          axisLabelFontSize: 14,
+                          axisLineWidth: DateGraph.AXIS_LINE_WIDTH };
+  MochiKit.Base.update(this.renderOptions_, attrs);
+  this.plotter_ = new DateGraphCanvasRenderer(this.hidden_, this.layout_,
+                                              this.renderOptions_);
+
+  this.createStatusMessage_();
+  this.createRollInterface_();
+  this.createDragInterface_();
+
+  MochiKit.DOM.addLoadEvent(this.start_());
+};
+
+/**
+ * Returns the current rolling period, as set by the user or an option.
+ * @return {Number} The number of days in the rolling window
+ */
+DateGraph.prototype.rollPeriod = function() {
+  return this.rollPeriod_;
+}
+
+/**
+ * Generates interface elements for the DateGraph: a containing div, a div to
+ * display the current point, and a textbox to adjust the rolling average
+ * period.
+ * @private
+ */
+DateGraph.prototype.createInterface_ = function() {
+  // Create the all-enclosing graph div
+  var enclosing = this.maindiv_;
+
+  this.graphDiv = MochiKit.DOM.DIV( { style: { 'width': this.width_ + "px",
+                                                'height': this.height_ + "px"
+                                                 }});
+  appendChildNodes(enclosing, this.graphDiv);
+
+  // Create the canvas to store
+  var canvas = MochiKit.DOM.CANVAS;
+  this.canvas_ = canvas( { style: { 'position': 'absolute' },
+                          width: this.width_,
+                          height: this.height_});
+  appendChildNodes(this.graphDiv, this.canvas_);
+
+  this.hidden_ = this.createPlotKitCanvas_(this.canvas_);
+  connect(this.hidden_, 'onmousemove', this, function(e) { this.mouseMove_(e) });
+  connect(this.hidden_, 'onmouseout', this, function(e) { this.mouseOut_(e) });
+}
+
+/**
+ * Creates the canvas containing the PlotKit graph. Only plotkit ever draws on
+ * this particular canvas. All DateGraph work is done on this.canvas_.
+ * @param {Object} canvas The DateGraph canvas to over which to overlay the plot
+ * @return {Object} The newly-created canvas
+ * @private
+ */
+DateGraph.prototype.createPlotKitCanvas_ = function(canvas) {
+  var h = document.createElement("canvas");
+  h.style.position = "absolute";
+  h.style.top = canvas.style.top;
+  h.style.left = canvas.style.left;
+  h.width = this.width_;
+  h.height = this.height_;
+  MochiKit.DOM.appendChildNodes(this.graphDiv, h);
+  return h;
+};
+
+/**
+ * Generate a set of distinct colors for the data series. This is done with a
+ * color wheel. Saturation/Value are customizable, and the hue is
+ * equally-spaced around the color wheel. If a custom set of colors is
+ * specified, that is used instead.
+ * @param {Object} attrs Various attributes, e.g. saturation and value
+ * @private
+ */
+DateGraph.prototype.setColors_ = function(attrs) {
+  var num = this.labels_.length;
+  this.colors_ = [];
+  if (!attrs.colors) {
+    var sat = attrs.colorSaturation || 1.0;
+    var val = attrs.colorValue || 0.5;
+    for (var i = 1; i <= num; i++) {
+      var hue = (1.0*i/(1+num));
+      this.colors_.push( MochiKit.Color.Color.fromHSV(hue, sat, val) );
+    }
+  } else {
+    for (var i = 0; i < num; i++) {
+      var colorStr = attrs.colors[i % attrs.colors.length];
+      this.colors_.push( MochiKit.Color.Color.fromString(colorStr) );
+    }
+  }
+}
+
+/**
+ * Create the div that contains information on the selected point(s)
+ * This goes in the top right of the canvas, unless an external div has already
+ * been specified.
+ * @private
+ */
+DateGraph.prototype.createStatusMessage_ = function(){
+  if (!this.labelsDiv_) {
+    var divWidth = 250;
+    var messagestyle = { "style": {
+      "position": "absolute",
+      "fontSize": "14px",
+      "zIndex": 10,
+      "width": divWidth + "px",
+      "top": "0px",
+      "left": this.width_ - divWidth + "px",
+      "background": "white",
+      "textAlign": "left",
+      "overflow": "hidden"}};
+    this.labelsDiv_ = MochiKit.DOM.DIV(messagestyle);
+    MochiKit.DOM.appendChildNodes(this.graphDiv, this.labelsDiv_);
+  }
+};
+
+/**
+ * Create the text box to adjust the averaging period
+ * @return {Object} The newly-created text box
+ * @private
+ */
+DateGraph.prototype.createRollInterface_ = function() {
+  var padding = this.plotter_.options.padding;
+  var textAttr = { "type": "text",
+                   "size": "2",
+                   "value": this.rollPeriod_,
+                   "style": { "position": "absolute",
+                              "zIndex": 10,
+                              "top": (this.height_ - 25 - padding.bottom) + "px",
+                              "left": (padding.left+1) + "px" }
+                  };
+  var roller = MochiKit.DOM.INPUT(textAttr);
+  var pa = this.graphDiv;
+  MochiKit.DOM.appendChildNodes(pa, roller);
+  connect(roller, 'onchange', this,
+          function() { this.adjustRoll(roller.value); });
+  return roller;
+}
+
+/**
+ * Set up all the mouse handlers needed to capture dragging behavior for zoom
+ * events. Uses MochiKit.Signal to attach all the event handlers.
+ * @private
+ */
+DateGraph.prototype.createDragInterface_ = function() {
+  var self = this;
+
+  // Tracks whether the mouse is down right now
+  var mouseDown = false;
+  var dragStartX = null;
+  var dragStartY = null;
+  var dragEndX = null;
+  var dragEndY = null;
+  var prevEndX = null;
+
+  // Utility function to convert page-wide coordinates to canvas coords
+  var px = PlotKit.Base.findPosX(this.canvas_);
+  var py = PlotKit.Base.findPosY(this.canvas_);
+  var getX = function(e) { return e.mouse().page.x - px };
+  var getY = function(e) { return e.mouse().page.y - py };
+
+  // Draw zoom rectangles when the mouse is down and the user moves around
+  connect(this.hidden_, 'onmousemove', function(event) {
+    if (mouseDown) {
+      dragEndX = getX(event);
+      dragEndY = getY(event);
+
+      self.drawZoomRect_(dragStartX, dragEndX, prevEndX);
+      prevEndX = dragEndX;
+    }
+  });
+
+  // Track the beginning of drag events
+  connect(this.hidden_, 'onmousedown', function(event) {
+    mouseDown = true;
+    dragStartX = getX(event);
+    dragStartY = getY(event);
+  });
+
+  // If the user releases the mouse button during a drag, but not over the
+  // canvas, then it doesn't count as a zooming action.
+  connect(document, 'onmouseup', this, function(event) {
+    if (mouseDown) {
+      mouseDown = false;
+      dragStartX = null;
+      dragStartY = null;
+    }
+  });
+
+  // Temporarily cancel the dragging event when the mouse leaves the graph
+  connect(this.hidden_, 'onmouseout', this, function(event) {
+    if (mouseDown) {
+      dragEndX = null;
+      dragEndY = null;
+    }
+  });
+
+  // If the mouse is released on the canvas during a drag event, then it's a
+  // zoom. Only do the zoom if it's over a large enough area (>= 10 pixels)
+  connect(this.hidden_, 'onmouseup', this, function(event) {
+    if (mouseDown) {
+      mouseDown = false;
+      dragEndX = getX(event);
+      dragEndY = getY(event);
+      var regionWidth = Math.abs(dragEndX - dragStartX);
+      var regionHeight = Math.abs(dragEndY - dragStartY);
+
+      if (regionWidth < 2 && regionHeight < 2 &&
+          self.clickCallback_ != null &&
+          self.lastx_ != undefined) {
+        self.clickCallback_(event, new Date(self.lastx_));
+      }
+
+      if (regionWidth >= 10) {
+        self.doZoom_(Math.min(dragStartX, dragEndX),
+                     Math.max(dragStartX, dragEndX));
+      } else {
+        self.canvas_.getContext("2d").clearRect(0, 0,
+                                           self.canvas_.width,
+                                           self.canvas_.height);
+      }
+
+      dragStartX = null;
+      dragStartY = null;
+    }
+  });
+
+  // Double-clicking zooms back out
+  connect(this.hidden_, 'ondblclick', this, function(event) {
+    self.dateWindow_ = null;
+    self.drawGraph_(self.rawData_);
+    var minDate = self.rawData_[0][0];
+    var maxDate = self.rawData_[self.rawData_.length - 1][0];
+    self.zoomCallback_(minDate, maxDate);
+  });
+};
+
+/**
+ * Draw a gray zoom rectangle over the desired area of the canvas. Also clears
+ * up any previous zoom rectangles that were drawn. This could be optimized to
+ * avoid extra redrawing, but it's tricky to avoid interactions with the status
+ * dots.
+ * @param {Number} startX The X position where the drag started, in canvas
+ * coordinates.
+ * @param {Number} endX The current X position of the drag, in canvas coords.
+ * @param {Number} prevEndX The value of endX on the previous call to this
+ * function. Used to avoid excess redrawing
+ * @private
+ */
+DateGraph.prototype.drawZoomRect_ = function(startX, endX, prevEndX) {
+  var ctx = this.canvas_.getContext("2d");
+
+  // Clean up from the previous rect if necessary
+  if (prevEndX) {
+    ctx.clearRect(Math.min(startX, prevEndX), 0,
+                  Math.abs(startX - prevEndX), this.height_);
+  }
+
+  // Draw a light-grey rectangle to show the new viewing area
+  if (endX && startX) {
+    ctx.fillStyle = "rgba(128,128,128,0.33)";
+    ctx.fillRect(Math.min(startX, endX), 0,
+                 Math.abs(endX - startX), this.height_);
+  }
+};
+
+/**
+ * Zoom to something containing [lowX, highX]. These are pixel coordinates
+ * in the canvas. The exact zoom window may be slightly larger if there are no
+ * data points near lowX or highX. This function redraws the graph.
+ * @param {Number} lowX The leftmost pixel value that should be visible.
+ * @param {Number} highX The rightmost pixel value that should be visible.
+ * @private
+ */
+DateGraph.prototype.doZoom_ = function(lowX, highX) {
+  // Find the earliest and latest dates contained in this canvasx range.
+  var points = this.layout_.points;
+  var minDate = null;
+  var maxDate = null;
+  // Find the nearest [minDate, maxDate] that contains [lowX, highX]
+  for (var i = 0; i < points.length; i++) {
+    var cx = points[i].canvasx;
+    var x = points[i].xval;
+    if (cx < lowX  && (minDate == null || x > minDate)) minDate = x;
+    if (cx > highX && (maxDate == null || x < maxDate)) maxDate = x;
+  }
+  // Use the extremes if either is missing
+  if (minDate == null) minDate = points[0].xval;
+  if (maxDate == null) maxDate = points[points.length-1].xval;
+
+  this.dateWindow_ = [minDate, maxDate];
+  this.drawGraph_(this.rawData_);
+  this.zoomCallback_(minDate, maxDate);
+};
+
+/**
+ * When the mouse moves in the canvas, display information about a nearby data
+ * point and draw dots over those points in the data series. This function
+ * takes care of cleanup of previously-drawn dots.
+ * @param {Object} event The mousemove event from the browser.
+ * @private
+ */
+DateGraph.prototype.mouseMove_ = function(event) {
+  var canvasx = event.mouse().page.x - PlotKit.Base.findPosX(this.hidden_);
+  var points = this.layout_.points;
+
+  var lastx = -1;
+  var lasty = -1;
+
+  // Loop through all the points and find the date nearest to our current
+  // location.
+  var minDist = 1e+100;
+  var idx = -1;
+  for (var i = 0; i < points.length; i++) {
+    var dist = Math.abs(points[i].canvasx - canvasx);
+    if (dist > minDist) break;
+    minDist = dist;
+    idx = i;
+  }
+  if (idx >= 0) lastx = points[idx].xval;
+  // Check that you can really highlight the last day's data
+  if (canvasx > points[points.length-1].canvasx)
+    lastx = points[points.length-1].xval;
+
+  // Extract the points we've selected
+  var selPoints = [];
+  for (var i = 0; i < points.length; i++) {
+    if (points[i].xval == lastx) {
+      selPoints.push(points[i]);
+    }
+  }
+
+  // Clear the previously drawn vertical, if there is one
+  var circleSize = 3;
+  var ctx = this.canvas_.getContext("2d");
+  if (this.previousVerticalX_ >= 0) {
+    var px = this.previousVerticalX_;
+    ctx.clearRect(px - circleSize - 1, 0, 2 * circleSize + 2, this.height_);
+  }
+
+  if (selPoints.length > 0) {
+    var canvasx = selPoints[0].canvasx;
+
+    // Set the status message to indicate the selected point(s)
+    var replace = this.xValueFormatter_(lastx) + ":";
+    var clen = this.colors_.length;
+    for (var i = 0; i < selPoints.length; i++) {
+      if (this.labelsSeparateLines) {
+        replace += "<br/>";
+      }
+      var point = selPoints[i];
+      replace += " <b><font color='" + this.colors_[i%clen].toHexString() + "'>"
+              + point.name + "</font></b>:"
+              + this.round_(point.yval, 2);
+    }
+    this.labelsDiv_.innerHTML = replace;
+
+    // Save last x position for callbacks.
+    this.lastx_ = lastx;
+
+    // Draw colored circles over the center of each selected point
+    ctx.save()
+    for (var i = 0; i < selPoints.length; i++) {
+      ctx.beginPath();
+      ctx.fillStyle = this.colors_[i%clen].toRGBString();
+      ctx.arc(canvasx, selPoints[i%clen].canvasy, circleSize, 0, 360, false);
+      ctx.fill();
+    }
+    ctx.restore();
+
+    this.previousVerticalX_ = canvasx;
+  }
+};
+
+/**
+ * The mouse has left the canvas. Clear out whatever artifacts remain
+ * @param {Object} event the mouseout event from the browser.
+ * @private
+ */
+DateGraph.prototype.mouseOut_ = function(event) {
+  // Get rid of the overlay data
+  var ctx = this.canvas_.getContext("2d");
+  ctx.clearRect(0, 0, this.width_, this.height_);
+  this.labelsDiv_.innerHTML = "";
+};
+
+/**
+ * Convert a JS date (millis since epoch) to YYYY/MM/DD
+ * @param {Number} date The JavaScript date (ms since epoch)
+ * @return {String} A date of the form "YYYY/MM/DD"
+ * @private
+ */
+DateGraph.prototype.dateString_ = function(date) {
+  var d = new Date(date);
+
+  // Get the year:
+  var year = "" + d.getFullYear();
+  // Get a 0 padded month string
+  var month = "" + (d.getMonth() + 1);  //months are 0-offset, sigh
+  if (month.length < 2)  month = "0" + month;
+  // Get a 0 padded day string
+  var day = "" + d.getDate();
+  if (day.length < 2)  day = "0" + day;
+
+  return year + "/" + month + "/" + day;
+};
+
+/**
+ * Round a number to the specified number of digits past the decimal point.
+ * @param {Number} num The number to round
+ * @param {Number} places The number of decimals to which to round
+ * @return {Number} The rounded number
+ * @private
+ */
+DateGraph.prototype.round_ = function(num, places) {
+  var shift = Math.pow(10, places);
+  return Math.round(num * shift)/shift;
+};
+
+/**
+ * Fires when there's data available to be graphed.
+ * @param {String} data Raw CSV data to be plotted
+ * @private
+ */
+DateGraph.prototype.loadedEvent_ = function(data) {
+  this.rawData_ = this.parseCSV_(data);
+  this.drawGraph_(this.rawData_);
+};
+
+DateGraph.prototype.months =  ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+DateGraph.prototype.quarters = ["Jan", "Apr", "Jul", "Oct"];
+
+/**
+ * Add ticks on the x-axis representing years, months, quarters, weeks, or days
+ * @private
+ */
+DateGraph.prototype.addXTicks_ = function() {
+  // Determine the correct ticks scale on the x-axis: quarterly, monthly, ...
+  var startDate, endDate;
+  if (this.dateWindow_) {
+    startDate = this.dateWindow_[0];
+    endDate = this.dateWindow_[1];
+  } else {
+    startDate = this.rawData_[0][0];
+    endDate   = this.rawData_[this.rawData_.length - 1][0];
+  }
+
+  var xTicks = this.xTicker_(startDate, endDate);
+  this.layout_.updateOptions({xTicks: xTicks});
+}
+
+/**
+ * Add ticks to the x-axis based on a date range.
+ * @param {Number} startDate Start of the date window (millis since epoch)
+ * @param {Number} endDate End of the date window (millis since epoch)
+ * @return {Array.<Object>} Array of {label, value} tuples.
+ * @public
+ */
+DateGraph.prototype.dateTicker = function(startDate, endDate) {
+  var ONE_DAY = 24*60*60*1000;
+  startDate = startDate / ONE_DAY;
+  endDate = endDate / ONE_DAY;
+  var dateSpan = endDate - startDate;
+
+  var scale = [];
+  var isMonthly = false;
+  var yearMod = 1;
+  if (dateSpan > 30 * 366) {      // decadal
+    isMonthly = true;
+    scale = ["Jan"];
+    yearMod = 10;
+  } else if (dateSpan > 4*366) {  // annual
+    scale = ["Jan"];
+    isMonthly = true;
+  } else if (dateSpan > 366) {    // quarterly
+    scale = this.quarters;
+    isMonthly = true;
+  } else if (dateSpan > 40) {     // monthly
+    scale = this.months;
+    isMonthly = true;
+  } else if (dateSpan > 10) {     // weekly
+    for (var week = startDate - 14; week < endDate + 14; week += 7) {
+      scale.push(week * ONE_DAY);
+    }
+  } else {                        // daily
+    for (var day = startDate - 14; day < endDate + 14; day += 1) {
+      scale.push(day * ONE_DAY);
+    }
+  }
+
+  var xTicks = [];
+
+  if (isMonthly) {
+    var startYear = 1900 + (new Date(startDate* ONE_DAY)).getYear();
+    var endYear   = 1900 + (new Date(endDate  * ONE_DAY)).getYear();
+    for (var i = startYear; i <= endYear; i++) {
+      if (i % yearMod != 0) continue;
+      for (var j = 0; j < scale.length; j++ ) {
+        var date = Date.parse(scale[j] + " 1, " + i);
+        xTicks.push( {label: scale[j] + "'" + ("" + i).substr(2,2), v: date } );
+      }
+    }
+  } else {
+    for (var i = 0; i < scale.length; i++) {
+      var date = new Date(scale[i]);
+      var year = date.getFullYear().toString();
+      var label = this.months[date.getMonth()] + date.getDate();
+      label += "'" + year.substr(year.length - 2, 2);
+      xTicks.push( {label: label, v: date} );
+    }
+  }
+  return xTicks;
+};
+
+/**
+ * Add ticks when the x axis has numbers on it (instead of dates)
+ * @param {Number} startDate Start of the date window (millis since epoch)
+ * @param {Number} endDate End of the date window (millis since epoch)
+ * @return {Array.<Object>} Array of {label, value} tuples.
+ * @public
+ */
+DateGraph.prototype.numericTicks = function(minV, maxV) {
+  var scale;
+  if (maxV <= 0.0) {
+    scale = 1.0;
+  } else {
+    scale = Math.pow( 10, Math.floor(Math.log(maxV)/Math.log(10.0)) );
+  }
+
+  // Add a smallish number of ticks at human-friendly points
+  var nTicks = (maxV - minV) / scale;
+  while (2 * nTicks < 20) {
+    nTicks *= 2;
+  }
+  if ((maxV - minV) / nTicks < this.minTickSize_) {
+    nTicks = this.round_((maxV - minV) / this.minTickSize_, 1);
+  }
+
+  // Construct labels for the ticks
+  var ticks = [];
+  for (var i = 0; i <= nTicks; i++) {
+    var tickV = minV + i * (maxV - minV) / nTicks;
+    var label = this.round_(tickV, 2);
+    if (this.labelsKMB_) {
+      var k = 1000;
+      if (tickV >= k*k*k) {
+        label = this.round_(tickV/(k*k*k), 1) + "B";
+      } else if (tickV >= k*k) {
+        label = this.round_(tickV/(k*k), 1) + "M";
+      } else if (tickV >= k) {
+        label = this.round_(tickV/k, 1) + "K";
+      }
+    }
+    ticks.push( {label: label, v: tickV} );
+  }
+  return ticks;
+};
+
+/**
+ * Adds appropriate ticks on the y-axis
+ * @param {Number} minY The minimum Y value in the data set
+ * @param {Number} maxY The maximum Y value in the data set
+ * @private
+ */
+DateGraph.prototype.addYTicks_ = function(minY, maxY) {
+  // Set the number of ticks so that the labels are human-friendly.
+  var ticks = this.numericTicks(minY, maxY);
+  this.layout_.updateOptions( { yAxis: [minY, maxY],
+                                yTicks: ticks } );
+};
+
+/**
+ * Update the graph with new data. Data is in the format
+ * [ [date1, val1, val2, ...], [date2, val1, val2, ...] if errorBars=false
+ * or, if errorBars=true,
+ * [ [date1, [val1,stddev1], [val2,stddev2], ...], [date2, ...], ...]
+ * @param {Array.<Object>} data The data (see above)
+ * @private
+ */
+DateGraph.prototype.drawGraph_ = function(data) {
+  var maxY = null;
+  this.layout_.removeAllDatasets();
+  // Loop over all fields in the dataset
+  for (var i = 1; i < data[0].length; i++) {
+    var series = [];
+    for (var j = 0; j < data.length; j++) {
+      var date = data[j][0];
+      series[j] = [date, data[j][i]];
+    }
+    series = this.rollingAverage(series, this.rollPeriod_);
+
+    // Prune down to the desired range, if necessary (for zooming)
+    var bars = this.errorBars_ || this.customBars_;
+    if (this.dateWindow_) {
+      var low = this.dateWindow_[0];
+      var high= this.dateWindow_[1];
+      var pruned = [];
+      for (var k = 0; k < series.length; k++) {
+        if (series[k][0] >= low && series[k][0] <= high) {
+          pruned.push(series[k]);
+          var y = bars ? series[k][1][0] : series[k][1];
+          if (maxY == null || y > maxY) maxY = y;
+        }
+      }
+      series = pruned;
+    } else {
+      for (var j = 0; j < series.length; j++) {
+        var y = bars ? series[j][1][0] : series[j][1];
+        if (maxY == null || y > maxY) {
+          maxY = bars ? y + series[j][1][1] : y;
+        }
+      }
+    }
+
+    if (bars) {
+      var vals = [];
+      for (var j=0; j<series.length; j++)
+        vals[j] = [series[j][0],
+                   series[j][1][0], series[j][1][1], series[j][1][2]];
+      this.layout_.addDataset(this.labels_[i - 1], vals);
+    } else {
+      this.layout_.addDataset(this.labels_[i - 1], series);
+    }
+  }
+
+  // Use some heuristics to come up with a good maxY value, unless it's been
+  // set explicitly by the user.
+  if (this.valueRange_ != null) {
+    this.addYTicks_(this.valueRange_[0], this.valueRange_[1]);
+  } else {
+    // Add some padding and round up to an integer to be human-friendly.
+    maxY *= 1.1;
+    if (maxY <= 0.0) maxY = 1.0;
+    else {
+      var scale = Math.pow(10, Math.floor(Math.log(maxY) / Math.log(10.0)));
+      maxY = scale * Math.ceil(maxY / scale);
+    }
+    this.addYTicks_(0, maxY);
+  }
+
+  this.addXTicks_();
+
+  // Tell PlotKit to use this new data and render itself
+  this.layout_.evaluateWithError();
+  this.plotter_.clear();
+  this.plotter_.render();
+  this.canvas_.getContext('2d').clearRect(0, 0,
+                                         this.canvas_.width, this.canvas_.height);
+};
+
+/**
+ * Calculates the rolling average of a data set.
+ * If originalData is [label, val], rolls the average of those.
+ * If originalData is [label, [, it's interpreted as [value, stddev]
+ *   and the roll is returned in the same form, with appropriately reduced
+ *   stddev for each value.
+ * Note that this is where fractional input (i.e. '5/10') is converted into
+ *   decimal values.
+ * @param {Array} originalData The data in the appropriate format (see above)
+ * @param {Number} rollPeriod The number of days over which to average the data
+ */
+DateGraph.prototype.rollingAverage = function(originalData, rollPeriod) {
+  if (originalData.length < 2)
+    return originalData;
+  var rollPeriod = Math.min(rollPeriod, originalData.length - 1);
+  var rollingData = [];
+  var sigma = this.sigma_;
+
+  if (this.fractions_) {
+    var num = 0;
+    var den = 0;  // numerator/denominator
+    var mult = 100.0;
+    for (var i = 0; i < originalData.length; i++) {
+      num += originalData[i][1][0];
+      den += originalData[i][1][1];
+      if (i - rollPeriod >= 0) {
+        num -= originalData[i - rollPeriod][1][0];
+        den -= originalData[i - rollPeriod][1][1];
+      }
+
+      var date = originalData[i][0];
+      var value = den ? num / den : 0.0;
+      if (this.errorBars_) {
+        if (this.wilsonInterval_) {
+          // For more details on this confidence interval, see:
+          // http://en.wikipedia.org/wiki/Binomial_confidence_interval
+          if (den) {
+            var p = value < 0 ? 0 : value, n = den;
+            var pm = sigma * Math.sqrt(p*(1-p)/n + sigma*sigma/(4*n*n));
+            var denom = 1 + sigma * sigma / den;
+            var low  = (p + sigma * sigma / (2 * den) - pm) / denom;
+            var high = (p + sigma * sigma / (2 * den) + pm) / denom;
+            rollingData[i] = [date,
+                              [p * mult, (p - low) * mult, (high - p) * mult]];
+          } else {
+            rollingData[i] = [date, [0, 0, 0]];
+          }
+        } else {
+          var stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
+          rollingData[i] = [date, [mult * value, mult * stddev, mult * stddev]];
+        }
+      } else {
+        rollingData[i] = [date, mult * value];
+      }
+    }
+  } else if (this.customBars_) {
+    // just ignore the rolling for now.
+    // TODO(danvk): do something reasonable.
+    for (var i = 0; i < originalData.length; i++) {
+      var data = originalData[i][1];
+      var y = data[1];
+      rollingData[i] = [originalData[i][0], [y, y - data[0], data[2] - y]];
+    }
+  } else {
+    // Calculate the rolling average for the first rollPeriod - 1 points where
+    // there is not enough data to roll over the full number of days
+    var num_init_points = Math.min(rollPeriod - 1, originalData.length - 2);
+    if (!this.errorBars_){
+      for (var i = 0; i < num_init_points; i++) {
+        var sum = 0;
+        for (var j = 0; j < i + 1; j++)
+          sum += originalData[j][1];
+        rollingData[i] = [originalData[i][0], sum / (i + 1)];
+      }
+      // Calculate the rolling average for the remaining points
+      for (var i = Math.min(rollPeriod - 1, originalData.length - 2);
+          i < originalData.length;
+          i++) {
+        var sum = 0;
+        for (var j = i - rollPeriod + 1; j < i + 1; j++)
+          sum += originalData[j][1];
+        rollingData[i] = [originalData[i][0], sum / rollPeriod];
+      }
+    } else {
+      for (var i = 0; i < num_init_points; i++) {
+        var sum = 0;
+        var variance = 0;
+        for (var j = 0; j < i + 1; j++) {
+          sum += originalData[j][1][0];
+          variance += Math.pow(originalData[j][1][1], 2);
+        }
+        var stddev = Math.sqrt(variance)/(i+1);
+        rollingData[i] = [originalData[i][0],
+                          [sum/(i+1), sigma * stddev, sigma * stddev]];
+      }
+      // Calculate the rolling average for the remaining points
+      for (var i = Math.min(rollPeriod - 1, originalData.length - 2);
+          i < originalData.length;
+          i++) {
+        var sum = 0;
+        var variance = 0;
+        for (var j = i - rollPeriod + 1; j < i + 1; j++) {
+          sum += originalData[j][1][0];
+          variance += Math.pow(originalData[j][1][1], 2);
+        }
+        var stddev = Math.sqrt(variance) / rollPeriod;
+        rollingData[i] = [originalData[i][0],
+                          [sum / rollPeriod, sigma * stddev, sigma * stddev]];
+      }
+    }
+  }
+
+  return rollingData;
+};
+
+/**
+ * Parses a date, returning the number of milliseconds since epoch. This can be
+ * passed in as an xValueParser in the DateGraph constructor.
+ * @param {String} A date in YYYYMMDD format.
+ * @return {Number} Milliseconds since epoch.
+ * @public
+ */
+DateGraph.prototype.dateParser = function(dateStr) {
+  var dateStrSlashed;
+  if (dateStr.search("-") != -1) {
+    dateStrSlashed = dateStr.replace("-", "/", "g");
+  } else if (dateStr.search("/") != -1) {
+    return Date.parse(dateStr);
+  } else {
+    dateStrSlashed = dateStr.substr(0,4) + "/" + dateStr.substr(4,2)
+                       + "/" + dateStr.substr(6,2);
+  }
+  return Date.parse(dateStrSlashed);
+};
+
+/**
+ * Parses a string in a special csv format.  We expect a csv file where each
+ * line is a date point, and the first field in each line is the date string.
+ * We also expect that all remaining fields represent series.
+ * if this.errorBars_ is set, then interpret the fields as:
+ * date, series1, stddev1, series2, stddev2, ...
+ * @param {Array.<Object>} data See above.
+ * @private
+ */
+DateGraph.prototype.parseCSV_ = function(data) {
+  var ret = [];
+  var lines = data.split("\n");
+  var start = this.labelsFromCSV_ ? 1 : 0;
+  if (this.labelsFromCSV_) {
+    var labels = lines[0].split(",");
+    labels.shift();  // a "date" parameter is assumed.
+    this.labels_ = labels;
+    // regenerate automatic colors.
+    this.setColors_(this.attrs_);
+    this.renderOptions_.colorScheme = this.colors_;
+    MochiKit.Base.update(this.plotter_.options, this.renderOptions_);
+    MochiKit.Base.update(this.layoutOptions_, this.attrs_);
+  }
+
+  for (var i = start; i < lines.length; i++) {
+    var line = lines[i];
+    if (line.length == 0) continue;  // skip blank lines
+    var inFields = line.split(',');
+    if (inFields.length < 2)
+      continue;
+
+    var fields = [];
+    fields[0] = this.xValueParser_(inFields[0]);
+
+    // If fractions are expected, parse the numbers as "A/B"
+    if (this.fractions_) {
+      for (var j = 1; j < inFields.length; j++) {
+        // TODO(danvk): figure out an appropriate way to flag parse errors.
+        var vals = inFields[j].split("/");
+        fields[j] = [parseFloat(vals[0]), parseFloat(vals[1])];
+      }
+    } else if (this.errorBars_) {
+      // If there are error bars, values are (value, stddev) pairs
+      for (var j = 1; j < inFields.length; j += 2)
+        fields[(j + 1) / 2] = [parseFloat(inFields[j]),
+                               parseFloat(inFields[j + 1])];
+    } else if (this.customBars_) {
+      // Bars are a low;center;high tuple
+      for (var j = 1; j < inFields.length; j++) {
+        var vals = inFields[j].split(";");
+        fields[j] = [ parseFloat(vals[0]),
+                      parseFloat(vals[1]),
+                      parseFloat(vals[2]) ];
+      }
+    } else {
+      // Values are just numbers
+      for (var j = 1; j < inFields.length; j++)
+        fields[j] = parseFloat(inFields[j]);
+    }
+    ret.push(fields);
+  }
+  return ret;
+};
+
+/**
+ * Get the CSV data. If it's in a function, call that function. If it's in a
+ * file, do an XMLHttpRequest to get it.
+ * @private
+ */
+DateGraph.prototype.start_ = function() {
+  if (typeof this.file_ == 'function') {
+    // Stubbed out to allow this to run off a filesystem
+    this.loadedEvent_(this.file_());
+  } else {
+    var req = new XMLHttpRequest();
+    var caller = this;
+    req.onreadystatechange = function () {
+      if (req.readyState == 4) {
+        if (req.status == 200) {
+          caller.loadedEvent_(req.responseText);
+        }
+      }
+    };
+
+    req.open("GET", this.file_, true);
+    req.send(null);
+  }
+};
+
+/**
+ * Changes various properties of the graph. These can include:
+ * <ul>
+ * <li>file: changes the source data for the graph</li>
+ * <li>errorBars: changes whether the data contains stddev</li>
+ * </ul>
+ * @param {Object} attrs The new properties and values
+ */
+DateGraph.prototype.updateOptions = function(attrs) {
+  if (attrs.errorBars) {
+    this.errorBars_ = attrs.errorBars;
+  }
+  if (attrs.customBars) {
+    this.customBars_ = attrs.customBars;
+  }
+  if (attrs.strokeWidth) {
+    this.strokeWidth_ = attrs.strokeWidth;
+  }
+  if (attrs.rollPeriod) {
+    this.rollPeriod_ = attrs.rollPeriod;
+  }
+  if (attrs.dateWindow) {
+    this.dateWindow_ = attrs.dateWindow;
+  }
+  if (attrs.valueRange) {
+    this.valueRange_ = attrs.valueRange;
+  }
+  if (attrs.minTickSize) {
+    this.minTickSize_ = attrs.minTickSize;
+  }
+  if (typeof(attrs.labels) != 'undefined') {
+    this.labels_ = attrs.labels;
+    this.labelsFromCSV_ = (attrs.labels == null);
+  }
+  this.layout_.updateOptions({ 'errorBars': this.errorBars_ });
+  if (attrs['file'] && attrs['file'] != this.file_) {
+    this.file_ = attrs['file'];
+    this.start_();
+  } else {
+    this.drawGraph_(this.rawData_);
+  }
+};
+
+/**
+ * Adjusts the number of days in the rolling average. Updates the graph to
+ * reflect the new averaging period.
+ * @param {Number} length Number of days over which to average the data.
+ */
+DateGraph.prototype.adjustRoll = function(length) {
+  this.rollPeriod_ = length;
+  this.drawGraph_(this.rawData_);
+};
diff --git a/dygraph.js b/dygraph.js
new file mode 100644 (file)
index 0000000..6369f11
--- /dev/null
@@ -0,0 +1,1063 @@
+// Copyright 2006 Dan Vanderkam (danvdk@gmail.com)
+// All Rights Reserved.
+
+/**
+ * @fileoverview Creates an interactive, zoomable graph based on a CSV file or
+ * string. DateGraph can handle multiple series with or without error bars. The
+ * date/value ranges will be automatically set. DateGraph uses the
+ * &lt;canvas&gt; tag, so it only works in FF1.5+.
+ * @author danvdk@gmail.com (Dan Vanderkam)
+
+  Usage:
+   <div id="graphdiv" style="width:800px; height:500px;"></div>
+   <script type="text/javascript">
+     new DateGraph(document.getElementById("graphdiv"),
+                   "datafile.csv",
+                     ["Series 1", "Series 2"],
+                     { }); // options
+   </script>
+
+ The CSV file is of the form
+
+   YYYYMMDD,A1,B1,C1
+   YYYYMMDD,A2,B2,C2
+
+ If null is passed as the third parameter (series names), then the first line
+ of the CSV file is assumed to contain names for each series.
+
+ If the 'errorBars' option is set in the constructor, the input should be of
+ the form
+
+   YYYYMMDD,A1,sigmaA1,B1,sigmaB1,...
+   YYYYMMDD,A2,sigmaA2,B2,sigmaB2,...
+
+ If the 'fractions' option is set, the input should be of the form:
+
+   YYYYMMDD,A1/B1,A2/B2,...
+   YYYYMMDD,A1/B1,A2/B2,...
+
+ And error bars will be calculated automatically using a binomial distribution.
+
+ For further documentation and examples, see http://www/~danvk/dg/
+
+ */
+
+/**
+ * An interactive, zoomable graph
+ * @param {String | Function} file A file containing CSV data or a function that
+ * returns this data. The expected format for each line is
+ * YYYYMMDD,val1,val2,... or, if attrs.errorBars is set,
+ * YYYYMMDD,val1,stddev1,val2,stddev2,...
+ * @param {Array.<String>} labels Labels for the data series
+ * @param {Object} attrs Various other attributes, e.g. errorBars determines
+ * whether the input data contains error ranges.
+ */
+DateGraph = function(div, file, labels, attrs) {
+  if (arguments.length > 0)
+    this.__init__(div, file, labels, attrs);
+};
+
+DateGraph.NAME = "DateGraph";
+DateGraph.VERSION = "1.1";
+DateGraph.__repr__ = function() {
+  return "[" + this.NAME + " " + this.VERSION + "]";
+};
+DateGraph.toString = function() {
+  return this.__repr__();
+};
+
+// Various default values
+DateGraph.DEFAULT_ROLL_PERIOD = 1;
+DateGraph.DEFAULT_WIDTH = 480;
+DateGraph.DEFAULT_HEIGHT = 320;
+DateGraph.DEFAULT_STROKE_WIDTH = 1.0;
+DateGraph.AXIS_LINE_WIDTH = 0.3;
+
+/**
+ * Initializes the DateGraph. This creates a new DIV and constructs the PlotKit
+ * and interaction &lt;canvas&gt; inside of it. See the constructor for details
+ * on the parameters.
+ * @param {String | Function} file Source data
+ * @param {Array.<String>} labels Names of the data series
+ * @param {Object} attrs Miscellaneous other options
+ * @private
+ */
+DateGraph.prototype.__init__ = function(div, file, labels, attrs) {
+  // Copy the important bits into the object
+  this.maindiv_ = div;
+  this.labels_ = labels;
+  this.file_ = file;
+  this.rollPeriod_ = attrs.rollPeriod || DateGraph.DEFAULT_ROLL_PERIOD;
+  this.previousVerticalX_ = -1;
+  this.width_ = parseInt(div.style.width, 10);
+  this.height_ = parseInt(div.style.height, 10);
+  this.errorBars_ = attrs.errorBars || false;
+  this.fractions_ = attrs.fractions || false;
+  this.strokeWidth_ = attrs.strokeWidth || DateGraph.DEFAULT_STROKE_WIDTH;
+  this.dateWindow_ = attrs.dateWindow || null;
+  this.valueRange_ = attrs.valueRange || null;
+  this.labelsSeparateLines = attrs.labelsSeparateLines || false;
+  this.labelsDiv_ = attrs.labelsDiv || null;
+  this.labelsKMB_ = attrs.labelsKMB || false;
+  this.minTickSize_ = attrs.minTickSize || 0;
+  this.xValueParser_ = attrs.xValueParser || DateGraph.prototype.dateParser;
+  this.xValueFormatter_ = attrs.xValueFormatter ||
+      DateGraph.prototype.dateString_;
+  this.xTicker_ = attrs.xTicker || DateGraph.prototype.dateTicker;
+  this.sigma_ = attrs.sigma || 2.0;
+  this.wilsonInterval_ = attrs.wilsonInterval || true;
+  this.customBars_ = attrs.customBars || false;
+  this.attrs_ = attrs;
+
+  // Make a note of whether labels will be pulled from the CSV file.
+  this.labelsFromCSV_ = (this.labels_ == null);
+  if (this.labels_ == null)
+    this.labels_ = [];
+
+  // Prototype of the callback is "void clickCallback(event, date)"
+  this.clickCallback_ = attrs.clickCallback || null;
+
+  // Prototype of zoom callback is "void dragCallback(minDate, maxDate)"
+  this.zoomCallback_ = attrs.zoomCallback || null;
+
+  // Create the containing DIV and other interactive elements
+  this.createInterface_();
+
+  // Create the PlotKit grapher
+  this.layoutOptions_ = { 'errorBars': (this.errorBars_ || this.customBars_),
+                          'xOriginIsZero': false };
+  MochiKit.Base.update(this.layoutOptions_, attrs);
+  this.setColors_(attrs);
+
+  this.layout_ = new DateGraphLayout(this.layoutOptions_);
+
+  this.renderOptions_ = { colorScheme: this.colors_,
+                          strokeColor: null,
+                          strokeWidth: this.strokeWidth_,
+                          axisLabelFontSize: 14,
+                          axisLineWidth: DateGraph.AXIS_LINE_WIDTH };
+  MochiKit.Base.update(this.renderOptions_, attrs);
+  this.plotter_ = new DateGraphCanvasRenderer(this.hidden_, this.layout_,
+                                              this.renderOptions_);
+
+  this.createStatusMessage_();
+  this.createRollInterface_();
+  this.createDragInterface_();
+
+  MochiKit.DOM.addLoadEvent(this.start_());
+};
+
+/**
+ * Returns the current rolling period, as set by the user or an option.
+ * @return {Number} The number of days in the rolling window
+ */
+DateGraph.prototype.rollPeriod = function() {
+  return this.rollPeriod_;
+}
+
+/**
+ * Generates interface elements for the DateGraph: a containing div, a div to
+ * display the current point, and a textbox to adjust the rolling average
+ * period.
+ * @private
+ */
+DateGraph.prototype.createInterface_ = function() {
+  // Create the all-enclosing graph div
+  var enclosing = this.maindiv_;
+
+  this.graphDiv = MochiKit.DOM.DIV( { style: { 'width': this.width_ + "px",
+                                                'height': this.height_ + "px"
+                                                 }});
+  appendChildNodes(enclosing, this.graphDiv);
+
+  // Create the canvas to store
+  var canvas = MochiKit.DOM.CANVAS;
+  this.canvas_ = canvas( { style: { 'position': 'absolute' },
+                          width: this.width_,
+                          height: this.height_});
+  appendChildNodes(this.graphDiv, this.canvas_);
+
+  this.hidden_ = this.createPlotKitCanvas_(this.canvas_);
+  connect(this.hidden_, 'onmousemove', this, function(e) { this.mouseMove_(e) });
+  connect(this.hidden_, 'onmouseout', this, function(e) { this.mouseOut_(e) });
+}
+
+/**
+ * Creates the canvas containing the PlotKit graph. Only plotkit ever draws on
+ * this particular canvas. All DateGraph work is done on this.canvas_.
+ * @param {Object} canvas The DateGraph canvas to over which to overlay the plot
+ * @return {Object} The newly-created canvas
+ * @private
+ */
+DateGraph.prototype.createPlotKitCanvas_ = function(canvas) {
+  var h = document.createElement("canvas");
+  h.style.position = "absolute";
+  h.style.top = canvas.style.top;
+  h.style.left = canvas.style.left;
+  h.width = this.width_;
+  h.height = this.height_;
+  MochiKit.DOM.appendChildNodes(this.graphDiv, h);
+  return h;
+};
+
+/**
+ * Generate a set of distinct colors for the data series. This is done with a
+ * color wheel. Saturation/Value are customizable, and the hue is
+ * equally-spaced around the color wheel. If a custom set of colors is
+ * specified, that is used instead.
+ * @param {Object} attrs Various attributes, e.g. saturation and value
+ * @private
+ */
+DateGraph.prototype.setColors_ = function(attrs) {
+  var num = this.labels_.length;
+  this.colors_ = [];
+  if (!attrs.colors) {
+    var sat = attrs.colorSaturation || 1.0;
+    var val = attrs.colorValue || 0.5;
+    for (var i = 1; i <= num; i++) {
+      var hue = (1.0*i/(1+num));
+      this.colors_.push( MochiKit.Color.Color.fromHSV(hue, sat, val) );
+    }
+  } else {
+    for (var i = 0; i < num; i++) {
+      var colorStr = attrs.colors[i % attrs.colors.length];
+      this.colors_.push( MochiKit.Color.Color.fromString(colorStr) );
+    }
+  }
+}
+
+/**
+ * Create the div that contains information on the selected point(s)
+ * This goes in the top right of the canvas, unless an external div has already
+ * been specified.
+ * @private
+ */
+DateGraph.prototype.createStatusMessage_ = function(){
+  if (!this.labelsDiv_) {
+    var divWidth = 250;
+    var messagestyle = { "style": {
+      "position": "absolute",
+      "fontSize": "14px",
+      "zIndex": 10,
+      "width": divWidth + "px",
+      "top": "0px",
+      "left": this.width_ - divWidth + "px",
+      "background": "white",
+      "textAlign": "left",
+      "overflow": "hidden"}};
+    this.labelsDiv_ = MochiKit.DOM.DIV(messagestyle);
+    MochiKit.DOM.appendChildNodes(this.graphDiv, this.labelsDiv_);
+  }
+};
+
+/**
+ * Create the text box to adjust the averaging period
+ * @return {Object} The newly-created text box
+ * @private
+ */
+DateGraph.prototype.createRollInterface_ = function() {
+  var padding = this.plotter_.options.padding;
+  var textAttr = { "type": "text",
+                   "size": "2",
+                   "value": this.rollPeriod_,
+                   "style": { "position": "absolute",
+                              "zIndex": 10,
+                              "top": (this.height_ - 25 - padding.bottom) + "px",
+                              "left": (padding.left+1) + "px" }
+                  };
+  var roller = MochiKit.DOM.INPUT(textAttr);
+  var pa = this.graphDiv;
+  MochiKit.DOM.appendChildNodes(pa, roller);
+  connect(roller, 'onchange', this,
+          function() { this.adjustRoll(roller.value); });
+  return roller;
+}
+
+/**
+ * Set up all the mouse handlers needed to capture dragging behavior for zoom
+ * events. Uses MochiKit.Signal to attach all the event handlers.
+ * @private
+ */
+DateGraph.prototype.createDragInterface_ = function() {
+  var self = this;
+
+  // Tracks whether the mouse is down right now
+  var mouseDown = false;
+  var dragStartX = null;
+  var dragStartY = null;
+  var dragEndX = null;
+  var dragEndY = null;
+  var prevEndX = null;
+
+  // Utility function to convert page-wide coordinates to canvas coords
+  var px = PlotKit.Base.findPosX(this.canvas_);
+  var py = PlotKit.Base.findPosY(this.canvas_);
+  var getX = function(e) { return e.mouse().page.x - px };
+  var getY = function(e) { return e.mouse().page.y - py };
+
+  // Draw zoom rectangles when the mouse is down and the user moves around
+  connect(this.hidden_, 'onmousemove', function(event) {
+    if (mouseDown) {
+      dragEndX = getX(event);
+      dragEndY = getY(event);
+
+      self.drawZoomRect_(dragStartX, dragEndX, prevEndX);
+      prevEndX = dragEndX;
+    }
+  });
+
+  // Track the beginning of drag events
+  connect(this.hidden_, 'onmousedown', function(event) {
+    mouseDown = true;
+    dragStartX = getX(event);
+    dragStartY = getY(event);
+  });
+
+  // If the user releases the mouse button during a drag, but not over the
+  // canvas, then it doesn't count as a zooming action.
+  connect(document, 'onmouseup', this, function(event) {
+    if (mouseDown) {
+      mouseDown = false;
+      dragStartX = null;
+      dragStartY = null;
+    }
+  });
+
+  // Temporarily cancel the dragging event when the mouse leaves the graph
+  connect(this.hidden_, 'onmouseout', this, function(event) {
+    if (mouseDown) {
+      dragEndX = null;
+      dragEndY = null;
+    }
+  });
+
+  // If the mouse is released on the canvas during a drag event, then it's a
+  // zoom. Only do the zoom if it's over a large enough area (>= 10 pixels)
+  connect(this.hidden_, 'onmouseup', this, function(event) {
+    if (mouseDown) {
+      mouseDown = false;
+      dragEndX = getX(event);
+      dragEndY = getY(event);
+      var regionWidth = Math.abs(dragEndX - dragStartX);
+      var regionHeight = Math.abs(dragEndY - dragStartY);
+
+      if (regionWidth < 2 && regionHeight < 2 &&
+          self.clickCallback_ != null &&
+          self.lastx_ != undefined) {
+        self.clickCallback_(event, new Date(self.lastx_));
+      }
+
+      if (regionWidth >= 10) {
+        self.doZoom_(Math.min(dragStartX, dragEndX),
+                     Math.max(dragStartX, dragEndX));
+      } else {
+        self.canvas_.getContext("2d").clearRect(0, 0,
+                                           self.canvas_.width,
+                                           self.canvas_.height);
+      }
+
+      dragStartX = null;
+      dragStartY = null;
+    }
+  });
+
+  // Double-clicking zooms back out
+  connect(this.hidden_, 'ondblclick', this, function(event) {
+    self.dateWindow_ = null;
+    self.drawGraph_(self.rawData_);
+    var minDate = self.rawData_[0][0];
+    var maxDate = self.rawData_[self.rawData_.length - 1][0];
+    self.zoomCallback_(minDate, maxDate);
+  });
+};
+
+/**
+ * Draw a gray zoom rectangle over the desired area of the canvas. Also clears
+ * up any previous zoom rectangles that were drawn. This could be optimized to
+ * avoid extra redrawing, but it's tricky to avoid interactions with the status
+ * dots.
+ * @param {Number} startX The X position where the drag started, in canvas
+ * coordinates.
+ * @param {Number} endX The current X position of the drag, in canvas coords.
+ * @param {Number} prevEndX The value of endX on the previous call to this
+ * function. Used to avoid excess redrawing
+ * @private
+ */
+DateGraph.prototype.drawZoomRect_ = function(startX, endX, prevEndX) {
+  var ctx = this.canvas_.getContext("2d");
+
+  // Clean up from the previous rect if necessary
+  if (prevEndX) {
+    ctx.clearRect(Math.min(startX, prevEndX), 0,
+                  Math.abs(startX - prevEndX), this.height_);
+  }
+
+  // Draw a light-grey rectangle to show the new viewing area
+  if (endX && startX) {
+    ctx.fillStyle = "rgba(128,128,128,0.33)";
+    ctx.fillRect(Math.min(startX, endX), 0,
+                 Math.abs(endX - startX), this.height_);
+  }
+};
+
+/**
+ * Zoom to something containing [lowX, highX]. These are pixel coordinates
+ * in the canvas. The exact zoom window may be slightly larger if there are no
+ * data points near lowX or highX. This function redraws the graph.
+ * @param {Number} lowX The leftmost pixel value that should be visible.
+ * @param {Number} highX The rightmost pixel value that should be visible.
+ * @private
+ */
+DateGraph.prototype.doZoom_ = function(lowX, highX) {
+  // Find the earliest and latest dates contained in this canvasx range.
+  var points = this.layout_.points;
+  var minDate = null;
+  var maxDate = null;
+  // Find the nearest [minDate, maxDate] that contains [lowX, highX]
+  for (var i = 0; i < points.length; i++) {
+    var cx = points[i].canvasx;
+    var x = points[i].xval;
+    if (cx < lowX  && (minDate == null || x > minDate)) minDate = x;
+    if (cx > highX && (maxDate == null || x < maxDate)) maxDate = x;
+  }
+  // Use the extremes if either is missing
+  if (minDate == null) minDate = points[0].xval;
+  if (maxDate == null) maxDate = points[points.length-1].xval;
+
+  this.dateWindow_ = [minDate, maxDate];
+  this.drawGraph_(this.rawData_);
+  this.zoomCallback_(minDate, maxDate);
+};
+
+/**
+ * When the mouse moves in the canvas, display information about a nearby data
+ * point and draw dots over those points in the data series. This function
+ * takes care of cleanup of previously-drawn dots.
+ * @param {Object} event The mousemove event from the browser.
+ * @private
+ */
+DateGraph.prototype.mouseMove_ = function(event) {
+  var canvasx = event.mouse().page.x - PlotKit.Base.findPosX(this.hidden_);
+  var points = this.layout_.points;
+
+  var lastx = -1;
+  var lasty = -1;
+
+  // Loop through all the points and find the date nearest to our current
+  // location.
+  var minDist = 1e+100;
+  var idx = -1;
+  for (var i = 0; i < points.length; i++) {
+    var dist = Math.abs(points[i].canvasx - canvasx);
+    if (dist > minDist) break;
+    minDist = dist;
+    idx = i;
+  }
+  if (idx >= 0) lastx = points[idx].xval;
+  // Check that you can really highlight the last day's data
+  if (canvasx > points[points.length-1].canvasx)
+    lastx = points[points.length-1].xval;
+
+  // Extract the points we've selected
+  var selPoints = [];
+  for (var i = 0; i < points.length; i++) {
+    if (points[i].xval == lastx) {
+      selPoints.push(points[i]);
+    }
+  }
+
+  // Clear the previously drawn vertical, if there is one
+  var circleSize = 3;
+  var ctx = this.canvas_.getContext("2d");
+  if (this.previousVerticalX_ >= 0) {
+    var px = this.previousVerticalX_;
+    ctx.clearRect(px - circleSize - 1, 0, 2 * circleSize + 2, this.height_);
+  }
+
+  if (selPoints.length > 0) {
+    var canvasx = selPoints[0].canvasx;
+
+    // Set the status message to indicate the selected point(s)
+    var replace = this.xValueFormatter_(lastx) + ":";
+    var clen = this.colors_.length;
+    for (var i = 0; i < selPoints.length; i++) {
+      if (this.labelsSeparateLines) {
+        replace += "<br/>";
+      }
+      var point = selPoints[i];
+      replace += " <b><font color='" + this.colors_[i%clen].toHexString() + "'>"
+              + point.name + "</font></b>:"
+              + this.round_(point.yval, 2);
+    }
+    this.labelsDiv_.innerHTML = replace;
+
+    // Save last x position for callbacks.
+    this.lastx_ = lastx;
+
+    // Draw colored circles over the center of each selected point
+    ctx.save()
+    for (var i = 0; i < selPoints.length; i++) {
+      ctx.beginPath();
+      ctx.fillStyle = this.colors_[i%clen].toRGBString();
+      ctx.arc(canvasx, selPoints[i%clen].canvasy, circleSize, 0, 360, false);
+      ctx.fill();
+    }
+    ctx.restore();
+
+    this.previousVerticalX_ = canvasx;
+  }
+};
+
+/**
+ * The mouse has left the canvas. Clear out whatever artifacts remain
+ * @param {Object} event the mouseout event from the browser.
+ * @private
+ */
+DateGraph.prototype.mouseOut_ = function(event) {
+  // Get rid of the overlay data
+  var ctx = this.canvas_.getContext("2d");
+  ctx.clearRect(0, 0, this.width_, this.height_);
+  this.labelsDiv_.innerHTML = "";
+};
+
+/**
+ * Convert a JS date (millis since epoch) to YYYY/MM/DD
+ * @param {Number} date The JavaScript date (ms since epoch)
+ * @return {String} A date of the form "YYYY/MM/DD"
+ * @private
+ */
+DateGraph.prototype.dateString_ = function(date) {
+  var d = new Date(date);
+
+  // Get the year:
+  var year = "" + d.getFullYear();
+  // Get a 0 padded month string
+  var month = "" + (d.getMonth() + 1);  //months are 0-offset, sigh
+  if (month.length < 2)  month = "0" + month;
+  // Get a 0 padded day string
+  var day = "" + d.getDate();
+  if (day.length < 2)  day = "0" + day;
+
+  return year + "/" + month + "/" + day;
+};
+
+/**
+ * Round a number to the specified number of digits past the decimal point.
+ * @param {Number} num The number to round
+ * @param {Number} places The number of decimals to which to round
+ * @return {Number} The rounded number
+ * @private
+ */
+DateGraph.prototype.round_ = function(num, places) {
+  var shift = Math.pow(10, places);
+  return Math.round(num * shift)/shift;
+};
+
+/**
+ * Fires when there's data available to be graphed.
+ * @param {String} data Raw CSV data to be plotted
+ * @private
+ */
+DateGraph.prototype.loadedEvent_ = function(data) {
+  this.rawData_ = this.parseCSV_(data);
+  this.drawGraph_(this.rawData_);
+};
+
+DateGraph.prototype.months =  ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+DateGraph.prototype.quarters = ["Jan", "Apr", "Jul", "Oct"];
+
+/**
+ * Add ticks on the x-axis representing years, months, quarters, weeks, or days
+ * @private
+ */
+DateGraph.prototype.addXTicks_ = function() {
+  // Determine the correct ticks scale on the x-axis: quarterly, monthly, ...
+  var startDate, endDate;
+  if (this.dateWindow_) {
+    startDate = this.dateWindow_[0];
+    endDate = this.dateWindow_[1];
+  } else {
+    startDate = this.rawData_[0][0];
+    endDate   = this.rawData_[this.rawData_.length - 1][0];
+  }
+
+  var xTicks = this.xTicker_(startDate, endDate);
+  this.layout_.updateOptions({xTicks: xTicks});
+}
+
+/**
+ * Add ticks to the x-axis based on a date range.
+ * @param {Number} startDate Start of the date window (millis since epoch)
+ * @param {Number} endDate End of the date window (millis since epoch)
+ * @return {Array.<Object>} Array of {label, value} tuples.
+ * @public
+ */
+DateGraph.prototype.dateTicker = function(startDate, endDate) {
+  var ONE_DAY = 24*60*60*1000;
+  startDate = startDate / ONE_DAY;
+  endDate = endDate / ONE_DAY;
+  var dateSpan = endDate - startDate;
+
+  var scale = [];
+  var isMonthly = false;
+  var yearMod = 1;
+  if (dateSpan > 30 * 366) {      // decadal
+    isMonthly = true;
+    scale = ["Jan"];
+    yearMod = 10;
+  } else if (dateSpan > 4*366) {  // annual
+    scale = ["Jan"];
+    isMonthly = true;
+  } else if (dateSpan > 366) {    // quarterly
+    scale = this.quarters;
+    isMonthly = true;
+  } else if (dateSpan > 40) {     // monthly
+    scale = this.months;
+    isMonthly = true;
+  } else if (dateSpan > 10) {     // weekly
+    for (var week = startDate - 14; week < endDate + 14; week += 7) {
+      scale.push(week * ONE_DAY);
+    }
+  } else {                        // daily
+    for (var day = startDate - 14; day < endDate + 14; day += 1) {
+      scale.push(day * ONE_DAY);
+    }
+  }
+
+  var xTicks = [];
+
+  if (isMonthly) {
+    var startYear = 1900 + (new Date(startDate* ONE_DAY)).getYear();
+    var endYear   = 1900 + (new Date(endDate  * ONE_DAY)).getYear();
+    for (var i = startYear; i <= endYear; i++) {
+      if (i % yearMod != 0) continue;
+      for (var j = 0; j < scale.length; j++ ) {
+        var date = Date.parse(scale[j] + " 1, " + i);
+        xTicks.push( {label: scale[j] + "'" + ("" + i).substr(2,2), v: date } );
+      }
+    }
+  } else {
+    for (var i = 0; i < scale.length; i++) {
+      var date = new Date(scale[i]);
+      var year = date.getFullYear().toString();
+      var label = this.months[date.getMonth()] + date.getDate();
+      label += "'" + year.substr(year.length - 2, 2);
+      xTicks.push( {label: label, v: date} );
+    }
+  }
+  return xTicks;
+};
+
+/**
+ * Add ticks when the x axis has numbers on it (instead of dates)
+ * @param {Number} startDate Start of the date window (millis since epoch)
+ * @param {Number} endDate End of the date window (millis since epoch)
+ * @return {Array.<Object>} Array of {label, value} tuples.
+ * @public
+ */
+DateGraph.prototype.numericTicks = function(minV, maxV) {
+  var scale;
+  if (maxV <= 0.0) {
+    scale = 1.0;
+  } else {
+    scale = Math.pow( 10, Math.floor(Math.log(maxV)/Math.log(10.0)) );
+  }
+
+  // Add a smallish number of ticks at human-friendly points
+  var nTicks = (maxV - minV) / scale;
+  while (2 * nTicks < 20) {
+    nTicks *= 2;
+  }
+  if ((maxV - minV) / nTicks < this.minTickSize_) {
+    nTicks = this.round_((maxV - minV) / this.minTickSize_, 1);
+  }
+
+  // Construct labels for the ticks
+  var ticks = [];
+  for (var i = 0; i <= nTicks; i++) {
+    var tickV = minV + i * (maxV - minV) / nTicks;
+    var label = this.round_(tickV, 2);
+    if (this.labelsKMB_) {
+      var k = 1000;
+      if (tickV >= k*k*k) {
+        label = this.round_(tickV/(k*k*k), 1) + "B";
+      } else if (tickV >= k*k) {
+        label = this.round_(tickV/(k*k), 1) + "M";
+      } else if (tickV >= k) {
+        label = this.round_(tickV/k, 1) + "K";
+      }
+    }
+    ticks.push( {label: label, v: tickV} );
+  }
+  return ticks;
+};
+
+/**
+ * Adds appropriate ticks on the y-axis
+ * @param {Number} minY The minimum Y value in the data set
+ * @param {Number} maxY The maximum Y value in the data set
+ * @private
+ */
+DateGraph.prototype.addYTicks_ = function(minY, maxY) {
+  // Set the number of ticks so that the labels are human-friendly.
+  var ticks = this.numericTicks(minY, maxY);
+  this.layout_.updateOptions( { yAxis: [minY, maxY],
+                                yTicks: ticks } );
+};
+
+/**
+ * Update the graph with new data. Data is in the format
+ * [ [date1, val1, val2, ...], [date2, val1, val2, ...] if errorBars=false
+ * or, if errorBars=true,
+ * [ [date1, [val1,stddev1], [val2,stddev2], ...], [date2, ...], ...]
+ * @param {Array.<Object>} data The data (see above)
+ * @private
+ */
+DateGraph.prototype.drawGraph_ = function(data) {
+  var maxY = null;
+  this.layout_.removeAllDatasets();
+  // Loop over all fields in the dataset
+  for (var i = 1; i < data[0].length; i++) {
+    var series = [];
+    for (var j = 0; j < data.length; j++) {
+      var date = data[j][0];
+      series[j] = [date, data[j][i]];
+    }
+    series = this.rollingAverage(series, this.rollPeriod_);
+
+    // Prune down to the desired range, if necessary (for zooming)
+    var bars = this.errorBars_ || this.customBars_;
+    if (this.dateWindow_) {
+      var low = this.dateWindow_[0];
+      var high= this.dateWindow_[1];
+      var pruned = [];
+      for (var k = 0; k < series.length; k++) {
+        if (series[k][0] >= low && series[k][0] <= high) {
+          pruned.push(series[k]);
+          var y = bars ? series[k][1][0] : series[k][1];
+          if (maxY == null || y > maxY) maxY = y;
+        }
+      }
+      series = pruned;
+    } else {
+      for (var j = 0; j < series.length; j++) {
+        var y = bars ? series[j][1][0] : series[j][1];
+        if (maxY == null || y > maxY) {
+          maxY = bars ? y + series[j][1][1] : y;
+        }
+      }
+    }
+
+    if (bars) {
+      var vals = [];
+      for (var j=0; j<series.length; j++)
+        vals[j] = [series[j][0],
+                   series[j][1][0], series[j][1][1], series[j][1][2]];
+      this.layout_.addDataset(this.labels_[i - 1], vals);
+    } else {
+      this.layout_.addDataset(this.labels_[i - 1], series);
+    }
+  }
+
+  // Use some heuristics to come up with a good maxY value, unless it's been
+  // set explicitly by the user.
+  if (this.valueRange_ != null) {
+    this.addYTicks_(this.valueRange_[0], this.valueRange_[1]);
+  } else {
+    // Add some padding and round up to an integer to be human-friendly.
+    maxY *= 1.1;
+    if (maxY <= 0.0) maxY = 1.0;
+    else {
+      var scale = Math.pow(10, Math.floor(Math.log(maxY) / Math.log(10.0)));
+      maxY = scale * Math.ceil(maxY / scale);
+    }
+    this.addYTicks_(0, maxY);
+  }
+
+  this.addXTicks_();
+
+  // Tell PlotKit to use this new data and render itself
+  this.layout_.evaluateWithError();
+  this.plotter_.clear();
+  this.plotter_.render();
+  this.canvas_.getContext('2d').clearRect(0, 0,
+                                         this.canvas_.width, this.canvas_.height);
+};
+
+/**
+ * Calculates the rolling average of a data set.
+ * If originalData is [label, val], rolls the average of those.
+ * If originalData is [label, [, it's interpreted as [value, stddev]
+ *   and the roll is returned in the same form, with appropriately reduced
+ *   stddev for each value.
+ * Note that this is where fractional input (i.e. '5/10') is converted into
+ *   decimal values.
+ * @param {Array} originalData The data in the appropriate format (see above)
+ * @param {Number} rollPeriod The number of days over which to average the data
+ */
+DateGraph.prototype.rollingAverage = function(originalData, rollPeriod) {
+  if (originalData.length < 2)
+    return originalData;
+  var rollPeriod = Math.min(rollPeriod, originalData.length - 1);
+  var rollingData = [];
+  var sigma = this.sigma_;
+
+  if (this.fractions_) {
+    var num = 0;
+    var den = 0;  // numerator/denominator
+    var mult = 100.0;
+    for (var i = 0; i < originalData.length; i++) {
+      num += originalData[i][1][0];
+      den += originalData[i][1][1];
+      if (i - rollPeriod >= 0) {
+        num -= originalData[i - rollPeriod][1][0];
+        den -= originalData[i - rollPeriod][1][1];
+      }
+
+      var date = originalData[i][0];
+      var value = den ? num / den : 0.0;
+      if (this.errorBars_) {
+        if (this.wilsonInterval_) {
+          // For more details on this confidence interval, see:
+          // http://en.wikipedia.org/wiki/Binomial_confidence_interval
+          if (den) {
+            var p = value < 0 ? 0 : value, n = den;
+            var pm = sigma * Math.sqrt(p*(1-p)/n + sigma*sigma/(4*n*n));
+            var denom = 1 + sigma * sigma / den;
+            var low  = (p + sigma * sigma / (2 * den) - pm) / denom;
+            var high = (p + sigma * sigma / (2 * den) + pm) / denom;
+            rollingData[i] = [date,
+                              [p * mult, (p - low) * mult, (high - p) * mult]];
+          } else {
+            rollingData[i] = [date, [0, 0, 0]];
+          }
+        } else {
+          var stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
+          rollingData[i] = [date, [mult * value, mult * stddev, mult * stddev]];
+        }
+      } else {
+        rollingData[i] = [date, mult * value];
+      }
+    }
+  } else if (this.customBars_) {
+    // just ignore the rolling for now.
+    // TODO(danvk): do something reasonable.
+    for (var i = 0; i < originalData.length; i++) {
+      var data = originalData[i][1];
+      var y = data[1];
+      rollingData[i] = [originalData[i][0], [y, y - data[0], data[2] - y]];
+    }
+  } else {
+    // Calculate the rolling average for the first rollPeriod - 1 points where
+    // there is not enough data to roll over the full number of days
+    var num_init_points = Math.min(rollPeriod - 1, originalData.length - 2);
+    if (!this.errorBars_){
+      for (var i = 0; i < num_init_points; i++) {
+        var sum = 0;
+        for (var j = 0; j < i + 1; j++)
+          sum += originalData[j][1];
+        rollingData[i] = [originalData[i][0], sum / (i + 1)];
+      }
+      // Calculate the rolling average for the remaining points
+      for (var i = Math.min(rollPeriod - 1, originalData.length - 2);
+          i < originalData.length;
+          i++) {
+        var sum = 0;
+        for (var j = i - rollPeriod + 1; j < i + 1; j++)
+          sum += originalData[j][1];
+        rollingData[i] = [originalData[i][0], sum / rollPeriod];
+      }
+    } else {
+      for (var i = 0; i < num_init_points; i++) {
+        var sum = 0;
+        var variance = 0;
+        for (var j = 0; j < i + 1; j++) {
+          sum += originalData[j][1][0];
+          variance += Math.pow(originalData[j][1][1], 2);
+        }
+        var stddev = Math.sqrt(variance)/(i+1);
+        rollingData[i] = [originalData[i][0],
+                          [sum/(i+1), sigma * stddev, sigma * stddev]];
+      }
+      // Calculate the rolling average for the remaining points
+      for (var i = Math.min(rollPeriod - 1, originalData.length - 2);
+          i < originalData.length;
+          i++) {
+        var sum = 0;
+        var variance = 0;
+        for (var j = i - rollPeriod + 1; j < i + 1; j++) {
+          sum += originalData[j][1][0];
+          variance += Math.pow(originalData[j][1][1], 2);
+        }
+        var stddev = Math.sqrt(variance) / rollPeriod;
+        rollingData[i] = [originalData[i][0],
+                          [sum / rollPeriod, sigma * stddev, sigma * stddev]];
+      }
+    }
+  }
+
+  return rollingData;
+};
+
+/**
+ * Parses a date, returning the number of milliseconds since epoch. This can be
+ * passed in as an xValueParser in the DateGraph constructor.
+ * @param {String} A date in YYYYMMDD format.
+ * @return {Number} Milliseconds since epoch.
+ * @public
+ */
+DateGraph.prototype.dateParser = function(dateStr) {
+  var dateStrSlashed;
+  if (dateStr.search("-") != -1) {
+    dateStrSlashed = dateStr.replace("-", "/", "g");
+  } else if (dateStr.search("/") != -1) {
+    return Date.parse(dateStr);
+  } else {
+    dateStrSlashed = dateStr.substr(0,4) + "/" + dateStr.substr(4,2)
+                       + "/" + dateStr.substr(6,2);
+  }
+  return Date.parse(dateStrSlashed);
+};
+
+/**
+ * Parses a string in a special csv format.  We expect a csv file where each
+ * line is a date point, and the first field in each line is the date string.
+ * We also expect that all remaining fields represent series.
+ * if this.errorBars_ is set, then interpret the fields as:
+ * date, series1, stddev1, series2, stddev2, ...
+ * @param {Array.<Object>} data See above.
+ * @private
+ */
+DateGraph.prototype.parseCSV_ = function(data) {
+  var ret = [];
+  var lines = data.split("\n");
+  var start = this.labelsFromCSV_ ? 1 : 0;
+  if (this.labelsFromCSV_) {
+    var labels = lines[0].split(",");
+    labels.shift();  // a "date" parameter is assumed.
+    this.labels_ = labels;
+    // regenerate automatic colors.
+    this.setColors_(this.attrs_);
+    this.renderOptions_.colorScheme = this.colors_;
+    MochiKit.Base.update(this.plotter_.options, this.renderOptions_);
+    MochiKit.Base.update(this.layoutOptions_, this.attrs_);
+  }
+
+  for (var i = start; i < lines.length; i++) {
+    var line = lines[i];
+    if (line.length == 0) continue;  // skip blank lines
+    var inFields = line.split(',');
+    if (inFields.length < 2)
+      continue;
+
+    var fields = [];
+    fields[0] = this.xValueParser_(inFields[0]);
+
+    // If fractions are expected, parse the numbers as "A/B"
+    if (this.fractions_) {
+      for (var j = 1; j < inFields.length; j++) {
+        // TODO(danvk): figure out an appropriate way to flag parse errors.
+        var vals = inFields[j].split("/");
+        fields[j] = [parseFloat(vals[0]), parseFloat(vals[1])];
+      }
+    } else if (this.errorBars_) {
+      // If there are error bars, values are (value, stddev) pairs
+      for (var j = 1; j < inFields.length; j += 2)
+        fields[(j + 1) / 2] = [parseFloat(inFields[j]),
+                               parseFloat(inFields[j + 1])];
+    } else if (this.customBars_) {
+      // Bars are a low;center;high tuple
+      for (var j = 1; j < inFields.length; j++) {
+        var vals = inFields[j].split(";");
+        fields[j] = [ parseFloat(vals[0]),
+                      parseFloat(vals[1]),
+                      parseFloat(vals[2]) ];
+      }
+    } else {
+      // Values are just numbers
+      for (var j = 1; j < inFields.length; j++)
+        fields[j] = parseFloat(inFields[j]);
+    }
+    ret.push(fields);
+  }
+  return ret;
+};
+
+/**
+ * Get the CSV data. If it's in a function, call that function. If it's in a
+ * file, do an XMLHttpRequest to get it.
+ * @private
+ */
+DateGraph.prototype.start_ = function() {
+  if (typeof this.file_ == 'function') {
+    // Stubbed out to allow this to run off a filesystem
+    this.loadedEvent_(this.file_());
+  } else {
+    var req = new XMLHttpRequest();
+    var caller = this;
+    req.onreadystatechange = function () {
+      if (req.readyState == 4) {
+        if (req.status == 200) {
+          caller.loadedEvent_(req.responseText);
+        }
+      }
+    };
+
+    req.open("GET", this.file_, true);
+    req.send(null);
+  }
+};
+
+/**
+ * Changes various properties of the graph. These can include:
+ * <ul>
+ * <li>file: changes the source data for the graph</li>
+ * <li>errorBars: changes whether the data contains stddev</li>
+ * </ul>
+ * @param {Object} attrs The new properties and values
+ */
+DateGraph.prototype.updateOptions = function(attrs) {
+  if (attrs.errorBars) {
+    this.errorBars_ = attrs.errorBars;
+  }
+  if (attrs.customBars) {
+    this.customBars_ = attrs.customBars;
+  }
+  if (attrs.strokeWidth) {
+    this.strokeWidth_ = attrs.strokeWidth;
+  }
+  if (attrs.rollPeriod) {
+    this.rollPeriod_ = attrs.rollPeriod;
+  }
+  if (attrs.dateWindow) {
+    this.dateWindow_ = attrs.dateWindow;
+  }
+  if (attrs.valueRange) {
+    this.valueRange_ = attrs.valueRange;
+  }
+  if (attrs.minTickSize) {
+    this.minTickSize_ = attrs.minTickSize;
+  }
+  if (typeof(attrs.labels) != 'undefined') {
+    this.labels_ = attrs.labels;
+    this.labelsFromCSV_ = (attrs.labels == null);
+  }
+  this.layout_.updateOptions({ 'errorBars': this.errorBars_ });
+  if (attrs['file'] && attrs['file'] != this.file_) {
+    this.file_ = attrs['file'];
+    this.start_();
+  } else {
+    this.drawGraph_(this.rawData_);
+  }
+};
+
+/**
+ * Adjusts the number of days in the rolling average. Updates the graph to
+ * reflect the new averaging period.
+ * @param {Number} length Number of days over which to average the data.
+ */
+DateGraph.prototype.adjustRoll = function(length) {
+  this.rollPeriod_ = length;
+  this.drawGraph_(this.rawData_);
+};
diff --git a/generate-combined.sh b/generate-combined.sh
new file mode 100755 (executable)
index 0000000..b118250
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+# Generates a single JS file that's easier to include.
+# This packed JS includes a partial copy of MochiKit and PlotKit.
+cat \
+mochikit_v14/packed/MochiKit/MochiKit.js \
+plotkit_v091/PlotKit/PlotKit_Packed.js \
+dygraph-canvas.js \
+dygraph.js \
+> dygraph-combined.js
diff --git a/mochikit_v14/LICENSE.txt b/mochikit_v14/LICENSE.txt
new file mode 100644 (file)
index 0000000..4d0065b
--- /dev/null
@@ -0,0 +1,69 @@
+MochiKit is dual-licensed software.  It is available under the terms of the
+MIT License, or the Academic Free License version 2.1.  The full text of
+each license is included below.
+
+MIT License
+===========
+
+Copyright (c) 2005 Bob Ippolito.  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Academic Free License v. 2.1
+============================
+
+Copyright (c) 2005 Bob Ippolito.  All rights reserved.
+
+This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license to do the following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, to make, use, sell and offer for sale the Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor hereby agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work, and by publishing the address of that information repository in a notice immediately following the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior written permission of the Licensor. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor except as expressly stated herein. No patent license is granted to make, use, sell or offer to sell embodiments of any patent claims other than the licensed claims defined in Section 2. No right is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any Original Work that Licensor otherwise would have a right to license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately proceeding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to Original Work is granted hereunder except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to any person for any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to liability for death or personal injury resulting from Licensor's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. Nothing else but this License (or another written agreement between Licensor and You) grants You permission to create Derivative Works based upon the Original Work or to exercise any of the rights granted in Section 1 herein, and any attempt to do so except under the terms of this License (or another written agreement between Licensor and You) is expressly prohibited by U.S. copyright law, the equivalent laws of other countries, and by international treaty. Therefore, by exercising any of the rights granted to You in Section 1 herein, You indicate Your acceptance of this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of the U.S. Copyright Act, 17 U.S.C. Â§ 101 et seq., the equivalent laws of other countries, and international treaty. This section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
+
+13) Miscellaneous. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. Permission is hereby granted to copy and distribute this license without modification. This license may not be modified without the express written permission of its copyright owner.
+
+
diff --git a/mochikit_v14/MochiKit/Async.js b/mochikit_v14/MochiKit/Async.js
new file mode 100644 (file)
index 0000000..c4bc6f5
--- /dev/null
@@ -0,0 +1,699 @@
+/***
+
+MochiKit.Async 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+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.4";
+MochiKit.Async.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.Async.toString = function () {
+    return this.__repr__();
+};
+
+/** @id MochiKit.Async.Deferred */
+MochiKit.Async.Deferred = function (/* optional */ canceller) {
+    this.chain = [];
+    this.id = this._nextId();
+    this.fired = -1;
+    this.paused = 0;
+    this.results = [null, null];
+    this.canceller = canceller;
+    this.silentlyCancelled = false;
+    this.chained = false;
+};
+
+MochiKit.Async.Deferred.prototype = {
+    /** @id MochiKit.Async.Deferred.prototype.repr */
+    repr: function () {
+        var state;
+        if (this.fired == -1) {
+            state = 'unfired';
+        } else if (this.fired === 0) {
+            state = 'success';
+        } else {
+            state = 'error';
+        }
+        return 'Deferred(' + this.id + ', ' + state + ')';
+    },
+
+    toString: MochiKit.Base.forwardCall("repr"),
+
+    _nextId: MochiKit.Base.counter(),
+
+    /** @id MochiKit.Async.Deferred.prototype.cancel */
+    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();
+        }
+    },
+
+    _resback: function (res) {
+        /***
+
+        The primitive that means either callback or errback
+
+        ***/
+        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;
+        }
+    },
+
+    /** @id MochiKit.Async.Deferred.prototype.callback */
+    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);
+    },
+
+    /** @id MochiKit.Async.Deferred.prototype.errback */
+    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);
+    },
+
+    /** @id MochiKit.Async.Deferred.prototype.addBoth */
+    addBoth: function (fn) {
+        if (arguments.length > 1) {
+            fn = MochiKit.Base.partial.apply(null, arguments);
+        }
+        return this.addCallbacks(fn, fn);
+    },
+
+    /** @id MochiKit.Async.Deferred.prototype.addCallback */
+    addCallback: function (fn) {
+        if (arguments.length > 1) {
+            fn = MochiKit.Base.partial.apply(null, arguments);
+        }
+        return this.addCallbacks(fn, null);
+    },
+
+    /** @id MochiKit.Async.Deferred.prototype.addErrback */
+    addErrback: function (fn) {
+        if (arguments.length > 1) {
+            fn = MochiKit.Base.partial.apply(null, arguments);
+        }
+        return this.addCallbacks(null, fn);
+    },
+
+    /** @id MochiKit.Async.Deferred.prototype.addCallbacks */
+    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 () {
+        /***
+
+        Used internally to exhaust the callback sequence when a result
+        is available.
+
+        ***/
+        var chain = this.chain;
+        var fired = this.fired;
+        var res = this.results[fired];
+        var self = this;
+        var cb = null;
+        while (chain.length > 0 && this.paused === 0) {
+            // Array
+            var pair = chain.shift();
+            var f = pair[fired];
+            if (f === null) {
+                continue;
+            }
+            try {
+                res = f(res);
+                fired = ((res instanceof Error) ? 1 : 0);
+                if (res instanceof MochiKit.Async.Deferred) {
+                    cb = function (res) {
+                        self._resback(res);
+                        self.paused--;
+                        if ((self.paused === 0) && (self.fired >= 0)) {
+                            self._fire();
+                        }
+                    };
+                    this.paused++;
+                }
+            } catch (err) {
+                fired = 1;
+                if (!(err instanceof Error)) {
+                    err = new MochiKit.Async.GenericError(err);
+                }
+                res = err;
+            }
+        }
+        this.fired = fired;
+        this.results[fired] = res;
+        if (cb && this.paused) {
+            // this is for "tail recursion" in case the dependent deferred
+            // is already fired
+            res.addBoth(cb);
+            res.chained = true;
+        }
+    }
+};
+
+MochiKit.Base.update(MochiKit.Async, {
+    /** @id MochiKit.Async.evalJSONRequest */
+    evalJSONRequest: function (/* req */) {
+        return eval('(' + arguments[0].responseText + ')');
+    },
+
+    /** @id MochiKit.Async.succeed */
+    succeed: function (/* optional */result) {
+        var d = new MochiKit.Async.Deferred();
+        d.callback.apply(d, arguments);
+        return d;
+    },
+
+    /** @id MochiKit.Async.fail */
+    fail: function (/* optional */result) {
+        var d = new MochiKit.Async.Deferred();
+        d.errback.apply(d, arguments);
+        return d;
+    },
+
+    /** @id MochiKit.Async.getXMLHttpRequest */
+    getXMLHttpRequest: function () {
+        var self = arguments.callee;
+        if (!self.XMLHttpRequest) {
+            var tryThese = [
+                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 < tryThese.length; i++) {
+                var func = tryThese[i];
+                try {
+                    self.XMLHttpRequest = func;
+                    return func();
+                } catch (e) {
+                    // pass
+                }
+            }
+        }
+        return self.XMLHttpRequest();
+    },
+
+    _xhr_onreadystatechange: function (d) {
+        // MochiKit.Logging.logDebug('this.readyState', this.readyState);
+        var m = MochiKit.Base;
+        if (this.readyState == 4) {
+            // IE SUCKS
+            try {
+                this.onreadystatechange = null;
+            } catch (e) {
+                try {
+                    this.onreadystatechange = m.noop;
+                } catch (e) {
+                }
+            }
+            var status = null;
+            try {
+                status = this.status;
+                if (!status && m.isNotEmpty(this.responseText)) {
+                    // 0 or undefined seems to mean cached or local
+                    status = 304;
+                }
+            } catch (e) {
+                // pass
+                // MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
+            }
+            // 200 is OK, 201 is CREATED, 204 is NO CONTENT
+            // 304 is NOT MODIFIED, 1223 is apparently a bug in IE
+            if (status == 200 || status == 201 || status == 204 ||
+                    status == 304 || status == 1223) {
+                d.callback(this);
+            } else {
+                var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
+                if (err.number) {
+                    // XXX: This seems to happen on page change
+                    d.errback(err);
+                } else {
+                    // XXX: this seems to happen when the server is unreachable
+                    d.errback(err);
+                }
+            }
+        }
+    },
+
+    _xhr_canceller: function (req) {
+        // IE SUCKS
+        try {
+            req.onreadystatechange = null;
+        } catch (e) {
+            try {
+                req.onreadystatechange = MochiKit.Base.noop;
+            } catch (e) {
+            }
+        }
+        req.abort();
+    },
+
+
+    /** @id MochiKit.Async.sendXMLHttpRequest */
+    sendXMLHttpRequest: function (req, /* optional */ sendContent) {
+        if (typeof(sendContent) == "undefined" || sendContent === null) {
+            sendContent = "";
+        }
+
+        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(sendContent);
+        } catch (e) {
+            try {
+                req.onreadystatechange = null;
+            } catch (ignore) {
+                // pass
+            }
+            d.errback(e);
+        }
+
+        return d;
+
+    },
+
+    /** @id MochiKit.Async.doXHR */
+    doXHR: function (url, opts) {
+        /*
+            Work around a Firefox bug by dealing with XHR during
+            the next event loop iteration. Maybe it's this one:
+            https://bugzilla.mozilla.org/show_bug.cgi?id=249843
+        */
+        var self = MochiKit.Async;
+        return self.callLater(0, self._doXHR, url, opts);
+    },
+
+    _doXHR: function (url, opts) {
+        var m = MochiKit.Base;
+        opts = m.update({
+            method: 'GET',
+            sendContent: ''
+            /*
+            queryString: undefined,
+            username: undefined,
+            password: undefined,
+            headers: undefined,
+            mimeType: undefined
+            */
+        }, opts);
+        var self = MochiKit.Async;
+        var req = self.getXMLHttpRequest();
+        if (opts.queryString) {
+            var qs = m.queryString(opts.queryString);
+            if (qs) {
+                url += "?" + qs;
+            }
+        }
+        // Safari will send undefined:undefined, so we have to check.
+        // We can't use apply, since the function is native.
+        if ('username' in opts) {
+            req.open(opts.method, url, true, opts.username, opts.password);
+        } else {
+            req.open(opts.method, url, true);
+        }
+        if (req.overrideMimeType && opts.mimeType) {
+            req.overrideMimeType(opts.mimeType);
+        }
+        if (opts.headers) {
+            var headers = opts.headers;
+            if (!m.isArrayLike(headers)) {
+                headers = m.items(headers);
+            }
+            for (var i = 0; i < headers.length; i++) {
+                var header = headers[i];
+                var name = header[0];
+                var value = header[1];
+                req.setRequestHeader(name, value);
+            }
+        }
+        return self.sendXMLHttpRequest(req, opts.sendContent);
+    },
+
+    _buildURL: function (url/*, ...*/) {
+        if (arguments.length > 1) {
+            var m = MochiKit.Base;
+            var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
+            if (qs) {
+                return url + "?" + qs;
+            }
+        }
+        return url;
+    },
+
+    /** @id MochiKit.Async.doSimpleXMLHttpRequest */
+    doSimpleXMLHttpRequest: function (url/*, ...*/) {
+        var self = MochiKit.Async;
+        url = self._buildURL.apply(self, arguments);
+        return self.doXHR(url);
+    },
+
+    /** @id MochiKit.Async.loadJSONDoc */
+    loadJSONDoc: function (url/*, ...*/) {
+        var self = MochiKit.Async;
+        url = self._buildURL.apply(self, arguments);
+        var d = self.doXHR(url, {
+            'mimeType': 'text/plain',
+            'headers': [['Accept', 'application/json']]
+        });
+        d = d.addCallback(self.evalJSONRequest);
+        return d;
+    },
+
+    /** @id MochiKit.Async.wait */
+    wait: function (seconds, /* optional */value) {
+        var d = new MochiKit.Async.Deferred();
+        var m = MochiKit.Base;
+        if (typeof(value) != 'undefined') {
+            d.addCallback(function () { return value; });
+        }
+        var timeout = setTimeout(
+            m.bind("callback", d),
+            Math.floor(seconds * 1000));
+        d.canceller = function () {
+            try {
+                clearTimeout(timeout);
+            } catch (e) {
+                // pass
+            }
+        };
+        return d;
+    },
+
+    /** @id MochiKit.Async.callLater */
+    callLater: function (seconds, func) {
+        var m = MochiKit.Base;
+        var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
+        return MochiKit.Async.wait(seconds).addCallback(
+            function (res) { return pfunc(); }
+        );
+    }
+});
+
+
+/** @id MochiKit.Async.DeferredLock */
+MochiKit.Async.DeferredLock = function () {
+    this.waiting = [];
+    this.locked = false;
+    this.id = this._nextId();
+};
+
+MochiKit.Async.DeferredLock.prototype = {
+    __class__: MochiKit.Async.DeferredLock,
+    /** @id MochiKit.Async.DeferredLock.prototype.acquire */
+    acquire: function () {
+        var d = new MochiKit.Async.Deferred();
+        if (this.locked) {
+            this.waiting.push(d);
+        } else {
+            this.locked = true;
+            d.callback(this);
+        }
+        return d;
+    },
+    /** @id MochiKit.Async.DeferredLock.prototype.release */
+    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 state;
+        if (this.locked) {
+            state = 'locked, ' + this.waiting.length + ' waiting';
+        } else {
+            state = 'unlocked';
+        }
+        return 'DeferredLock(' + this.id + ', ' + state + ')';
+    },
+    toString: MochiKit.Base.forwardCall("repr")
+
+};
+
+/** @id MochiKit.Async.DeferredList */
+MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
+
+    // call parent constructor
+    MochiKit.Async.Deferred.apply(this, [canceller]);
+
+    this.list = list;
+    var resultList = [];
+    this.resultList = resultList;
+
+    this.finishedCount = 0;
+    this.fireOnOneCallback = fireOnOneCallback;
+    this.fireOnOneErrback = fireOnOneErrback;
+    this.consumeErrors = consumeErrors;
+
+    var cb = MochiKit.Base.bind(this._cbDeferred, this);
+    for (var i = 0; i < list.length; i++) {
+        var d = list[i];
+        resultList.push(undefined);
+        d.addCallback(cb, i, true);
+        d.addErrback(cb, i, false);
+    }
+
+    if (list.length === 0 && !fireOnOneCallback) {
+        this.callback(this.resultList);
+    }
+
+};
+
+MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();
+
+MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
+    this.resultList[index] = [succeeded, result];
+    this.finishedCount += 1;
+    if (this.fired == -1) {
+        if (succeeded && this.fireOnOneCallback) {
+            this.callback([index, result]);
+        } else if (!succeeded && this.fireOnOneErrback) {
+            this.errback(result);
+        } else if (this.finishedCount == this.list.length) {
+            this.callback(this.resultList);
+        }
+    }
+    if (!succeeded && this.consumeErrors) {
+        result = null;
+    }
+    return result;
+};
+
+/** @id MochiKit.Async.gatherResults */
+MochiKit.Async.gatherResults = function (deferredList) {
+    var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
+    d.addCallback(function (results) {
+        var ret = [];
+        for (var i = 0; i < results.length; i++) {
+            ret.push(results[i][1]);
+        }
+        return ret;
+    });
+    return d;
+};
+
+/** @id MochiKit.Async.maybeDeferred */
+MochiKit.Async.maybeDeferred = function (func) {
+    var self = MochiKit.Async;
+    var result;
+    try {
+        var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
+        if (r instanceof self.Deferred) {
+            result = r;
+        } else if (r instanceof Error) {
+            result = self.fail(r);
+        } else {
+            result = self.succeed(r);
+        }
+    } catch (e) {
+        result = self.fail(e);
+    }
+    return result;
+};
+
+
+MochiKit.Async.EXPORT = [
+    "AlreadyCalledError",
+    "CancelledError",
+    "BrowserComplianceError",
+    "GenericError",
+    "XMLHttpRequestError",
+    "Deferred",
+    "succeed",
+    "fail",
+    "getXMLHttpRequest",
+    "doSimpleXMLHttpRequest",
+    "loadJSONDoc",
+    "wait",
+    "callLater",
+    "sendXMLHttpRequest",
+    "DeferredLock",
+    "DeferredList",
+    "gatherResults",
+    "maybeDeferred",
+    "doXHR"
+];
+
+MochiKit.Async.EXPORT_OK = [
+    "evalJSONRequest"
+];
+
+MochiKit.Async.__new__ = function () {
+    var m = MochiKit.Base;
+    var ne = m.partial(m._newNamedError, this);
+
+    ne("AlreadyCalledError",
+        /** @id MochiKit.Async.AlreadyCalledError */
+        function (deferred) {
+            /***
+
+            Raised by the Deferred if callback or errback happens
+            after it was already fired.
+
+            ***/
+            this.deferred = deferred;
+        }
+    );
+
+    ne("CancelledError",
+        /** @id MochiKit.Async.CancelledError */
+        function (deferred) {
+            /***
+
+            Raised by the Deferred cancellation mechanism.
+
+            ***/
+            this.deferred = deferred;
+        }
+    );
+
+    ne("BrowserComplianceError",
+        /** @id MochiKit.Async.BrowserComplianceError */
+        function (msg) {
+            /***
+
+            Raised when the JavaScript runtime is not capable of performing
+            the given function.  Technically, this should really never be
+            raised because a non-conforming JavaScript runtime probably
+            isn't going to support exceptions in the first place.
+
+            ***/
+            this.message = msg;
+        }
+    );
+
+    ne("GenericError",
+        /** @id MochiKit.Async.GenericError */
+        function (msg) {
+            this.message = msg;
+        }
+    );
+
+    ne("XMLHttpRequestError",
+        /** @id MochiKit.Async.XMLHttpRequestError */
+        function (req, msg) {
+            /***
+
+            Raised when an XMLHttpRequest does not complete for any reason.
+
+            ***/
+            this.req = req;
+            this.message = msg;
+            try {
+                // Strange but true that this can raise in some cases.
+                this.number = req.status;
+            } catch (e) {
+                // pass
+            }
+        }
+    );
+
+
+    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);
diff --git a/mochikit_v14/MochiKit/Base.js b/mochikit_v14/MochiKit/Base.js
new file mode 100644 (file)
index 0000000..c526978
--- /dev/null
@@ -0,0 +1,1404 @@
+/***
+
+MochiKit.Base 1.4
+
+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 = {};
+}
+if (typeof(MochiKit.__export__) == "undefined") {
+    MochiKit.__export__ = (MochiKit.__compat__  ||
+        (typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
+    );
+}
+
+MochiKit.Base.VERSION = "1.4";
+MochiKit.Base.NAME = "MochiKit.Base";
+/** @id MochiKit.Base.update */
+MochiKit.Base.update = function (self, obj/*, ... */) {
+    if (self === null) {
+        self = {};
+    }
+    for (var i = 1; i < arguments.length; i++) {
+        var o = arguments[i];
+        if (typeof(o) != 'undefined' && o !== null) {
+            for (var k in o) {
+                self[k] = o[k];
+            }
+        }
+    }
+    return self;
+};
+
+MochiKit.Base.update(MochiKit.Base, {
+    __repr__: function () {
+        return "[" + this.NAME + " " + this.VERSION + "]";
+    },
+
+    toString: function () {
+        return this.__repr__();
+    },
+
+    /** @id MochiKit.Base.camelize */
+    camelize: function (selector) {
+        /* from dojo.style.toCamelCase */
+        var arr = selector.split('-');
+        var cc = arr[0];
+        for (var i = 1; i < arr.length; i++) {
+            cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
+        }
+        return cc;
+    },
+
+    /** @id MochiKit.Base.counter */
+    counter: function (n/* = 1 */) {
+        if (arguments.length === 0) {
+            n = 1;
+        }
+        return function () {
+            return n++;
+        };
+    },
+
+    /** @id MochiKit.Base.clone */
+    clone: function (obj) {
+        var me = arguments.callee;
+        if (arguments.length == 1) {
+            me.prototype = obj;
+            return new me();
+        }
+    },
+
+    _flattenArray: function (res, lst) {
+        for (var i = 0; i < lst.length; i++) {
+            var o = lst[i];
+            if (o instanceof Array) {
+                arguments.callee(res, o);
+            } else {
+                res.push(o);
+            }
+        }
+        return res;
+    },
+
+    /** @id MochiKit.Base.flattenArray */
+    flattenArray: function (lst) {
+        return MochiKit.Base._flattenArray([], lst);
+    },
+
+    /** @id MochiKit.Base.flattenArguments */
+    flattenArguments: function (lst/* ...*/) {
+        var res = [];
+        var m = MochiKit.Base;
+        var args = m.extend(null, arguments);
+        while (args.length) {
+            var o = args.shift();
+            if (o && typeof(o) == "object" && typeof(o.length) == "number") {
+                for (var i = o.length - 1; i >= 0; i--) {
+                    args.unshift(o[i]);
+                }
+            } else {
+                res.push(o);
+            }
+        }
+        return res;
+    },
+
+    /** @id MochiKit.Base.extend */
+    extend: function (self, obj, /* optional */skip) {
+        // Extend an array with an array-like object starting
+        // from the skip index
+        if (!skip) {
+            skip = 0;
+        }
+        if (obj) {
+            // allow iterable fall-through, but skip the full isArrayLike
+            // check for speed, this is called often.
+            var l = obj.length;
+            if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
+                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 (!self) {
+                self = [];
+            }
+            for (var i = skip; i < l; i++) {
+                self.push(obj[i]);
+            }
+        }
+        // This mutates, but it's convenient to return because
+        // it's often used like a constructor when turning some
+        // ghetto array-like to a real array
+        return self;
+    },
+
+
+    /** @id MochiKit.Base.updatetree */
+    updatetree: function (self, obj/*, ...*/) {
+        if (self === null) {
+            self = {};
+        }
+        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(self[k]) == 'object' && typeof(v) == 'object') {
+                        arguments.callee(self[k], v);
+                    } else {
+                        self[k] = v;
+                    }
+                }
+            }
+        }
+        return self;
+    },
+
+    /** @id MochiKit.Base.setdefault */
+    setdefault: function (self, obj/*, ...*/) {
+        if (self === null) {
+            self = {};
+        }
+        for (var i = 1; i < arguments.length; i++) {
+            var o = arguments[i];
+            for (var k in o) {
+                if (!(k in self)) {
+                    self[k] = o[k];
+                }
+            }
+        }
+        return self;
+    },
+
+    /** @id MochiKit.Base.keys */
+    keys: function (obj) {
+        var rval = [];
+        for (var prop in obj) {
+            rval.push(prop);
+        }
+        return rval;
+    },
+
+    /** @id MochiKit.Base.values */
+    values: function (obj) {
+        var rval = [];
+        for (var prop in obj) {
+            rval.push(obj[prop]);
+        }
+        return rval;
+    },
+
+     /** @id MochiKit.Base.items */
+    items: function (obj) {
+        var rval = [];
+        var e;
+        for (var prop in obj) {
+            var v;
+            try {
+                v = obj[prop];
+            } catch (e) {
+                continue;
+            }
+            rval.push([prop, v]);
+        }
+        return rval;
+    },
+
+
+    _newNamedError: function (module, name, func) {
+        func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
+        module[name] = func;
+    },
+
+
+    /** @id MochiKit.Base.operator */
+    operator: {
+        // unary logic operators
+        /** @id MochiKit.Base.truth */
+        truth: function (a) { return !!a; },
+        /** @id MochiKit.Base.lognot */
+        lognot: function (a) { return !a; },
+        /** @id MochiKit.Base.identity */
+        identity: function (a) { return a; },
+
+        // bitwise unary operators
+        /** @id MochiKit.Base.not */
+        not: function (a) { return ~a; },
+        /** @id MochiKit.Base.neg */
+        neg: function (a) { return -a; },
+
+        // binary operators
+        /** @id MochiKit.Base.add */
+        add: function (a, b) { return a + b; },
+        /** @id MochiKit.Base.sub */
+        sub: function (a, b) { return a - b; },
+        /** @id MochiKit.Base.div */
+        div: function (a, b) { return a / b; },
+        /** @id MochiKit.Base.mod */
+        mod: function (a, b) { return a % b; },
+        /** @id MochiKit.Base.mul */
+        mul: function (a, b) { return a * b; },
+
+        // bitwise binary operators
+        /** @id MochiKit.Base.and */
+        and: function (a, b) { return a & b; },
+        /** @id MochiKit.Base.or */
+        or: function (a, b) { return a | b; },
+        /** @id MochiKit.Base.xor */
+        xor: function (a, b) { return a ^ b; },
+        /** @id MochiKit.Base.lshift */
+        lshift: function (a, b) { return a << b; },
+        /** @id MochiKit.Base.rshift */
+        rshift: function (a, b) { return a >> b; },
+        /** @id MochiKit.Base.zrshift */
+        zrshift: function (a, b) { return a >>> b; },
+
+        // near-worthless built-in comparators
+        /** @id MochiKit.Base.eq */
+        eq: function (a, b) { return a == b; },
+        /** @id MochiKit.Base.ne */
+        ne: function (a, b) { return a != b; },
+        /** @id MochiKit.Base.gt */
+        gt: function (a, b) { return a > b; },
+        /** @id MochiKit.Base.ge */
+        ge: function (a, b) { return a >= b; },
+        /** @id MochiKit.Base.lt */
+        lt: function (a, b) { return a < b; },
+        /** @id MochiKit.Base.le */
+        le: function (a, b) { return a <= b; },
+
+        // strict built-in comparators
+        seq: function (a, b) { return a === b; },
+        sne: function (a, b) { return a !== b; },
+
+        // compare comparators
+        /** @id MochiKit.Base.ceq */
+        ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; },
+        /** @id MochiKit.Base.cne */
+        cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; },
+        /** @id MochiKit.Base.cgt */
+        cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; },
+        /** @id MochiKit.Base.cge */
+        cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; },
+        /** @id MochiKit.Base.clt */
+        clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; },
+        /** @id MochiKit.Base.cle */
+        cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; },
+
+        // binary logical operators
+        /** @id MochiKit.Base.logand */
+        logand: function (a, b) { return a && b; },
+        /** @id MochiKit.Base.logor */
+        logor: function (a, b) { return a || b; },
+        /** @id MochiKit.Base.contains */
+        contains: function (a, b) { return b in a; }
+    },
+
+    /** @id MochiKit.Base.forwardCall */
+    forwardCall: function (func) {
+        return function () {
+            return this[func].apply(this, arguments);
+        };
+    },
+
+    /** @id MochiKit.Base.itemgetter */
+    itemgetter: function (func) {
+        return function (arg) {
+            return arg[func];
+        };
+    },
+
+    /** @id MochiKit.Base.typeMatcher */
+    typeMatcher: function (/* typ */) {
+        var types = {};
+        for (var i = 0; i < arguments.length; i++) {
+            var typ = arguments[i];
+            types[typ] = typ;
+        }
+        return function () {
+            for (var i = 0; i < arguments.length; i++) {
+                if (!(typeof(arguments[i]) in types)) {
+                    return false;
+                }
+            }
+            return true;
+        };
+    },
+
+    /** @id MochiKit.Base.isNull */
+    isNull: function (/* ... */) {
+        for (var i = 0; i < arguments.length; i++) {
+            if (arguments[i] !== null) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    /** @id MochiKit.Base.isUndefinedOrNull */
+    isUndefinedOrNull: function (/* ... */) {
+        for (var i = 0; i < arguments.length; i++) {
+            var o = arguments[i];
+            if (!(typeof(o) == 'undefined' || o === null)) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    /** @id MochiKit.Base.isEmpty */
+    isEmpty: function (obj) {
+        return !MochiKit.Base.isNotEmpty.apply(this, arguments);
+    },
+
+    /** @id MochiKit.Base.isNotEmpty */
+    isNotEmpty: function (obj) {
+        for (var i = 0; i < arguments.length; i++) {
+            var o = arguments[i];
+            if (!(o && o.length)) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    /** @id MochiKit.Base.isArrayLike */
+    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' ||
+                o.nodeType === 3
+            ) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    /** @id MochiKit.Base.isDateLike */
+    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;
+    },
+
+
+    /** @id MochiKit.Base.xmap */
+    xmap: function (fn/*, obj... */) {
+        if (fn === null) {
+            return MochiKit.Base.extend(null, arguments, 1);
+        }
+        var rval = [];
+        for (var i = 1; i < arguments.length; i++) {
+            rval.push(fn(arguments[i]));
+        }
+        return rval;
+    },
+
+    /** @id MochiKit.Base.map */
+    map: function (fn, lst/*, lst... */) {
+        var m = MochiKit.Base;
+        var itr = MochiKit.Iter;
+        var isArrayLike = m.isArrayLike;
+        if (arguments.length <= 2) {
+            // allow an iterable to be passed
+            if (!isArrayLike(lst)) {
+                if (itr) {
+                    // fast path for map(null, iterable)
+                    lst = itr.list(lst);
+                    if (fn === null) {
+                        return lst;
+                    }
+                } else {
+                    throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+                }
+            }
+            // fast path for map(null, lst)
+            if (fn === null) {
+                return m.extend(null, lst);
+            }
+            // disabled fast path for map(fn, lst)
+            /*
+            if (false && typeof(Array.prototype.map) == 'function') {
+                // Mozilla fast-path
+                return Array.prototype.map.call(lst, fn);
+            }
+            */
+            var rval = [];
+            for (var i = 0; i < lst.length; i++) {
+                rval.push(fn(lst[i]));
+            }
+            return rval;
+        } else {
+            // default for map(null, ...) is zip(...)
+            if (fn === null) {
+                fn = Array;
+            }
+            var length = null;
+            for (i = 1; i < arguments.length; i++) {
+                // allow iterables to be passed
+                if (!isArrayLike(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");
+                    }
+                }
+                // find the minimum length
+                var l = arguments[i].length;
+                if (length === null || length > l) {
+                    length = l;
+                }
+            }
+            rval = [];
+            for (i = 0; i < length; i++) {
+                var args = [];
+                for (var j = 1; j < arguments.length; j++) {
+                    args.push(arguments[j][i]);
+                }
+                rval.push(fn.apply(this, args));
+            }
+            return rval;
+        }
+    },
+
+    /** @id MochiKit.Base.xfilter */
+    xfilter: function (fn/*, obj... */) {
+        var rval = [];
+        if (fn === null) {
+            fn = MochiKit.Base.operator.truth;
+        }
+        for (var i = 1; i < arguments.length; i++) {
+            var o = arguments[i];
+            if (fn(o)) {
+                rval.push(o);
+            }
+        }
+        return rval;
+    },
+
+    /** @id MochiKit.Base.filter */
+    filter: function (fn, lst, self) {
+        var rval = [];
+        // allow an iterable to be passed
+        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') {
+            // Mozilla fast-path
+            return Array.prototype.filter.call(lst, fn, self);
+        } else if (typeof(self) == 'undefined' || self === null) {
+            for (var i = 0; i < lst.length; i++) {
+                var o = lst[i];
+                if (fn(o)) {
+                    rval.push(o);
+                }
+            }
+        } else {
+            for (i = 0; i < lst.length; i++) {
+                o = lst[i];
+                if (fn.call(self, o)) {
+                    rval.push(o);
+                }
+            }
+        }
+        return rval;
+    },
+
+
+    _wrapDumbFunction: function (func) {
+        return function () {
+            // fast path!
+            switch (arguments.length) {
+                case 0: return func();
+                case 1: return func(arguments[0]);
+                case 2: return func(arguments[0], arguments[1]);
+                case 3: return func(arguments[0], arguments[1], arguments[2]);
+            }
+            var args = [];
+            for (var i = 0; i < arguments.length; i++) {
+                args.push("arguments[" + i + "]");
+            }
+            return eval("(func(" + args.join(",") + "))");
+        };
+    },
+
+    /** @id MochiKit.Base.methodcaller */
+    methodcaller: function (func/*, args... */) {
+        var args = MochiKit.Base.extend(null, arguments, 1);
+        if (typeof(func) == "function") {
+            return function (obj) {
+                return func.apply(obj, args);
+            };
+        } else {
+            return function (obj) {
+                return obj[func].apply(obj, args);
+            };
+        }
+    },
+
+    /** @id MochiKit.Base.method */
+    method: function (self, func) {
+        var m = MochiKit.Base;
+        return m.bind.apply(this, m.extend([func, self], arguments, 2));
+    },
+
+    /** @id MochiKit.Base.compose */
+    compose: function (f1, f2/*, f3, ... fN */) {
+        var fnlist = [];
+        var m = MochiKit.Base;
+        if (arguments.length === 0) {
+            throw new TypeError("compose() requires at least one argument");
+        }
+        for (var i = 0; i < arguments.length; i++) {
+            var fn = arguments[i];
+            if (typeof(fn) != "function") {
+                throw new TypeError(m.repr(fn) + " is not a function");
+            }
+            fnlist.push(fn);
+        }
+        return function () {
+            var args = arguments;
+            for (var i = fnlist.length - 1; i >= 0; i--) {
+                args = [fnlist[i].apply(this, args)];
+            }
+            return args[0];
+        };
+    },
+
+    /** @id MochiKit.Base.bind */
+    bind: function (func, self/* args... */) {
+        if (typeof(func) == "string") {
+            func = self[func];
+        }
+        var im_func = func.im_func;
+        var im_preargs = func.im_preargs;
+        var im_self = func.im_self;
+        var m = MochiKit.Base;
+        if (typeof(func) == "function" && typeof(func.apply) == "undefined") {
+            // this is for cases where JavaScript sucks ass and gives you a
+            // really dumb built-in function like alert() that doesn't have
+            // an apply
+            func = m._wrapDumbFunction(func);
+        }
+        if (typeof(im_func) != 'function') {
+            im_func = func;
+        }
+        if (typeof(self) != 'undefined') {
+            im_self = self;
+        }
+        if (typeof(im_preargs) == 'undefined') {
+            im_preargs = [];
+        } else  {
+            im_preargs = im_preargs.slice();
+        }
+        m.extend(im_preargs, arguments, 2);
+        var newfunc = function () {
+            var args = arguments;
+            var me = arguments.callee;
+            if (me.im_preargs.length > 0) {
+                args = m.concat(me.im_preargs, args);
+            }
+            var self = me.im_self;
+            if (!self) {
+                self = this;
+            }
+            return me.im_func.apply(self, args);
+        };
+        newfunc.im_self = im_self;
+        newfunc.im_func = im_func;
+        newfunc.im_preargs = im_preargs;
+        return newfunc;
+    },
+
+    /** @id MochiKit.Base.bindMethods */
+    bindMethods: function (self) {
+        var bind = MochiKit.Base.bind;
+        for (var k in self) {
+            var func = self[k];
+            if (typeof(func) == 'function') {
+                self[k] = bind(func, self);
+            }
+        }
+    },
+
+    /** @id MochiKit.Base.registerComparator */
+    registerComparator: function (name, check, comparator, /* optional */ override) {
+        MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
+    },
+
+    _primitives: {'boolean': true, 'string': true, 'number': true},
+
+    /** @id MochiKit.Base.compare */
+    compare: function (a, b) {
+        if (a == b) {
+            return 0;
+        }
+        var aIsNull = (typeof(a) == 'undefined' || a === null);
+        var bIsNull = (typeof(b) == 'undefined' || b === null);
+        if (aIsNull && bIsNull) {
+            return 0;
+        } else if (aIsNull) {
+            return -1;
+        } else if (bIsNull) {
+            return 1;
+        }
+        var m = MochiKit.Base;
+        // bool, number, string have meaningful comparisons
+        var prim = m._primitives;
+        if (!(typeof(a) in prim && typeof(b) in prim)) {
+            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;
+        }
+        // These types can't be compared
+        var repr = m.repr;
+        throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared");
+    },
+
+    /** @id MochiKit.Base.compareDateLike */
+    compareDateLike: function (a, b) {
+        return MochiKit.Base.compare(a.getTime(), b.getTime());
+    },
+
+    /** @id MochiKit.Base.compareArrayLike */
+    compareArrayLike: function (a, b) {
+        var compare = MochiKit.Base.compare;
+        var count = a.length;
+        var rval = 0;
+        if (count > b.length) {
+            rval = 1;
+            count = b.length;
+        } else if (count < b.length) {
+            rval = -1;
+        }
+        for (var i = 0; i < count; i++) {
+            var cmp = compare(a[i], b[i]);
+            if (cmp) {
+                return cmp;
+            }
+        }
+        return rval;
+    },
+
+    /** @id MochiKit.Base.registerRepr */
+    registerRepr: function (name, check, wrap, /* optional */override) {
+        MochiKit.Base.reprRegistry.register(name, check, wrap, override);
+    },
+
+    /** @id MochiKit.Base.repr */
+    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 ostring = (o + "");
+        } catch (e) {
+            return "[" + typeof(o) + "]";
+        }
+        if (typeof(o) == "function") {
+            o = ostring.replace(/^\s+/, "");
+            var idx = o.indexOf("{");
+            if (idx != -1) {
+                o = o.substr(0, idx) + "{...}";
+            }
+        }
+        return ostring;
+    },
+
+    /** @id MochiKit.Base.reprArrayLike */
+    reprArrayLike: function (o) {
+        var m = MochiKit.Base;
+        return "[" + m.map(m.repr, o).join(", ") + "]";
+    },
+
+    /** @id MochiKit.Base.reprString */
+    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");
+    },
+
+    /** @id MochiKit.Base.reprNumber */
+    reprNumber: function (o) {
+        return o + "";
+    },
+
+    /** @id MochiKit.Base.registerJSON */
+    registerJSON: function (name, check, wrap, /* optional */override) {
+        MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
+    },
+
+
+    /** @id MochiKit.Base.evalJSON */
+    evalJSON: function () {
+        return eval("(" + arguments[0] + ")");
+    },
+
+    /** @id MochiKit.Base.serializeJSON */
+    serializeJSON: function (o) {
+        var objtype = typeof(o);
+        if (objtype == "number" || objtype == "boolean") {
+            return o + "";
+        } else if (o === null) {
+            return "null";
+        }
+        var m = MochiKit.Base;
+        var reprString = m.reprString;
+        if (objtype == "string") {
+            return reprString(o);
+        }
+        // recurse
+        var me = arguments.callee;
+        // short-circuit for objects that support "json" serialization
+        // if they return "self" then just pass-through...
+        var newObj;
+        if (typeof(o.__json__) == "function") {
+            newObj = o.__json__();
+            if (o !== newObj) {
+                return me(newObj);
+            }
+        }
+        if (typeof(o.json) == "function") {
+            newObj = o.json();
+            if (o !== newObj) {
+                return me(newObj);
+            }
+        }
+        // array
+        if (objtype != "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(", ") + "]";
+        }
+        // look in the registry
+        try {
+            newObj = m.jsonRegistry.match(o);
+            if (o !== newObj) {
+                return me(newObj);
+            }
+        } catch (e) {
+            if (e != m.NotFound) {
+                // something really bad happened
+                throw e;
+            }
+        }
+        // undefined is outside of the spec
+        if (objtype == "undefined") {
+            throw new TypeError("undefined can not be serialized as JSON");
+        }
+        // it's a function with no adapter, bad
+        if (objtype == "function") {
+            return null;
+        }
+        // generic object code path
+        res = [];
+        for (var k in o) {
+            var useKey;
+            if (typeof(k) == "number") {
+                useKey = '"' + k + '"';
+            } else if (typeof(k) == "string") {
+                useKey = reprString(k);
+            } else {
+                // skip non-string or number keys
+                continue;
+            }
+            val = me(o[k]);
+            if (typeof(val) != "string") {
+                // skip non-serializable values
+                continue;
+            }
+            res.push(useKey + ":" + val);
+        }
+        return "{" + res.join(", ") + "}";
+    },
+
+
+    /** @id MochiKit.Base.objEqual */
+    objEqual: function (a, b) {
+        return (MochiKit.Base.compare(a, b) === 0);
+    },
+
+    /** @id MochiKit.Base.arrayEqual */
+    arrayEqual: function (self, arr) {
+        if (self.length != arr.length) {
+            return false;
+        }
+        return (MochiKit.Base.compare(self, arr) === 0);
+    },
+
+    /** @id MochiKit.Base.concat */
+    concat: function (/* lst... */) {
+        var rval = [];
+        var extend = MochiKit.Base.extend;
+        for (var i = 0; i < arguments.length; i++) {
+            extend(rval, arguments[i]);
+        }
+        return rval;
+    },
+
+    /** @id MochiKit.Base.keyComparator */
+    keyComparator: function (key/* ... */) {
+        // fast-path for single key comparisons
+        var m = MochiKit.Base;
+        var compare = m.compare;
+        if (arguments.length == 1) {
+            return function (a, b) {
+                return compare(a[key], b[key]);
+            };
+        }
+        var compareKeys = m.extend(null, arguments);
+        return function (a, b) {
+            var rval = 0;
+            // keep comparing until something is inequal or we run out of
+            // keys to compare
+            for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
+                var key = compareKeys[i];
+                rval = compare(a[key], b[key]);
+            }
+            return rval;
+        };
+    },
+
+    /** @id MochiKit.Base.reverseKeyComparator */
+    reverseKeyComparator: function (key) {
+        var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
+        return function (a, b) {
+            return comparator(b, a);
+        };
+    },
+
+    /** @id MochiKit.Base.partial */
+    partial: function (func) {
+        var m = MochiKit.Base;
+        return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
+    },
+
+    /** @id MochiKit.Base.listMinMax */
+    listMinMax: function (which, lst) {
+        if (lst.length === 0) {
+            return null;
+        }
+        var cur = lst[0];
+        var compare = MochiKit.Base.compare;
+        for (var i = 1; i < lst.length; i++) {
+            var o = lst[i];
+            if (compare(o, cur) == which) {
+                cur = o;
+            }
+        }
+        return cur;
+    },
+
+    /** @id MochiKit.Base.objMax */
+    objMax: function (/* obj... */) {
+        return MochiKit.Base.listMinMax(1, arguments);
+    },
+
+    /** @id MochiKit.Base.objMin */
+    objMin: function (/* obj... */) {
+        return MochiKit.Base.listMinMax(-1, arguments);
+    },
+
+    /** @id MochiKit.Base.findIdentical */
+    findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
+        if (typeof(end) == "undefined" || end === null) {
+            end = lst.length;
+        }
+        if (typeof(start) == "undefined" || start === null) {
+            start = 0;
+        }
+        for (var i = start; i < end; i++) {
+            if (lst[i] === value) {
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    /** @id MochiKit.Base.mean */
+    mean: function(/* lst... */) {
+        /* http://www.nist.gov/dads/HTML/mean.html */
+        var sum = 0;
+
+        var m = MochiKit.Base;
+        var args = m.extend(null, arguments);
+        var count = args.length;
+
+        while (args.length) {
+            var o = args.shift();
+            if (o && typeof(o) == "object" && typeof(o.length) == "number") {
+                count += o.length - 1;
+                for (var i = o.length - 1; i >= 0; i--) {
+                    sum += o[i];
+                }
+            } else {
+                sum += o;
+            }
+        }
+
+        if (count <= 0) {
+            throw new TypeError('mean() requires at least one argument');
+        }
+
+        return sum/count;
+    },
+
+    /** @id MochiKit.Base.median */
+    median: function(/* lst... */) {
+        /* http://www.nist.gov/dads/HTML/median.html */
+        var data = MochiKit.Base.flattenArguments(arguments);
+        if (data.length === 0) {
+            throw new TypeError('median() requires at least one argument');
+        }
+        data.sort(compare);
+        if (data.length % 2 == 0) {
+            var upper = data.length / 2;
+            return (data[upper] + data[upper - 1]) / 2;
+        } else {
+            return data[(data.length - 1) / 2];
+        }
+    },
+
+    /** @id MochiKit.Base.findValue */
+    findValue: function (lst, value, start/* = 0 */, /* optional */end) {
+        if (typeof(end) == "undefined" || end === null) {
+            end = lst.length;
+        }
+        if (typeof(start) == "undefined" || start === null) {
+            start = 0;
+        }
+        var cmp = MochiKit.Base.compare;
+        for (var i = start; i < end; i++) {
+            if (cmp(lst[i], value) === 0) {
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    /** @id MochiKit.Base.nodeWalk */
+    nodeWalk: function (node, visitor) {
+        var nodes = [node];
+        var extend = MochiKit.Base.extend;
+        while (nodes.length) {
+            var res = visitor(nodes.shift());
+            if (res) {
+                extend(nodes, res);
+            }
+        }
+    },
+
+
+    /** @id MochiKit.Base.nameFunctions */
+    nameFunctions: function (namespace) {
+        var base = namespace.NAME;
+        if (typeof(base) == 'undefined') {
+            base = '';
+        } else {
+            base = base + '.';
+        }
+        for (var name in namespace) {
+            var o = namespace[name];
+            if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
+                try {
+                    o.NAME = base + name;
+                } catch (e) {
+                    // pass
+                }
+            }
+        }
+    },
+
+
+    /** @id MochiKit.Base.queryString */
+    queryString: function (names, values) {
+        // check to see if names is a string or a DOM element, and if
+        // MochiKit.DOM is available.  If so, drop it like it's a form
+        // Ugliest conditional in MochiKit?  Probably!
+        if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
+            && (typeof(names) == "string" || (
+                typeof(names.nodeType) != "undefined" && names.nodeType > 0
+            ))
+        ) {
+            var kv = MochiKit.DOM.formContents(names);
+            names = kv[0];
+            values = kv[1];
+        } else if (arguments.length == 1) {
+            // Allow the return value of formContents to be passed directly
+            if (typeof(names.length) == "number" && names.length == 2) {
+                return arguments.callee(names[0], names[1]);
+            }
+            var o = names;
+            names = [];
+            values = [];
+            for (var k in o) {
+                var v = o[k];
+                if (typeof(v) == "function") {
+                    continue;
+                } else if (typeof(v) != "string" &&
+                        typeof(v.length) == "number") {
+                    for (var i = 0; i < v.length; i++) {
+                        names.push(k);
+                        values.push(v[i]);
+                    }
+                } else {
+                    names.push(k);
+                    values.push(v);
+                }
+            }
+        }
+        var rval = [];
+        var len = Math.min(names.length, values.length);
+        var urlEncode = MochiKit.Base.urlEncode;
+        for (var i = 0; i < len; i++) {
+            v = values[i];
+            if (typeof(v) != 'undefined' && v !== null) {
+                rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
+            }
+        }
+        return rval.join("&");
+    },
+
+
+    /** @id MochiKit.Base.parseQueryString */
+    parseQueryString: function (encodedString, useArrays) {
+        // strip a leading '?' from the encoded string
+        var qstr = (encodedString.charAt(0) == "?")
+            ? encodedString.substring(1)
+            : encodedString;
+        var pairs = qstr.replace(/\+/g, "%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
+        var o = {};
+        var decode;
+        if (typeof(decodeURIComponent) != "undefined") {
+            decode = decodeURIComponent;
+        } else {
+            decode = unescape;
+        }
+        if (useArrays) {
+            for (var i = 0; i < pairs.length; i++) {
+                var pair = pairs[i].split("=");
+                var name = decode(pair.shift());
+                if (!name) {
+                    continue;
+                }
+                var arr = o[name];
+                if (!(arr instanceof Array)) {
+                    arr = [];
+                    o[name] = arr;
+                }
+                arr.push(decode(pair.join("=")));
+            }
+        } else {
+            for (i = 0; i < pairs.length; i++) {
+                pair = pairs[i].split("=");
+                var name = pair.shift();
+                if (!name) {
+                    continue;
+                }
+                o[decode(name)] = decode(pair.join("="));
+            }
+        }
+        return o;
+    }
+});
+
+/** @id MochiKit.Base.AdapterRegistry */
+MochiKit.Base.AdapterRegistry = function () {
+    this.pairs = [];
+};
+
+MochiKit.Base.AdapterRegistry.prototype = {
+    /** @id MochiKit.Base.AdapterRegistry.prototype.register */
+    register: function (name, check, wrap, /* optional */ override) {
+        if (override) {
+            this.pairs.unshift([name, check, wrap]);
+        } else {
+            this.pairs.push([name, check, wrap]);
+        }
+    },
+
+    /** @id MochiKit.Base.AdapterRegistry.prototype.match */
+    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;
+    },
+
+    /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
+    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 = [
+    "flattenArray",
+    "noop",
+    "camelize",
+    "counter",
+    "clone",
+    "extend",
+    "update",
+    "updatetree",
+    "setdefault",
+    "keys",
+    "values",
+    "items",
+    "NamedError",
+    "operator",
+    "forwardCall",
+    "itemgetter",
+    "typeMatcher",
+    "isCallable",
+    "isUndefined",
+    "isUndefinedOrNull",
+    "isNull",
+    "isEmpty",
+    "isNotEmpty",
+    "isArrayLike",
+    "isDateLike",
+    "xmap",
+    "map",
+    "xfilter",
+    "filter",
+    "methodcaller",
+    "compose",
+    "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",
+    "average",
+    "mean",
+    "median"
+];
+
+MochiKit.Base.EXPORT_OK = [
+    "nameFunctions",
+    "comparatorRegistry",
+    "reprRegistry",
+    "jsonRegistry",
+    "compareDateLike",
+    "compareArrayLike",
+    "reprArrayLike",
+    "reprString",
+    "reprNumber"
+];
+
+MochiKit.Base._exportSymbols = function (globals, module) {
+    if (!MochiKit.__export__) {
+        return;
+    }
+    var all = module.EXPORT_TAGS[":all"];
+    for (var i = 0; i < all.length; i++) {
+        globals[all[i]] = module[all[i]];
+    }
+};
+
+MochiKit.Base.__new__ = function () {
+    // A singleton raised when no suitable adapter is found
+    var m = this;
+
+    // convenience
+    /** @id MochiKit.Base.noop */
+    m.noop = m.operator.identity;
+
+    // Backwards compat
+    m.forward = m.forwardCall;
+    m.find = m.findValue;
+
+    if (typeof(encodeURIComponent) != "undefined") {
+        /** @id MochiKit.Base.urlEncode */
+        m.urlEncode = function (unencoded) {
+            return encodeURIComponent(unencoded).replace(/\'/g, '%27');
+        };
+    } else {
+        m.urlEncode = function (unencoded) {
+            return escape(unencoded
+                ).replace(/\+/g, '%2B'
+                ).replace(/\"/g,'%22'
+                ).rval.replace(/\'/g, '%27');
+        };
+    }
+
+    /** @id MochiKit.Base.NamedError */
+    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")
+    });
+
+    /** @id MochiKit.Base.NotFound */
+    m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
+
+
+    /** @id MochiKit.Base.listMax */
+    m.listMax = m.partial(m.listMinMax, 1);
+    /** @id MochiKit.Base.listMin */
+    m.listMin = m.partial(m.listMinMax, -1);
+
+    /** @id MochiKit.Base.isCallable */
+    m.isCallable = m.typeMatcher('function');
+    /** @id MochiKit.Base.isUndefined */
+    m.isUndefined = m.typeMatcher('undefined');
+
+    /** @id MochiKit.Base.merge */
+    m.merge = m.partial(m.update, null);
+    /** @id MochiKit.Base.zip */
+    m.zip = m.partial(m.map, null);
+
+    /** @id MochiKit.Base.average */
+    m.average = m.mean;
+
+    /** @id MochiKit.Base.comparatorRegistry */
+    m.comparatorRegistry = new m.AdapterRegistry();
+    m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
+    m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
+
+    /** @id MochiKit.Base.reprRegistry */
+    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);
+
+    /** @id MochiKit.Base.jsonRegistry */
+    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__();
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+    compare = MochiKit.Base.compare;
+    compose = MochiKit.Base.compose;
+    serializeJSON = MochiKit.Base.serializeJSON;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.Base);
diff --git a/mochikit_v14/MochiKit/Color.js b/mochikit_v14/MochiKit/Color.js
new file mode 100644 (file)
index 0000000..708f490
--- /dev/null
@@ -0,0 +1,902 @@
+/***
+
+MochiKit.Color 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito and others.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Color');
+    dojo.require('MochiKit.Base');
+    dojo.require('MochiKit.DOM');
+    dojo.require('MochiKit.Style');
+}
+
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use("MochiKit.Base", []);
+    JSAN.use("MochiKit.DOM", []);
+    JSAN.use("MochiKit.Style", []);
+}
+
+try {
+    if (typeof(MochiKit.Base) == 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.Color depends on MochiKit.Base";
+}
+
+try {
+    if (typeof(MochiKit.DOM) == 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.Color depends on MochiKit.DOM";
+}
+
+try {
+    if (typeof(MochiKit.Style) == 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.Color depends on MochiKit.Style";
+}
+
+if (typeof(MochiKit.Color) == "undefined") {
+    MochiKit.Color = {};
+}
+
+MochiKit.Color.NAME = "MochiKit.Color";
+MochiKit.Color.VERSION = "1.4";
+
+MochiKit.Color.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Color.toString = function () {
+    return this.__repr__();
+};
+
+
+/** @id MochiKit.Color.Color */
+MochiKit.Color.Color = function (red, green, blue, alpha) {
+    if (typeof(alpha) == 'undefined' || alpha === null) {
+        alpha = 1.0;
+    }
+    this.rgb = {
+        r: red,
+        g: green,
+        b: blue,
+        a: alpha
+    };
+};
+
+
+// Prototype methods
+
+MochiKit.Color.Color.prototype = {
+
+    __class__: MochiKit.Color.Color,
+
+    /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
+    colorWithAlpha: function (alpha) {
+        var rgb = this.rgb;
+        var m = MochiKit.Color;
+        return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.colorWithHue */
+    colorWithHue: function (hue) {
+        // get an HSL model, and set the new hue...
+        var hsl = this.asHSL();
+        hsl.h = hue;
+        var m = MochiKit.Color;
+        // convert back to RGB...
+        return m.Color.fromHSL(hsl);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
+    colorWithSaturation: function (saturation) {
+        // get an HSL model, and set the new hue...
+        var hsl = this.asHSL();
+        hsl.s = saturation;
+        var m = MochiKit.Color;
+        // convert back to RGB...
+        return m.Color.fromHSL(hsl);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.colorWithLightness */
+    colorWithLightness: function (lightness) {
+        // get an HSL model, and set the new hue...
+        var hsl = this.asHSL();
+        hsl.l = lightness;
+        var m = MochiKit.Color;
+        // convert back to RGB...
+        return m.Color.fromHSL(hsl);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
+    darkerColorWithLevel: function (level) {
+        var hsl  = this.asHSL();
+        hsl.l = Math.max(hsl.l - level, 0);
+        var m = MochiKit.Color;
+        return m.Color.fromHSL(hsl);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
+    lighterColorWithLevel: function (level) {
+        var hsl  = this.asHSL();
+        hsl.l = Math.min(hsl.l + level, 1);
+        var m = MochiKit.Color;
+        return m.Color.fromHSL(hsl);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.blendedColor */
+    blendedColor: function (other, /* optional */ fraction) {
+        if (typeof(fraction) == 'undefined' || fraction === null) {
+            fraction = 0.5;
+        }
+        var sf = 1.0 - fraction;
+        var s = this.rgb;
+        var d = other.rgb;
+        var df = fraction;
+        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)
+        );
+    },
+
+    /** @id MochiKit.Color.Color.prototype.compareRGB */
+    compareRGB: function (other) {
+        var a = this.asRGB();
+        var b = other.asRGB();
+        return MochiKit.Base.compare(
+            [a.r, a.g, a.b, a.a],
+            [b.r, b.g, b.b, b.a]
+        );
+    },
+
+    /** @id MochiKit.Color.Color.prototype.isLight */
+    isLight: function () {
+        return this.asHSL().b > 0.5;
+    },
+
+    /** @id MochiKit.Color.Color.prototype.isDark */
+    isDark: function () {
+        return (!this.isLight());
+    },
+
+    /** @id MochiKit.Color.Color.prototype.toHSLString */
+    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;
+    },
+
+    /** @id MochiKit.Color.Color.prototype.toRGBString */
+    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;
+    },
+
+    /** @id MochiKit.Color.Color.prototype.asRGB */
+    asRGB: function () {
+        return MochiKit.Base.clone(this.rgb);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.toHexString */
+    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;
+    },
+
+    /** @id MochiKit.Color.Color.prototype.asHSV */
+    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);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.asHSL */
+    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);
+    },
+
+    /** @id MochiKit.Color.Color.prototype.toString */
+    toString: function () {
+        return this.toRGBString();
+    },
+
+    /** @id MochiKit.Color.Color.prototype.repr */
+    repr: function () {
+        var c = this.rgb;
+        var col = [c.r, c.g, c.b, c.a];
+        return this.__class__.NAME + "(" + col.join(", ") + ")";
+    }
+
+};
+
+// Constructor methods
+
+MochiKit.Base.update(MochiKit.Color.Color, {
+    /** @id MochiKit.Color.Color.fromRGB */
+    fromRGB: function (red, green, blue, alpha) {
+        // designated initializer
+        var Color = MochiKit.Color.Color;
+        if (arguments.length == 1) {
+            var rgb = red;
+            red = rgb.r;
+            green = rgb.g;
+            blue = rgb.b;
+            if (typeof(rgb.a) == 'undefined') {
+                alpha = undefined;
+            } else {
+                alpha = rgb.a;
+            }
+        }
+        return new Color(red, green, blue, alpha);
+    },
+
+    /** @id MochiKit.Color.Color.fromHSL */
+    fromHSL: function (hue, saturation, lightness, alpha) {
+        var m = MochiKit.Color;
+        return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
+    },
+
+    /** @id MochiKit.Color.Color.fromHSV */
+    fromHSV: function (hue, saturation, value, alpha) {
+        var m = MochiKit.Color;
+        return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
+    },
+
+    /** @id MochiKit.Color.Color.fromName */
+    fromName: function (name) {
+        var Color = MochiKit.Color.Color;
+        // Opera 9 seems to "quote" named colors(?!)
+        if (name.charAt(0) == '"') {
+            name = name.substr(1, name.length - 2);
+        }
+        var htmlColor = Color._namedColors[name.toLowerCase()];
+        if (typeof(htmlColor) == 'string') {
+            return Color.fromHexString(htmlColor);
+        } else if (name == "transparent") {
+            return Color.transparentColor();
+        }
+        return null;
+    },
+
+    /** @id MochiKit.Color.Color.fromString */
+    fromString: function (colorString) {
+        var self = MochiKit.Color.Color;
+        var three = colorString.substr(0, 3);
+        if (three == "rgb") {
+            return self.fromRGBString(colorString);
+        } else if (three == "hsl") {
+            return self.fromHSLString(colorString);
+        } else if (colorString.charAt(0) == "#") {
+            return self.fromHexString(colorString);
+        }
+        return self.fromName(colorString);
+    },
+
+
+    /** @id MochiKit.Color.Color.fromHexString */
+    fromHexString: function (hexCode) {
+        if (hexCode.charAt(0) == '#') {
+            hexCode = hexCode.substring(1);
+        }
+        var components = [];
+        var i, hex;
+        if (hexCode.length == 3) {
+            for (i = 0; i < 3; i++) {
+                hex = hexCode.substr(i, 1);
+                components.push(parseInt(hex + hex, 16) / 255.0);
+            }
+        } else {
+            for (i = 0; i < 6; i += 2) {
+                hex = hexCode.substr(i, 2);
+                components.push(parseInt(hex, 16) / 255.0);
+            }
+        }
+        var Color = MochiKit.Color.Color;
+        return Color.fromRGB.apply(Color, components);
+    },
+
+
+    _fromColorString: function (pre, method, scales, colorCode) {
+        // parses either HSL or RGB
+        if (colorCode.indexOf(pre) === 0) {
+            colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
+        }
+        var colorChunks = colorCode.split(/\s*,\s*/);
+        var colorFloats = [];
+        for (var i = 0; i < colorChunks.length; i++) {
+            var c = colorChunks[i];
+            var val;
+            var three = c.substring(c.length - 3);
+            if (c.charAt(c.length - 1) == '%') {
+                val = 0.01 * parseFloat(c.substring(0, c.length - 1));
+            } else if (three == "deg") {
+                val = parseFloat(c) / 360.0;
+            } else if (three == "rad") {
+                val = parseFloat(c) / (Math.PI * 2);
+            } else {
+                val = scales[i] * parseFloat(c);
+            }
+            colorFloats.push(val);
+        }
+        return this[method].apply(this, colorFloats);
+    },
+
+    /** @id MochiKit.Color.Color.fromComputedStyle */
+    fromComputedStyle: function (elem, style) {
+        var d = MochiKit.DOM;
+        var cls = MochiKit.Color.Color;
+        for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
+            var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
+            if (!actualColor) {
+                continue;
+            }
+            var color = cls.fromString(actualColor);
+            if (!color) {
+                break;
+            }
+            if (color.asRGB().a > 0) {
+                return color;
+            }
+        }
+        return null;
+    },
+
+    /** @id MochiKit.Color.Color.fromBackground */
+    fromBackground: function (elem) {
+        var cls = MochiKit.Color.Color;
+        return cls.fromComputedStyle(
+            elem, "backgroundColor", "background-color") || cls.whiteColor();
+    },
+
+    /** @id MochiKit.Color.Color.fromText */
+    fromText: function (elem) {
+        var cls = MochiKit.Color.Color;
+        return cls.fromComputedStyle(
+            elem, "color", "color") || cls.blackColor();
+    },
+
+    /** @id MochiKit.Color.Color.namedColors */
+    namedColors: function () {
+        return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
+    }
+});
+
+
+// Module level functions
+
+MochiKit.Base.update(MochiKit.Color, {
+    /** @id MochiKit.Color.clampColorComponent */
+    clampColorComponent: function (v, scale) {
+        v *= scale;
+        if (v < 0) {
+            return 0;
+        } else if (v > scale) {
+            return scale;
+        } else {
+            return v;
+        }
+    },
+
+    _hslValue: function (n1, n2, hue) {
+        if (hue > 6.0) {
+            hue -= 6.0;
+        } else if (hue < 0.0) {
+            hue += 6.0;
+        }
+        var val;
+        if (hue < 1.0) {
+            val = n1 + (n2 - n1) * hue;
+        } else if (hue < 3.0) {
+            val = n2;
+        } else if (hue < 4.0) {
+            val = n1 + (n2 - n1) * (4.0 - hue);
+        } else {
+            val = n1;
+        }
+        return val;
+    },
+
+    /** @id MochiKit.Color.hsvToRGB */
+    hsvToRGB: function (hue, saturation, value, alpha) {
+        if (arguments.length == 1) {
+            var hsv = hue;
+            hue = hsv.h;
+            saturation = hsv.s;
+            value = hsv.v;
+            alpha = hsv.a;
+        }
+        var red;
+        var green;
+        var blue;
+        if (saturation === 0) {
+            red = value;
+            green = value;
+            blue = value;
+        } else {
+            var i = Math.floor(hue * 6);
+            var f = (hue * 6) - i;
+            var p = value * (1 - saturation);
+            var q = value * (1 - (saturation * f));
+            var t = value * (1 - (saturation * (1 - f)));
+            switch (i) {
+                case 1: red = q; green = value; blue = p; break;
+                case 2: red = p; green = value; blue = t; break;
+                case 3: red = p; green = q; blue = value; break;
+                case 4: red = t; green = p; blue = value; break;
+                case 5: red = value; green = p; blue = q; break;
+                case 6: // fall through
+                case 0: red = value; green = t; blue = p; break;
+            }
+        }
+        return {
+            r: red,
+            g: green,
+            b: blue,
+            a: alpha
+        };
+    },
+
+    /** @id MochiKit.Color.hslToRGB */
+    hslToRGB: function (hue, saturation, lightness, alpha) {
+        if (arguments.length == 1) {
+            var hsl = hue;
+            hue = hsl.h;
+            saturation = hsl.s;
+            lightness = hsl.l;
+            alpha = hsl.a;
+        }
+        var red;
+        var green;
+        var blue;
+        if (saturation === 0) {
+            red = lightness;
+            green = lightness;
+            blue = lightness;
+        } else {
+            var m2;
+            if (lightness <= 0.5) {
+                m2 = lightness * (1.0 + saturation);
+            } else {
+                m2 = lightness + saturation - (lightness * saturation);
+            }
+            var m1 = (2.0 * lightness) - m2;
+            var f = MochiKit.Color._hslValue;
+            var h6 = hue * 6.0;
+            red = f(m1, m2, h6 + 2);
+            green = f(m1, m2, h6);
+            blue = f(m1, m2, h6 - 2);
+        }
+        return {
+            r: red,
+            g: green,
+            b: blue,
+            a: alpha
+        };
+    },
+
+    /** @id MochiKit.Color.rgbToHSV */
+    rgbToHSV: function (red, green, blue, alpha) {
+        if (arguments.length == 1) {
+            var rgb = red;
+            red = rgb.r;
+            green = rgb.g;
+            blue = rgb.b;
+            alpha = rgb.a;
+        }
+        var max = Math.max(Math.max(red, green), blue);
+        var min = Math.min(Math.min(red, green), blue);
+        var hue;
+        var saturation;
+        var value = max;
+        if (min == max) {
+            hue = 0;
+            saturation = 0;
+        } else {
+            var delta = (max - min);
+            saturation = delta / max;
+
+            if (red == max) {
+                hue = (green - blue) / delta;
+            } else if (green == max) {
+                hue = 2 + ((blue - red) / delta);
+            } else {
+                hue = 4 + ((red - green) / delta);
+            }
+            hue /= 6;
+            if (hue < 0) {
+                hue += 1;
+            }
+            if (hue > 1) {
+                hue -= 1;
+            }
+        }
+        return {
+            h: hue,
+            s: saturation,
+            v: value,
+            a: alpha
+        };
+    },
+
+    /** @id MochiKit.Color.rgbToHSL */
+    rgbToHSL: function (red, green, blue, alpha) {
+        if (arguments.length == 1) {
+            var rgb = red;
+            red = rgb.r;
+            green = rgb.g;
+            blue = rgb.b;
+            alpha = rgb.a;
+        }
+        var max = Math.max(red, Math.max(green, blue));
+        var min = Math.min(red, Math.min(green, blue));
+        var hue;
+        var saturation;
+        var lightness = (max + min) / 2.0;
+        var delta = max - min;
+        if (delta === 0) {
+            hue = 0;
+            saturation = 0;
+        } else {
+            if (lightness <= 0.5) {
+                saturation = delta / (max + min);
+            } else {
+                saturation = delta / (2 - max - min);
+            }
+            if (red == max) {
+                hue = (green - blue) / delta;
+            } else if (green == max) {
+                hue = 2 + ((blue - red) / delta);
+            } else {
+                hue = 4 + ((red - green) / delta);
+            }
+            hue /= 6;
+            if (hue < 0) {
+                hue += 1;
+            }
+            if (hue > 1) {
+                hue -= 1;
+            }
+
+        }
+        return {
+            h: hue,
+            s: saturation,
+            l: lightness,
+            a: alpha
+        };
+    },
+
+    /** @id MochiKit.Color.toColorPart */
+    toColorPart: function (num) {
+        num = Math.round(num);
+        var digits = num.toString(16);
+        if (num < 16) {
+            return '0' + digits;
+        }
+        return digits;
+    },
+
+    __new__: function () {
+        var m = MochiKit.Base;
+        /** @id MochiKit.Color.fromRGBString */
+        this.Color.fromRGBString = m.bind(
+            this.Color._fromColorString, this.Color, "rgb", "fromRGB",
+            [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
+        );
+        /** @id MochiKit.Color.fromHSLString */
+        this.Color.fromHSLString = m.bind(
+            this.Color._fromColorString, this.Color, "hsl", "fromHSL",
+            [1.0/360.0, 0.01, 0.01, 1]
+        );
+
+        var third = 1.0 / 3.0;
+        /** @id MochiKit.Color.colors */
+        var colors = {
+            // NSColor colors plus transparent
+            /** @id MochiKit.Color.blackColor */
+            black: [0, 0, 0],
+            /** @id MochiKit.Color.blueColor */
+            blue: [0, 0, 1],
+            /** @id MochiKit.Color.brownColor */
+            brown: [0.6, 0.4, 0.2],
+            /** @id MochiKit.Color.cyanColor */
+            cyan: [0, 1, 1],
+            /** @id MochiKit.Color.darkGrayColor */
+            darkGray: [third, third, third],
+            /** @id MochiKit.Color.grayColor */
+            gray: [0.5, 0.5, 0.5],
+            /** @id MochiKit.Color.greenColor */
+            green: [0, 1, 0],
+            /** @id MochiKit.Color.lightGrayColor */
+            lightGray: [2 * third, 2 * third, 2 * third],
+            /** @id MochiKit.Color.magentaColor */
+            magenta: [1, 0, 1],
+            /** @id MochiKit.Color.orangeColor */
+            orange: [1, 0.5, 0],
+            /** @id MochiKit.Color.purpleColor */
+            purple: [0.5, 0, 0.5],
+            /** @id MochiKit.Color.redColor */
+            red: [1, 0, 0],
+            /** @id MochiKit.Color.transparentColor */
+            transparent: [0, 0, 0, 0],
+            /** @id MochiKit.Color.whiteColor */
+            white: [1, 1, 1],
+            /** @id MochiKit.Color.yellowColor */
+            yellow: [1, 1, 0]
+        };
+
+        var makeColor = 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 colors) {
+            var name = k + "Color";
+            var bindArgs = m.concat(
+                [makeColor, this.Color, name],
+                colors[k]
+            );
+            this.Color[name] = m.bind.apply(null, bindArgs);
+        }
+
+        var isColor = function () {
+            for (var i = 0; i < arguments.length; i++) {
+                if (!(arguments[i] instanceof Color)) {
+                    return false;
+                }
+            }
+            return true;
+        };
+
+        var compareColor = function (a, b) {
+            return a.compareRGB(b);
+        };
+
+        m.nameFunctions(this);
+
+        m.registerComparator(this.Color.NAME, isColor, compareColor);
+
+        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);
+
+// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
+
+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"
+};
diff --git a/mochikit_v14/MochiKit/Controls.js b/mochikit_v14/MochiKit/Controls.js
new file mode 100644 (file)
index 0000000..c044ef2
--- /dev/null
@@ -0,0 +1,1388 @@
+/***
+Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+          (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+          (c) 2005 Jon Tirsen (http://www.tirsen.com)
+Contributors:
+    Richard Livsey
+    Rahul Bhargava
+    Rob Wills
+    Mochi-ized By Thomas Herve (_firstname_@nimail.org)
+
+See scriptaculous.js for full license.
+
+Autocompleter.Base handles all the autocompletion functionality
+that's independent of the data source for autocompletion. This
+includes drawing the autocompletion menu, observing keyboard
+and mouse events, and similar.
+
+Specific autocompleters need to provide, at the very least,
+a getUpdatedChoices function that will be invoked every time
+the text inside the monitored textbox changes. This method
+should get the text for which to provide autocompletion by
+invoking this.getToken(), NOT by directly accessing
+this.element.value. This is to allow incremental tokenized
+autocompletion. Specific auto-completion logic (AJAX, etc)
+belongs in getUpdatedChoices.
+
+Tokenized incremental autocompletion is enabled automatically
+when an autocompleter is instantiated with the 'tokens' option
+in the options parameter, e.g.:
+new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+will incrementally autocomplete with a comma as the token.
+Additionally, ',' in the above example can be replaced with
+a token array, e.g. { tokens: [',', '\n'] } which
+enables autocompletion on multiple tokens. This is most
+useful when one of the tokens is \n (a newline), as it
+allows smart autocompletion after linebreaks.
+
+***/
+
+MochiKit.Base.update(MochiKit.Base, {
+    ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+
+/** @id MochiKit.Base.stripScripts */
+    stripScripts: function (str) {
+        return str.replace(new RegExp(MochiKit.Base.ScriptFragment, 'img'), '');
+    },
+
+/** @id MochiKit.Base.stripTags */
+    stripTags: function(str) {
+        return str.replace(/<\/?[^>]+>/gi, '');
+    },
+
+/** @id MochiKit.Base.extractScripts */
+    extractScripts: function (str) {
+        var matchAll = new RegExp(MochiKit.Base.ScriptFragment, 'img');
+        var matchOne = new RegExp(MochiKit.Base.ScriptFragment, 'im');
+        return MochiKit.Base.map(function (scriptTag) {
+            return (scriptTag.match(matchOne) || ['', ''])[1];
+        }, str.match(matchAll) || []);
+    },
+
+/** @id MochiKit.Base.evalScripts */
+    evalScripts: function (str) {
+        return MochiKit.Base.map(function (scr) {
+            eval(scr);
+        }, MochiKit.Base.extractScripts(str));
+    }
+});
+
+MochiKit.Form = {
+
+/** @id MochiKit.Form.serialize */
+    serialize: function (form) {
+        var elements = MochiKit.Form.getElements(form);
+        var queryComponents = [];
+
+        for (var i = 0; i < elements.length; i++) {
+            var queryComponent = MochiKit.Form.serializeElement(elements[i]);
+            if (queryComponent) {
+                queryComponents.push(queryComponent);
+            }
+        }
+
+        return queryComponents.join('&');
+    },
+
+/** @id MochiKit.Form.getElements */
+    getElements: function (form) {
+        form = MochiKit.DOM.getElement(form);
+        var elements = [];
+
+        for (var tagName in MochiKit.Form.Serializers) {
+            var tagElements = form.getElementsByTagName(tagName);
+            for (var j = 0; j < tagElements.length; j++) {
+                elements.push(tagElements[j]);
+            }
+        }
+        return elements;
+    },
+
+/** @id MochiKit.Form.serializeElement */
+    serializeElement: function (element) {
+        element = MochiKit.DOM.getElement(element);
+        var method = element.tagName.toLowerCase();
+        var parameter = MochiKit.Form.Serializers[method](element);
+
+        if (parameter) {
+            var key = encodeURIComponent(parameter[0]);
+            if (key.length === 0) {
+                return;
+            }
+
+            if (!(parameter[1] instanceof Array)) {
+                parameter[1] = [parameter[1]];
+            }
+
+            return parameter[1].map(function (value) {
+                return key + '=' + encodeURIComponent(value);
+            }).join('&');
+        }
+    }
+};
+
+MochiKit.Form.Serializers = {
+
+/** @id MochiKit.Form.Serializers.input */
+    input: function (element) {
+        switch (element.type.toLowerCase()) {
+            case 'submit':
+            case 'hidden':
+            case 'password':
+            case 'text':
+                return MochiKit.Form.Serializers.textarea(element);
+            case 'checkbox':
+            case 'radio':
+                return MochiKit.Form.Serializers.inputSelector(element);
+        }
+        return false;
+    },
+
+/** @id MochiKit.Form.Serializers.inputSelector */
+    inputSelector: function (element) {
+        if (element.checked) {
+            return [element.name, element.value];
+        }
+    },
+
+/** @id MochiKit.Form.Serializers.textarea */
+    textarea: function (element) {
+        return [element.name, element.value];
+    },
+
+/** @id MochiKit.Form.Serializers.select */
+    select: function (element) {
+        return MochiKit.Form.Serializers[element.type == 'select-one' ?
+        'selectOne' : 'selectMany'](element);
+    },
+
+/** @id MochiKit.Form.Serializers.selectOne */
+    selectOne: function (element) {
+        var value = '', opt, index = element.selectedIndex;
+        if (index >= 0) {
+            opt = element.options[index];
+            value = opt.value;
+            if (!value && !('value' in opt)) {
+                value = opt.text;
+            }
+        }
+        return [element.name, value];
+    },
+
+/** @id MochiKit.Form.Serializers.selectMany */
+    selectMany: function (element) {
+        var value = [];
+        for (var i = 0; i < element.length; i++) {
+            var opt = element.options[i];
+            if (opt.selected) {
+                var optValue = opt.value;
+                if (!optValue && !('value' in opt)) {
+                    optValue = opt.text;
+                }
+                value.push(optValue);
+            }
+        }
+        return [element.name, value];
+    }
+};
+
+/** @id Ajax */
+var Ajax = {
+    activeRequestCount: 0
+};
+
+Ajax.Responders = {
+    responders: [],
+
+/** @id Ajax.Responders.register */
+    register: function (responderToAdd) {
+        if (MochiKit.Base.find(this.responders, responderToAdd) == -1) {
+            this.responders.push(responderToAdd);
+        }
+    },
+
+/** @id Ajax.Responders.unregister */
+    unregister: function (responderToRemove) {
+        this.responders = this.responders.without(responderToRemove);
+    },
+
+/** @id Ajax.Responders.dispatch */
+    dispatch: function (callback, request, transport, json) {
+        MochiKit.Iter.forEach(this.responders, function (responder) {
+            if (responder[callback] &&
+                typeof(responder[callback]) == 'function') {
+                try {
+                    responder[callback].apply(responder, [request, transport, json]);
+                } catch (e) {}
+            }
+        });
+    }
+};
+
+Ajax.Responders.register({
+
+/** @id Ajax.Responders.onCreate */
+    onCreate: function () {
+        Ajax.activeRequestCount++;
+    },
+
+/** @id Ajax.Responders.onComplete */
+    onComplete: function () {
+        Ajax.activeRequestCount--;
+    }
+});
+
+/** @id Ajax.Base */
+Ajax.Base = function () {};
+
+Ajax.Base.prototype = {
+
+/** @id Ajax.Base.prototype.setOptions */
+    setOptions: function (options) {
+        this.options = {
+            method: 'post',
+            asynchronous: true,
+            parameters:   ''
+        }
+        MochiKit.Base.update(this.options, options || {});
+    },
+
+/** @id Ajax.Base.prototype.responseIsSuccess */
+    responseIsSuccess: function () {
+        return this.transport.status == undefined
+            || this.transport.status === 0
+            || (this.transport.status >= 200 && this.transport.status < 300);
+    },
+
+/** @id Ajax.Base.prototype.responseIsFailure */
+    responseIsFailure: function () {
+        return !this.responseIsSuccess();
+    }
+};
+
+/** @id Ajax.Request */
+Ajax.Request = function (url, options) {
+    this.__init__(url, options);
+};
+
+/** @id Ajax.Events */
+Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded',
+                       'Interactive', 'Complete'];
+
+MochiKit.Base.update(Ajax.Request.prototype, Ajax.Base.prototype);
+
+MochiKit.Base.update(Ajax.Request.prototype, {
+    __init__: function (url, options) {
+        this.transport = MochiKit.Async.getXMLHttpRequest();
+        this.setOptions(options);
+        this.request(url);
+    },
+
+/** @id Ajax.Request.prototype.request */
+    request: function (url) {
+        var parameters = this.options.parameters || '';
+        if (parameters.length > 0){
+            parameters += '&_=';
+        }
+
+        try {
+            this.url = url;
+            if (this.options.method == 'get' && parameters.length > 0) {
+                this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
+            }
+            Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+            this.transport.open(this.options.method, this.url,
+                                this.options.asynchronous);
+
+            if (this.options.asynchronous) {
+                this.transport.onreadystatechange = MochiKit.Base.bind(this.onStateChange, this);
+                setTimeout(MochiKit.Base.bind(function () {
+                    this.respondToReadyState(1);
+                }, this), 10);
+            }
+
+            this.setRequestHeaders();
+
+            var body = this.options.postBody ? this.options.postBody : parameters;
+            this.transport.send(this.options.method == 'post' ? body : null);
+
+        } catch (e) {
+            this.dispatchException(e);
+        }
+    },
+
+/** @id Ajax.Request.prototype.setRequestHeaders */
+    setRequestHeaders: function () {
+        var requestHeaders = ['X-Requested-With', 'XMLHttpRequest'];
+
+        if (this.options.method == 'post') {
+            requestHeaders.push('Content-type',
+                                'application/x-www-form-urlencoded');
+
+            /* Force 'Connection: close' for Mozilla browsers to work around
+             * a bug where XMLHttpRequest sends an incorrect Content-length
+             * header. See Mozilla Bugzilla #246651.
+             */
+            if (this.transport.overrideMimeType) {
+                requestHeaders.push('Connection', 'close');
+            }
+        }
+
+        if (this.options.requestHeaders) {
+            requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+        }
+
+        for (var i = 0; i < requestHeaders.length; i += 2) {
+            this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
+        }
+    },
+
+/** @id Ajax.Request.prototype.onStateChange */
+    onStateChange: function () {
+        var readyState = this.transport.readyState;
+        if (readyState != 1) {
+            this.respondToReadyState(this.transport.readyState);
+        }
+    },
+
+/** @id Ajax.Request.prototype.header */
+    header: function (name) {
+        try {
+          return this.transport.getResponseHeader(name);
+        } catch (e) {}
+    },
+
+/** @id Ajax.Request.prototype.evalJSON */
+    evalJSON: function () {
+        try {
+          return eval(this.header('X-JSON'));
+        } catch (e) {}
+    },
+
+/** @id Ajax.Request.prototype.evalResponse */
+    evalResponse: function () {
+        try {
+          return eval(this.transport.responseText);
+        } catch (e) {
+          this.dispatchException(e);
+        }
+    },
+
+/** @id Ajax.Request.prototype.respondToReadyState */
+    respondToReadyState: function (readyState) {
+        var event = Ajax.Request.Events[readyState];
+        var transport = this.transport, json = this.evalJSON();
+
+        if (event == 'Complete') {
+            try {
+                (this.options['on' + this.transport.status]
+                || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+                || MochiKit.Base.noop)(transport, json);
+            } catch (e) {
+                this.dispatchException(e);
+            }
+
+            if ((this.header('Content-type') || '').match(/^text\/javascript/i)) {
+                this.evalResponse();
+            }
+        }
+
+        try {
+            (this.options['on' + event] || MochiKit.Base.noop)(transport, json);
+            Ajax.Responders.dispatch('on' + event, this, transport, json);
+        } catch (e) {
+            this.dispatchException(e);
+        }
+
+        /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+        if (event == 'Complete') {
+            this.transport.onreadystatechange = MochiKit.Base.noop;
+        }
+    },
+
+/** @id Ajax.Request.prototype.dispatchException */
+    dispatchException: function (exception) {
+        (this.options.onException || MochiKit.Base.noop)(this, exception);
+        Ajax.Responders.dispatch('onException', this, exception);
+    }
+});
+
+/** @id Ajax.Updater */
+Ajax.Updater = function (container, url, options) {
+    this.__init__(container, url, options);
+};
+
+MochiKit.Base.update(Ajax.Updater.prototype, Ajax.Request.prototype);
+
+MochiKit.Base.update(Ajax.Updater.prototype, {
+    __init__: function (container, url, options) {
+        this.containers = {
+            success: container.success ? MochiKit.DOM.getElement(container.success) : MochiKit.DOM.getElement(container),
+            failure: container.failure ? MochiKit.DOM.getElement(container.failure) :
+                (container.success ? null : MochiKit.DOM.getElement(container))
+        }
+        this.transport = MochiKit.Async.getXMLHttpRequest();
+        this.setOptions(options);
+
+        var onComplete = this.options.onComplete || MochiKit.Base.noop;
+        this.options.onComplete = MochiKit.Base.bind(function (transport, object) {
+            this.updateContent();
+            onComplete(transport, object);
+        }, this);
+
+        this.request(url);
+    },
+
+/** @id Ajax.Updater.prototype.updateContent */
+    updateContent: function () {
+        var receiver = this.responseIsSuccess() ?
+            this.containers.success : this.containers.failure;
+        var response = this.transport.responseText;
+
+        if (!this.options.evalScripts) {
+            response = MochiKit.Base.stripScripts(response);
+        }
+
+        if (receiver) {
+            if (this.options.insertion) {
+                new this.options.insertion(receiver, response);
+            } else {
+                MochiKit.DOM.getElement(receiver).innerHTML =
+                    MochiKit.Base.stripScripts(response);
+                setTimeout(function () {
+                    MochiKit.Base.evalScripts(response);
+                }, 10);
+            }
+        }
+
+        if (this.responseIsSuccess()) {
+            if (this.onComplete) {
+                setTimeout(MochiKit.Base.bind(this.onComplete, this), 10);
+            }
+        }
+    }
+});
+
+/** @id Field */
+var Field = {
+
+/** @id clear */
+    clear: function () {
+        for (var i = 0; i < arguments.length; i++) {
+            MochiKit.DOM.getElement(arguments[i]).value = '';
+        }
+    },
+
+/** @id focus */
+    focus: function (element) {
+        MochiKit.DOM.getElement(element).focus();
+    },
+
+/** @id present */
+    present: function () {
+        for (var i = 0; i < arguments.length; i++) {
+            if (MochiKit.DOM.getElement(arguments[i]).value == '') {
+                return false;
+            }
+        }
+        return true;
+    },
+
+/** @id select */
+    select: function (element) {
+        MochiKit.DOM.getElement(element).select();
+    },
+
+/** @id activate */
+    activate: function (element) {
+        element = MochiKit.DOM.getElement(element);
+        element.focus();
+        if (element.select) {
+            element.select();
+        }
+    },
+
+/** @id scrollFreeActivate */
+    scrollFreeActivate: function (field) {
+        setTimeout(function () {
+            Field.activate(field);
+        }, 1);
+    }
+};
+
+
+/** @id Autocompleter */
+var Autocompleter = {};
+
+/** @id Autocompleter.Base */
+Autocompleter.Base = function () {};
+
+Autocompleter.Base.prototype = {
+
+/** @id Autocompleter.Base.prototype.baseInitialize */
+    baseInitialize: function (element, update, options) {
+        this.element = MochiKit.DOM.getElement(element);
+        this.update = MochiKit.DOM.getElement(update);
+        this.hasFocus = false;
+        this.changed = false;
+        this.active = false;
+        this.index = 0;
+        this.entryCount = 0;
+
+        if (this.setOptions) {
+            this.setOptions(options);
+        }
+        else {
+            this.options = options || {};
+        }
+
+        this.options.paramName = this.options.paramName || this.element.name;
+        this.options.tokens = this.options.tokens || [];
+        this.options.frequency = this.options.frequency || 0.4;
+        this.options.minChars = this.options.minChars || 1;
+        this.options.onShow = this.options.onShow || function (element, update) {
+                if (!update.style.position || update.style.position == 'absolute') {
+                    update.style.position = 'absolute';
+                    MochiKit.Position.clone(element, update, {
+                        setHeight: false,
+                        offsetTop: element.offsetHeight
+                    });
+                }
+                MochiKit.Visual.appear(update, {duration:0.15});
+            };
+        this.options.onHide = this.options.onHide || function (element, update) {
+                MochiKit.Visual.fade(update, {duration: 0.15});
+            };
+
+        if (typeof(this.options.tokens) == 'string') {
+            this.options.tokens = new Array(this.options.tokens);
+        }
+
+        this.observer = null;
+
+        this.element.setAttribute('autocomplete', 'off');
+
+        MochiKit.Style.hideElement(this.update);
+
+        MochiKit.Signal.connect(this.element, 'onblur', this, this.onBlur);
+        MochiKit.Signal.connect(this.element, 'onkeypress', this, this.onKeyPress, this);
+    },
+
+/** @id Autocompleter.Base.prototype.show */
+    show: function () {
+        if (MochiKit.Style.getStyle(this.update, 'display') == 'none') {
+            this.options.onShow(this.element, this.update);
+        }
+        if (!this.iefix && /MSIE/.test(navigator.userAgent &&
+            (MochiKit.Style.getStyle(this.update, 'position') == 'absolute'))) {
+            new Insertion.After(this.update,
+             '<iframe id="' + this.update.id + '_iefix" '+
+             'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+             'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+            this.iefix = MochiKit.DOM.getElement(this.update.id + '_iefix');
+        }
+        if (this.iefix) {
+            setTimeout(MochiKit.Base.bind(this.fixIEOverlapping, this), 50);
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.fixIEOverlapping */
+    fixIEOverlapping: function () {
+        MochiKit.Position.clone(this.update, this.iefix);
+        this.iefix.style.zIndex = 1;
+        this.update.style.zIndex = 2;
+        MochiKit.Style.showElement(this.iefix);
+    },
+
+/** @id Autocompleter.Base.prototype.hide */
+    hide: function () {
+        this.stopIndicator();
+        if (MochiKit.Style.getStyle(this.update, 'display') != 'none') {
+            this.options.onHide(this.element, this.update);
+        }
+        if (this.iefix) {
+            MochiKit.Style.hideElement(this.iefix);
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.startIndicator */
+    startIndicator: function () {
+        if (this.options.indicator) {
+            MochiKit.Style.showElement(this.options.indicator);
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.stopIndicator */
+    stopIndicator: function () {
+        if (this.options.indicator) {
+            MochiKit.Style.hideElement(this.options.indicator);
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.onKeyPress */
+    onKeyPress: function (event) {
+        if (this.active) {
+            if (event.key().string == "KEY_TAB" || event.key().string == "KEY_RETURN") {
+                 this.selectEntry();
+                 MochiKit.Event.stop(event);
+            } else if (event.key().string == "KEY_ESCAPE") {
+                 this.hide();
+                 this.active = false;
+                 MochiKit.Event.stop(event);
+                 return;
+            } else if (event.key().string == "KEY_LEFT" || event.key().string == "KEY_RIGHT") {
+                 return;
+            } else if (event.key().string == "KEY_UP") {
+                 this.markPrevious();
+                 this.render();
+                 if (/AppleWebKit'/.test(navigator.appVersion)) {
+                     event.stop();
+                 }
+                 return;
+            } else if (event.key().string == "KEY_DOWN") {
+                 this.markNext();
+                 this.render();
+                 if (/AppleWebKit'/.test(navigator.appVersion)) {
+                     event.stop();
+                 }
+                 return;
+            }
+        } else {
+            if (event.key().string == "KEY_TAB" || event.key().string == "KEY_RETURN") {
+                return;
+            }
+        }
+
+        this.changed = true;
+        this.hasFocus = true;
+
+        if (this.observer) {
+            clearTimeout(this.observer);
+        }
+        this.observer = setTimeout(MochiKit.Base.bind(this.onObserverEvent, this),
+                                   this.options.frequency*1000);
+    },
+
+/** @id Autocompleter.Base.prototype.findElement */
+    findElement: function (event, tagName) {
+        var element = event.target;
+        while (element.parentNode && (!element.tagName ||
+              (element.tagName.toUpperCase() != tagName.toUpperCase()))) {
+            element = element.parentNode;
+        }
+        return element;
+    },
+
+/** @id Autocompleter.Base.prototype.hover */
+    onHover: function (event) {
+        var element = this.findElement(event, 'LI');
+        if (this.index != element.autocompleteIndex) {
+            this.index = element.autocompleteIndex;
+            this.render();
+        }
+        event.stop();
+    },
+
+/** @id Autocompleter.Base.prototype.onClick */
+    onClick: function (event) {
+        var element = this.findElement(event, 'LI');
+        this.index = element.autocompleteIndex;
+        this.selectEntry();
+        this.hide();
+    },
+
+/** @id Autocompleter.Base.prototype.onBlur */
+    onBlur: function (event) {
+        // needed to make click events working
+        setTimeout(MochiKit.Base.bind(this.hide, this), 250);
+        this.hasFocus = false;
+        this.active = false;
+    },
+
+/** @id Autocompleter.Base.prototype.render */
+    render: function () {
+        if (this.entryCount > 0) {
+            for (var i = 0; i < this.entryCount; i++) {
+                this.index == i ?
+                    MochiKit.DOM.addElementClass(this.getEntry(i), 'selected') :
+                    MochiKit.DOM.removeElementClass(this.getEntry(i), 'selected');
+            }
+            if (this.hasFocus) {
+                this.show();
+                this.active = true;
+            }
+        } else {
+            this.active = false;
+            this.hide();
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.markPrevious */
+    markPrevious: function () {
+        if (this.index > 0) {
+            this.index--
+        } else {
+            this.index = this.entryCount-1;
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.markNext */
+    markNext: function () {
+        if (this.index < this.entryCount-1) {
+            this.index++
+        } else {
+            this.index = 0;
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.getEntry */
+    getEntry: function (index) {
+        return this.update.firstChild.childNodes[index];
+    },
+
+/** @id Autocompleter.Base.prototype.getCurrentEntry */
+    getCurrentEntry: function () {
+        return this.getEntry(this.index);
+    },
+
+/** @id Autocompleter.Base.prototype.selectEntry */
+    selectEntry: function () {
+        this.active = false;
+        this.updateElement(this.getCurrentEntry());
+    },
+
+/** @id Autocompleter.Base.prototype.collectTextNodesIgnoreClass */
+    collectTextNodesIgnoreClass: function (element, className) {
+        return MochiKit.Base.flattenArray(MochiKit.Base.map(function (node) {
+            if (node.nodeType == 3) {
+                return node.nodeValue;
+            } else if (node.hasChildNodes() && !MochiKit.DOM.hasElementClass(node, className)) {
+                return this.collectTextNodesIgnoreClass(node, className);
+            }
+            return '';
+        }, MochiKit.DOM.getElement(element).childNodes)).join('');
+    },
+
+/** @id Autocompleter.Base.prototype.updateElement */
+    updateElement: function (selectedElement) {
+        if (this.options.updateElement) {
+            this.options.updateElement(selectedElement);
+            return;
+        }
+        var value = '';
+        if (this.options.select) {
+            var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
+            if (nodes.length > 0) {
+                value = MochiKit.DOM.scrapeText(nodes[0]);
+            }
+        } else {
+            value = this.collectTextNodesIgnoreClass(selectedElement, 'informal');
+        }
+        var lastTokenPos = this.findLastToken();
+        if (lastTokenPos != -1) {
+            var newValue = this.element.value.substr(0, lastTokenPos + 1);
+            var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
+            if (whitespace) {
+                newValue += whitespace[0];
+            }
+            this.element.value = newValue + value;
+        } else {
+            this.element.value = value;
+        }
+        this.element.focus();
+
+        if (this.options.afterUpdateElement) {
+            this.options.afterUpdateElement(this.element, selectedElement);
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.updateChoices */
+    updateChoices: function (choices) {
+        if (!this.changed && this.hasFocus) {
+            this.update.innerHTML = choices;
+            var d = MochiKit.DOM;
+            d.removeEmptyTextNodes(this.update);
+            d.removeEmptyTextNodes(this.update.firstChild);
+
+            if (this.update.firstChild && this.update.firstChild.childNodes) {
+                this.entryCount = this.update.firstChild.childNodes.length;
+                for (var i = 0; i < this.entryCount; i++) {
+                    var entry = this.getEntry(i);
+                    entry.autocompleteIndex = i;
+                    this.addObservers(entry);
+                }
+            } else {
+                this.entryCount = 0;
+            }
+
+            this.stopIndicator();
+
+            this.index = 0;
+            this.render();
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.addObservers */
+    addObservers: function (element) {
+        MochiKit.Signal.connect(element, 'onmouseover', this, this.onHover);
+        MochiKit.Signal.connect(element, 'onclick', this, this.onClick);
+    },
+
+/** @id Autocompleter.Base.prototype.onObserverEvent */
+    onObserverEvent: function () {
+        this.changed = false;
+        if (this.getToken().length >= this.options.minChars) {
+            this.startIndicator();
+            this.getUpdatedChoices();
+        } else {
+            this.active = false;
+            this.hide();
+        }
+    },
+
+/** @id Autocompleter.Base.prototype.getToken */
+    getToken: function () {
+        var tokenPos = this.findLastToken();
+        if (tokenPos != -1) {
+            var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
+        } else {
+            var ret = this.element.value;
+        }
+        return /\n/.test(ret) ? '' : ret;
+    },
+
+/** @id Autocompleter.Base.prototype.findLastToken */
+    findLastToken: function () {
+        var lastTokenPos = -1;
+
+        for (var i = 0; i < this.options.tokens.length; i++) {
+            var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
+            if (thisTokenPos > lastTokenPos) {
+                lastTokenPos = thisTokenPos;
+            }
+        }
+        return lastTokenPos;
+    }
+}
+
+/** @id Ajax.Autocompleter */
+Ajax.Autocompleter = function (element, update, url, options) {
+    this.__init__(element, update, url, options);
+};
+
+MochiKit.Base.update(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype);
+
+MochiKit.Base.update(Ajax.Autocompleter.prototype, {
+    __init__: function (element, update, url, options) {
+        this.baseInitialize(element, update, options);
+        this.options.asynchronous = true;
+        this.options.onComplete = MochiKit.Base.bind(this.onComplete, this);
+        this.options.defaultParams = this.options.parameters || null;
+        this.url = url;
+    },
+
+/** @id Ajax.Autocompleter.prototype.getUpdatedChoices */
+    getUpdatedChoices: function () {
+        var entry = encodeURIComponent(this.options.paramName) + '=' +
+            encodeURIComponent(this.getToken());
+
+        this.options.parameters = this.options.callback ?
+            this.options.callback(this.element, entry) : entry;
+
+        if (this.options.defaultParams) {
+            this.options.parameters += '&' + this.options.defaultParams;
+        }
+        new Ajax.Request(this.url, this.options);
+    },
+
+/** @id Ajax.Autocompleter.prototype.onComplete */
+    onComplete: function (request) {
+        this.updateChoices(request.responseText);
+    }
+});
+
+/***
+
+The local array autocompleter. Used when you'd prefer to
+inject an array of autocompletion options into the page, rather
+than sending out Ajax queries, which can be quite slow sometimes.
+
+The constructor takes four parameters. The first two are, as usual,
+the id of the monitored textbox, and id of the autocompletion menu.
+The third is the array you want to autocomplete from, and the fourth
+is the options block.
+
+Extra local autocompletion options:
+- choices - How many autocompletion choices to offer
+
+- partialSearch - If false, the autocompleter will match entered
+                                       text only at the beginning of strings in the
+                                       autocomplete array. Defaults to true, which will
+                                       match text at the beginning of any *word* in the
+                                       strings in the autocomplete array. If you want to
+                                       search anywhere in the string, additionally set
+                                       the option fullSearch to true (default: off).
+
+- fullSsearch - Search anywhere in autocomplete array strings.
+
+- partialChars - How many characters to enter before triggering
+                                    a partial match (unlike minChars, which defines
+                                    how many characters are required to do any match
+                                    at all). Defaults to 2.
+
+- ignoreCase - Whether to ignore case when autocompleting.
+                                Defaults to true.
+
+It's possible to pass in a custom function as the 'selector'
+option, if you prefer to write your own autocompletion logic.
+In that case, the other options above will not apply unless
+you support them.
+
+***/
+
+/** @id Autocompleter.Local */
+Autocompleter.Local = function (element, update, array, options) {
+    this.__init__(element, update, array, options);
+};
+
+MochiKit.Base.update(Autocompleter.Local.prototype, Autocompleter.Base.prototype);
+
+MochiKit.Base.update(Autocompleter.Local.prototype, {
+    __init__: function (element, update, array, options) {
+        this.baseInitialize(element, update, options);
+        this.options.array = array;
+    },
+
+/** @id Autocompleter.Local.prototype.getUpdatedChoices */
+    getUpdatedChoices: function () {
+        this.updateChoices(this.options.selector(this));
+    },
+
+/** @id Autocompleter.Local.prototype.setOptions */
+    setOptions: function (options) {
+        this.options = MochiKit.Base.update({
+            choices: 10,
+            partialSearch: true,
+            partialChars: 2,
+            ignoreCase: true,
+            fullSearch: false,
+            selector: function (instance) {
+                var ret = [];  // Beginning matches
+                var partial = [];  // Inside matches
+                var entry = instance.getToken();
+                var count = 0;
+
+                for (var i = 0; i < instance.options.array.length &&
+                    ret.length < instance.options.choices ; i++) {
+
+                    var elem = instance.options.array[i];
+                    var foundPos = instance.options.ignoreCase ?
+                        elem.toLowerCase().indexOf(entry.toLowerCase()) :
+                        elem.indexOf(entry);
+
+                    while (foundPos != -1) {
+                        if (foundPos === 0 && elem.length != entry.length) {
+                            ret.push('<li><strong>' + elem.substr(0, entry.length) + '</strong>' +
+                                elem.substr(entry.length) + '</li>');
+                            break;
+                        } else if (entry.length >= instance.options.partialChars &&
+                            instance.options.partialSearch && foundPos != -1) {
+                            if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos - 1, 1))) {
+                                partial.push('<li>' + elem.substr(0, foundPos) + '<strong>' +
+                                    elem.substr(foundPos, entry.length) + '</strong>' + elem.substr(
+                                    foundPos + entry.length) + '</li>');
+                                break;
+                            }
+                        }
+
+                        foundPos = instance.options.ignoreCase ?
+                            elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+                            elem.indexOf(entry, foundPos + 1);
+
+                    }
+                }
+                if (partial.length) {
+                    ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+                }
+                return '<ul>' + ret.join('') + '</ul>';
+            }
+        }, options || {});
+    }
+});
+
+/***
+
+AJAX in-place editor
+
+see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
+
+Use this if you notice weird scrolling problems on some browsers,
+the DOM might be a bit confused when this gets called so do this
+waits 1 ms (with setTimeout) until it does the activation
+
+***/
+
+/** @id Ajax.InPlaceEditor */
+Ajax.InPlaceEditor = function (element, url, options) {
+    this.__init__(element, url, options);
+};
+
+/** @id Ajax.InPlaceEditor.defaultHighlightColor */
+Ajax.InPlaceEditor.defaultHighlightColor = '#FFFF99';
+
+Ajax.InPlaceEditor.prototype = {
+    __init__: function (element, url, options) {
+        this.url = url;
+        this.element = MochiKit.DOM.getElement(element);
+
+        this.options = MochiKit.Base.update({
+            okButton: true,
+            okText: 'ok',
+            cancelLink: true,
+            cancelText: 'cancel',
+            savingText: 'Saving...',
+            clickToEditText: 'Click to edit',
+            okText: 'ok',
+            rows: 1,
+            onComplete: function (transport, element) {
+                new MochiKit.Visual.Highlight(element, {startcolor: this.options.highlightcolor});
+            },
+            onFailure: function (transport) {
+                alert('Error communicating with the server: ' + MochiKit.Base.stripTags(transport.responseText));
+            },
+            callback: function (form) {
+                return MochiKit.DOM.formContents(form);
+            },
+            handleLineBreaks: true,
+            loadingText: 'Loading...',
+            savingClassName: 'inplaceeditor-saving',
+            loadingClassName: 'inplaceeditor-loading',
+            formClassName: 'inplaceeditor-form',
+            highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
+            highlightendcolor: '#FFFFFF',
+            externalControl: null,
+            submitOnBlur: false,
+            ajaxOptions: {}
+        }, options || {});
+
+        if (!this.options.formId && this.element.id) {
+            this.options.formId = this.element.id + '-inplaceeditor';
+            if (MochiKit.DOM.getElement(this.options.formId)) {
+                // there's already a form with that name, don't specify an id
+                this.options.formId = null;
+            }
+        }
+
+        if (this.options.externalControl) {
+            this.options.externalControl = MochiKit.DOM.getElement(this.options.externalControl);
+        }
+
+        this.originalBackground = MochiKit.Style.getStyle(this.element, 'background-color');
+        if (!this.originalBackground) {
+            this.originalBackground = 'transparent';
+        }
+
+        this.element.title = this.options.clickToEditText;
+
+        this.onclickListener = MochiKit.Signal.connect(this.element, 'onclick', this, this.enterEditMode);
+        this.mouseoverListener = MochiKit.Signal.connect(this.element, 'onmouseover', this, this.enterHover);
+        this.mouseoutListener = MochiKit.Signal.connect(this.element, 'onmouseout', this, this.leaveHover);
+        if (this.options.externalControl) {
+            this.onclickListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
+                'onclick', this, this.enterEditMode);
+            this.mouseoverListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
+                'onmouseover', this, this.enterHover);
+            this.mouseoutListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
+                'onmouseout', this, this.leaveHover);
+        }
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.enterEditMode */
+    enterEditMode: function (evt) {
+        if (this.saving) {
+            return;
+        }
+        if (this.editing) {
+            return;
+        }
+        this.editing = true;
+        this.onEnterEditMode();
+        if (this.options.externalControl) {
+            MochiKit.Style.hideElement(this.options.externalControl);
+        }
+        MochiKit.Style.hideElement(this.element);
+        this.createForm();
+        this.element.parentNode.insertBefore(this.form, this.element);
+        Field.scrollFreeActivate(this.editField);
+        // stop the event to avoid a page refresh in Safari
+        if (evt) {
+            evt.stop();
+        }
+        return false;
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.createForm */
+    createForm: function () {
+        this.form = document.createElement('form');
+        this.form.id = this.options.formId;
+        MochiKit.DOM.addElementClass(this.form, this.options.formClassName)
+        this.form.onsubmit = MochiKit.Base.bind(this.onSubmit, this);
+
+        this.createEditField();
+
+        if (this.options.textarea) {
+            var br = document.createElement('br');
+            this.form.appendChild(br);
+        }
+
+        if (this.options.okButton) {
+            okButton = document.createElement('input');
+            okButton.type = 'submit';
+            okButton.value = this.options.okText;
+            this.form.appendChild(okButton);
+        }
+
+        if (this.options.cancelLink) {
+            cancelLink = document.createElement('a');
+            cancelLink.href = '#';
+            cancelLink.appendChild(document.createTextNode(this.options.cancelText));
+            cancelLink.onclick = MochiKit.Base.bind(this.onclickCancel, this);
+            this.form.appendChild(cancelLink);
+        }
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.hasHTMLLineBreaks */
+    hasHTMLLineBreaks: function (string) {
+        if (!this.options.handleLineBreaks) {
+            return false;
+        }
+        return string.match(/<br/i) || string.match(/<p>/i);
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.convertHTMLLineBreaks */
+    convertHTMLLineBreaks: function (string) {
+        return string.replace(/<br>/gi, '\n').replace(/<br\/>/gi, '\n').replace(/<\/p>/gi, '\n').replace(/<p>/gi, '');
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.createEditField */
+    createEditField: function () {
+        var text;
+        if (this.options.loadTextURL) {
+            text = this.options.loadingText;
+        } else {
+            text = this.getText();
+        }
+
+        var obj = this;
+
+        if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
+            this.options.textarea = false;
+            var textField = document.createElement('input');
+            textField.obj = this;
+            textField.type = 'text';
+            textField.name = 'value';
+            textField.value = text;
+            textField.style.backgroundColor = this.options.highlightcolor;
+            var size = this.options.size || this.options.cols || 0;
+            if (size !== 0) {
+                textField.size = size;
+            }
+            if (this.options.submitOnBlur) {
+                textField.onblur = MochiKit.Base.bind(this.onSubmit, this);
+            }
+            this.editField = textField;
+        } else {
+            this.options.textarea = true;
+            var textArea = document.createElement('textarea');
+            textArea.obj = this;
+            textArea.name = 'value';
+            textArea.value = this.convertHTMLLineBreaks(text);
+            textArea.rows = this.options.rows;
+            textArea.cols = this.options.cols || 40;
+            if (this.options.submitOnBlur) {
+                textArea.onblur = MochiKit.Base.bind(this.onSubmit, this);
+            }
+            this.editField = textArea;
+        }
+
+        if (this.options.loadTextURL) {
+            this.loadExternalText();
+        }
+        this.form.appendChild(this.editField);
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.getText */
+    getText: function () {
+        return this.element.innerHTML;
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.loadExternalText */
+    loadExternalText: function () {
+        MochiKit.DOM.addElementClass(this.form, this.options.loadingClassName);
+        this.editField.disabled = true;
+        new Ajax.Request(
+            this.options.loadTextURL,
+            MochiKit.Base.update({
+                asynchronous: true,
+                onComplete: MochiKit.Base.bind(this.onLoadedExternalText, this)
+            }, this.options.ajaxOptions)
+        );
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onLoadedExternalText */
+    onLoadedExternalText: function (transport) {
+        MochiKit.DOM.removeElementClass(this.form, this.options.loadingClassName);
+        this.editField.disabled = false;
+        this.editField.value = MochiKit.Base.stripTags(transport);
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onclickCancel */
+    onclickCancel: function () {
+        this.onComplete();
+        this.leaveEditMode();
+        return false;
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onFailure */
+    onFailure: function (transport) {
+        this.options.onFailure(transport);
+        if (this.oldInnerHTML) {
+            this.element.innerHTML = this.oldInnerHTML;
+            this.oldInnerHTML = null;
+        }
+        return false;
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onSubmit */
+    onSubmit: function () {
+        // onLoading resets these so we need to save them away for the Ajax call
+        var form = this.form;
+        var value = this.editField.value;
+
+        // do this first, sometimes the ajax call returns before we get a
+        // chance to switch on Saving which means this will actually switch on
+        // Saving *after* we have left edit mode causing Saving to be
+        // displayed indefinitely
+        this.onLoading();
+
+        new Ajax.Updater(
+            {
+                success: this.element,
+                 // dont update on failure (this could be an option)
+                failure: null
+            },
+            this.url,
+            MochiKit.Base.update({
+                parameters: this.options.callback(form, value),
+                onComplete: MochiKit.Base.bind(this.onComplete, this),
+                onFailure: MochiKit.Base.bind(this.onFailure, this)
+            }, this.options.ajaxOptions)
+        );
+        // stop the event to avoid a page refresh in Safari
+        if (arguments.length > 1) {
+            arguments[0].stop();
+        }
+        return false;
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onLoading */
+    onLoading: function () {
+        this.saving = true;
+        this.removeForm();
+        this.leaveHover();
+        this.showSaving();
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onSaving */
+    showSaving: function () {
+        this.oldInnerHTML = this.element.innerHTML;
+        this.element.innerHTML = this.options.savingText;
+        MochiKit.DOM.addElementClass(this.element, this.options.savingClassName);
+        this.element.style.backgroundColor = this.originalBackground;
+        MochiKit.Style.showElement(this.element);
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.removeForm */
+    removeForm: function () {
+        if (this.form) {
+            if (this.form.parentNode) {
+                MochiKit.DOM.removeElement(this.form);
+            }
+            this.form = null;
+        }
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.enterHover */
+    enterHover: function () {
+        if (this.saving) {
+            return;
+        }
+        this.element.style.backgroundColor = this.options.highlightcolor;
+        if (this.effect) {
+            this.effect.cancel();
+        }
+        MochiKit.DOM.addElementClass(this.element, this.options.hoverClassName)
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.leaveHover */
+    leaveHover: function () {
+        if (this.options.backgroundColor) {
+            this.element.style.backgroundColor = this.oldBackground;
+        }
+        MochiKit.DOM.removeElementClass(this.element, this.options.hoverClassName)
+        if (this.saving) {
+            return;
+        }
+        this.effect = new MochiKit.Visual.Highlight(this.element, {
+            startcolor: this.options.highlightcolor,
+            endcolor: this.options.highlightendcolor,
+            restorecolor: this.originalBackground
+        });
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.leaveEditMode */
+    leaveEditMode: function () {
+        MochiKit.DOM.removeElementClass(this.element, this.options.savingClassName);
+        this.removeForm();
+        this.leaveHover();
+        this.element.style.backgroundColor = this.originalBackground;
+        MochiKit.Style.showElement(this.element);
+        if (this.options.externalControl) {
+            MochiKit.Style.showElement(this.options.externalControl);
+        }
+        this.editing = false;
+        this.saving = false;
+        this.oldInnerHTML = null;
+        this.onLeaveEditMode();
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onComplete */
+    onComplete: function (transport) {
+        this.leaveEditMode();
+        MochiKit.Base.bind(this.options.onComplete, this)(transport, this.element);
+    },
+
+/** @id Ajax.InPlaceEditor.prototype.onEnterEditMode */
+    onEnterEditMode: function () {},
+
+/** @id Ajax.InPlaceEditor.prototype.onLeaveEditMode */
+    onLeaveEditMode: function () {},
+
+ /** @id Ajax.InPlaceEditor.prototype.dispose */
+    dispose: function () {
+        if (this.oldInnerHTML) {
+            this.element.innerHTML = this.oldInnerHTML;
+        }
+        this.leaveEditMode();
+        MochiKit.Signal.disconnect(this.onclickListener);
+        MochiKit.Signal.disconnect(this.mouseoverListener);
+        MochiKit.Signal.disconnect(this.mouseoutListener);
+        if (this.options.externalControl) {
+            MochiKit.Signal.disconnect(this.onclickListenerExternal);
+            MochiKit.Signal.disconnect(this.mouseoverListenerExternal);
+            MochiKit.Signal.disconnect(this.mouseoutListenerExternal);
+        }
+    }
+};
+
diff --git a/mochikit_v14/MochiKit/DOM.js b/mochikit_v14/MochiKit/DOM.js
new file mode 100644 (file)
index 0000000..02fe5bf
--- /dev/null
@@ -0,0 +1,1276 @@
+/***
+
+MochiKit.DOM 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide("MochiKit.DOM");
+    dojo.require("MochiKit.Base");
+}
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use("MochiKit.Base", []);
+}
+
+try {
+    if (typeof(MochiKit.Base) == 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.DOM depends on MochiKit.Base!";
+}
+
+if (typeof(MochiKit.DOM) == 'undefined') {
+    MochiKit.DOM = {};
+}
+
+MochiKit.DOM.NAME = "MochiKit.DOM";
+MochiKit.DOM.VERSION = "1.4";
+MochiKit.DOM.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.DOM.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.DOM.EXPORT = [
+    "removeEmptyTextNodes",
+    "formContents",
+    "currentWindow",
+    "currentDocument",
+    "withWindow",
+    "withDocument",
+    "registerDOMConverter",
+    "coerceToDOM",
+    "createDOM",
+    "createDOMFunc",
+    "isChildNode",
+    "getNodeAttribute",
+    "removeNodeAttribute",
+    "setNodeAttribute",
+    "updateNodeAttributes",
+    "appendChildNodes",
+    "insertSiblingNodesAfter",
+    "insertSiblingNodesBefore",
+    "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",
+    "$",
+    "getElementsByTagAndClassName",
+    "addToCallStack",
+    "addLoadEvent",
+    "focusOnLoad",
+    "setElementClass",
+    "toggleElementClass",
+    "addElementClass",
+    "removeElementClass",
+    "swapElementClass",
+    "hasElementClass",
+    "escapeHTML",
+    "toHTML",
+    "emitHTML",
+    "scrapeText",
+    "isParent",
+    "getFirstParentByTagAndClassName",
+    "makeClipping",
+    "undoClipping",
+    "makePositioned",
+    "undoPositioned",
+    "getFirstElementByTagAndClassName"
+];
+
+MochiKit.DOM.EXPORT_OK = [
+    "domConverters"
+];
+
+MochiKit.DOM.DEPRECATED = [
+    ['computedStyle', 'MochiKit.Style.getStyle', '1.4'],
+    /** @id MochiKit.DOM.elementDimensions  */
+    ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'],
+    /** @id MochiKit.DOM.elementPosition  */
+    ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'],
+    ['hideElement', 'MochiKit.Style.hideElement', '1.4'],
+    /** @id MochiKit.DOM.setElementDimensions */
+    ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'],
+    /** @id MochiKit.DOM.setElementPosition */
+    ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'],
+    ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'],
+    /** @id MochiKit.DOM.setOpacity */
+    ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'],
+    ['showElement', 'MochiKit.Style.showElement', '1.4'],
+    /** @id MochiKit.DOM.Coordinates */
+    ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken
+    /** @id MochiKit.DOM.Dimensions */
+    ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken
+];
+
+/** @id MochiKit.DOM.getViewportDimensions */
+MochiKit.DOM.getViewportDimensions = new Function('' +
+    'if (!MochiKit["Style"]) {' +
+    '    throw new Error("This function has been deprecated and depends on MochiKit.Style.");' +
+    '}' +
+    'return MochiKit.Style.getViewportDimensions.apply(this, arguments);');
+
+MochiKit.Base.update(MochiKit.DOM, {
+
+    /** @id MochiKit.DOM.currentWindow */
+    currentWindow: function () {
+        return MochiKit.DOM._window;
+    },
+
+    /** @id MochiKit.DOM.currentDocument */
+    currentDocument: function () {
+        return MochiKit.DOM._document;
+    },
+
+    /** @id MochiKit.DOM.withWindow */
+    withWindow: function (win, func) {
+        var self = MochiKit.DOM;
+        var oldDoc = self._document;
+        var oldWin = self._window;
+        var rval;
+        try {
+            self._window = win;
+            self._document = win.document;
+            rval = func();
+        } catch (e) {
+            self._window = oldWin;
+            self._document = oldDoc;
+            throw e;
+        }
+        self._window = oldWin;
+        self._document = oldDoc;
+        return rval;
+    },
+
+    /** @id MochiKit.DOM.formContents  */
+    formContents: function (elem/* = document.body */) {
+        var names = [];
+        var values = [];
+        var m = MochiKit.Base;
+        var self = MochiKit.DOM;
+        if (typeof(elem) == "undefined" || elem === null) {
+            elem = self._document.body;
+        } else {
+            elem = self.getElement(elem);
+        }
+        m.nodeWalk(elem, function (elem) {
+            var name = elem.name;
+            if (m.isNotEmpty(name)) {
+                var tagName = elem.tagName.toUpperCase();
+                if (tagName === "INPUT"
+                    && (elem.type == "radio" || elem.type == "checkbox")
+                    && !elem.checked
+                ) {
+                    return null;
+                }
+                if (tagName === "SELECT") {
+                    if (elem.type == "select-one") {
+                        if (elem.selectedIndex >= 0) {
+                            var opt = elem.options[elem.selectedIndex];
+                            var v = opt.value;
+                            if (!v) {
+                                var h = opt.outerHTML;
+                                // internet explorer sure does suck.
+                                if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
+                                    v = opt.text;
+                                }
+                            }
+                            names.push(name);
+                            values.push(v);
+                            return null;
+                        }
+                        // no form elements?
+                        names.push(name);
+                        values.push("");
+                        return null;
+                    } else {
+                        var opts = elem.options;
+                        if (!opts.length) {
+                            names.push(name);
+                            values.push("");
+                            return null;
+                        }
+                        for (var i = 0; i < opts.length; i++) {
+                            var opt = opts[i];
+                            if (!opt.selected) {
+                                continue;
+                            }
+                            var v = opt.value;
+                            if (!v) {
+                                var h = opt.outerHTML;
+                                // internet explorer sure does suck.
+                                if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
+                                    v = opt.text;
+                                }
+                            }
+                            names.push(name);
+                            values.push(v);
+                        }
+                        return null;
+                    }
+                }
+                if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
+                    || tagName === "DIV"
+                ) {
+                    return elem.childNodes;
+                }
+                names.push(name);
+                values.push(elem.value || '');
+                return null;
+            }
+            return elem.childNodes;
+        });
+        return [names, values];
+    },
+
+    /** @id MochiKit.DOM.withDocument */
+    withDocument: function (doc, func) {
+        var self = MochiKit.DOM;
+        var oldDoc = self._document;
+        var rval;
+        try {
+            self._document = doc;
+            rval = func();
+        } catch (e) {
+            self._document = oldDoc;
+            throw e;
+        }
+        self._document = oldDoc;
+        return rval;
+    },
+
+    /** @id MochiKit.DOM.registerDOMConverter */
+    registerDOMConverter: function (name, check, wrap, /* optional */override) {
+        MochiKit.DOM.domConverters.register(name, check, wrap, override);
+    },
+
+    /** @id MochiKit.DOM.coerceToDOM */
+    coerceToDOM: function (node, ctx) {
+        var m = MochiKit.Base;
+        var im = MochiKit.Iter;
+        var self = MochiKit.DOM;
+        if (im) {
+            var iter = im.iter;
+            var repeat = im.repeat;
+            var map = m.map;
+        }
+        var domConverters = self.domConverters;
+        var coerceToDOM = arguments.callee;
+        var NotFound = m.NotFound;
+        while (true) {
+            if (typeof(node) == 'undefined' || node === null) {
+                return null;
+            }
+            // this is a safari childNodes object, avoiding crashes w/ attr
+            // lookup
+            if (typeof(node) == "function" &&
+                    typeof(node.length) == "number" &&
+                    !(node instanceof Function)) {
+                node = im.list(node);
+            }
+            if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
+                return node;
+            }
+            if (typeof(node) == 'number' || typeof(node) == 'boolean') {
+                node = node.toString();
+                // FALL THROUGH
+            }
+            if (typeof(node) == 'string') {
+                return self._document.createTextNode(node);
+            }
+            if (typeof(node.__dom__) == 'function') {
+                node = node.__dom__(ctx);
+                continue;
+            }
+            if (typeof(node.dom) == 'function') {
+                node = node.dom(ctx);
+                continue;
+            }
+            if (typeof(node) == 'function') {
+                node = node.apply(ctx, [ctx]);
+                continue;
+            }
+
+            if (im) {
+                // iterable
+                var iterNodes = null;
+                try {
+                    iterNodes = iter(node);
+                } catch (e) {
+                    // pass
+                }
+                if (iterNodes) {
+                    return map(coerceToDOM, iterNodes, repeat(ctx));
+                }
+            }
+
+            // adapter
+            try {
+                node = domConverters.match(node, ctx);
+                continue;
+            } catch (e) {
+                if (e != NotFound) {
+                    throw e;
+                }
+            }
+
+            // fallback
+            return self._document.createTextNode(node.toString());
+        }
+        // mozilla warnings aren't too bright
+        return undefined;
+    },
+
+    /** @id MochiKit.DOM.isChildNode */
+    isChildNode: function (node, maybeparent) {
+        var self = MochiKit.DOM;
+        if (typeof(node) == "string") {
+            node = self.getElement(node);
+        }
+        if (typeof(maybeparent) == "string") {
+            maybeparent = self.getElement(maybeparent);
+        }
+        if (node === maybeparent) {
+            return true;
+        }
+        while (node && node.tagName.toUpperCase() != "BODY") {
+            node = node.parentNode;
+            if (node === maybeparent) {
+                return true;
+            }
+        }
+        return false;
+    },
+
+    /** @id MochiKit.DOM.setNodeAttribute */
+    setNodeAttribute: function (node, attr, value) {
+        var o = {};
+        o[attr] = value;
+        try {
+            return MochiKit.DOM.updateNodeAttributes(node, o);
+        } catch (e) {
+            // pass
+        }
+        return null;
+    },
+
+    /** @id MochiKit.DOM.getNodeAttribute */
+    getNodeAttribute: function (node, attr) {
+        var self = MochiKit.DOM;
+        var rename = self.attributeArray.renames[attr];
+        node = self.getElement(node);
+        try {
+            if (rename) {
+                return node[rename];
+            }
+            return node.getAttribute(attr);
+        } catch (e) {
+            // pass
+        }
+        return null;
+    },
+
+    /** @id MochiKit.DOM.removeNodeAttribute */
+    removeNodeAttribute: function (node, attr) {
+        var self = MochiKit.DOM;
+        var rename = self.attributeArray.renames[attr];
+        node = self.getElement(node);
+        try {
+            if (rename) {
+                return node[rename];
+            }
+            return node.removeAttribute(attr);
+        } catch (e) {
+            // pass
+        }
+        return null;
+    },
+
+    /** @id MochiKit.DOM.updateNodeAttributes */
+    updateNodeAttributes: function (node, attrs) {
+        var elem = node;
+        var self = MochiKit.DOM;
+        if (typeof(node) == 'string') {
+            elem = self.getElement(node);
+        }
+        if (attrs) {
+            var updatetree = MochiKit.Base.updatetree;
+            if (self.attributeArray.compliant) {
+                // not IE, good.
+                for (var k in attrs) {
+                    var v = attrs[k];
+                    if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
+                        if (k == "style" && MochiKit.Style) {
+                            MochiKit.Style.setStyle(elem, v);
+                        } else {
+                            updatetree(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 {
+                // IE is insane in the membrane
+                var renames = self.attributeArray.renames;
+                for (var k in attrs) {
+                    v = attrs[k];
+                    var renamed = renames[k];
+                    if (k == "style" && typeof(v) == "string") {
+                        elem.style.cssText = v;
+                    } else if (typeof(renamed) == "string") {
+                        elem[renamed] = v;
+                    } else if (typeof(elem[k]) == 'object'
+                            && typeof(v) == 'object') {
+                        if (k == "style" && MochiKit.Style) {
+                            MochiKit.Style.setStyle(elem, v);
+                        } else {
+                            updatetree(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;
+    },
+
+    /** @id MochiKit.DOM.appendChildNodes */
+    appendChildNodes: function (node/*, nodes...*/) {
+        var elem = node;
+        var self = MochiKit.DOM;
+        if (typeof(node) == 'string') {
+            elem = self.getElement(node);
+        }
+        var nodeStack = [
+            self.coerceToDOM(
+                MochiKit.Base.extend(null, arguments, 1),
+                elem
+            )
+        ];
+        var concat = MochiKit.Base.concat;
+        while (nodeStack.length) {
+            var n = nodeStack.shift();
+            if (typeof(n) == 'undefined' || n === null) {
+                // pass
+            } else if (typeof(n.nodeType) == 'number') {
+                elem.appendChild(n);
+            } else {
+                nodeStack = concat(n, nodeStack);
+            }
+        }
+        return elem;
+    },
+
+
+    /** @id MochiKit.DOM.insertSiblingNodesBefore */
+    insertSiblingNodesBefore: function (node/*, nodes...*/) {
+        var elem = node;
+        var self = MochiKit.DOM;
+        if (typeof(node) == 'string') {
+            elem = self.getElement(node);
+        }
+        var nodeStack = [
+            self.coerceToDOM(
+                MochiKit.Base.extend(null, arguments, 1),
+                elem
+            )
+        ];
+        var parentnode = elem.parentNode;
+        var concat = MochiKit.Base.concat;
+        while (nodeStack.length) {
+            var n = nodeStack.shift();
+            if (typeof(n) == 'undefined' || n === null) {
+                // pass
+            } else if (typeof(n.nodeType) == 'number') {
+                parentnode.insertBefore(n, elem);
+            } else {
+                nodeStack = concat(n, nodeStack);
+            }
+        }
+        return parentnode;
+    },
+
+    /** @id MochiKit.DOM.insertSiblingNodesAfter */
+    insertSiblingNodesAfter: function (node/*, nodes...*/) {
+        var elem = node;
+        var self = MochiKit.DOM;
+
+        if (typeof(node) == 'string') {
+            elem = self.getElement(node);
+        }
+        var nodeStack = [
+            self.coerceToDOM(
+                MochiKit.Base.extend(null, arguments, 1),
+                elem
+            )
+        ];
+
+        if (elem.nextSibling) {
+            return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
+        }
+        else {
+            return self.appendChildNodes(elem.parentNode, nodeStack);
+        }
+    },
+
+    /** @id MochiKit.DOM.replaceChildNodes */
+    replaceChildNodes: function (node/*, nodes...*/) {
+        var elem = node;
+        var self = MochiKit.DOM;
+        if (typeof(node) == 'string') {
+            elem = self.getElement(node);
+            arguments[0] = elem;
+        }
+        var child;
+        while ((child = elem.firstChild)) {
+            elem.removeChild(child);
+        }
+        if (arguments.length < 2) {
+            return elem;
+        } else {
+            return self.appendChildNodes.apply(this, arguments);
+        }
+    },
+
+    /** @id MochiKit.DOM.createDOM */
+    createDOM: function (name, attrs/*, nodes... */) {
+        var elem;
+        var self = MochiKit.DOM;
+        var m = MochiKit.Base;
+        if (typeof(attrs) == "string" || typeof(attrs) == "number") {
+            var args = m.extend([name, null], arguments, 1);
+            return arguments.callee.apply(this, args);
+        }
+        if (typeof(name) == 'string') {
+            // Internet Explorer is dumb
+            var xhtml = self._xhtml;
+            if (attrs && !self.attributeArray.compliant) {
+                // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
+                var contents = "";
+                if ('name' in attrs) {
+                    contents += ' name="' + self.escapeHTML(attrs.name) + '"';
+                }
+                if (name == 'input' && 'type' in attrs) {
+                    contents += ' type="' + self.escapeHTML(attrs.type) + '"';
+                }
+                if (contents) {
+                    name = "<" + name + contents + ">";
+                    xhtml = false;
+                }
+            }
+            var d = self._document;
+            if (xhtml && d === document) {
+                elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
+            } else {
+                elem = d.createElement(name);
+            }
+        } else {
+            elem = name;
+        }
+        if (attrs) {
+            self.updateNodeAttributes(elem, attrs);
+        }
+        if (arguments.length <= 2) {
+            return elem;
+        } else {
+            var args = m.extend([elem], arguments, 2);
+            return self.appendChildNodes.apply(this, args);
+        }
+    },
+
+    /** @id MochiKit.DOM.createDOMFunc */
+    createDOMFunc: function (/* tag, attrs, *nodes */) {
+        var m = MochiKit.Base;
+        return m.partial.apply(
+            this,
+            m.extend([MochiKit.DOM.createDOM], arguments)
+        );
+    },
+
+    /** @id MochiKit.DOM.removeElement */
+    removeElement: function (elem) {
+        var e = MochiKit.DOM.getElement(elem);
+        e.parentNode.removeChild(e);
+        return e;
+    },
+
+    /** @id MochiKit.DOM.swapDOM */
+    swapDOM: function (dest, src) {
+        var self = MochiKit.DOM;
+        dest = self.getElement(dest);
+        var parent = dest.parentNode;
+        if (src) {
+            src = self.getElement(src);
+            parent.replaceChild(src, dest);
+        } else {
+            parent.removeChild(dest);
+        }
+        return src;
+    },
+
+    /** @id MochiKit.DOM.getElement */
+    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);
+        }
+    },
+
+    /** @id MochiKit.DOM.getElementsByTagAndClassName */
+    getElementsByTagAndClassName: function (tagName, className,
+            /* optional */parent) {
+        var self = MochiKit.DOM;
+        if (typeof(tagName) == 'undefined' || tagName === null) {
+            tagName = '*';
+        }
+        if (typeof(parent) == 'undefined' || parent === null) {
+            parent = self._document;
+        }
+        parent = self.getElement(parent);
+        var children = (parent.getElementsByTagName(tagName)
+            || self._document.all);
+        if (typeof(className) == 'undefined' || className === null) {
+            return MochiKit.Base.extend(null, children);
+        }
+
+        var elements = [];
+        for (var i = 0; i < children.length; i++) {
+            var child = children[i];
+            var cls = child.className;
+            if (!cls) {
+                continue;
+            }
+            var classNames = cls.split(' ');
+            for (var j = 0; j < classNames.length; j++) {
+                if (classNames[j] == className) {
+                    elements.push(child);
+                    break;
+                }
+            }
+        }
+
+        return elements;
+    },
+
+    _newCallStack: function (path, once) {
+        var rval = function () {
+            var callStack = arguments.callee.callStack;
+            for (var i = 0; i < callStack.length; i++) {
+                if (callStack[i].apply(this, arguments) === false) {
+                    break;
+                }
+            }
+            if (once) {
+                try {
+                    this[path] = null;
+                } catch (e) {
+                    // pass
+                }
+            }
+        };
+        rval.callStack = [];
+        return rval;
+    },
+
+    /** @id MochiKit.DOM.addToCallStack */
+    addToCallStack: function (target, path, func, once) {
+        var self = MochiKit.DOM;
+        var existing = target[path];
+        var regfunc = existing;
+        if (!(typeof(existing) == 'function'
+                && typeof(existing.callStack) == "object"
+                && existing.callStack !== null)) {
+            regfunc = self._newCallStack(path, once);
+            if (typeof(existing) == 'function') {
+                regfunc.callStack.push(existing);
+            }
+            target[path] = regfunc;
+        }
+        regfunc.callStack.push(func);
+    },
+
+    /** @id MochiKit.DOM.addLoadEvent */
+    addLoadEvent: function (func) {
+        var self = MochiKit.DOM;
+        self.addToCallStack(self._window, "onload", func, true);
+
+    },
+
+    /** @id MochiKit.DOM.focusOnLoad */
+    focusOnLoad: function (element) {
+        var self = MochiKit.DOM;
+        self.addLoadEvent(function () {
+            element = self.getElement(element);
+            if (element) {
+                element.focus();
+            }
+        });
+    },
+
+    /** @id MochiKit.DOM.setElementClass */
+    setElementClass: function (element, className) {
+        var self = MochiKit.DOM;
+        var obj = self.getElement(element);
+        if (self.attributeArray.compliant) {
+            obj.setAttribute("class", className);
+        } else {
+            obj.setAttribute("className", className);
+        }
+    },
+
+    /** @id MochiKit.DOM.toggleElementClass */
+    toggleElementClass: function (className/*, element... */) {
+        var self = MochiKit.DOM;
+        for (var i = 1; i < arguments.length; i++) {
+            var obj = self.getElement(arguments[i]);
+            if (!self.addElementClass(obj, className)) {
+                self.removeElementClass(obj, className);
+            }
+        }
+    },
+
+    /** @id MochiKit.DOM.addElementClass */
+    addElementClass: function (element, className) {
+        var self = MochiKit.DOM;
+        var obj = self.getElement(element);
+        var cls = obj.className;
+        // trivial case, no className yet
+        if (cls == undefined || cls.length === 0) {
+            self.setElementClass(obj, className);
+            return true;
+        }
+        // the other trivial case, already set as the only class
+        if (cls == className) {
+            return false;
+        }
+        var classes = cls.split(" ");
+        for (var i = 0; i < classes.length; i++) {
+            // already present
+            if (classes[i] == className) {
+                return false;
+            }
+        }
+        // append class
+        self.setElementClass(obj, cls + " " + className);
+        return true;
+    },
+
+    /** @id MochiKit.DOM.removeElementClass */
+    removeElementClass: function (element, className) {
+        var self = MochiKit.DOM;
+        var obj = self.getElement(element);
+        var cls = obj.className;
+        // trivial case, no className yet
+        if (cls == undefined || cls.length === 0) {
+            return false;
+        }
+        // other trivial case, set only to className
+        if (cls == className) {
+            self.setElementClass(obj, "");
+            return true;
+        }
+        var classes = cls.split(" ");
+        for (var i = 0; i < classes.length; i++) {
+            // already present
+            if (classes[i] == className) {
+                // only check sane case where the class is used once
+                classes.splice(i, 1);
+                self.setElementClass(obj, classes.join(" "));
+                return true;
+            }
+        }
+        // not found
+        return false;
+    },
+
+    /** @id MochiKit.DOM.swapElementClass */
+    swapElementClass: function (element, fromClass, toClass) {
+        var obj = MochiKit.DOM.getElement(element);
+        var res = MochiKit.DOM.removeElementClass(obj, fromClass);
+        if (res) {
+            MochiKit.DOM.addElementClass(obj, toClass);
+        }
+        return res;
+    },
+
+    /** @id MochiKit.DOM.hasElementClass */
+    hasElementClass: function (element, className/*...*/) {
+        var obj = MochiKit.DOM.getElement(element);
+        var cls = obj.className;
+        if (!cls) {
+            return false;
+        }
+        var classes = cls.split(" ");
+        for (var i = 1; i < arguments.length; i++) {
+            var good = false;
+            for (var j = 0; j < classes.length; j++) {
+                if (classes[j] == arguments[i]) {
+                    good = true;
+                    break;
+                }
+            }
+            if (!good) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    /** @id MochiKit.DOM.escapeHTML */
+    escapeHTML: function (s) {
+        return s.replace(/&/g, "&amp;"
+            ).replace(/"/g, "&quot;"
+            ).replace(/</g, "&lt;"
+            ).replace(/>/g, "&gt;");
+    },
+
+    /** @id MochiKit.DOM.toHTML */
+    toHTML: function (dom) {
+        return MochiKit.DOM.emitHTML(dom).join("");
+    },
+
+    /** @id MochiKit.DOM.emitHTML */
+    emitHTML: function (dom, /* optional */lst) {
+        if (typeof(lst) == 'undefined' || lst === null) {
+            lst = [];
+        }
+        // queue is the call stack, we're doing this non-recursively
+        var queue = [dom];
+        var self = MochiKit.DOM;
+        var escapeHTML = self.escapeHTML;
+        var attributeArray = self.attributeArray;
+        while (queue.length) {
+            dom = queue.pop();
+            if (typeof(dom) == 'string') {
+                lst.push(dom);
+            } else if (dom.nodeType == 1) {
+                // we're not using higher order stuff here
+                // because safari has heisenbugs.. argh.
+                //
+                // I think it might have something to do with
+                // garbage collection and function calls.
+                lst.push('<' + dom.tagName.toLowerCase());
+                var attributes = [];
+                var domAttr = attributeArray(dom);
+                for (var i = 0; i < domAttr.length; i++) {
+                    var a = domAttr[i];
+                    attributes.push([
+                        " ",
+                        a.name,
+                        '="',
+                        escapeHTML(a.value),
+                        '"'
+                    ]);
+                }
+                attributes.sort();
+                for (i = 0; i < attributes.length; i++) {
+                    var attrs = attributes[i];
+                    for (var j = 0; j < attrs.length; j++) {
+                        lst.push(attrs[j]);
+                    }
+                }
+                if (dom.hasChildNodes()) {
+                    lst.push(">");
+                    // queue is the FILO call stack, so we put the close tag
+                    // on first
+                    queue.push("</" + dom.tagName.toLowerCase() + ">");
+                    var cnodes = dom.childNodes;
+                    for (i = cnodes.length - 1; i >= 0; i--) {
+                        queue.push(cnodes[i]);
+                    }
+                } else {
+                    lst.push('/>');
+                }
+            } else if (dom.nodeType == 3) {
+                lst.push(escapeHTML(dom.nodeValue));
+            }
+        }
+        return lst;
+    },
+
+    /** @id MochiKit.DOM.scrapeText */
+    scrapeText: function (node, /* optional */asArray) {
+        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 nodeValue = node.nodeValue;
+            if (typeof(nodeValue) == 'string') {
+                rval.push(nodeValue);
+            }
+        })(MochiKit.DOM.getElement(node));
+        if (asArray) {
+            return rval;
+        } else {
+            return rval.join("");
+        }
+    },
+
+    /** @id MochiKit.DOM.removeEmptyTextNodes */
+    removeEmptyTextNodes: function (element) {
+        element = MochiKit.DOM.getElement(element);
+        for (var i = 0; i < element.childNodes.length; i++) {
+            var node = element.childNodes[i];
+            if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
+                node.parentNode.removeChild(node);
+            }
+        }
+    },
+
+    /** @id MochiKit.DOM.makeClipping */
+    makeClipping: function (element) {
+        element = MochiKit.DOM.getElement(element);
+        var oldOverflow = element.style.overflow;
+        if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
+            element.style.overflow = 'hidden';
+        }
+        return oldOverflow;
+    },
+
+    /** @id MochiKit.DOM.undoClipping */
+    undoClipping: function (element, overflow) {
+        element = MochiKit.DOM.getElement(element);
+        if (!overflow) {
+            return;
+        }
+        element.style.overflow = overflow;
+    },
+
+    /** @id MochiKit.DOM.makePositioned */
+    makePositioned: function (element) {
+        element = MochiKit.DOM.getElement(element);
+        var pos = MochiKit.Style.getStyle(element, 'position');
+        if (pos == 'static' || !pos) {
+            element.style.position = 'relative';
+            // Opera returns the offset relative to the positioning context,
+            // when an element is position relative but top and left have
+            // not been defined
+            if (/Opera/.test(navigator.userAgent)) {
+                element.style.top = 0;
+                element.style.left = 0;
+            }
+        }
+    },
+
+    /** @id MochiKit.DOM.undoPositioned */
+    undoPositioned: function (element) {
+        element = MochiKit.DOM.getElement(element);
+        if (element.style.position == 'relative') {
+            element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
+        }
+    },
+
+    /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
+    getFirstElementByTagAndClassName: function (tagName, className,
+            /* optional */parent) {
+        var self = MochiKit.DOM;
+        if (typeof(tagName) == 'undefined' || tagName === null) {
+            tagName = '*';
+        }
+        if (typeof(parent) == 'undefined' || parent === null) {
+            parent = self._document;
+        }
+        parent = self.getElement(parent);
+        var children = (parent.getElementsByTagName(tagName)
+            || self._document.all);
+        if (typeof(className) == 'undefined' || className === null) {
+            return children[0];
+        }
+
+        for (var i = 0; i < children.length; i++) {
+            var child = children[i];
+            var classNames = child.className.split(' ');
+            for (var j = 0; j < classNames.length; j++) {
+                if (classNames[j] == className) {
+                    return child;
+                }
+            }
+        }
+    },
+
+    /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
+    getFirstParentByTagAndClassName: function (elem, tagName, className) {
+        var self = MochiKit.DOM;
+        elem = self.getElement(elem);
+        if (typeof(tagName) == 'undefined' || tagName === null) {
+            tagName = '*';
+        } else {
+            tagName = tagName.toUpperCase();
+        }
+        if (typeof(className) == 'undefined' || className === null) {
+            className = null;
+        }
+
+        var classList = '';
+        var curTagName = '';
+        while (elem && elem.tagName) {
+            elem = elem.parentNode;
+            if (tagName == '*' && className === null) {
+                return elem;
+            }
+            classList = elem.className.split(' ');
+            curTagName = elem.tagName.toUpperCase();
+            if (className === null && tagName == curTagName) {
+                return elem;
+            } else if (className !== null) {
+                for (var i = 0; i < classList.length; i++) {
+                    if (tagName == '*' && classList[i] == className) {
+                        return elem;
+                    } else if (tagName == curTagName && classList[i] == className) {
+                        return elem;
+                    }
+                }
+            }
+        }
+        return elem;
+    },
+
+    /** @id MochiKit.DOM.isParent */
+    isParent: function (child, element) {
+        if (!child.parentNode || child == element) {
+            return false;
+        }
+
+        if (child.parentNode == element) {
+            return true;
+        }
+
+        return MochiKit.DOM.isParent(child.parentNode, element);
+    },
+
+    __new__: function (win) {
+
+        var m = MochiKit.Base;
+        if (typeof(document) != "undefined") {
+            this._document = document;
+            var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+            this._xhtml = (document.documentElement &&
+                document.createElementNS &&
+                document.documentElement.namespaceURI === kXULNSURI);
+        } else if (MochiKit.MockDOM) {
+            this._document = MochiKit.MockDOM.document;
+        }
+        this._window = win;
+
+        this.domConverters = new m.AdapterRegistry();
+
+        var __tmpElement = this._document.createElement("span");
+        var attributeArray;
+        if (__tmpElement && __tmpElement.attributes &&
+                __tmpElement.attributes.length > 0) {
+            // for braindead browsers (IE) that insert extra junk
+            var filter = m.filter;
+            attributeArray = function (node) {
+                return filter(attributeArray.ignoreAttrFilter, node.attributes);
+            };
+            attributeArray.ignoreAttr = {};
+            var attrs = __tmpElement.attributes;
+            var ignoreAttr = attributeArray.ignoreAttr;
+            for (var i = 0; i < attrs.length; i++) {
+                var a = attrs[i];
+                ignoreAttr[a.name] = a.value;
+            }
+            attributeArray.ignoreAttrFilter = function (a) {
+                return (attributeArray.ignoreAttr[a.name] != a.value);
+            };
+            attributeArray.compliant = false;
+            attributeArray.renames = {
+                "class": "className",
+                "checked": "defaultChecked",
+                "usemap": "useMap",
+                "for": "htmlFor",
+                "readonly": "readOnly",
+                "colspan": "colSpan",
+                "bgcolor": "bgColor",
+                "cellspacing": "cellSpacing",
+                "cellpadding": "cellPadding"
+            };
+        } else {
+            attributeArray = function (node) {
+                /***
+
+                    Return an array of attributes for a given node,
+                    filtering out attributes that don't belong for
+                    that are inserted by "Certain Browsers".
+
+                ***/
+                return node.attributes;
+            };
+            attributeArray.compliant = true;
+            attributeArray.renames = {};
+        }
+        this.attributeArray = attributeArray;
+
+        // FIXME: this really belongs in Base, and could probably be cleaner
+        var _deprecated = function(fromModule, arr) {
+            var modules = arr[1].split('.');
+            var str = '';
+            var obj = {};
+
+            str += 'if (!MochiKit.' + modules[1] + ') { throw new Error("';
+            str += 'This function has been deprecated and depends on MochiKit.';
+            str += modules[1] + '.");}';
+            str += 'return MochiKit.' + modules[1] + '.' + arr[0];
+            str += '.apply(this, arguments);';
+
+            obj[modules[2]] = new Function(str);
+            MochiKit.Base.update(MochiKit[fromModule], obj);
+        }
+        for (var i; i < MochiKit.DOM.DEPRECATED.length; i++) {
+            _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]);
+        }
+
+        // shorthand for createDOM syntax
+        var createDOMFunc = this.createDOMFunc;
+        /** @id MochiKit.DOM.UL */
+        this.UL = createDOMFunc("ul");
+        /** @id MochiKit.DOM.OL */
+        this.OL = createDOMFunc("ol");
+        /** @id MochiKit.DOM.LI */
+        this.LI = createDOMFunc("li");
+        /** @id MochiKit.DOM.TD */
+        this.TD = createDOMFunc("td");
+        /** @id MochiKit.DOM.TR */
+        this.TR = createDOMFunc("tr");
+        /** @id MochiKit.DOM.TBODY */
+        this.TBODY = createDOMFunc("tbody");
+        /** @id MochiKit.DOM.THEAD */
+        this.THEAD = createDOMFunc("thead");
+        /** @id MochiKit.DOM.TFOOT */
+        this.TFOOT = createDOMFunc("tfoot");
+        /** @id MochiKit.DOM.TABLE */
+        this.TABLE = createDOMFunc("table");
+        /** @id MochiKit.DOM.TH */
+        this.TH = createDOMFunc("th");
+        /** @id MochiKit.DOM.INPUT */
+        this.INPUT = createDOMFunc("input");
+        /** @id MochiKit.DOM.SPAN */
+        this.SPAN = createDOMFunc("span");
+        /** @id MochiKit.DOM.A */
+        this.A = createDOMFunc("a");
+        /** @id MochiKit.DOM.DIV */
+        this.DIV = createDOMFunc("div");
+        /** @id MochiKit.DOM.IMG */
+        this.IMG = createDOMFunc("img");
+        /** @id MochiKit.DOM.BUTTON */
+        this.BUTTON = createDOMFunc("button");
+        /** @id MochiKit.DOM.TT */
+        this.TT = createDOMFunc("tt");
+        /** @id MochiKit.DOM.PRE */
+        this.PRE = createDOMFunc("pre");
+        /** @id MochiKit.DOM.H1 */
+        this.H1 = createDOMFunc("h1");
+        /** @id MochiKit.DOM.H2 */
+        this.H2 = createDOMFunc("h2");
+        /** @id MochiKit.DOM.H3 */
+        this.H3 = createDOMFunc("h3");
+        /** @id MochiKit.DOM.BR */
+        this.BR = createDOMFunc("br");
+        /** @id MochiKit.DOM.HR */
+        this.HR = createDOMFunc("hr");
+        /** @id MochiKit.DOM.LABEL */
+        this.LABEL = createDOMFunc("label");
+        /** @id MochiKit.DOM.TEXTAREA */
+        this.TEXTAREA = createDOMFunc("textarea");
+        /** @id MochiKit.DOM.FORM */
+        this.FORM = createDOMFunc("form");
+        /** @id MochiKit.DOM.P */
+        this.P = createDOMFunc("p");
+        /** @id MochiKit.DOM.SELECT */
+        this.SELECT = createDOMFunc("select");
+        /** @id MochiKit.DOM.OPTION */
+        this.OPTION = createDOMFunc("option");
+        /** @id MochiKit.DOM.OPTGROUP */
+        this.OPTGROUP = createDOMFunc("optgroup");
+        /** @id MochiKit.DOM.LEGEND */
+        this.LEGEND = createDOMFunc("legend");
+        /** @id MochiKit.DOM.FIELDSET */
+        this.FIELDSET = createDOMFunc("fieldset");
+        /** @id MochiKit.DOM.STRONG */
+        this.STRONG = createDOMFunc("strong");
+        /** @id MochiKit.DOM.CANVAS */
+        this.CANVAS = createDOMFunc("canvas");
+
+        /** @id MochiKit.DOM.$ */
+        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));
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+    withWindow = MochiKit.DOM.withWindow;
+    withDocument = MochiKit.DOM.withDocument;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.DOM);
diff --git a/mochikit_v14/MochiKit/DateTime.js b/mochikit_v14/MochiKit/DateTime.js
new file mode 100644 (file)
index 0000000..c0b03ee
--- /dev/null
@@ -0,0 +1,216 @@
+/***
+
+MochiKit.DateTime 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+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.4";
+MochiKit.DateTime.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.DateTime.toString = function () {
+    return this.__repr__();
+};
+
+/** @id MochiKit.DateTime.isoDate */
+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}))?)?)?)?)?/;
+
+/** @id MochiKit.DateTime.isoTimestamp */
+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.0 * 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);
+};
+
+/** @id MochiKit.DateTime.toISOTime */
+MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
+    if (typeof(date) == "undefined" || date === null) {
+        return null;
+    }
+    var hh = date.getHours();
+    var mm = date.getMinutes();
+    var ss = date.getSeconds();
+    var lst = [
+        ((realISO && (hh < 10)) ? "0" + hh : hh),
+        ((mm < 10) ? "0" + mm : mm),
+        ((ss < 10) ? "0" + ss : ss)
+    ];
+    return lst.join(":");
+};
+
+/** @id MochiKit.DateTime.toISOTimeStamp */
+MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
+    if (typeof(date) == "undefined" || date === null) {
+        return null;
+    }
+    var sep = realISO ? "T" : " ";
+    var foot = realISO ? "Z" : "";
+    if (realISO) {
+        date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
+    }
+    return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot;
+};
+
+/** @id MochiKit.DateTime.toISODate */
+MochiKit.DateTime.toISODate = function (date) {
+    if (typeof(date) == "undefined" || date === null) {
+        return null;
+    }
+    var _padTwo = MochiKit.DateTime._padTwo;
+    return [
+        date.getFullYear(),
+        _padTwo(date.getMonth() + 1),
+        _padTwo(date.getDate())
+    ].join("-");
+};
+
+/** @id MochiKit.DateTime.americanDate */
+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;
+};
+
+/** @id MochiKit.DateTime.toPaddedAmericanDate */
+MochiKit.DateTime.toPaddedAmericanDate = function (d) {
+    if (typeof(d) == "undefined" || d === null) {
+        return null;
+    }
+    var _padTwo = MochiKit.DateTime._padTwo;
+    return [
+        _padTwo(d.getMonth() + 1),
+        _padTwo(d.getDate()),
+        d.getFullYear()
+    ].join('/');
+};
+
+/** @id MochiKit.DateTime.toAmericanDate */
+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 () {
+    // MochiKit.Base.nameFunctions(this);
+    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) {
+                // pass
+            }
+        }
+    }
+};
+
+MochiKit.DateTime.__new__();
+
+if (typeof(MochiKit.Base) != "undefined") {
+    MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
+} else {
+    (function (globals, module) {
+        if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
+            || (MochiKit.__export__ === false)) {
+            var all = module.EXPORT_TAGS[":all"];
+            for (var i = 0; i < all.length; i++) {
+                globals[all[i]] = module[all[i]];
+            }
+        }
+    })(this, MochiKit.DateTime);
+}
diff --git a/mochikit_v14/MochiKit/DragAndDrop.js b/mochikit_v14/MochiKit/DragAndDrop.js
new file mode 100644 (file)
index 0000000..c471ffe
--- /dev/null
@@ -0,0 +1,824 @@
+/***
+MochiKit.DragAndDrop 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+    Mochi-ized By Thomas Herve (_firstname_@nimail.org)
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.DragAndDrop');
+    dojo.require('MochiKit.Base');
+    dojo.require('MochiKit.DOM');
+    dojo.require('MochiKit.Iter');
+    dojo.require('MochiKit.Visual');
+    dojo.require('MochiKit.Signal');
+}
+
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use("MochiKit.Base", []);
+    JSAN.use("MochiKit.DOM", []);
+    JSAN.use("MochiKit.Visual", []);
+    JSAN.use("MochiKit.Iter", []);
+    JSAN.use("MochiKit.Signal", []);
+}
+
+try {
+    if (typeof(MochiKit.Base) == 'undefined' ||
+        typeof(MochiKit.DOM) == 'undefined' ||
+        typeof(MochiKit.Visual) == 'undefined' ||
+        typeof(MochiKit.Signal) == 'undefined' ||
+        typeof(MochiKit.Iter) == 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM, MochiKit.Visual, MochiKit.Signal and MochiKit.Iter!";
+}
+
+if (typeof(MochiKit.DragAndDrop) == 'undefined') {
+    MochiKit.DragAndDrop = {};
+}
+
+MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop';
+MochiKit.DragAndDrop.VERSION = '1.4';
+
+MochiKit.DragAndDrop.__repr__ = function () {
+    return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+
+MochiKit.DragAndDrop.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.DragAndDrop.EXPORT = [
+    "Droppable",
+    "Draggable"
+];
+
+MochiKit.DragAndDrop.EXPORT_OK = [
+    "Droppables",
+    "Draggables"
+];
+
+MochiKit.DragAndDrop.Droppables = {
+    /***
+
+    Manage all droppables. Shouldn't be used, use the Droppable object instead.
+
+    ***/
+    drops: [],
+
+    remove: function (element) {
+        this.drops = MochiKit.Base.filter(function (d) {
+            return d.element != MochiKit.DOM.getElement(element);
+        }, this.drops);
+    },
+
+    register: function (drop) {
+        this.drops.push(drop);
+    },
+
+    unregister: function (drop) {
+        this.drops = MochiKit.Base.filter(function (d) {
+            return d != drop;
+        }, this.drops);
+    },
+
+    prepare: function (element) {
+        MochiKit.Base.map(function (drop) {
+            if (drop.isAccepted(element)) {
+                if (drop.options.activeclass) {
+                    MochiKit.DOM.addElementClass(drop.element,
+                                                 drop.options.activeclass);
+                }
+                drop.options.onactive(drop.element, element);
+            }
+        }, this.drops);
+    },
+
+    findDeepestChild: function (drops) {
+        deepest = drops[0];
+
+        for (i = 1; i < drops.length; ++i) {
+            if (MochiKit.DOM.isParent(drops[i].element, deepest.element)) {
+                deepest = drops[i];
+            }
+        }
+        return deepest;
+    },
+
+    show: function (point, element) {
+        if (!this.drops.length) {
+            return;
+        }
+        var affected = [];
+
+        if (this.last_active) {
+            this.last_active.deactivate();
+        }
+        MochiKit.Iter.forEach(this.drops, function (drop) {
+            if (drop.isAffected(point, element)) {
+                affected.push(drop);
+            }
+        });
+        if (affected.length > 0) {
+            drop = this.findDeepestChild(affected);
+            MochiKit.Position.within(drop.element, point.page.x, point.page.y);
+            drop.options.onhover(element, drop.element,
+                MochiKit.Position.overlap(drop.options.overlap, drop.element));
+            drop.activate();
+        }
+    },
+
+    fire: function (event, element) {
+        if (!this.last_active) {
+            return;
+        }
+        MochiKit.Position.prepare();
+
+        if (this.last_active.isAffected(event.mouse(), element)) {
+            this.last_active.options.ondrop(element,
+               this.last_active.element, event);
+        }
+    },
+
+    reset: function (element) {
+        MochiKit.Base.map(function (drop) {
+            if (drop.options.activeclass) {
+                MochiKit.DOM.removeElementClass(drop.element,
+                                                drop.options.activeclass);
+            }
+            drop.options.ondesactive(drop.element, element);
+        }, this.drops);
+        if (this.last_active) {
+            this.last_active.deactivate();
+        }
+    }
+};
+
+/** @id MochiKit.DragAndDrop.Droppable */
+MochiKit.DragAndDrop.Droppable = function (element, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, options);
+    }
+    this.__init__(element, options);
+};
+
+MochiKit.DragAndDrop.Droppable.prototype = {
+    /***
+
+    A droppable object. Simple use is to create giving an element:
+
+        new MochiKit.DragAndDrop.Droppable('myelement');
+
+    Generally you'll want to define the 'ondrop' function and maybe the
+    'accept' option to filter draggables.
+
+    ***/
+    __class__: MochiKit.DragAndDrop.Droppable,
+
+    __init__: function (element, /* optional */options) {
+        var d = MochiKit.DOM;
+        var b = MochiKit.Base;
+        this.element = d.getElement(element);
+        this.options = b.update({
+
+            /** @id MochiKit.DragAndDrop.greedy */
+            greedy: true,
+
+            /** @id MochiKit.DragAndDrop.hoverclass */
+            hoverclass: null,
+
+            /** @id MochiKit.DragAndDrop.activeclass */
+            activeclass: null,
+
+            /** @id MochiKit.DragAndDrop.hoverfunc */
+            hoverfunc: b.noop,
+
+            /** @id MochiKit.DragAndDrop.accept */
+            accept: null,
+
+            /** @id MochiKit.DragAndDrop.onactive */
+            onactive: b.noop,
+
+            /** @id MochiKit.DragAndDrop.ondesactive */
+            ondesactive: b.noop,
+
+            /** @id MochiKit.DragAndDrop.onhover */
+            onhover: b.noop,
+
+            /** @id MochiKit.DragAndDrop.ondrop */
+            ondrop: b.noop,
+
+            /** @id MochiKit.DragAndDrop.containment */
+            containment: [],
+            tree: false
+        }, options || {});
+
+        // cache containers
+        this.options._containers = [];
+        b.map(MochiKit.Base.bind(function (c) {
+            this.options._containers.push(d.getElement(c));
+        }, this), this.options.containment);
+
+        d.makePositioned(this.element); // fix IE
+
+        MochiKit.DragAndDrop.Droppables.register(this);
+    },
+
+    /** @id MochiKit.DragAndDrop.isContained */
+    isContained: function (element) {
+        if (this.options._containers.length) {
+            var containmentNode;
+            if (this.options.tree) {
+                containmentNode = element.treeNode;
+            } else {
+                containmentNode = element.parentNode;
+            }
+            return MochiKit.Iter.some(this.options._containers, function (c) {
+                return containmentNode == c;
+            });
+        } else {
+            return true;
+        }
+    },
+
+    /** @id MochiKit.DragAndDrop.isAccepted */
+    isAccepted: function (element) {
+        return ((!this.options.accept) || MochiKit.Iter.some(
+          this.options.accept, function (c) {
+            return MochiKit.DOM.hasElementClass(element, c);
+        }));
+    },
+
+    /** @id MochiKit.DragAndDrop.isAffected */
+    isAffected: function (point, element) {
+        return ((this.element != element) &&
+                this.isContained(element) &&
+                this.isAccepted(element) &&
+                MochiKit.Position.within(this.element, point.page.x,
+                                                       point.page.y));
+    },
+
+    /** @id MochiKit.DragAndDrop.deactivate */
+    deactivate: function () {
+        /***
+
+        A droppable is deactivate when a draggable has been over it and left.
+
+        ***/
+        if (this.options.hoverclass) {
+            MochiKit.DOM.removeElementClass(this.element,
+                                            this.options.hoverclass);
+        }
+        this.options.hoverfunc(this.element, false);
+        MochiKit.DragAndDrop.Droppables.last_active = null;
+    },
+
+    /** @id MochiKit.DragAndDrop.activate */
+    activate: function () {
+        /***
+
+        A droppable is active when a draggable is over it.
+
+        ***/
+        if (this.options.hoverclass) {
+            MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
+        }
+        this.options.hoverfunc(this.element, true);
+        MochiKit.DragAndDrop.Droppables.last_active = this;
+    },
+
+    /** @id MochiKit.DragAndDrop.destroy */
+    destroy: function () {
+        /***
+
+        Delete this droppable.
+
+        ***/
+        MochiKit.DragAndDrop.Droppables.unregister(this);
+    },
+
+    /** @id MochiKit.DragAndDrop.repr */
+    repr: function () {
+        return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
+    }
+};
+
+MochiKit.DragAndDrop.Draggables = {
+    /***
+
+    Manage draggables elements. Not intended to direct use.
+
+    ***/
+    drags: [],
+
+    register: function (draggable) {
+        if (this.drags.length === 0) {
+            var conn = MochiKit.Signal.connect;
+            this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
+            this.eventMouseMove = conn(document, 'onmousemove', this,
+                                       this.updateDrag);
+            this.eventKeypress = conn(document, 'onkeypress', this,
+                                      this.keyPress);
+        }
+        this.drags.push(draggable);
+    },
+
+    unregister: function (draggable) {
+        this.drags = MochiKit.Base.filter(function (d) {
+            return d != draggable;
+        }, this.drags);
+        if (this.drags.length === 0) {
+            var disc = MochiKit.Signal.disconnect;
+            disc(this.eventMouseUp);
+            disc(this.eventMouseMove);
+            disc(this.eventKeypress);
+        }
+    },
+
+    activate: function (draggable) {
+        // allows keypress events if window is not currently focused
+        // fails for Safari
+        window.focus();
+        this.activeDraggable = draggable;
+    },
+
+    deactivate: function () {
+        this.activeDraggable = null;
+    },
+
+    updateDrag: function (event) {
+        if (!this.activeDraggable) {
+            return;
+        }
+        var pointer = event.mouse();
+        // Mozilla-based browsers fire successive mousemove events with
+        // the same coordinates, prevent needless redrawing (moz bug?)
+        if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) ==
+                                  MochiKit.Base.repr(pointer.page))) {
+            return;
+        }
+        this._lastPointer = pointer;
+        this.activeDraggable.updateDrag(event, pointer);
+    },
+
+    endDrag: function (event) {
+        if (!this.activeDraggable) {
+            return;
+        }
+        this._lastPointer = null;
+        this.activeDraggable.endDrag(event);
+        this.activeDraggable = null;
+    },
+
+    keyPress: function (event) {
+        if (this.activeDraggable) {
+            this.activeDraggable.keyPress(event);
+        }
+    },
+
+    notify: function (eventName, draggable, event) {
+        MochiKit.Signal.signal(this, eventName, draggable, event);
+    }
+};
+
+/** @id MochiKit.DragAndDrop.Draggable */
+MochiKit.DragAndDrop.Draggable = function (element, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, options);
+    }
+    this.__init__(element, options);
+};
+
+MochiKit.DragAndDrop.Draggable.prototype = {
+    /***
+
+    A draggable object. Simple instantiate :
+
+        new MochiKit.DragAndDrop.Draggable('myelement');
+
+    ***/
+    __class__ : MochiKit.DragAndDrop.Draggable,
+
+    __init__: function (element, /* optional */options) {
+        var v = MochiKit.Visual;
+        var b = MochiKit.Base;
+        options = b.update({
+
+            /** @id MochiKit.DragAndDrop.handle */
+            handle: false,
+
+            /** @id MochiKit.DragAndDrop.starteffect */
+            starteffect: function (innerelement) {
+                this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0;
+                new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
+            },
+            /** @id MochiKit.DragAndDrop.reverteffect */
+            reverteffect: function (innerelement, top_offset, left_offset) {
+                var dur = Math.sqrt(Math.abs(top_offset^2) +
+                          Math.abs(left_offset^2))*0.02;
+                return new v.Move(innerelement,
+                            {x: -left_offset, y: -top_offset, duration: dur});
+            },
+
+            /** @id MochiKit.DragAndDrop.endeffect */
+            endeffect: function (innerelement) {
+                new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
+            },
+
+            /** @id MochiKit.DragAndDrop.onchange */
+            onchange: b.noop,
+
+            /** @id MochiKit.DragAndDrop.zindex */
+            zindex: 1000,
+
+            /** @id MochiKit.DragAndDrop.revert */
+            revert: false,
+
+            /** @id MochiKit.DragAndDrop.scroll */
+            scroll: false,
+
+            /** @id MochiKit.DragAndDrop.scrollSensitivity */
+            scrollSensitivity: 20,
+
+            /** @id MochiKit.DragAndDrop.scrollSpeed */
+            scrollSpeed: 15,
+            // false, or xy or [x, y] or function (x, y){return [x, y];}
+
+            /** @id MochiKit.DragAndDrop.snap */
+            snap: false
+        }, options || {});
+
+        var d = MochiKit.DOM;
+        this.element = d.getElement(element);
+
+        if (options.handle && (typeof(options.handle) == 'string')) {
+            this.handle = d.getFirstElementByTagAndClassName(null,
+                                       options.handle, this.element);
+        }
+        if (!this.handle) {
+            this.handle = d.getElement(options.handle);
+        }
+        if (!this.handle) {
+            this.handle = this.element;
+        }
+
+        if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+            options.scroll = d.getElement(options.scroll);
+            this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
+        }
+
+        d.makePositioned(this.element);  // fix IE
+
+        this.delta = this.currentDelta();
+        this.options = options;
+        this.dragging = false;
+
+        this.eventMouseDown = MochiKit.Signal.connect(this.handle,
+                              'onmousedown', this, this.initDrag);
+        MochiKit.DragAndDrop.Draggables.register(this);
+    },
+
+    /** @id MochiKit.DragAndDrop.destroy */
+    destroy: function () {
+        MochiKit.Signal.disconnect(this.eventMouseDown);
+        MochiKit.DragAndDrop.Draggables.unregister(this);
+    },
+
+    /** @id MochiKit.DragAndDrop.currentDelta */
+    currentDelta: function () {
+        var s = MochiKit.Style.getStyle;
+        return [
+          parseInt(s(this.element, 'left') || '0'),
+          parseInt(s(this.element, 'top') || '0')];
+    },
+
+    /** @id MochiKit.DragAndDrop.initDrag */
+    initDrag: function (event) {
+        if (!event.mouse().button.left) {
+            return;
+        }
+        // abort on form elements, fixes a Firefox issue
+        var src = event.target();
+        var tagName = (src.tagName || '').toUpperCase();
+        if (tagName === 'INPUT' || tagName === 'SELECT' ||
+            tagName === 'OPTION' || tagName === 'BUTTON' ||
+            tagName === 'TEXTAREA') {
+            return;
+        }
+
+        if (this._revert) {
+            this._revert.cancel();
+            this._revert = null;
+        }
+
+        var pointer = event.mouse();
+        var pos = MochiKit.Position.cumulativeOffset(this.element);
+        this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y];
+
+        MochiKit.DragAndDrop.Draggables.activate(this);
+        event.stop();
+    },
+
+    /** @id MochiKit.DragAndDrop.startDrag */
+    startDrag: function (event) {
+        this.dragging = true;
+        if (this.options.selectclass) {
+            MochiKit.DOM.addElementClass(this.element,
+                                         this.options.selectclass);
+        }
+        if (this.options.zindex) {
+            this.originalZ = parseInt(MochiKit.Style.getStyle(this.element,
+                                      'z-index') || '0');
+            this.element.style.zIndex = this.options.zindex;
+        }
+
+        if (this.options.ghosting) {
+            this._clone = this.element.cloneNode(true);
+            this.ghostPosition = MochiKit.Position.absolutize(this.element);
+            this.element.parentNode.insertBefore(this._clone, this.element);
+        }
+
+        if (this.options.scroll) {
+            if (this.options.scroll == window) {
+                var where = this._getWindowScroll(this.options.scroll);
+                this.originalScrollLeft = where.left;
+                this.originalScrollTop = where.top;
+            } else {
+                this.originalScrollLeft = this.options.scroll.scrollLeft;
+                this.originalScrollTop = this.options.scroll.scrollTop;
+            }
+        }
+
+        MochiKit.DragAndDrop.Droppables.prepare(this.element);
+        MochiKit.DragAndDrop.Draggables.notify('start', this, event);
+        if (this.options.starteffect) {
+            this.options.starteffect(this.element);
+        }
+    },
+
+    /** @id MochiKit.DragAndDrop.updateDrag */
+    updateDrag: function (event, pointer) {
+        if (!this.dragging) {
+            this.startDrag(event);
+        }
+        MochiKit.Position.prepare();
+        MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
+        MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
+        this.draw(pointer);
+        this.options.onchange(this);
+
+        if (this.options.scroll) {
+            this.stopScrolling();
+            var p, q;
+            if (this.options.scroll == window) {
+                var s = this._getWindowScroll(this.options.scroll);
+                p = new MochiKit.Style.Coordinates(s.left, s.top);
+                q = new MochiKit.Style.Coordinates(s.left + s.width,
+                                                   s.top + s.height);
+            } else {
+                p = MochiKit.Position.page(this.options.scroll);
+                p.x += this.options.scroll.scrollLeft;
+                p.y += this.options.scroll.scrollTop;
+                p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
+                p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
+                q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
+                                                   p.y + this.options.scroll.offsetHeight);
+            }
+            var speed = [0, 0];
+            if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
+                speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
+            } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
+                speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
+            }
+            if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
+                speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
+            } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
+                speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
+            }
+            this.startScrolling(speed);
+        }
+
+        // fix AppleWebKit rendering
+        if (/AppleWebKit'/.test(navigator.appVersion)) {
+            window.scrollBy(0, 0);
+        }
+        event.stop();
+    },
+
+    /** @id MochiKit.DragAndDrop.finishDrag */
+    finishDrag: function (event, success) {
+        var dr = MochiKit.DragAndDrop;
+        this.dragging = false;
+        if (this.options.selectclass) {
+            MochiKit.DOM.removeElementClass(this.element,
+                                            this.options.selectclass);
+        }
+
+        if (this.options.ghosting) {
+            // XXX: from a user point of view, it would be better to remove
+            // the node only *after* the MochiKit.Visual.Move end when used
+            // with revert.
+            MochiKit.Position.relativize(this.element, this.ghostPosition);
+            MochiKit.DOM.removeElement(this._clone);
+            this._clone = null;
+        }
+
+        if (success) {
+            dr.Droppables.fire(event, this.element);
+        }
+        dr.Draggables.notify('end', this, event);
+
+        var revert = this.options.revert;
+        if (revert && typeof(revert) == 'function') {
+            revert = revert(this.element);
+        }
+
+        var d = this.currentDelta();
+        if (revert && this.options.reverteffect) {
+            this._revert = this.options.reverteffect(this.element,
+                d[1] - this.delta[1], d[0] - this.delta[0]);
+        } else {
+            this.delta = d;
+        }
+
+        if (this.options.zindex) {
+            this.element.style.zIndex = this.originalZ;
+        }
+
+        if (this.options.endeffect) {
+            this.options.endeffect(this.element);
+        }
+
+        dr.Draggables.deactivate();
+        dr.Droppables.reset(this.element);
+    },
+
+    /** @id MochiKit.DragAndDrop.keyPress */
+    keyPress: function (event) {
+        if (event.key().string != "KEY_ESCAPE") {
+            return;
+        }
+        this.finishDrag(event, false);
+        event.stop();
+    },
+
+    /** @id MochiKit.DragAndDrop.endDrag */
+    endDrag: function (event) {
+        if (!this.dragging) {
+            return;
+        }
+        this.stopScrolling();
+        this.finishDrag(event, true);
+        event.stop();
+    },
+
+    /** @id MochiKit.DragAndDrop.draw */
+    draw: function (point) {
+        var pos = MochiKit.Position.cumulativeOffset(this.element);
+        var d = this.currentDelta();
+        pos.x -= d[0];
+        pos.y -= d[1];
+
+        if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+            pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
+            pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
+        }
+
+        var p = [point.page.x - pos.x - this.offset[0],
+                 point.page.y - pos.y - this.offset[1]];
+
+        if (this.options.snap) {
+            if (typeof(this.options.snap) == 'function') {
+                p = this.options.snap(p[0], p[1]);
+            } else {
+                if (this.options.snap instanceof Array) {
+                    var i = -1;
+                    p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
+                            i += 1;
+                            return Math.round(v/this.options.snap[i]) *
+                                   this.options.snap[i];
+                        }, this), p);
+                } else {
+                    p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
+                        return Math.round(v/this.options.snap) *
+                               this.options.snap;
+                        }, this), p);
+                }
+            }
+        }
+        var style = this.element.style;
+        if ((!this.options.constraint) ||
+            (this.options.constraint == 'horizontal')) {
+            style.left = p[0] + 'px';
+        }
+        if ((!this.options.constraint) ||
+            (this.options.constraint == 'vertical')) {
+            style.top = p[1] + 'px';
+        }
+        if (style.visibility == 'hidden') {
+            style.visibility = '';  // fix gecko rendering
+        }
+    },
+
+    /** @id MochiKit.DragAndDrop.stopScrolling */
+    stopScrolling: function () {
+        if (this.scrollInterval) {
+            clearInterval(this.scrollInterval);
+            this.scrollInterval = null;
+            MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
+        }
+    },
+
+    /** @id MochiKit.DragAndDrop.startScrolling */
+    startScrolling: function (speed) {
+        if (!speed[0] && !speed[1]) {
+            return;
+        }
+        this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
+                            speed[1] * this.options.scrollSpeed];
+        this.lastScrolled = new Date();
+        this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
+    },
+
+    /** @id MochiKit.DragAndDrop.scroll */
+    scroll: function () {
+        var current = new Date();
+        var delta = current - this.lastScrolled;
+        this.lastScrolled = current;
+
+        if (this.options.scroll == window) {
+            var s = this._getWindowScroll(this.options.scroll);
+            if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+                var dm = delta / 1000;
+                this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0],
+                                             s.top + dm * this.scrollSpeed[1]);
+            }
+        } else {
+            this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+            this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+        }
+
+        var d = MochiKit.DragAndDrop;
+
+        MochiKit.Position.prepare();
+        d.Droppables.show(d.Draggables._lastPointer, this.element);
+        d.Draggables.notify('drag', this);
+        if (this._isScrollChild) {
+            d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
+            d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
+            d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
+            if (d.Draggables._lastScrollPointer.x < 0) {
+                d.Draggables._lastScrollPointer.x = 0;
+            }
+            if (d.Draggables._lastScrollPointer.y < 0) {
+                d.Draggables._lastScrollPointer.y = 0;
+            }
+            this.draw(d.Draggables._lastScrollPointer);
+        }
+
+        this.options.onchange(this);
+    },
+
+    _getWindowScroll: function (win) {
+        var vp, w, h;
+        MochiKit.DOM.withWindow(win, function () {
+            vp = MochiKit.Style.getViewportPosition(win.document);
+        });
+        if (win.innerWidth) {
+            w = win.innerWidth;
+            h = win.innerHeight;
+        } else if (win.document.documentElement && win.document.documentElement.clientWidth) {
+            w = win.document.documentElement.clientWidth;
+            h = win.document.documentElement.clientHeight;
+        } else {
+            w = win.document.body.offsetWidth;
+            h = win.document.body.offsetHeight;
+        }
+        return {top: vp.x, left: vp.y, width: w, height: h};
+    },
+
+    /** @id MochiKit.DragAndDrop.repr */
+    repr: function () {
+        return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
+    }
+};
+
+MochiKit.DragAndDrop.__new__ = function () {
+    MochiKit.Base.nameFunctions(this);
+
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
+    };
+};
+
+MochiKit.DragAndDrop.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);
+
diff --git a/mochikit_v14/MochiKit/Format.js b/mochikit_v14/MochiKit/Format.js
new file mode 100644 (file)
index 0000000..937b681
--- /dev/null
@@ -0,0 +1,304 @@
+/***
+
+MochiKit.Format 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+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.4";
+MochiKit.Format.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.Format.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
+    return function (num) {
+        num = parseFloat(num);
+        if (typeof(num) == "undefined" || num === null || isNaN(num)) {
+            return placeholder;
+        }
+        var curheader = header;
+        var curfooter = footer;
+        if (num < 0) {
+            num = -num;
+        } else {
+            curheader = curheader.replace(/-/, "");
+        }
+        var me = arguments.callee;
+        var fmt = MochiKit.Format.formatLocale(locale);
+        if (isPercent) {
+            num = num * 100.0;
+            curfooter = fmt.percent + curfooter;
+        }
+        num = MochiKit.Format.roundToFixed(num, precision);
+        var parts = num.split(/\./);
+        var whole = parts[0];
+        var frac = (parts.length == 1) ? "" : parts[1];
+        var res = "";
+        while (whole.length < leadingZeros) {
+            whole = "0" + whole;
+        }
+        if (separatorAt) {
+            while (whole.length > separatorAt) {
+                var i = whole.length - separatorAt;
+                //res = res + fmt.separator + whole.substring(i, whole.length);
+                res = fmt.separator + whole.substring(i, whole.length) + res;
+                whole = whole.substring(0, i);
+            }
+        }
+        res = whole + res;
+        if (precision > 0) {
+            while (frac.length < trailingZeros) {
+                frac = frac + "0";
+            }
+            res = res + fmt.decimal + frac;
+        }
+        return curheader + res + curfooter;
+    };
+};
+
+/** @id MochiKit.Format.numberFormatter */
+MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
+    // http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
+    // | 0 | leading or trailing zeros
+    // | # | just the number
+    // | , | separator
+    // | . | decimal separator
+    // | % | Multiply by 100 and format as percent
+    if (typeof(placeholder) == "undefined") {
+        placeholder = "";
+    }
+    var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
+    if (!match) {
+        throw TypeError("Invalid pattern");
+    }
+    var header = pattern.substr(0, match.index);
+    var footer = pattern.substr(match.index + match[0].length);
+    if (header.search(/-/) == -1) {
+        header = header + "-";
+    }
+    var whole = match[1];
+    var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
+    var isPercent = (typeof(match[3]) == "string" && match[3] != "");
+    var tmp = whole.split(/,/);
+    var separatorAt;
+    if (typeof(locale) == "undefined") {
+        locale = "default";
+    }
+    if (tmp.length == 1) {
+        separatorAt = null;
+    } else {
+        separatorAt = tmp[1].length;
+    }
+    var leadingZeros = whole.length - whole.replace(/0/g, "").length;
+    var trailingZeros = frac.length - frac.replace(/0/g, "").length;
+    var precision = frac.length;
+    var rval = MochiKit.Format._numberFormatter(
+        placeholder, header, footer, locale, isPercent, precision,
+        leadingZeros, separatorAt, trailingZeros
+    );
+    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;
+};
+
+/** @id MochiKit.Format.formatLocale */
+MochiKit.Format.formatLocale = function (locale) {
+    if (typeof(locale) == "undefined" || locale === null) {
+        locale = "default";
+    }
+    if (typeof(locale) == "string") {
+        var rval = MochiKit.Format.LOCALE[locale];
+        if (typeof(rval) == "string") {
+            rval = arguments.callee(rval);
+            MochiKit.Format.LOCALE[locale] = rval;
+        }
+        return rval;
+    } else {
+        return locale;
+    }
+};
+
+/** @id MochiKit.Format.twoDigitAverage */
+MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
+    if (denominator) {
+        var res = numerator / denominator;
+        if (!isNaN(res)) {
+            return MochiKit.Format.twoDigitFloat(numerator / denominator);
+        }
+    }
+    return "0";
+};
+
+/** @id MochiKit.Format.twoDigitFloat */
+MochiKit.Format.twoDigitFloat = function (someFloat) {
+    var sign = (someFloat < 0 ? '-' : '');
+    var s = Math.floor(Math.abs(someFloat) * 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;
+    }
+};
+
+/** @id MochiKit.Format.lstrip */
+MochiKit.Format.lstrip = function (str, /* optional */chars) {
+    str = str + "";
+    if (typeof(str) != "string") {
+        return null;
+    }
+    if (!chars) {
+        return str.replace(/^\s+/, "");
+    } else {
+        return str.replace(new RegExp("^[" + chars + "]+"), "");
+    }
+};
+
+/** @id MochiKit.Format.rstrip */
+MochiKit.Format.rstrip = function (str, /* optional */chars) {
+    str = str + "";
+    if (typeof(str) != "string") {
+        return null;
+    }
+    if (!chars) {
+        return str.replace(/\s+$/, "");
+    } else {
+        return str.replace(new RegExp("[" + chars + "]+$"), "");
+    }
+};
+
+/** @id MochiKit.Format.strip */
+MochiKit.Format.strip = function (str, /* optional */chars) {
+    var self = MochiKit.Format;
+    return self.rstrip(self.lstrip(str, chars), chars);
+};
+
+/** @id MochiKit.Format.truncToFixed */
+MochiKit.Format.truncToFixed = function (aNumber, precision) {
+    aNumber = Math.floor(aNumber * Math.pow(10, precision));
+    var res = (aNumber * Math.pow(10, -precision)).toFixed(precision);
+    if (res.charAt(0) == ".") {
+        res = "0" + res;
+    }
+    return res;
+};
+
+/** @id MochiKit.Format.roundToFixed */
+MochiKit.Format.roundToFixed = function (aNumber, precision) {
+    return MochiKit.Format.truncToFixed(
+        aNumber + 0.5 * Math.pow(10, -precision),
+        precision
+    );
+};
+
+/** @id MochiKit.Format.percentFormat */
+MochiKit.Format.percentFormat = function (someFloat) {
+    return MochiKit.Format.twoDigitFloat(100 * someFloat) + '%';
+};
+
+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 () {
+    // MochiKit.Base.nameFunctions(this);
+    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) {
+                // pass
+            }
+        }
+    }
+};
+
+MochiKit.Format.__new__();
+
+if (typeof(MochiKit.Base) != "undefined") {
+    MochiKit.Base._exportSymbols(this, MochiKit.Format);
+} else {
+    (function (globals, module) {
+        if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
+            || (MochiKit.__export__ === false)) {
+            var all = module.EXPORT_TAGS[":all"];
+            for (var i = 0; i < all.length; i++) {
+                globals[all[i]] = module[all[i]];
+            }
+        }
+    })(this, MochiKit.Format);
+}
diff --git a/mochikit_v14/MochiKit/Iter.js b/mochikit_v14/MochiKit/Iter.js
new file mode 100644 (file)
index 0000000..c2fcbee
--- /dev/null
@@ -0,0 +1,851 @@
+/***
+
+MochiKit.Iter 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+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.4";
+MochiKit.Base.update(MochiKit.Iter, {
+    __repr__: function () {
+        return "[" + this.NAME + " " + this.VERSION + "]";
+    },
+    toString: function () {
+        return this.__repr__();
+    },
+
+    /** @id MochiKit.Iter.registerIteratorFactory  */
+    registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
+        MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
+    },
+
+    /** @id MochiKit.Iter.iter */
+    iter: function (iterable, /* optional */ sentinel) {
+        var self = MochiKit.Iter;
+        if (arguments.length == 2) {
+            return self.takewhile(
+                function (a) { return a != sentinel; },
+                iterable
+            );
+        }
+        if (typeof(iterable.next) == 'function') {
+            return iterable;
+        } else if (typeof(iterable.iter) == 'function') {
+            return iterable.iter();
+        /*
+        }  else if (typeof(iterable.__iterator__) == 'function') {
+            //
+            // XXX: We can't support JavaScript 1.7 __iterator__ directly
+            //      because of Object.prototype.__iterator__
+            //
+            return iterable.__iterator__();
+        */
+        }
+
+        try {
+            return self.iteratorRegistry.match(iterable);
+        } catch (e) {
+            var m = MochiKit.Base;
+            if (e == m.NotFound) {
+                e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
+            }
+            throw e;
+        }
+    },
+
+    /** @id MochiKit.Iter.count */
+    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)
+        };
+    },
+
+    /** @id MochiKit.Iter.cycle */
+    cycle: function (p) {
+        var self = MochiKit.Iter;
+        var m = MochiKit.Base;
+        var lst = [];
+        var iterator = self.iter(p);
+        return {
+            repr: function () { return "cycle(...)"; },
+            toString: m.forwardCall("repr"),
+            next: function () {
+                try {
+                    var rval = iterator.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();
+                }
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.repeat */
+    repeat: function (elem, /* optional */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;
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.next */
+    next: function (iterator) {
+        return iterator.next();
+    },
+
+    /** @id MochiKit.Iter.izip */
+    izip: function (p, q/*, ...*/) {
+        var m = MochiKit.Base;
+        var self = MochiKit.Iter;
+        var next = self.next;
+        var iterables = m.map(self.iter, arguments);
+        return {
+            repr: function () { return "izip(...)"; },
+            toString: m.forwardCall("repr"),
+            next: function () { return m.map(next, iterables); }
+        };
+    },
+
+    /** @id MochiKit.Iter.ifilter */
+    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;
+                    }
+                }
+                // mozilla warnings aren't too bright
+                return undefined;
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.ifilterfalse */
+    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;
+                    }
+                }
+                // mozilla warnings aren't too bright
+                return undefined;
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.islice */
+    islice: function (seq/*, [start,] stop[, step] */) {
+        var self = MochiKit.Iter;
+        var m = MochiKit.Base;
+        seq = self.iter(seq);
+        var start = 0;
+        var stop = 0;
+        var step = 1;
+        var i = -1;
+        if (arguments.length == 2) {
+            stop = arguments[1];
+        } else if (arguments.length == 3) {
+            start = arguments[1];
+            stop = arguments[2];
+        } else {
+            start = arguments[1];
+            stop = arguments[2];
+            step = arguments[3];
+        }
+        return {
+            repr: function () {
+                return "islice(" + ["...", start, stop, step].join(", ") + ")";
+            },
+            toString: m.forwardCall("repr"),
+            next: function () {
+                var rval;
+                while (i < start) {
+                    rval = seq.next();
+                    i++;
+                }
+                if (start >= stop) {
+                    throw self.StopIteration;
+                }
+                start += step;
+                return rval;
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.imap */
+    imap: function (fun, p, q/*, ...*/) {
+        var m = MochiKit.Base;
+        var self = MochiKit.Iter;
+        var iterables = 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, iterables));
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.applymap */
+    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());
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.chain */
+    chain: function (p, q/*, ...*/) {
+        // dumb fast path
+        var self = MochiKit.Iter;
+        var m = MochiKit.Base;
+        if (arguments.length == 1) {
+            return self.iter(arguments[0]);
+        }
+        var argiter = m.map(self.iter, arguments);
+        return {
+            repr: function () { return "chain(...)"; },
+            toString: m.forwardCall("repr"),
+            next: function () {
+                while (argiter.length > 1) {
+                    try {
+                        return argiter[0].next();
+                    } catch (e) {
+                        if (e != self.StopIteration) {
+                            throw e;
+                        }
+                        argiter.shift();
+                    }
+                }
+                if (argiter.length == 1) {
+                    // optimize last element
+                    var arg = argiter.shift();
+                    this.next = m.bind("next", arg);
+                    return this.next();
+                }
+                throw self.StopIteration;
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.takewhile */
+    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;
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.dropwhile */
+    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 (ident, sync, iterable) {
+        sync.pos[ident] = -1;
+        var m = MochiKit.Base;
+        var listMin = m.listMin;
+        return {
+            repr: function () { return "tee(" + ident + ", ...)"; },
+            toString: m.forwardCall("repr"),
+            next: function () {
+                var rval;
+                var i = sync.pos[ident];
+
+                if (i == sync.max) {
+                    rval = iterable.next();
+                    sync.deque.push(rval);
+                    sync.max += 1;
+                    sync.pos[ident] += 1;
+                } else {
+                    rval = sync.deque[i - sync.min];
+                    sync.pos[ident] += 1;
+                    if (i == sync.min && listMin(sync.pos) != sync.min) {
+                        sync.min += 1;
+                        sync.deque.shift();
+                    }
+                }
+                return rval;
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.tee */
+    tee: function (iterable, n/* = 2 */) {
+        var rval = [];
+        var sync = {
+            "pos": [],
+            "deque": [],
+            "max": -1,
+            "min": -1
+        };
+        if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
+            n = 2;
+        }
+        var self = MochiKit.Iter;
+        iterable = self.iter(iterable);
+        var _tee = self._tee;
+        for (var i = 0; i < n; i++) {
+            rval.push(_tee(i, sync, iterable));
+        }
+        return rval;
+    },
+
+    /** @id MochiKit.Iter.list */
+    list: function (iterable) {
+        // Fast-path for Array and Array-like
+        var rval;
+        if (iterable instanceof Array) {
+            return iterable.slice();
+        } 
+        // this is necessary to avoid a Safari crash
+        if (typeof(iterable) == "function" &&
+                !(iterable instanceof Function) &&
+                typeof(iterable.length) == 'number') {
+            rval = [];
+            for (var i = 0; i < iterable.length; i++) {
+                rval.push(iterable[i]);
+            }
+            return rval;
+        }
+
+        var self = MochiKit.Iter;
+        iterable = self.iter(iterable);
+        var rval = [];
+        try {
+            while (true) {
+                rval.push(iterable.next());
+            }
+        } catch (e) {
+            if (e != self.StopIteration) {
+                throw e;
+            }
+            return rval;
+        }
+        // mozilla warnings aren't too bright
+        return undefined;
+    },
+
+
+    /** @id MochiKit.Iter.reduce */
+    reduce: function (fn, iterable, /* optional */initial) {
+        var i = 0;
+        var x = initial;
+        var self = MochiKit.Iter;
+        iterable = self.iter(iterable);
+        if (arguments.length < 3) {
+            try {
+                x = iterable.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, iterable.next());
+            }
+        } catch (e) {
+            if (e != self.StopIteration) {
+                throw e;
+            }
+        }
+        return x;
+    },
+
+    /** @id MochiKit.Iter.range */
+    range: function (/* [start,] stop[, step] */) {
+        var start = 0;
+        var stop = 0;
+        var step = 1;
+        if (arguments.length == 1) {
+            stop = arguments[0];
+        } else if (arguments.length == 2) {
+            start = arguments[0];
+            stop = arguments[1];
+        } else if (arguments.length == 3) {
+            start = 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 && start >= stop) || (step < 0 && start <= stop)) {
+                    throw MochiKit.Iter.StopIteration;
+                }
+                var rval = start;
+                start += step;
+                return rval;
+            },
+            repr: function () {
+                return "range(" + [start, stop, step].join(", ") + ")";
+            },
+            toString: MochiKit.Base.forwardCall("repr")
+        };
+    },
+
+    /** @id MochiKit.Iter.sum */
+    sum: function (iterable, start/* = 0 */) {
+        if (typeof(start) == "undefined" || start === null) {
+            start = 0;
+        }
+        var x = start;
+        var self = MochiKit.Iter;
+        iterable = self.iter(iterable);
+        try {
+            while (true) {
+                x += iterable.next();
+            }
+        } catch (e) {
+            if (e != self.StopIteration) {
+                throw e;
+            }
+        }
+        return x;
+    },
+
+    /** @id MochiKit.Iter.exhaust */
+    exhaust: function (iterable) {
+        var self = MochiKit.Iter;
+        iterable = self.iter(iterable);
+        try {
+            while (true) {
+                iterable.next();
+            }
+        } catch (e) {
+            if (e != self.StopIteration) {
+                throw e;
+            }
+        }
+    },
+
+    /** @id MochiKit.Iter.forEach */
+    forEach: function (iterable, func, /* optional */self) {
+        var m = MochiKit.Base;
+        if (arguments.length > 2) {
+            func = m.bind(func, self);
+        }
+        // fast path for array
+        if (m.isArrayLike(iterable)) {
+            try {
+                for (var i = 0; i < iterable.length; i++) {
+                    func(iterable[i]);
+                }
+            } catch (e) {
+                if (e != MochiKit.Iter.StopIteration) {
+                    throw e;
+                }
+            }
+        } else {
+            self = MochiKit.Iter;
+            self.exhaust(self.imap(func, iterable));
+        }
+    },
+
+    /** @id MochiKit.Iter.every */
+    every: function (iterable, func) {
+        var self = MochiKit.Iter;
+        try {
+            self.ifilterfalse(func, iterable).next();
+            return false;
+        } catch (e) {
+            if (e != self.StopIteration) {
+                throw e;
+            }
+            return true;
+        }
+    },
+
+    /** @id MochiKit.Iter.sorted */
+    sorted: function (iterable, /* optional */cmp) {
+        var rval = MochiKit.Iter.list(iterable);
+        if (arguments.length == 1) {
+            cmp = MochiKit.Base.compare;
+        }
+        rval.sort(cmp);
+        return rval;
+    },
+
+    /** @id MochiKit.Iter.reversed */
+    reversed: function (iterable) {
+        var rval = MochiKit.Iter.list(iterable);
+        rval.reverse();
+        return rval;
+    },
+
+    /** @id MochiKit.Iter.some */
+    some: function (iterable, func) {
+        var self = MochiKit.Iter;
+        try {
+            self.ifilter(func, iterable).next();
+            return true;
+        } catch (e) {
+            if (e != self.StopIteration) {
+                throw e;
+            }
+            return false;
+        }
+    },
+
+    /** @id MochiKit.Iter.iextend */
+    iextend: function (lst, iterable) {
+        if (MochiKit.Base.isArrayLike(iterable)) {
+            // fast-path for array-like
+            for (var i = 0; i < iterable.length; i++) {
+                lst.push(iterable[i]);
+            }
+        } else {
+            var self = MochiKit.Iter;
+            iterable = self.iter(iterable);
+            try {
+                while (true) {
+                    lst.push(iterable.next());
+                }
+            } catch (e) {
+                if (e != self.StopIteration) {
+                    throw e;
+                }
+            }
+        }
+        return lst;
+    },
+
+    /** @id MochiKit.Iter.groupby */
+    groupby: function(iterable, /* optional */ keyfunc) {
+        var m = MochiKit.Base;
+        var self = MochiKit.Iter;
+        if (arguments.length < 2) {
+            keyfunc = m.operator.identity;
+        }
+        iterable = self.iter(iterable);
+
+        // shared
+        var pk = undefined;
+        var k = undefined;
+        var v;
+
+        function fetch() {
+            v = iterable.next();
+            k = keyfunc(v);
+        };
+
+        function eat() {
+            var ret = v;
+            v = undefined;
+            return ret;
+        };
+
+        var first = true;
+        var compare = m.compare;
+        return {
+            repr: function () { return "groupby(...)"; },
+            next: function() {
+                // iterator-next
+
+                // iterate until meet next group
+                while (compare(k, pk) === 0) {
+                    fetch();
+                    if (first) {
+                        first = false;
+                        break;
+                    }
+                }
+                pk = k;
+                return [k, {
+                    next: function() {
+                        // subiterator-next
+                        if (v == undefined) { // Is there something to eat?
+                            fetch();
+                        }
+                        if (compare(k, pk) !== 0) {
+                            throw self.StopIteration;
+                        }
+                        return eat();
+                    }
+                }];
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.groupby_as_array */
+    groupby_as_array: function (iterable, /* optional */ keyfunc) {
+        var m = MochiKit.Base;
+        var self = MochiKit.Iter;
+        if (arguments.length < 2) {
+            keyfunc = m.operator.identity;
+        }
+
+        iterable = self.iter(iterable);
+        var result = [];
+        var first = true;
+        var prev_key;
+        var compare = m.compare;
+        while (true) {
+            try {
+                var value = iterable.next();
+                var key = keyfunc(value);
+            } catch (e) {
+                if (e == self.StopIteration) {
+                    break;
+                }
+                throw e;
+            }
+            if (first || compare(key, prev_key) !== 0) {
+                var values = [];
+                result.push([key, values]);
+            }
+            values.push(value);
+            first = false;
+            prev_key = key;
+        }
+        return result;
+    },
+
+    /** @id MochiKit.Iter.arrayLikeIter */
+    arrayLikeIter: function (iterable) {
+        var i = 0;
+        return {
+            repr: function () { return "arrayLikeIter(...)"; },
+            toString: MochiKit.Base.forwardCall("repr"),
+            next: function () {
+                if (i >= iterable.length) {
+                    throw MochiKit.Iter.StopIteration;
+                }
+                return iterable[i++];
+            }
+        };
+    },
+
+    /** @id MochiKit.Iter.hasIterateNext */
+    hasIterateNext: function (iterable) {
+        return (iterable && typeof(iterable.iterateNext) == "function");
+    },
+
+    /** @id MochiKit.Iter.iterateNextIter */
+    iterateNextIter: function (iterable) {
+        return {
+            repr: function () { return "iterateNextIter(...)"; },
+            toString: MochiKit.Base.forwardCall("repr"),
+            next: function () {
+                var rval = iterable.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;
+    // Re-use StopIteration if exists (e.g. SpiderMonkey)
+    if (typeof(StopIteration) != "undefined") {
+        this.StopIteration = StopIteration;
+    } else {
+        /** @id MochiKit.Iter.StopIteration */
+        this.StopIteration = new m.NamedError("StopIteration");
+    }
+    this.iteratorRegistry = new m.AdapterRegistry();
+    // Register the iterator factory for arrays
+    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__();
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+    reduce = MochiKit.Iter.reduce;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.Iter);
diff --git a/mochikit_v14/MochiKit/Logging.js b/mochikit_v14/MochiKit/Logging.js
new file mode 100644 (file)
index 0000000..4d25c3e
--- /dev/null
@@ -0,0 +1,321 @@
+/***
+
+MochiKit.Logging 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+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.4";
+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"
+];
+
+
+/** @id MochiKit.Logging.LogMessage */
+MochiKit.Logging.LogMessage = function (num, level, info) {
+    this.num = num;
+    this.level = level;
+    this.info = info;
+    this.timestamp = new Date();
+};
+
+MochiKit.Logging.LogMessage.prototype = {
+     /** @id MochiKit.Logging.LogMessage.prototype.repr */
+    repr: function () {
+        var m = MochiKit.Base;
+        return 'LogMessage(' +
+            m.map(
+                m.repr,
+                [this.num, this.level, this.info]
+            ).join(', ') + ')';
+    },
+    /** @id MochiKit.Logging.LogMessage.prototype.toString */
+    toString: MochiKit.Base.forwardCall("repr")
+};
+
+MochiKit.Base.update(MochiKit.Logging, {
+    /** @id MochiKit.Logging.logLevelAtLeast */
+    logLevelAtLeast: function (minLevel) {
+        var self = MochiKit.Logging;
+        if (typeof(minLevel) == 'string') {
+            minLevel = self.LogLevel[minLevel];
+        }
+        return function (msg) {
+            var msgLevel = msg.level;
+            if (typeof(msgLevel) == 'string') {
+                msgLevel = self.LogLevel[msgLevel];
+            }
+            return msgLevel >= minLevel;
+        };
+    },
+
+    /** @id MochiKit.Logging.isLogMessage */
+    isLogMessage: function (/* ... */) {
+        var LogMessage = MochiKit.Logging.LogMessage;
+        for (var i = 0; i < arguments.length; i++) {
+            if (!(arguments[i] instanceof LogMessage)) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    /** @id MochiKit.Logging.compareLogMessage */
+    compareLogMessage: function (a, b) {
+        return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
+    },
+
+    /** @id MochiKit.Logging.alertListener */
+    alertListener: function (msg) {
+        alert(
+            "num: " + msg.num +
+            "\nlevel: " +  msg.level +
+            "\ninfo: " + msg.info.join(" ")
+        );
+    }
+
+});
+
+/** @id MochiKit.Logging.Logger */
+MochiKit.Logging.Logger = function (/* optional */maxSize) {
+    this.counter = 0;
+    if (typeof(maxSize) == 'undefined' || maxSize === null) {
+        maxSize = -1;
+    }
+    this.maxSize = maxSize;
+    this._messages = [];
+    this.listeners = {};
+    this.useNativeConsole = false;
+};
+
+MochiKit.Logging.Logger.prototype = {
+    /** @id MochiKit.Logging.Logger.prototype.clear */
+    clear: function () {
+        this._messages.splice(0, this._messages.length);
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.logToConsole */
+    logToConsole: function (msg) {
+        if (typeof(window) != "undefined" && window.console
+                && window.console.log) {
+            // Safari and FireBug 0.4
+            // Percent replacement is a workaround for cute Safari crashing bug
+            window.console.log(msg.replace(/%/g, '\uFF05'));
+        } else if (typeof(opera) != "undefined" && opera.postError) {
+            // Opera
+            opera.postError(msg);
+        } else if (typeof(printfire) == "function") {
+            // FireBug 0.3 and earlier
+            printfire(msg);
+        } else if (typeof(Debug) != "undefined" && Debug.writeln) {
+            // IE Web Development Helper (?)
+            // http://www.nikhilk.net/Entry.aspx?id=93
+            Debug.writeln(msg);
+        } else if (typeof(debug) != "undefined" && debug.trace) {
+            // Atlas framework (?)
+            // http://www.nikhilk.net/Entry.aspx?id=93
+            debug.trace(msg);
+        }
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */
+    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);
+        }
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.addListener */
+    addListener: function (ident, filter, listener) {
+        if (typeof(filter) == 'string') {
+            filter = MochiKit.Logging.logLevelAtLeast(filter);
+        }
+        var entry = [filter, listener];
+        entry.ident = ident;
+        this.listeners[ident] = entry;
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.removeListener */
+    removeListener: function (ident) {
+        delete this.listeners[ident];
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.baseLog */
+    baseLog: function (level, message/*, ...*/) {
+        var msg = new MochiKit.Logging.LogMessage(
+            this.counter,
+            level,
+            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();
+        }
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.getMessages */
+    getMessages: function (howMany) {
+        var firstMsg = 0;
+        if (!(typeof(howMany) == 'undefined' || howMany === null)) {
+            firstMsg = Math.max(0, this._messages.length - howMany);
+        }
+        return this._messages.slice(firstMsg);
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.getMessageText */
+    getMessageText: function (howMany) {
+        if (typeof(howMany) == 'undefined' || howMany === null) {
+            howMany = 30;
+        }
+        var messages = this.getMessages(howMany);
+        if (messages.length) {
+            var lst = map(function (m) {
+                return '\n  [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
+            }, messages);
+            lst.unshift('LAST ' + messages.length + ' MESSAGES:');
+            return lst.join('');
+        }
+        return '';
+    },
+
+    /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */
+    debuggingBookmarklet: function (inline) {
+        if (typeof(MochiKit.LoggingPane) == "undefined") {
+            alert(this.getMessageText());
+        } else {
+            MochiKit.LoggingPane.createLoggingPane(inline || 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 partial = m.partial;
+
+    var Logger = this.Logger;
+    var baseLog = Logger.prototype.baseLog;
+    m.update(this.Logger.prototype, {
+        debug: partial(baseLog, 'DEBUG'),
+        log: partial(baseLog, 'INFO'),
+        error: partial(baseLog, 'ERROR'),
+        fatal: partial(baseLog, 'FATAL'),
+        warning: partial(baseLog, 'WARNING')
+    });
+
+    // indirectly find logger so it can be replaced
+    var self = this;
+    var connectLog = function (name) {
+        return function () {
+            self.logger[name].apply(self.logger, arguments);
+        };
+    };
+
+    /** @id MochiKit.Logging.log */
+    this.log = connectLog('log');
+    /** @id MochiKit.Logging.logError */
+    this.logError = connectLog('error');
+    /** @id MochiKit.Logging.logDebug */
+    this.logDebug = connectLog('debug');
+    /** @id MochiKit.Logging.logFatal */
+    this.logFatal = connectLog('fatal');
+    /** @id MochiKit.Logging.logWarning */
+    this.logWarning = connectLog('warning');
+    this.logger = new Logger();
+    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") {
+    // FireBug really should be less lame about this global function
+    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);
diff --git a/mochikit_v14/MochiKit/LoggingPane.js b/mochikit_v14/MochiKit/LoggingPane.js
new file mode 100644 (file)
index 0000000..3798ae4
--- /dev/null
@@ -0,0 +1,374 @@
+/***
+
+MochiKit.LoggingPane 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+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.4";
+MochiKit.LoggingPane.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.LoggingPane.toString = function () {
+    return this.__repr__();
+};
+
+/** @id MochiKit.LoggingPane.createLoggingPane */
+MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
+    var m = MochiKit.LoggingPane;
+    inline = !(!inline);
+    if (m._loggingPane && m._loggingPane.inline != inline) {
+        m._loggingPane.closePane();
+        m._loggingPane = null;
+    }
+    if (!m._loggingPane || m._loggingPane.closed) {
+        m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
+    }
+    return m._loggingPane;
+};
+
+/** @id MochiKit.LoggingPane.LoggingPane */
+MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
+
+    /* Use a div if inline, pop up a window if not */
+    /* Create the elements */
+    if (typeof(logger) == "undefined" || logger === null) {
+        logger = MochiKit.Logging.logger;
+    }
+    this.logger = logger;
+    var update = MochiKit.Base.update;
+    var updatetree = MochiKit.Base.updatetree;
+    var bind = MochiKit.Base.bind;
+    var clone = MochiKit.Base.clone;
+    var win = window;
+    var uid = "_MochiKit_LoggingPane";
+    if (typeof(MochiKit.DOM) != "undefined") {
+        win = MochiKit.DOM.currentWindow();
+    }
+    if (!inline) {
+        // name the popup with the base URL for uniqueness
+        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;
+
+    // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
+    var debugPane = doc.getElementById(uid);
+    var existing_pane = !!debugPane;
+    if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
+        debugPane.loggingPane.logger = this.logger;
+        debugPane.loggingPane.buildAndApplyFilter();
+        return debugPane.loggingPane;
+    }
+
+    if (existing_pane) {
+        // clear any existing contents
+        var child;
+        while ((child = debugPane.firstChild)) {
+            debugPane.removeChild(child);
+        }
+    } else {
+        debugPane = doc.createElement("div");
+        debugPane.id = uid;
+    }
+    debugPane.loggingPane = this;
+    var levelFilterField = doc.createElement("input");
+    var infoFilterField = doc.createElement("input");
+    var filterButton = doc.createElement("button");
+    var loadButton = doc.createElement("button");
+    var clearButton = doc.createElement("button");
+    var closeButton = doc.createElement("button");
+    var logPaneArea = doc.createElement("div");
+    var logPane = doc.createElement("div");
+
+    /* Set up the functions */
+    var listenerId = uid + "_Listener";
+    this.colorTable = clone(this.colorTable);
+    var messages = [];
+    var messageFilter = null;
+
+    /** @id MochiKit.LoggingPane.messageLevel */
+    var messageLevel = function (msg) {
+        var level = msg.level;
+        if (typeof(level) == "number") {
+            level = MochiKit.Logging.LogLevel[level];
+        }
+        return level;
+    };
+
+    /** @id MochiKit.LoggingPane.messageText */
+    var messageText = function (msg) {
+        return msg.info.join(" ");
+    };
+
+    /** @id MochiKit.LoggingPane.addMessageText */
+    var addMessageText = bind(function (msg) {
+        var level = messageLevel(msg);
+        var text = messageText(msg);
+        var c = this.colorTable[level];
+        var p = doc.createElement("span");
+        p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
+        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(level + ": " + text));
+        logPane.appendChild(p);
+        logPane.appendChild(doc.createElement("br"));
+        if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
+            logPaneArea.scrollTop = 0;
+        } else {
+            logPaneArea.scrollTop = logPaneArea.scrollHeight;
+        }
+    }, this);
+
+    /** @id MochiKit.LoggingPane.addMessage */
+    var addMessage = function (msg) {
+        messages[messages.length] = msg;
+        addMessageText(msg);
+    };
+
+    /** @id MochiKit.LoggingPane.buildMessageFilter */
+    var buildMessageFilter = function () {
+        var levelre, infore;
+        try {
+            /* Catch any exceptions that might arise due to invalid regexes */
+            levelre = new RegExp(levelFilterField.value);
+            infore = new RegExp(infoFilterField.value);
+        } catch(e) {
+            /* If there was an error with the regexes, do no filtering */
+            logDebug("Error in filter regex: " + e.message);
+            return null;
+        }
+
+        return function (msg) {
+            return (
+                levelre.test(messageLevel(msg)) &&
+                infore.test(messageText(msg))
+            );
+        };
+    };
+
+    /** @id MochiKit.LoggingPane.clearMessagePane */
+    var clearMessagePane = function () {
+        while (logPane.firstChild) {
+            logPane.removeChild(logPane.firstChild);
+        }
+    };
+
+    /** @id MochiKit.LoggingPane.clearMessages */
+    var clearMessages = function () {
+        messages = [];
+        clearMessagePane();
+    };
+
+    /** @id MochiKit.LoggingPane.closePane */
+    var closePane = bind(function () {
+        if (this.closed) {
+            return;
+        }
+        this.closed = true;
+        if (MochiKit.LoggingPane._loggingPane == this) {
+            MochiKit.LoggingPane._loggingPane = null;
+        }
+        this.logger.removeListener(listenerId);
+        try {
+            try {
+              debugPane.loggingPane = null;
+            } catch(e) { logFatal("Bookmarklet was closed incorrectly."); }
+            if (inline) {
+                debugPane.parentNode.removeChild(debugPane);
+            } else {
+                this.win.close();
+            }
+        } catch(e) {}
+    }, this);
+
+    /** @id MochiKit.LoggingPane.filterMessages */
+    var filterMessages = function () {
+        clearMessagePane();
+
+        for (var i = 0; i < messages.length; i++) {
+            var msg = messages[i];
+            if (messageFilter === null || messageFilter(msg)) {
+                addMessageText(msg);
+            }
+        }
+    };
+
+    this.buildAndApplyFilter = function () {
+        messageFilter = buildMessageFilter();
+
+        filterMessages();
+
+        this.logger.removeListener(listenerId);
+        this.logger.addListener(listenerId, messageFilter, addMessage);
+    };
+
+
+    /** @id MochiKit.LoggingPane.loadMessages */
+    var loadMessages = bind(function () {
+        messages = this.logger.getMessages();
+        filterMessages();
+    }, this);
+
+    /** @id MochiKit.LoggingPane.filterOnEnter */
+    var filterOnEnter = bind(function (event) {
+        event = event || window.event;
+        key = event.which || event.keyCode;
+        if (key == 13) {
+            this.buildAndApplyFilter();
+        }
+    }, this);
+
+    /* Create the debug pane */
+    var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
+    if (inline) {
+        style += "; height: 10em; border-top: 2px solid black";
+    } else {
+        style += "; height: 100%;";
+    }
+    debugPane.style.cssText = style;
+
+    if (!existing_pane) {
+        doc.body.appendChild(debugPane);
+    }
+
+    /* Create the filter fields */
+    style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
+
+    updatetree(levelFilterField, {
+        "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
+        "onkeypress": filterOnEnter,
+        "style": style
+    });
+    debugPane.appendChild(levelFilterField);
+
+    updatetree(infoFilterField, {
+        "value": ".*",
+        "onkeypress": filterOnEnter,
+        "style": style
+    });
+    debugPane.appendChild(infoFilterField);
+
+    /* Create the buttons */
+    style = "width: 8%; display:inline; font: " + this.logFont;
+
+    filterButton.appendChild(doc.createTextNode("Filter"));
+    filterButton.onclick = bind("buildAndApplyFilter", this);
+    filterButton.style.cssText = style;
+    debugPane.appendChild(filterButton);
+
+    loadButton.appendChild(doc.createTextNode("Load"));
+    loadButton.onclick = loadMessages;
+    loadButton.style.cssText = style;
+    debugPane.appendChild(loadButton);
+
+    clearButton.appendChild(doc.createTextNode("Clear"));
+    clearButton.onclick = clearMessages;
+    clearButton.style.cssText = style;
+    debugPane.appendChild(clearButton);
+
+    closeButton.appendChild(doc.createTextNode("Close"));
+    closeButton.onclick = closePane;
+    closeButton.style.cssText = style;
+    debugPane.appendChild(closeButton);
+
+    /* Create the logging pane */
+    logPaneArea.style.cssText = "overflow: auto; width: 100%";
+    logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
+
+    logPaneArea.appendChild(logPane);
+    debugPane.appendChild(logPaneArea);
+
+    this.buildAndApplyFilter();
+    loadMessages();
+
+    if (inline) {
+        this.win = undefined;
+    } else {
+        this.win = win;
+    }
+    this.inline = inline;
+    this.closePane = closePane;
+    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);
diff --git a/mochikit_v14/MochiKit/MochiKit.js b/mochikit_v14/MochiKit/MochiKit.js
new file mode 100644 (file)
index 0000000..3a13b24
--- /dev/null
@@ -0,0 +1,154 @@
+/***
+
+MochiKit.MochiKit 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+if (typeof(MochiKit) == 'undefined') {
+    MochiKit = {};
+}
+
+if (typeof(MochiKit.MochiKit) == 'undefined') {
+    /** @id MochiKit.MochiKit */
+    MochiKit.MochiKit = {};
+}
+
+MochiKit.MochiKit.NAME = "MochiKit.MochiKit";
+MochiKit.MochiKit.VERSION = "1.4";
+MochiKit.MochiKit.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+/** @id MochiKit.MochiKit.toString */
+MochiKit.MochiKit.toString = function () {
+    return this.__repr__();
+};
+
+/** @id MochiKit.MochiKit.SUBMODULES */
+MochiKit.MochiKit.SUBMODULES = [
+    "Base",
+    "Iter",
+    "Logging",
+    "DateTime",
+    "Format",
+    "Async",
+    "DOM",
+    "Selector",
+    "Style",
+    "LoggingPane",
+    "Color",
+    "Signal",
+    "Position",
+    "Visual"
+];
+
+if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') {
+    if (typeof(dojo) != 'undefined') {
+        dojo.provide('MochiKit.MochiKit');
+        dojo.require("MochiKit.*");
+    }
+    if (typeof(JSAN) != 'undefined') {
+        (function (lst) {
+            for (var i = 0; i < lst.length; i++) {
+                JSAN.use("MochiKit." + lst[i], []);
+            }
+        })(MochiKit.MochiKit.SUBMODULES);
+    }
+    (function () {
+        var extend = MochiKit.Base.extend;
+        var self = MochiKit.MochiKit;
+        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 = MochiKit[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(MochiKit.__compat__) == 'undefined') {
+        MochiKit.__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(/MochiKit.js$/)) {
+                base = src.substring(0, src.lastIndexOf('MochiKit.js'));
+                baseElem = scripts[i];
+            }
+        }
+        if (base === null) {
+            return;
+        }
+        var modules = MochiKit.MochiKit.SUBMODULES;
+        for (var i = 0; i < modules.length; i++) {
+            if (MochiKit[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", "MochiKit_" + 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>');
+            }
+        };
+    })();
+}
diff --git a/mochikit_v14/MochiKit/MockDOM.js b/mochikit_v14/MochiKit/MockDOM.js
new file mode 100644 (file)
index 0000000..92558cb
--- /dev/null
@@ -0,0 +1,115 @@
+/***
+
+MochiKit.MockDOM 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+if (typeof(MochiKit) == "undefined") {
+    MochiKit = {};
+}
+
+if (typeof(MochiKit.MockDOM) == "undefined") {
+    MochiKit.MockDOM = {};
+}
+
+MochiKit.MockDOM.NAME = "MochiKit.MockDOM";
+MochiKit.MockDOM.VERSION = "1.4";
+
+MochiKit.MockDOM.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+/** @id MochiKit.MockDOM.toString */
+MochiKit.MockDOM.toString = function () {
+    return this.__repr__();
+};
+
+/** @id MochiKit.MockDOM.createDocument */
+MochiKit.MockDOM.createDocument = function () {
+    var doc = new MochiKit.MockDOM.MockElement("DOCUMENT");
+    doc.body = doc.createElement("BODY");
+    doc.appendChild(doc.body);
+    return doc;
+};
+
+/** @id MochiKit.MockDOM.MockElement */
+MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) {
+    this.tagName = this.nodeName = name.toUpperCase();
+    this.ownerDocument = ownerDocument || null;
+    if (name == "DOCUMENT") {
+        this.nodeType = 9;
+        this.childNodes = [];
+    } else if (typeof(data) == "string") {
+        this.nodeValue = data;
+        this.nodeType = 3;
+    } else {
+        this.nodeType = 1;
+        this.childNodes = [];
+    }
+    if (name.substring(0, 1) == "<") {
+        var nameattr = name.substring(
+            name.indexOf('"') + 1, name.lastIndexOf('"'));
+        name = name.substring(1, name.indexOf(" "));
+        this.tagName = this.nodeName = name.toUpperCase();
+        this.setAttribute("name", nameattr);
+    }
+};
+
+MochiKit.MockDOM.MockElement.prototype = {
+    /** @id MochiKit.MockDOM.MockElement.prototype.createElement */
+    createElement: function (tagName) {
+        return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument);
+    },
+    /** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */
+    createTextNode: function (text) {
+        return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument);
+    },
+    /** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */
+    setAttribute: function (name, value) {
+        this[name] = value;
+    },
+    /** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */
+    getAttribute: function (name) {
+        return this[name];
+    },
+    /** @id MochiKit.MockDOM.MockElement.prototype.appendChild */
+    appendChild: function (child) {
+        this.childNodes.push(child);
+    },
+    /** @id MochiKit.MockDOM.MockElement.prototype.toString */
+    toString: function () {
+        return "MockElement(" + this.tagName + ")";
+    },
+    /** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */
+    getElementsByTagName: function (tagName) {
+        var foundElements = [];
+        MochiKit.Base.nodeWalk(this, function(node){
+            if (tagName == '*' || tagName == node.tagName) {
+                foundElements.push(node);
+                return node.childNodes;
+            }
+        });
+        return foundElements;
+    }
+};
+
+    /** @id MochiKit.MockDOM.EXPORT_OK */
+MochiKit.MockDOM.EXPORT_OK = [
+    "mockElement",
+    "createDocument"
+];
+
+    /** @id MochiKit.MockDOM.EXPORT */
+MochiKit.MockDOM.EXPORT = [
+    "document"
+];
+
+MochiKit.MockDOM.__new__ = function () {
+    this.document = this.createDocument();
+};
+
+MochiKit.MockDOM.__new__();
diff --git a/mochikit_v14/MochiKit/Position.js b/mochikit_v14/MochiKit/Position.js
new file mode 100644 (file)
index 0000000..23b0f18
--- /dev/null
@@ -0,0 +1,258 @@
+/***
+
+MochiKit.Position 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005-2006 Bob Ippolito and others.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Position');
+    dojo.require('MochiKit.Base');
+    dojo.require('MochiKit.DOM');
+    dojo.require('MochiKit.Style');
+}
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use('MochiKit.Base', []);
+    JSAN.use('MochiKit.DOM', []);
+    JSAN.use('MochiKit.Style', []);
+}
+
+try {
+    if (typeof(MochiKit.Base) == 'undefined' ||
+        typeof(MochiKit.Style) == 'undefined' ||
+        typeof(MochiKit.DOM) == 'undefined') {
+        throw '';
+    }
+} catch (e) {
+    throw 'MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!';
+}
+
+if (typeof(MochiKit.Position) == 'undefined') {
+    MochiKit.Position = {};
+}
+
+MochiKit.Position.NAME = 'MochiKit.Position';
+MochiKit.Position.VERSION = '1.4';
+MochiKit.Position.__repr__ = function () {
+    return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+MochiKit.Position.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.Position.EXPORT_OK = [];
+
+MochiKit.Position.EXPORT = [
+];
+
+
+MochiKit.Base.update(MochiKit.Position, {
+    // set to true if needed, warning: firefox performance problems
+    // NOT neeeded for page scrolling, only if draggable contained in
+    // scrollable elements
+    includeScrollOffsets: false,
+
+    /** @id MochiKit.Position.prepare */
+    prepare: function () {
+        var deltaX =  window.pageXOffset
+                   || document.documentElement.scrollLeft
+                   || document.body.scrollLeft
+                   || 0;
+        var deltaY =  window.pageYOffset
+                   || document.documentElement.scrollTop
+                   || document.body.scrollTop
+                   || 0;
+        this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
+    },
+
+    /** @id MochiKit.Position.cumulativeOffset */
+    cumulativeOffset: function (element) {
+        var valueT = 0;
+        var valueL = 0;
+        do {
+            valueT += element.offsetTop  || 0;
+            valueL += element.offsetLeft || 0;
+            element = element.offsetParent;
+        } while (element);
+        return new MochiKit.Style.Coordinates(valueL, valueT);
+    },
+
+    /** @id MochiKit.Position.realOffset */
+    realOffset: function (element) {
+        var valueT = 0;
+        var valueL = 0;
+        do {
+            valueT += element.scrollTop  || 0;
+            valueL += element.scrollLeft || 0;
+            element = element.parentNode;
+        } while (element);
+        return new MochiKit.Style.Coordinates(valueL, valueT);
+    },
+
+    /** @id MochiKit.Position.within */
+    within: function (element, x, y) {
+        if (this.includeScrollOffsets) {
+            return this.withinIncludingScrolloffsets(element, x, y);
+        }
+        this.xcomp = x;
+        this.ycomp = y;
+        this.offset = this.cumulativeOffset(element);
+        if (element.style.position == "fixed") {
+            this.offset.x += this.windowOffset.x;
+            this.offset.y += this.windowOffset.y;
+        }
+
+        return (y >= this.offset.y &&
+                y <  this.offset.y + element.offsetHeight &&
+                x >= this.offset.x &&
+                x <  this.offset.x + element.offsetWidth);
+    },
+
+    /** @id MochiKit.Position.withinIncludingScrolloffsets */
+    withinIncludingScrolloffsets: function (element, x, y) {
+        var offsetcache = this.realOffset(element);
+
+        this.xcomp = x + offsetcache.x - this.windowOffset.x;
+        this.ycomp = y + offsetcache.y - this.windowOffset.y;
+        this.offset = this.cumulativeOffset(element);
+
+        return (this.ycomp >= this.offset.y &&
+                this.ycomp <  this.offset.y + element.offsetHeight &&
+                this.xcomp >= this.offset.x &&
+                this.xcomp <  this.offset.x + element.offsetWidth);
+    },
+
+    // within must be called directly before
+    /** @id MochiKit.Position.overlap */
+    overlap: function (mode, element) {
+        if (!mode) {
+            return 0;
+        }
+        if (mode == 'vertical') {
+          return ((this.offset.y + element.offsetHeight) - this.ycomp) /
+                 element.offsetHeight;
+        }
+        if (mode == 'horizontal') {
+          return ((this.offset.x + element.offsetWidth) - this.xcomp) /
+                 element.offsetWidth;
+        }
+    },
+
+    /** @id MochiKit.Position.absolutize */
+    absolutize: function (element) {
+        element = MochiKit.DOM.getElement(element);
+        if (element.style.position == 'absolute') {
+            return;
+        }
+        MochiKit.Position.prepare();
+
+        var offsets = MochiKit.Position.positionedOffset(element);
+        var width = element.clientWidth;
+        var height = element.clientHeight;
+
+        var oldStyle = {
+            'position': element.style.position,
+            'left': offsets.x - parseFloat(element.style.left  || 0),
+            'top': offsets.y - parseFloat(element.style.top || 0),
+            'width': element.style.width,
+            'height': element.style.height
+        };
+
+        element.style.position = 'absolute';
+        element.style.top = offsets.y + 'px';
+        element.style.left = offsets.x + 'px';
+        element.style.width = width + 'px';
+        element.style.height = height + 'px';
+
+        return oldStyle;
+    },
+
+    /** @id MochiKit.Position.positionedOffset */
+    positionedOffset: function (element) {
+        var valueT = 0, valueL = 0;
+        do {
+            valueT += element.offsetTop  || 0;
+            valueL += element.offsetLeft || 0;
+            element = element.offsetParent;
+            if (element) {
+                p = MochiKit.Style.getStyle(element, 'position');
+                if (p == 'relative' || p == 'absolute') {
+                    break;
+                }
+            }
+        } while (element);
+        return new MochiKit.Style.Coordinates(valueL, valueT);
+    },
+
+    /** @id MochiKit.Position.relativize */
+    relativize: function (element, oldPos) {
+        element = MochiKit.DOM.getElement(element);
+        if (element.style.position == 'relative') {
+            return;
+        }
+        MochiKit.Position.prepare();
+
+        var top = parseFloat(element.style.top || 0) -
+                  (oldPos['top'] || 0);
+        var left = parseFloat(element.style.left || 0) -
+                   (oldPos['left'] || 0);
+
+        element.style.position = oldPos['position'];
+        element.style.top = top + 'px';
+        element.style.left = left + 'px';
+        element.style.width = oldPos['width'];
+        element.style.height = oldPos['height'];
+    },
+
+    /** @id MochiKit.Position.clone */
+    clone: function (source, target) {
+        source = MochiKit.DOM.getElement(source);
+        target = MochiKit.DOM.getElement(target);
+        target.style.position = 'absolute';
+        var offsets = this.cumulativeOffset(source);
+        target.style.top = offsets.y + 'px';
+        target.style.left = offsets.x + 'px';
+        target.style.width = source.offsetWidth + 'px';
+        target.style.height = source.offsetHeight + 'px';
+    },
+
+    /** @id MochiKit.Position.page */
+    page: function (forElement) {
+        var valueT = 0;
+        var valueL = 0;
+
+        var element = forElement;
+        do {
+            valueT += element.offsetTop  || 0;
+            valueL += element.offsetLeft || 0;
+
+            // Safari fix
+            if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
+                break;
+            }
+        } while (element = element.offsetParent);
+
+        element = forElement;
+        do {
+            valueT -= element.scrollTop  || 0;
+            valueL -= element.scrollLeft || 0;
+        } while (element = element.parentNode);
+
+        return new MochiKit.Style.Coordinates(valueL, valueT);
+    }
+});
+
+MochiKit.Position.__new__ = function (win) {
+    var m = MochiKit.Base;
+    this.EXPORT_TAGS = {
+        ':common': this.EXPORT,
+        ':all': m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+
+    m.nameFunctions(this);
+};
+
+MochiKit.Position.__new__(this);
\ No newline at end of file
diff --git a/mochikit_v14/MochiKit/Selector.js b/mochikit_v14/MochiKit/Selector.js
new file mode 100644 (file)
index 0000000..f5d1afa
--- /dev/null
@@ -0,0 +1,431 @@
+/***
+
+MochiKit.Selector 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito and others.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Selector');
+    dojo.require('MochiKit.Base');
+    dojo.require('MochiKit.DOM');
+    dojo.require('MochiKit.Iter');
+}
+
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use("MochiKit.Base", []);
+    JSAN.use("MochiKit.DOM", []);
+    JSAN.use("MochiKit.Iter", []);
+}
+
+try {
+    if (typeof(MochiKit.Base) === 'undefined' ||
+        typeof(MochiKit.DOM) === 'undefined' ||
+        typeof(MochiKit.Iter) === 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.Selector depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
+}
+
+if (typeof(MochiKit.Selector) == 'undefined') {
+    MochiKit.Selector = {};
+}
+
+MochiKit.Selector.NAME = "MochiKit.Selector";
+
+MochiKit.Selector.VERSION = "1.4";
+
+MochiKit.Selector.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Selector.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.Selector.EXPORT = [
+    "Selector",
+    "findChildElements",
+    "findDocElements",
+    "$$"
+];
+
+MochiKit.Selector.EXPORT_OK = [
+];
+
+MochiKit.Selector.Selector = function (expression) {
+    this.params = {classNames: [], pseudoClassNames: []};
+    this.expression = expression.toString().replace(/(^\s+|\s+$)/g, '');
+    this.parseExpression();
+    this.compileMatcher();
+};
+
+MochiKit.Selector.Selector.prototype = {
+    /***
+
+    Selector class: convenient object to make CSS selections.
+
+    ***/
+    __class__: MochiKit.Selector.Selector,
+
+    /** @id MochiKit.Selector.Selector.prototype.parseExpression */
+    parseExpression: function () {
+        function abort(message) {
+            throw 'Parse error in selector: ' + message;
+        }
+
+        if (this.expression == '')  {
+            abort('empty expression');
+        }
+
+        var repr = MochiKit.Base.repr;
+        var params = this.params;
+        var expr = this.expression;
+        var match, modifier, clause, rest;
+        while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
+            params.attributes = params.attributes || [];
+            params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
+            expr = match[1];
+        }
+
+        if (expr == '*') {
+            return this.params.wildcard = true;
+        }
+
+        while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) {
+            modifier = match[1];
+            clause = match[2];
+            rest = match[3];
+            switch (modifier) {
+                case '#':
+                    params.id = clause;
+                    break;
+                case '.':
+                    params.classNames.push(clause);
+                    break;
+                case ':':
+                    params.pseudoClassNames.push(clause);
+                    break;
+                case '':
+                case undefined:
+                    params.tagName = clause.toUpperCase();
+                    break;
+                default:
+                    abort(repr(expr));
+            }
+            expr = rest;
+        }
+
+        if (expr.length > 0) {
+            abort(repr(expr));
+        }
+    },
+
+    /** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */
+    buildMatchExpression: function () {
+        var repr = MochiKit.Base.repr;
+        var params = this.params;
+        var conditions = [];
+        var clause, i;
+
+        function childElements(element) {
+            return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)";
+        }
+
+        if (params.wildcard) {
+            conditions.push('true');
+        }
+        if (clause = params.id) {
+            conditions.push('element.id == ' + repr(clause));
+        }
+        if (clause = params.tagName) {
+            conditions.push('element.tagName.toUpperCase() == ' + repr(clause));
+        }
+        if ((clause = params.classNames).length > 0) {
+            for (i = 0; i < clause.length; i++) {
+                conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')');
+            }
+        }
+        if ((clause = params.pseudoClassNames).length > 0) {
+            for (i = 0; i < clause.length; i++) {
+                var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/);
+                var pseudoClass = match[1];
+                var pseudoClassArgument = match[2];
+                switch (pseudoClass) {
+                    case 'root':
+                        conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break;
+                    case 'nth-child':
+                    case 'nth-last-child':
+                    case 'nth-of-type':
+                    case 'nth-last-of-type':
+                        match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
+                        if (!match) {
+                            throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument;
+                        }
+                        var a, b;
+                        if (match[0] == 'odd') {
+                            a = 2;
+                            b = 1;
+                        } else if (match[0] == 'even') {
+                            a = 2;
+                            b = 0;
+                        } else {
+                            a = match[2] && parseInt(match) || null;
+                            b = parseInt(match[3]);
+                        }
+                        conditions.push('this.nthChild(element,' + a + ',' + b
+                                        + ',' + !!pseudoClass.match('^nth-last')    // Reverse
+                                        + ',' + !!pseudoClass.match('of-type$')     // Restrict to same tagName
+                                        + ')');
+                        break;
+                    case 'first-child':
+                        conditions.push('this.nthChild(element, null, 1)');
+                        break;
+                    case 'last-child':
+                        conditions.push('this.nthChild(element, null, 1, true)');
+                        break;
+                    case 'first-of-type':
+                        conditions.push('this.nthChild(element, null, 1, false, true)');
+                        break;
+                    case 'last-of-type':
+                        conditions.push('this.nthChild(element, null, 1, true, true)');
+                        break;
+                    case 'only-child':
+                        conditions.push(childElements('element.parentNode') + '.length == 1');
+                        break;
+                    case 'only-of-type':
+                        conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1');
+                        break;
+                    case 'empty':
+                        conditions.push('element.childNodes.length == 0');
+                        break;
+                    case 'enabled':
+                        conditions.push('(this.isUIElement(element) && element.disabled === false)');
+                        break;
+                    case 'disabled':
+                        conditions.push('(this.isUIElement(element) && element.disabled === true)');
+                        break;
+                    case 'checked':
+                        conditions.push('(this.isUIElement(element) && element.checked === true)');
+                        break;
+                    case 'not':
+                        var subselector = new MochiKit.Selector.Selector(pseudoClassArgument);
+                        conditions.push('!( ' + subselector.buildMatchExpression() + ')')
+                        break;
+                }
+            }
+        }
+        if (clause = params.attributes) {
+            MochiKit.Base.map(function (attribute) {
+                var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')';
+                var splitValueBy = function (delimiter) {
+                    return value + '.split(' + repr(delimiter) + ')';
+                }
+
+                switch (attribute.operator) {
+                    case '=':
+                        conditions.push(value + ' == ' + repr(attribute.value));
+                        break;
+                    case '~=':
+                        conditions.push(value + ' && MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1');
+                        break;
+                    case '^=':
+                        conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value));
+                        break;
+                    case '$=':
+                        conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value));
+                        break;
+                    case '*=':
+                        conditions.push(value + '.match(' + repr(attribute.value) + ')');
+                        break;
+                    case '|=':
+                        conditions.push(
+                            value + ' && ' + splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase())
+                        );
+                        break;
+                    case '!=':
+                        conditions.push(value + ' != ' + repr(attribute.value));
+                        break;
+                    case '':
+                    case undefined:
+                        conditions.push(value + ' != null');
+                        break;
+                    default:
+                        throw 'Unknown operator ' + attribute.operator + ' in selector';
+                }
+            }, clause);
+        }
+
+        return conditions.join(' && ');
+    },
+
+    /** @id MochiKit.Selector.Selector.prototype.compileMatcher */
+    compileMatcher: function () {
+        this.match = new Function('element', 'if (!element.tagName) return false; \
+                return ' + this.buildMatchExpression());
+    },
+
+    /** @id MochiKit.Selector.Selector.prototype.nthChild */
+    nthChild: function (element, a, b, reverse, sametag){
+        var siblings = MochiKit.Base.filter(function (node) {
+            return node.nodeType == 1;
+        }, element.parentNode.childNodes);
+        if (sametag) {
+            siblings = MochiKit.Base.filter(function (node) {
+                return node.tagName == element.tagName;
+            }, siblings);
+        }
+        if (reverse) {
+            siblings = MochiKit.Iter.reversed(siblings);
+        }
+        if (a) {
+            var actualIndex = MochiKit.Base.findIdentical(siblings, element);
+            return ((actualIndex + 1 - b) / a) % 1 == 0;
+        } else {
+            return b == MochiKit.Base.findIdentical(siblings, element) + 1;
+        }
+    },
+
+    /** @id MochiKit.Selector.Selector.prototype.isUIElement */
+    isUIElement: function (element) {
+        return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'],
+                element.tagName.toLowerCase()) > -1;
+    },
+
+    /** @id MochiKit.Selector.Selector.prototype.findElements */
+    findElements: function (scope, axis) {
+        var element;
+
+        if (axis == undefined) {
+            axis = "";
+        }
+
+        function inScope(element, scope) {
+            if (axis == "") {
+                return MochiKit.DOM.isChildNode(element, scope);
+            } else if (axis == ">") {
+                return element.parentNode == scope;
+            } else if (axis == "+") {
+                return element == nextSiblingElement(scope);
+            } else if (axis == "~") {
+                var sibling = scope;
+                while (sibling = nextSiblingElement(sibling)) {
+                    if (element == sibling) {
+                        return true;
+                    }
+                }
+                return false;
+            } else {
+                throw "Invalid axis: " + axis;
+            }
+        }
+
+        if (element = MochiKit.DOM.getElement(this.params.id)) {
+            if (this.match(element)) {
+                if (!scope || inScope(element, scope)) {
+                    return [element];
+                }
+            }
+        }
+
+        function nextSiblingElement(node) {
+            node = node.nextSibling;
+            while (node && node.nodeType != 1) {
+                node = node.nextSibling;
+            }
+            return node;
+        }
+
+        if (axis == "") {
+            scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*');
+        } else if (axis == ">") {
+            if (!scope) {
+                throw "> combinator not allowed without preceeding expression";
+            }
+            scope = MochiKit.Base.filter(function (node) {
+                return node.nodeType == 1;
+            }, scope.childNodes);
+        } else if (axis == "+") {
+            if (!scope) {
+                throw "+ combinator not allowed without preceeding expression";
+            }
+            scope = nextSiblingElement(scope) && [nextSiblingElement(scope)];
+        } else if (axis == "~") {
+            if (!scope) {
+                throw "~ combinator not allowed without preceeding expression";
+            }
+            var newscope = [];
+            while (nextSiblingElement(scope)) {
+                scope = nextSiblingElement(scope);
+                newscope.push(scope);
+            }
+            scope = newscope;
+        }
+
+        if (!scope) {
+            return [];
+        }
+
+        var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) {
+            return this.match(scopeElt);
+        }, this), scope);
+
+        return results;
+    },
+
+    /** @id MochiKit.Selector.Selector.prototype.repr */
+    repr: function () {
+        return 'Selector(' + this.expression + ')';
+    },
+
+    toString: MochiKit.Base.forwardCall("repr")
+};
+
+MochiKit.Base.update(MochiKit.Selector, {
+
+    /** @id MochiKit.Selector.findChildElements */
+    findChildElements: function (element, expressions) {
+        return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) {
+            var nextScope = "";
+            return MochiKit.Iter.reduce(function (results, expr) {
+                if (match = expr.match(/^[>+~]$/)) {
+                    nextScope = match[0];
+                    return results;
+                } else {
+                    var selector = new MochiKit.Selector.Selector(expr);
+                    var elements = MochiKit.Iter.reduce(function (elements, result) {
+                        return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope));
+                    }, results, []);
+                    nextScope = "";
+                    return elements;
+                }
+            }, expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/), [null]);
+        }, expressions));
+    },
+
+    findDocElements: function () {
+        return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments);
+    },
+
+    __new__: function () {
+        var m = MochiKit.Base;
+
+        this.$$ = this.findDocElements;
+
+        this.EXPORT_TAGS = {
+            ":common": this.EXPORT,
+            ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+        };
+
+        m.nameFunctions(this);
+    }
+});
+
+MochiKit.Selector.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Selector);
+
diff --git a/mochikit_v14/MochiKit/Signal.js b/mochikit_v14/MochiKit/Signal.js
new file mode 100644 (file)
index 0000000..7293841
--- /dev/null
@@ -0,0 +1,898 @@
+/***
+
+MochiKit.Signal 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Signal');
+    dojo.require('MochiKit.Base');
+    dojo.require('MochiKit.DOM');
+    dojo.require('MochiKit.Style');
+}
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use('MochiKit.Base', []);
+    JSAN.use('MochiKit.DOM', []);
+    JSAN.use('MochiKit.Style', []);
+}
+
+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!';
+}
+
+try {
+    if (typeof(MochiKit.Style) == 'undefined') {
+        throw '';
+    }
+} catch (e) {
+    throw 'MochiKit.Signal depends on MochiKit.Style!';
+}
+
+if (typeof(MochiKit.Signal) == 'undefined') {
+    MochiKit.Signal = {};
+}
+
+MochiKit.Signal.NAME = 'MochiKit.Signal';
+MochiKit.Signal.VERSION = '1.4';
+
+MochiKit.Signal._observers = [];
+
+/** @id MochiKit.Signal.Event */
+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());
+
+        if (this.type() &&
+            this.type().indexOf('key') === 0 ||
+            this.type().indexOf('mouse') === 0 ||
+            this.type().indexOf('click') != -1 ||
+            this.type() == 'contextmenu') {
+            str += ', 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;
+    },
+
+     /** @id MochiKit.Signal.Event.prototype.toString */
+    toString: function () {
+        return this.__repr__();
+    },
+
+    /** @id MochiKit.Signal.Event.prototype.src */
+    src: function () {
+        return this._src;
+    },
+
+    /** @id MochiKit.Signal.Event.prototype.event  */
+    event: function () {
+        return this._event;
+    },
+
+    /** @id MochiKit.Signal.Event.prototype.type */
+    type: function () {
+        return this._event.type || undefined;
+    },
+
+    /** @id MochiKit.Signal.Event.prototype.target */
+    target: function () {
+        return this._event.target || this._event.srcElement;
+    },
+
+    _relatedTarget: null,
+    /** @id MochiKit.Signal.Event.prototype.relatedTarget */
+    relatedTarget: function () {
+        if (this._relatedTarget !== null) {
+            return this._relatedTarget;
+        }
+
+        var elem = null;
+        if (this.type() == 'mouseover') {
+            elem = (this._event.relatedTarget ||
+                this._event.fromElement);
+        } else if (this.type() == 'mouseout') {
+            elem = (this._event.relatedTarget ||
+                this._event.toElement);
+        }
+        if (elem !== null) {
+            this._relatedTarget = elem;
+            return elem;
+        }
+
+        return undefined;
+    },
+
+    _modifier: null,
+    /** @id MochiKit.Signal.Event.prototype.modifier */
+    modifier: function () {
+        if (this._modifier !== null) {
+            return this._modifier;
+        }
+        var m = {};
+        m.alt = this._event.altKey;
+        m.ctrl = this._event.ctrlKey;
+        m.meta = this._event.metaKey || false; // IE and Opera punt here
+        m.shift = this._event.shiftKey;
+        m.any = m.alt || m.ctrl || m.shift || m.meta;
+        this._modifier = m;
+        return m;
+    },
+
+    _key: null,
+    /** @id MochiKit.Signal.Event.prototype.key */
+    key: function () {
+        if (this._key !== null) {
+            return this._key;
+        }
+        var k = {};
+        if (this.type() && this.type().indexOf('key') === 0) {
+
+            /*
+
+                If you're looking for a special key, look for it in keydown or
+                keyup, but never keypress. If you're looking for a Unicode
+                chracter, look for it with keypress, but never keyup or
+                keydown.
+
+                Notes:
+
+                FF key event behavior:
+                key     event   charCode    keyCode
+                DOWN    ku,kd   0           40
+                DOWN    kp      0           40
+                ESC     ku,kd   0           27
+                ESC     kp      0           27
+                a       ku,kd   0           65
+                a       kp      97          0
+                shift+a ku,kd   0           65
+                shift+a kp      65          0
+                1       ku,kd   0           49
+                1       kp      49          0
+                shift+1 ku,kd   0           0
+                shift+1 kp      33          0
+
+                IE key event behavior:
+                (IE doesn't fire keypress events for special keys.)
+                key     event   keyCode
+                DOWN    ku,kd   40
+                DOWN    kp      undefined
+                ESC     ku,kd   27
+                ESC     kp      27
+                a       ku,kd   65
+                a       kp      97
+                shift+a ku,kd   65
+                shift+a kp      65
+                1       ku,kd   49
+                1       kp      49
+                shift+1 ku,kd   49
+                shift+1 kp      33
+
+                Safari key event behavior:
+                (Safari sets charCode and keyCode to something crazy for
+                special keys.)
+                key     event   charCode    keyCode
+                DOWN    ku,kd   63233       40
+                DOWN    kp      63233       63233
+                ESC     ku,kd   27          27
+                ESC     kp      27          27
+                a       ku,kd   97          65
+                a       kp      97          97
+                shift+a ku,kd   65          65
+                shift+a kp      65          65
+                1       ku,kd   49          49
+                1       kp      49          49
+                shift+1 ku,kd   33          49
+                shift+1 kp      33          33
+
+            */
+
+            /* look for special keys here */
+            if (this.type() == 'keydown' || this.type() == 'keyup') {
+                k.code = this._event.keyCode;
+                k.string = (MochiKit.Signal._specialKeys[k.code] ||
+                    'KEY_UNKNOWN');
+                this._key = k;
+                return k;
+
+            /* look for characters here */
+            } else if (this.type() == 'keypress') {
+
+                /*
+
+                    Special key behavior:
+
+                    IE: does not fire keypress events for special keys
+                    FF: sets charCode to 0, and sets the correct keyCode
+                    Safari: sets keyCode and charCode to something stupid
+
+                */
+
+                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') { // IE
+                    k.code = this._event.keyCode;
+                    k.string = String.fromCharCode(k.code);
+                }
+
+                this._key = k;
+                return k;
+            }
+        }
+        return undefined;
+    },
+
+    _mouse: null,
+    /** @id MochiKit.Signal.Event.prototype.mouse */
+    mouse: function () {
+        if (this._mouse !== null) {
+            return this._mouse;
+        }
+
+        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.Style.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.Style.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 {
+                /*
+
+                    The IE shortcut can be off by two. We fix it. See:
+                    http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
+
+                    This is similar to the method used in
+                    MochiKit.Style.getElementPosition().
+
+                */
+                var de = MochiKit.DOM._document.documentElement;
+                var b = MochiKit.DOM._document.body;
+
+                m.page.x = e.clientX +
+                    (de.scrollLeft || b.scrollLeft) -
+                    (de.clientLeft || 0);
+
+                m.page.y = e.clientY +
+                    (de.scrollTop || b.scrollTop) -
+                    (de.clientTop || 0);
+
+            }
+            if (this.type() != 'mousemove') {
+                m.button = {};
+                m.button.left = false;
+                m.button.right = false;
+                m.button.middle = false;
+
+                /* we could check e.button, but which is more consistent */
+                if (e.which) {
+                    m.button.left = (e.which == 1);
+                    m.button.middle = (e.which == 2);
+                    m.button.right = (e.which == 3);
+
+                    /*
+
+                        Mac browsers and right click:
+
+                            - Safari doesn't fire any click events on a right
+                              click:
+                              http://bugs.webkit.org/show_bug.cgi?id=6595
+
+                            - Firefox fires the event, and sets ctrlKey = true
+
+                            - Opera fires the event, and sets metaKey = true
+
+                        oncontextmenu is fired on right clicks between
+                        browsers and across platforms.
+
+                    */
+
+                } else {
+                    m.button.left = !!(e.button & 1);
+                    m.button.right = !!(e.button & 2);
+                    m.button.middle = !!(e.button & 4);
+                }
+            }
+            this._mouse = m;
+            return m;
+        }
+        return undefined;
+    },
+
+    /** @id MochiKit.Signal.Event.prototype.stop */
+    stop: function () {
+        this.stopPropagation();
+        this.preventDefault();
+    },
+
+    /** @id MochiKit.Signal.Event.prototype.stopPropagation */
+    stopPropagation: function () {
+        if (this._event.stopPropagation) {
+            this._event.stopPropagation();
+        } else {
+            this._event.cancelBubble = true;
+        }
+    },
+
+    /** @id MochiKit.Signal.Event.prototype.preventDefault */
+    preventDefault: function () {
+        if (this._event.preventDefault) {
+            this._event.preventDefault();
+        } else if (this._confirmUnload === null) {
+            this._event.returnValue = false;
+        }
+    },
+
+    _confirmUnload: null,
+
+    /** @id MochiKit.Signal.Event.prototype.confirmUnload */
+    confirmUnload: function (msg) {
+        if (this.type() == 'beforeunload') {
+            this._confirmUnload = msg;
+            this._event.returnValue = msg;
+        }
+    }
+});
+
+/* Safari sets keyCode to these special values onkeypress. */
+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 KEY_F1 - KEY_F12 */
+(function () {
+    var _specialMacKeys = MochiKit.Signal._specialMacKeys;
+    for (i = 63236; i <= 63242; i++) {
+        // no F0
+        _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
+    }
+})();
+
+/* Standard keyboard key codes. */
+MochiKit.Signal._specialKeys = {
+    8: 'KEY_BACKSPACE',
+    9: 'KEY_TAB',
+    12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
+    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', // weird, for Safari and IE only
+    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'
+    // undefined: 'KEY_UNKNOWN'
+};
+
+(function () {
+    /* for KEY_0 - KEY_9 */
+    var _specialKeys = MochiKit.Signal._specialKeys;
+    for (var i = 48; i <= 57; i++) {
+        _specialKeys[i] = 'KEY_' + (i - 48);
+    }
+
+    /* for KEY_A - KEY_Z */
+    for (i = 65; i <= 90; i++) {
+        _specialKeys[i] = 'KEY_' + String.fromCharCode(i);
+    }
+
+    /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
+    for (i = 96; i <= 105; i++) {
+        _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
+    }
+
+    /* for KEY_F1 - KEY_F12 */
+    for (i = 112; i <= 123; i++) {
+        // no F0
+        _specialKeys[i] = 'KEY_F' + (i - 112 + 1);
+    }
+})();
+
+/* Internal object to keep track of created signals. */
+MochiKit.Signal.Ident = function (ident) {
+    this.source = ident.source;
+    this.signal = ident.signal;
+    this.listener = ident.listener;
+    this.isDOM = ident.isDOM;
+    this.objOrFunc = ident.objOrFunc;
+    this.funcOrStr = ident.funcOrStr;
+    this.connected = ident.connected;
+};
+
+MochiKit.Signal.Ident.prototype = {};
+
+MochiKit.Base.update(MochiKit.Signal, {
+
+    __repr__: function () {
+        return '[' + this.NAME + ' ' + this.VERSION + ']';
+    },
+
+    toString: function () {
+        return this.__repr__();
+    },
+
+    _unloadCache: function () {
+        var self = MochiKit.Signal;
+        var observers = self._observers;
+
+        for (var i = 0; i < observers.length; i++) {
+            if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') {
+                self._disconnect(observers[i]);
+            }
+        }
+    },
+
+    _listener: function (src, sig, func, obj, isDOM) {
+        var self = MochiKit.Signal;
+        var E = self.Event;
+        if (!isDOM) {
+            return MochiKit.Base.bind(func, obj);
+        }
+        obj = obj || src;
+        if (typeof(func) == "string") {
+            if (sig === 'onload' || sig === 'onunload') {
+                return function (nativeEvent) {
+                    obj[func].apply(obj, [new E(src, nativeEvent)]);
+                    
+                    var ident = new MochiKit.Signal.Ident({
+                        source: src, signal: sig, objOrFunc: obj, funcOrStr: func});
+                    
+                    MochiKit.Signal._disconnect(ident);
+                };
+            } else {
+                return function (nativeEvent) {
+                    obj[func].apply(obj, [new E(src, nativeEvent)]);
+                };
+            }
+        } else {
+            if (sig === 'onload' || sig === 'onunload') {
+                return function (nativeEvent) {
+                    func.apply(obj, [new E(src, nativeEvent)]);
+                    MochiKit.Signal.disconnect(src, sig, func);
+                    
+                    var ident = new MochiKit.Signal.Ident({
+                        source: src, signal: sig, objOrFunc: func});
+                    
+                    MochiKit.Signal._disconnect(ident);
+                };
+            } else {
+                return function (nativeEvent) {
+                    func.apply(obj, [new E(src, nativeEvent)]);
+                };
+            }
+        }
+    },
+
+    _browserAlreadyHasMouseEnterAndLeave: function () {
+        return /MSIE/.test(navigator.userAgent);
+    },
+
+    _mouseEnterListener: function (src, sig, func, obj) {
+        var E = MochiKit.Signal.Event;
+        return function (nativeEvent) {
+            var e = new E(src, nativeEvent);
+            try {
+                e.relatedTarget().nodeName;
+            } catch (err) {
+                /* probably hit a permission denied error; possibly one of
+                 * firefox's screwy anonymous DIVs inside an input element.
+                 * Allow this event to propogate up.
+                 */
+                return;
+            }
+            e.stop();
+            if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) {
+                /* We've moved between our node and a child. Ignore. */
+                return;
+            }
+            e.type = function () { return sig; };
+            if (typeof(func) == "string") {
+                return obj[func].apply(obj, [e]);
+            } else {
+                return func.apply(obj, [e]);
+            }
+        };
+    },
+
+    _getDestPair: function (objOrFunc, funcOrStr) {
+        var obj = null;
+        var func = null;
+        if (typeof(funcOrStr) != 'undefined') {
+            obj = objOrFunc;
+            func = funcOrStr;
+            if (typeof(funcOrStr) == 'string') {
+                if (typeof(objOrFunc[funcOrStr]) != "function") {
+                    throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
+                }
+            } else if (typeof(funcOrStr) != 'function') {
+                throw new Error("'funcOrStr' must be a function or string");
+            }
+        } else if (typeof(objOrFunc) != "function") {
+            throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
+        } else {
+            func = objOrFunc;
+        }
+        return [obj, func];
+    },
+
+    /** @id MochiKit.Signal.connect */
+    connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
+        src = MochiKit.DOM.getElement(src);
+        var self = MochiKit.Signal;
+
+        if (typeof(sig) != 'string') {
+            throw new Error("'sig' must be a string");
+        }
+
+        var destPair = self._getDestPair(objOrFunc, funcOrStr);
+        var obj = destPair[0];
+        var func = destPair[1];
+        if (typeof(obj) == 'undefined' || obj === null) {
+            obj = src;
+        }
+
+        var isDOM = !!(src.addEventListener || src.attachEvent);
+        if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave")
+                  && !self._browserAlreadyHasMouseEnterAndLeave()) {
+            var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
+            if (sig === "onmouseenter") {
+                sig = "onmouseover";
+            } else {
+                sig = "onmouseout";
+            }
+        } else {
+            var listener = self._listener(src, sig, func, obj, isDOM);
+        }
+
+        if (src.addEventListener) {
+            src.addEventListener(sig.substr(2), listener, false);
+        } else if (src.attachEvent) {
+            src.attachEvent(sig, listener); // useCapture unsupported
+        }
+
+        var ident = new MochiKit.Signal.Ident({
+            source: src, 
+            signal: sig, 
+            listener: listener, 
+            isDOM: isDOM, 
+            objOrFunc: objOrFunc, 
+            funcOrStr: funcOrStr, 
+            connected: true
+        });
+        self._observers.push(ident);
+
+        if (!isDOM && typeof(src.__connect__) == 'function') {
+            var args = MochiKit.Base.extend([ident], arguments, 1);
+            src.__connect__.apply(src, args);
+        }
+
+        return ident;
+    },
+
+    _disconnect: function (ident) {
+        // already disconnected
+        if (!ident.connected) {
+            return;
+        }
+        ident.connected = false;
+        // check isDOM
+        if (!ident.isDOM) {
+            return;
+        }
+        var src = ident.source;
+        var sig = ident.signal;
+        var listener = ident.listener;
+
+        if (src.removeEventListener) {
+            src.removeEventListener(sig.substr(2), listener, false);
+        } else if (src.detachEvent) {
+            src.detachEvent(sig, listener); // useCapture unsupported
+        } else {
+            throw new Error("'src' must be a DOM element");
+        }
+    },
+
+     /** @id MochiKit.Signal.disconnect */
+    disconnect: function (ident) {
+        var self = MochiKit.Signal;
+        var observers = self._observers;
+        var m = MochiKit.Base;
+        if (arguments.length > 1) {
+            // compatibility API
+            var src = MochiKit.DOM.getElement(arguments[0]);
+            var sig = arguments[1];
+            var obj = arguments[2];
+            var func = arguments[3];
+            for (var i = observers.length - 1; i >= 0; i--) {
+                var o = observers[i];
+                if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) {
+                    self._disconnect(o);
+                    if (!self._lock) {
+                        observers.splice(i, 1);
+                    } else {
+                        self._dirty = true;
+                    }
+                    return true;
+                }
+            }
+        } else {
+            var idx = m.findIdentical(observers, ident);
+            if (idx >= 0) {
+                self._disconnect(ident);
+                if (!self._lock) {
+                    observers.splice(idx, 1);
+                } else {
+                    self._dirty = true;
+                }
+                return true;
+            }
+        }
+        return false;
+    },
+
+    /** @id MochiKit.Signal.disconnectAllTo */
+    disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) {
+        var self = MochiKit.Signal;
+        var observers = self._observers;
+        var disconnect = self._disconnect;
+        var locked = self._lock;
+        var dirty = self._dirty;
+        if (typeof(funcOrStr) === 'undefined') {
+            funcOrStr = null;
+        }
+        for (var i = observers.length - 1; i >= 0; i--) {
+            var ident = observers[i];
+            if (ident.objOrFunc === objOrFunc &&
+                    (funcOrStr === null || ident.funcOrStr === funcOrStr)) {
+                disconnect(ident);
+                if (locked) {
+                    dirty = true;
+                } else {
+                    observers.splice(i, 1);
+                }
+            }
+        }
+        self._dirty = dirty;
+    },
+
+    /** @id MochiKit.Signal.disconnectAll */
+    disconnectAll: function (src/* optional */, sig) {
+        src = MochiKit.DOM.getElement(src);
+        var m = MochiKit.Base;
+        var signals = m.flattenArguments(m.extend(null, arguments, 1));
+        var self = MochiKit.Signal;
+        var disconnect = self._disconnect;
+        var observers = self._observers;
+        var i, ident;
+        var locked = self._lock;
+        var dirty = self._dirty;
+        if (signals.length === 0) {
+            // disconnect all
+            for (i = observers.length - 1; i >= 0; i--) {
+                ident = observers[i];
+                if (ident.source === src) {
+                    disconnect(ident);
+                    if (!locked) {
+                        observers.splice(i, 1);
+                    } else {
+                        dirty = true;
+                    }
+                }
+            }
+        } else {
+            var sigs = {};
+            for (i = 0; i < signals.length; i++) {
+                sigs[signals[i]] = true;
+            }
+            for (i = observers.length - 1; i >= 0; i--) {
+                ident = observers[i];
+                if (ident.source === src && ident.signal in sigs) {
+                    disconnect(ident);
+                    if (!locked) {
+                        observers.splice(i, 1);
+                    } else {
+                        dirty = true;
+                    }
+                }
+            }
+        }
+        self._dirty = dirty;
+    },
+
+    /** @id MochiKit.Signal.signal */
+    signal: function (src, sig) {
+        var self = MochiKit.Signal;
+        var observers = self._observers;
+        src = MochiKit.DOM.getElement(src);
+        var args = MochiKit.Base.extend(null, arguments, 2);
+        var errors = [];
+        self._lock = true;
+        for (var i = 0; i < observers.length; i++) {
+            var ident = observers[i];
+            if (ident.source === src && ident.signal === sig) {
+                try {
+                    ident.listener.apply(src, args);
+                } catch (e) {
+                    errors.push(e);
+                }
+            }
+        }
+        self._lock = false;
+        if (self._dirty) {
+            self._dirty = false;
+            for (var i = observers.length - 1; i >= 0; i--) {
+                if (!observers[i].connected) {
+                    observers.splice(i, 1);
+                }
+            }
+        }
+        if (errors.length == 1) {
+            throw errors[0];
+        } else if (errors.length > 1) {
+            var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
+            e.errors = errors;
+            throw e;
+        }
+    }
+
+});
+
+MochiKit.Signal.EXPORT_OK = [];
+
+MochiKit.Signal.EXPORT = [
+    'connect',
+    'disconnect',
+    'signal',
+    'disconnectAll',
+    'disconnectAllTo'
+];
+
+MochiKit.Signal.__new__ = function (win) {
+    var m = MochiKit.Base;
+    this._document = document;
+    this._window = win;
+    this._lock = false;
+    this._dirty = false;
+
+    try {
+        this.connect(window, 'onunload', this._unloadCache);
+    } catch (e) {
+        // pass: might not be a browser
+    }
+
+    this.EXPORT_TAGS = {
+        ':common': this.EXPORT,
+        ':all': m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+
+    m.nameFunctions(this);
+};
+
+MochiKit.Signal.__new__(this);
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+    connect = MochiKit.Signal.connect;
+    disconnect = MochiKit.Signal.disconnect;
+    disconnectAll = MochiKit.Signal.disconnectAll;
+    signal = MochiKit.Signal.signal;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.Signal);
diff --git a/mochikit_v14/MochiKit/Sortable.js b/mochikit_v14/MochiKit/Sortable.js
new file mode 100644 (file)
index 0000000..8976ec0
--- /dev/null
@@ -0,0 +1,589 @@
+/***
+Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+    Mochi-ized By Thomas Herve (_firstname_@nimail.org)
+
+See scriptaculous.js for full license.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Sortable');
+    dojo.require('MochiKit.Base');
+    dojo.require('MochiKit.DOM');
+    dojo.require('MochiKit.Iter');
+}
+
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use("MochiKit.Base", []);
+    JSAN.use("MochiKit.DOM", []);
+    JSAN.use("MochiKit.Iter", []);
+}
+
+try {
+    if (typeof(MochiKit.Base) == 'undefined' ||
+        typeof(MochiKit.DOM) == 'undefined' ||
+        typeof(MochiKit.Iter) == 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
+}
+
+if (typeof(MochiKit.Sortable) == 'undefined') {
+    MochiKit.Sortable = {};
+}
+
+MochiKit.Sortable.NAME = 'MochiKit.Sortable';
+MochiKit.Sortable.VERSION = '1.4';
+
+MochiKit.Sortable.__repr__ = function () {
+    return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+
+MochiKit.Sortable.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.Sortable.EXPORT = [
+];
+
+MochiKit.Sortable.EXPORT_OK = [
+];
+
+MochiKit.Base.update(MochiKit.Sortable, {
+    /***
+
+    Manage sortables. Mainly use the create function to add a sortable.
+
+    ***/
+    sortables: {},
+
+    _findRootElement: function (element) {
+        while (element.tagName.toUpperCase() != "BODY") {
+            if (element.id && MochiKit.Sortable.sortables[element.id]) {
+                return element;
+            }
+            element = element.parentNode;
+        }
+    },
+
+    /** @id MochiKit.Sortable.options */
+    options: function (element) {
+        element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
+        if (!element) {
+            return;
+        }
+        return MochiKit.Sortable.sortables[element.id];
+    },
+
+    /** @id MochiKit.Sortable.destroy */
+    destroy: function (element){
+        var s = MochiKit.Sortable.options(element);
+        var b = MochiKit.Base;
+        var d = MochiKit.DragAndDrop;
+
+        if (s) {
+            MochiKit.Signal.disconnect(s.startHandle);
+            MochiKit.Signal.disconnect(s.endHandle);
+            b.map(function (dr) {
+                d.Droppables.remove(dr);
+            }, s.droppables);
+            b.map(function (dr) {
+                dr.destroy();
+            }, s.draggables);
+
+            delete MochiKit.Sortable.sortables[s.element.id];
+        }
+    },
+
+    /** @id MochiKit.Sortable.create */
+    create: function (element, options) {
+        element = MochiKit.DOM.getElement(element);
+        var self = MochiKit.Sortable;
+
+        /** @id MochiKit.Sortable.options */
+        options = MochiKit.Base.update({
+
+            /** @id MochiKit.Sortable.element */
+            element: element,
+
+            /** @id MochiKit.Sortable.tag */
+            tag: 'li',  // assumes li children, override with tag: 'tagname'
+
+            /** @id MochiKit.Sortable.dropOnEmpty */
+            dropOnEmpty: false,
+
+            /** @id MochiKit.Sortable.tree */
+            tree: false,
+
+            /** @id MochiKit.Sortable.treeTag */
+            treeTag: 'ul',
+
+            /** @id MochiKit.Sortable.overlap */
+            overlap: 'vertical',  // one of 'vertical', 'horizontal'
+
+            /** @id MochiKit.Sortable.constraint */
+            constraint: 'vertical',  // one of 'vertical', 'horizontal', false
+            // also takes array of elements (or ids); or false
+
+            /** @id MochiKit.Sortable.containment */
+            containment: [element],
+
+            /** @id MochiKit.Sortable.handle */
+            handle: false,  // or a CSS class
+
+            /** @id MochiKit.Sortable.only */
+            only: false,
+
+            /** @id MochiKit.Sortable.hoverclass */
+            hoverclass: null,
+
+            /** @id MochiKit.Sortable.ghosting */
+            ghosting: false,
+
+            /** @id MochiKit.Sortable.scroll */
+            scroll: false,
+
+            /** @id MochiKit.Sortable.scrollSensitivity */
+            scrollSensitivity: 20,
+
+            /** @id MochiKit.Sortable.scrollSpeed */
+            scrollSpeed: 15,
+
+            /** @id MochiKit.Sortable.format */
+            format: /^[^_]*_(.*)$/,
+
+            /** @id MochiKit.Sortable.onChange */
+            onChange: MochiKit.Base.noop,
+
+            /** @id MochiKit.Sortable.onUpdate */
+            onUpdate: MochiKit.Base.noop,
+
+            /** @id MochiKit.Sortable.accept */
+            accept: null
+        }, options);
+
+        // clear any old sortable with same element
+        self.destroy(element);
+
+        // build options for the draggables
+        var options_for_draggable = {
+            revert: true,
+            ghosting: options.ghosting,
+            scroll: options.scroll,
+            scrollSensitivity: options.scrollSensitivity,
+            scrollSpeed: options.scrollSpeed,
+            constraint: options.constraint,
+            handle: options.handle
+        };
+
+        if (options.starteffect) {
+            options_for_draggable.starteffect = options.starteffect;
+        }
+
+        if (options.reverteffect) {
+            options_for_draggable.reverteffect = options.reverteffect;
+        } else if (options.ghosting) {
+            options_for_draggable.reverteffect = function (innerelement) {
+                innerelement.style.top = 0;
+                innerelement.style.left = 0;
+            };
+        }
+
+        if (options.endeffect) {
+            options_for_draggable.endeffect = options.endeffect;
+        }
+
+        if (options.zindex) {
+            options_for_draggable.zindex = options.zindex;
+        }
+
+        // build options for the droppables
+        var options_for_droppable = {
+            overlap: options.overlap,
+            containment: options.containment,
+            hoverclass: options.hoverclass,
+            onhover: self.onHover,
+            tree: options.tree,
+            accept: options.accept
+        }
+
+        var options_for_tree = {
+            onhover: self.onEmptyHover,
+            overlap: options.overlap,
+            containment: options.containment,
+            hoverclass: options.hoverclass,
+            accept: options.accept
+        }
+
+        // fix for gecko engine
+        MochiKit.DOM.removeEmptyTextNodes(element);
+
+        options.draggables = [];
+        options.droppables = [];
+
+        // drop on empty handling
+        if (options.dropOnEmpty || options.tree) {
+            new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
+            options.droppables.push(element);
+        }
+        MochiKit.Base.map(function (e) {
+            // handles are per-draggable
+            var handle = options.handle ?
+                MochiKit.DOM.getFirstElementByTagAndClassName(null,
+                    options.handle, e) : e;
+            options.draggables.push(
+                new MochiKit.DragAndDrop.Draggable(e,
+                    MochiKit.Base.update(options_for_draggable,
+                                         {handle: handle})));
+            new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
+            if (options.tree) {
+                e.treeNode = element;
+            }
+            options.droppables.push(e);
+        }, (self.findElements(element, options) || []));
+
+        if (options.tree) {
+            MochiKit.Base.map(function (e) {
+                new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
+                e.treeNode = element;
+                options.droppables.push(e);
+            }, (self.findTreeElements(element, options) || []));
+        }
+
+        // keep reference
+        self.sortables[element.id] = options;
+
+        options.lastValue = self.serialize(element);
+        options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
+                                MochiKit.Base.partial(self.onStart, element));
+        options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
+                                MochiKit.Base.partial(self.onEnd, element));
+    },
+
+    /** @id MochiKit.Sortable.onStart */
+    onStart: function (element, draggable) {
+        var self = MochiKit.Sortable;
+        var options = self.options(element);
+        options.lastValue = self.serialize(options.element);
+    },
+
+    /** @id MochiKit.Sortable.onEnd */
+    onEnd: function (element, draggable) {
+        var self = MochiKit.Sortable;
+        self.unmark();
+        var options = self.options(element);
+        if (options.lastValue != self.serialize(options.element)) {
+            options.onUpdate(options.element);
+        }
+    },
+
+    // return all suitable-for-sortable elements in a guaranteed order
+
+    /** @id MochiKit.Sortable.findElements */
+    findElements: function (element, options) {
+        return MochiKit.Sortable.findChildren(
+            element, options.only, options.tree ? true : false, options.tag);
+    },
+
+    /** @id MochiKit.Sortable.findTreeElements */
+    findTreeElements: function (element, options) {
+        return MochiKit.Sortable.findChildren(
+            element, options.only, options.tree ? true : false, options.treeTag);
+    },
+
+    /** @id MochiKit.Sortable.findChildren */
+    findChildren: function (element, only, recursive, tagName) {
+        if (!element.hasChildNodes()) {
+            return null;
+        }
+        tagName = tagName.toUpperCase();
+        if (only) {
+            only = MochiKit.Base.flattenArray([only]);
+        }
+        var elements = [];
+        MochiKit.Base.map(function (e) {
+            if (e.tagName &&
+                e.tagName.toUpperCase() == tagName &&
+               (!only ||
+                MochiKit.Iter.some(only, function (c) {
+                    return MochiKit.DOM.hasElementClass(e, c);
+                }))) {
+                elements.push(e);
+            }
+            if (recursive) {
+                var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName);
+                if (grandchildren && grandchildren.length > 0) {
+                    elements = elements.concat(grandchildren);
+                }
+            }
+        }, element.childNodes);
+        return elements;
+    },
+
+    /** @id MochiKit.Sortable.onHover */
+    onHover: function (element, dropon, overlap) {
+        if (MochiKit.DOM.isParent(dropon, element)) {
+            return;
+        }
+        var self = MochiKit.Sortable;
+
+        if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
+            return;
+        } else if (overlap > 0.5) {
+            self.mark(dropon, 'before');
+            if (dropon.previousSibling != element) {
+                var oldParentNode = element.parentNode;
+                element.style.visibility = 'hidden';  // fix gecko rendering
+                dropon.parentNode.insertBefore(element, dropon);
+                if (dropon.parentNode != oldParentNode) {
+                    self.options(oldParentNode).onChange(element);
+                }
+                self.options(dropon.parentNode).onChange(element);
+            }
+        } else {
+            self.mark(dropon, 'after');
+            var nextElement = dropon.nextSibling || null;
+            if (nextElement != element) {
+                var oldParentNode = element.parentNode;
+                element.style.visibility = 'hidden';  // fix gecko rendering
+                dropon.parentNode.insertBefore(element, nextElement);
+                if (dropon.parentNode != oldParentNode) {
+                    self.options(oldParentNode).onChange(element);
+                }
+                self.options(dropon.parentNode).onChange(element);
+            }
+        }
+    },
+
+    _offsetSize: function (element, type) {
+        if (type == 'vertical' || type == 'height') {
+            return element.offsetHeight;
+        } else {
+            return element.offsetWidth;
+        }
+    },
+
+    /** @id MochiKit.Sortable.onEmptyHover */
+    onEmptyHover: function (element, dropon, overlap) {
+        var oldParentNode = element.parentNode;
+        var self = MochiKit.Sortable;
+        var droponOptions = self.options(dropon);
+
+        if (!MochiKit.DOM.isParent(dropon, element)) {
+            var index;
+
+            var children = self.findElements(dropon, {tag: droponOptions.tag,
+                                                      only: droponOptions.only});
+            var child = null;
+
+            if (children) {
+                var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+                for (index = 0; index < children.length; index += 1) {
+                    if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
+                        offset -= self._offsetSize(children[index], droponOptions.overlap);
+                    } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+                        child = index + 1 < children.length ? children[index + 1] : null;
+                        break;
+                    } else {
+                        child = children[index];
+                        break;
+                    }
+                }
+            }
+
+            dropon.insertBefore(element, child);
+
+            self.options(oldParentNode).onChange(element);
+            droponOptions.onChange(element);
+        }
+    },
+
+    /** @id MochiKit.Sortable.unmark */
+    unmark: function () {
+        var m = MochiKit.Sortable._marker;
+        if (m) {
+            MochiKit.Style.hideElement(m);
+        }
+    },
+
+    /** @id MochiKit.Sortable.mark */
+    mark: function (dropon, position) {
+        // mark on ghosting only
+        var d = MochiKit.DOM;
+        var self = MochiKit.Sortable;
+        var sortable = self.options(dropon.parentNode);
+        if (sortable && !sortable.ghosting) {
+            return;
+        }
+
+        if (!self._marker) {
+            self._marker = d.getElement('dropmarker') ||
+                        document.createElement('DIV');
+            MochiKit.Style.hideElement(self._marker);
+            d.addElementClass(self._marker, 'dropmarker');
+            self._marker.style.position = 'absolute';
+            document.getElementsByTagName('body').item(0).appendChild(self._marker);
+        }
+        var offsets = MochiKit.Position.cumulativeOffset(dropon);
+        self._marker.style.left = offsets.x + 'px';
+        self._marker.style.top = offsets.y + 'px';
+
+        if (position == 'after') {
+            if (sortable.overlap == 'horizontal') {
+                self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
+            } else {
+                self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
+            }
+        }
+        MochiKit.Style.showElement(self._marker);
+    },
+
+    _tree: function (element, options, parent) {
+        var self = MochiKit.Sortable;
+        var children = self.findElements(element, options) || [];
+
+        for (var i = 0; i < children.length; ++i) {
+            var match = children[i].id.match(options.format);
+
+            if (!match) {
+                continue;
+            }
+
+            var child = {
+                id: encodeURIComponent(match ? match[1] : null),
+                element: element,
+                parent: parent,
+                children: [],
+                position: parent.children.length,
+                container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
+            }
+
+            /* Get the element containing the children and recurse over it */
+            if (child.container) {
+                self._tree(child.container, options, child)
+            }
+
+            parent.children.push (child);
+        }
+
+        return parent;
+    },
+
+    /* Finds the first element of the given tag type within a parent element.
+       Used for finding the first LI[ST] within a L[IST]I[TEM].*/
+    _findChildrenElement: function (element, containerTag) {
+        if (element && element.hasChildNodes) {
+            containerTag = containerTag.toUpperCase();
+            for (var i = 0; i < element.childNodes.length; ++i) {
+                if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
+                    return element.childNodes[i];
+                }
+            }
+        }
+        return null;
+    },
+
+    /** @id MochiKit.Sortable.tree */
+    tree: function (element, options) {
+        element = MochiKit.DOM.getElement(element);
+        var sortableOptions = MochiKit.Sortable.options(element);
+        options = MochiKit.Base.update({
+            tag: sortableOptions.tag,
+            treeTag: sortableOptions.treeTag,
+            only: sortableOptions.only,
+            name: element.id,
+            format: sortableOptions.format
+        }, options || {});
+
+        var root = {
+            id: null,
+            parent: null,
+            children: new Array,
+            container: element,
+            position: 0
+        }
+
+        return MochiKit.Sortable._tree(element, options, root);
+    },
+
+    /**
+     * Specifies the sequence for the Sortable.
+     * @param {Node} element    Element to use as the Sortable.
+     * @param {Object} newSequence    New sequence to use.
+     * @param {Object} options    Options to use fro the Sortable.
+     */
+    setSequence: function (element, newSequence, options) {
+        var self = MochiKit.Sortable;
+        var b = MochiKit.Base;
+        element = MochiKit.DOM.getElement(element);
+        options = b.update(self.options(element), options || {});
+
+        var nodeMap = {};
+        b.map(function (n) {
+            var m = n.id.match(options.format);
+            if (m) {
+                nodeMap[m[1]] = [n, n.parentNode];
+            }
+            n.parentNode.removeChild(n);
+        }, self.findElements(element, options));
+
+        b.map(function (ident) {
+            var n = nodeMap[ident];
+            if (n) {
+                n[1].appendChild(n[0]);
+                delete nodeMap[ident];
+            }
+        }, newSequence);
+    },
+
+    /* Construct a [i] index for a particular node */
+    _constructIndex: function (node) {
+        var index = '';
+        do {
+            if (node.id) {
+                index = '[' + node.position + ']' + index;
+            }
+        } while ((node = node.parent) != null);
+        return index;
+    },
+
+    /** @id MochiKit.Sortable.sequence */
+    sequence: function (element, options) {
+        element = MochiKit.DOM.getElement(element);
+        var self = MochiKit.Sortable;
+        var options = MochiKit.Base.update(self.options(element), options || {});
+
+        return MochiKit.Base.map(function (item) {
+            return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+        }, MochiKit.DOM.getElement(self.findElements(element, options) || []));
+    },
+
+    /**
+     * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
+     * These options override the Sortable options for the serialization only.
+     * @param {Node} element    Element to serialize.
+     * @param {Object} options    Serialization options.
+     */
+    serialize: function (element, options) {
+        element = MochiKit.DOM.getElement(element);
+        var self = MochiKit.Sortable;
+        options = MochiKit.Base.update(self.options(element), options || {});
+        var name = encodeURIComponent(options.name || element.id);
+
+        if (options.tree) {
+            return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
+                return [name + self._constructIndex(item) + "[id]=" +
+                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+            }, self.tree(element, options).children)).join('&');
+        } else {
+            return MochiKit.Base.map(function (item) {
+                return name + "[]=" + encodeURIComponent(item);
+            }, self.sequence(element, options)).join('&');
+        }
+    }
+});
+
+// trunk compatibility
+MochiKit.Sortable.Sortable = MochiKit.Sortable;
diff --git a/mochikit_v14/MochiKit/Style.js b/mochikit_v14/MochiKit/Style.js
new file mode 100644 (file)
index 0000000..93e7786
--- /dev/null
@@ -0,0 +1,445 @@
+/***
+
+MochiKit.Style 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005-2006 Bob Ippolito, Beau Hartshorne.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Style');
+    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.Style depends on MochiKit.Base!';
+}
+
+try {
+    if (typeof(MochiKit.DOM) == 'undefined') {
+        throw '';
+    }
+} catch (e) {
+    throw 'MochiKit.Style depends on MochiKit.DOM!';
+}
+
+
+if (typeof(MochiKit.Style) == 'undefined') {
+    MochiKit.Style = {};
+}
+
+MochiKit.Style.NAME = 'MochiKit.Style';
+MochiKit.Style.VERSION = '1.4';
+MochiKit.Style.__repr__ = function () {
+    return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+MochiKit.Style.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.Style.EXPORT_OK = [];
+
+MochiKit.Style.EXPORT = [
+    'setStyle',
+    'setOpacity',
+    'getStyle',
+    'getElementDimensions',
+    'elementDimensions', // deprecated
+    'setElementDimensions',
+    'getElementPosition',
+    'elementPosition', // deprecated
+    'setElementPosition',
+    'setDisplayForElement',
+    'hideElement',
+    'showElement',
+    'getViewportDimensions',
+    'getViewportPosition',
+    'Dimensions',
+    'Coordinates'
+];
+
+
+/*
+
+    Dimensions
+
+*/
+/** @id MochiKit.Style.Dimensions */
+MochiKit.Style.Dimensions = function (w, h) {
+    this.w = w;
+    this.h = h;
+};
+
+MochiKit.Style.Dimensions.prototype.__repr__ = function () {
+    var repr = MochiKit.Base.repr;
+    return '{w: '  + repr(this.w) + ', h: ' + repr(this.h) + '}';
+};
+
+MochiKit.Style.Dimensions.prototype.toString = function () {
+    return this.__repr__();
+};
+
+
+/*
+
+    Coordinates
+
+*/
+/** @id MochiKit.Style.Coordinates */
+MochiKit.Style.Coordinates = function (x, y) {
+    this.x = x;
+    this.y = y;
+};
+
+MochiKit.Style.Coordinates.prototype.__repr__ = function () {
+    var repr = MochiKit.Base.repr;
+    return '{x: '  + repr(this.x) + ', y: ' + repr(this.y) + '}';
+};
+
+MochiKit.Style.Coordinates.prototype.toString = function () {
+    return this.__repr__();
+};
+
+
+MochiKit.Base.update(MochiKit.Style, {
+
+    /** @id MochiKit.Style.getStyle */
+    getStyle: function (elem, cssProperty) {
+        var dom = MochiKit.DOM;
+        var d = dom._document;
+
+        elem = dom.getElement(elem);
+        cssProperty = MochiKit.Base.camelize(cssProperty);
+
+        if (!elem || elem == d) {
+            return undefined;
+        }
+        if (cssProperty == 'opacity' && elem.filters) {
+            var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
+            if (opacity && opacity[1]) {
+                return parseFloat(opacity[1]) / 100;
+            }
+            return 1.0;
+        }
+        var value = elem.style ? elem.style[cssProperty] : null;
+        if (!value) {
+            if (d.defaultView && d.defaultView.getComputedStyle) {
+                var css = d.defaultView.getComputedStyle(elem, null);
+                cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
+                    ).toLowerCase(); // from dojo.style.toSelectorCase
+                value = css ? css.getPropertyValue(cssProperty) : null;
+            } else if (elem.currentStyle) {
+                value = elem.currentStyle[cssProperty];
+            }
+        }
+        if (cssProperty == 'opacity') {
+            value = parseFloat(value);
+        }
+
+        if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
+            if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
+                value = 'auto';
+            }
+        }
+
+        return value == 'auto' ? null : value;
+    },
+
+    /** @id MochiKit.Style.setStyle */
+    setStyle: function (elem, style) {
+        elem = MochiKit.DOM.getElement(elem);
+        for (var name in style) {
+            if (name == 'opacity') {
+                MochiKit.Style.setOpacity(elem, style[name]);
+            } else {
+                elem.style[MochiKit.Base.camelize(name)] = style[name];
+            }
+        }
+    },
+
+    /** @id MochiKit.Style.setOpacity */
+    setOpacity: function (elem, o) {
+        elem = MochiKit.DOM.getElement(elem);
+        var self = MochiKit.Style;
+        if (o == 1) {
+            var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
+            elem.style["opacity"] = toSet ? 0.999999 : 1.0;
+            if (/MSIE/.test(navigator.userAgent)) {
+                elem.style['filter'] =
+                    self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
+            }
+        } else {
+            if (o < 0.00001) {
+                o = 0;
+            }
+            elem.style["opacity"] = o;
+            if (/MSIE/.test(navigator.userAgent)) {
+                elem.style['filter'] =
+                    self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
+            }
+        }
+    },
+
+    /*
+
+        getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
+        Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+        License: BSD, http://developer.yahoo.net/yui/license.txt
+
+    */
+
+    /** @id MochiKit.Style.getElementPosition */
+    getElementPosition: function (elem, /* optional */relativeTo) {
+        var self = MochiKit.Style;
+        var dom = MochiKit.DOM;
+        elem = dom.getElement(elem);
+
+        if (!elem ||
+            (!(elem.x && elem.y) &&
+            (!elem.parentNode === null ||
+            self.getStyle(elem, 'display') == 'none'))) {
+            return undefined;
+        }
+
+        var c = new self.Coordinates(0, 0);
+        var box = null;
+        var parent = null;
+
+        var d = MochiKit.DOM._document;
+        var de = d.documentElement;
+        var b = d.body;
+
+        if (!elem.parentNode && elem.x && elem.y) {
+            /* it's just a MochiKit.Style.Coordinates object */
+            c.x += elem.x || 0;
+            c.y += elem.y || 0;
+        } else if (elem.getBoundingClientRect) { // IE shortcut
+            /*
+
+                The IE shortcut can be off by two. We fix it. See:
+                http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
+
+                This is similar to the method used in
+                MochiKit.Signal.Event.mouse().
+
+            */
+            box = elem.getBoundingClientRect();
+
+            c.x += box.left +
+                (de.scrollLeft || b.scrollLeft) -
+                (de.clientLeft || 0);
+
+            c.y += box.top +
+                (de.scrollTop || b.scrollTop) -
+                (de.clientTop || 0);
+
+        } else if (elem.offsetParent) {
+            c.x += elem.offsetLeft;
+            c.y += elem.offsetTop;
+            parent = elem.offsetParent;
+
+            if (parent != elem) {
+                while (parent) {
+                    c.x += parent.offsetLeft;
+                    c.y += parent.offsetTop;
+                    parent = parent.offsetParent;
+                }
+            }
+
+            /*
+
+                Opera < 9 and old Safari (absolute) incorrectly account for
+                body offsetTop and offsetLeft.
+
+            */
+            var ua = navigator.userAgent.toLowerCase();
+            if ((typeof(opera) != 'undefined' &&
+                parseFloat(opera.version()) < 9) ||
+                (ua.indexOf('AppleWebKit') != -1 &&
+                self.getStyle(elem, 'position') == 'absolute')) {
+
+                c.x -= b.offsetLeft;
+                c.y -= b.offsetTop;
+
+            }
+        }
+
+        if (typeof(relativeTo) != 'undefined') {
+            relativeTo = arguments.callee(relativeTo);
+            if (relativeTo) {
+                c.x -= (relativeTo.x || 0);
+                c.y -= (relativeTo.y || 0);
+            }
+        }
+
+        if (elem.parentNode) {
+            parent = elem.parentNode;
+        } else {
+            parent = null;
+        }
+
+        while (parent) {
+            var tagName = parent.tagName.toUpperCase();
+            if (tagName === 'BODY' || tagName === 'HTML') {
+                break;
+            }
+            var disp = self.getStyle(parent, 'display');
+            // Handle strange Opera bug for some display
+            if (disp != 'inline' && disp != 'table-row') {
+                c.x -= parent.scrollLeft;
+                c.y -= parent.scrollTop;
+            }
+            if (parent.parentNode) {
+                parent = parent.parentNode;
+            } else {
+                parent = null;
+            }
+        }
+
+        return c;
+    },
+
+    /** @id MochiKit.Style.setElementPosition */
+    setElementPosition: function (elem, newPos/* optional */, units) {
+        elem = MochiKit.DOM.getElement(elem);
+        if (typeof(units) == 'undefined') {
+            units = 'px';
+        }
+        var newStyle = {};
+        var isUndefNull = MochiKit.Base.isUndefinedOrNull;
+        if (!isUndefNull(newPos.x)) {
+            newStyle['left'] = newPos.x + units;
+        }
+        if (!isUndefNull(newPos.y)) {
+            newStyle['top'] = newPos.y + units;
+        }
+        MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
+    },
+
+    /** @id MochiKit.Style.getElementDimensions */
+    getElementDimensions: function (elem) {
+        var self = MochiKit.Style;
+        var dom = MochiKit.DOM;
+        if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
+            return new self.Dimensions(elem.w || 0, elem.h || 0);
+        }
+        elem = dom.getElement(elem);
+        if (!elem) {
+            return undefined;
+        }
+        var disp = self.getStyle(elem, 'display');
+        // display can be empty/undefined on WebKit/KHTML
+        if (disp != 'none' && disp !== '' && typeof(disp) != 'undefined') {
+            return new self.Dimensions(elem.offsetWidth || 0,
+                elem.offsetHeight || 0);
+        }
+        var s = elem.style;
+        var originalVisibility = s.visibility;
+        var originalPosition = s.position;
+        s.visibility = 'hidden';
+        s.position = 'absolute';
+        s.display = '';
+        var originalWidth = elem.offsetWidth;
+        var originalHeight = elem.offsetHeight;
+        s.display = 'none';
+        s.position = originalPosition;
+        s.visibility = originalVisibility;
+        return new self.Dimensions(originalWidth, originalHeight);
+    },
+
+    /** @id MochiKit.Style.setElementDimensions */
+    setElementDimensions: function (elem, newSize/* optional */, units) {
+        elem = MochiKit.DOM.getElement(elem);
+        if (typeof(units) == 'undefined') {
+            units = 'px';
+        }
+        var newStyle = {};
+        var isUndefNull = MochiKit.Base.isUndefinedOrNull;
+        if (!isUndefNull(newSize.w)) {
+            newStyle['width'] = newSize.w + units;
+        }
+        if (!isUndefNull(newSize.h)) {
+            newStyle['height'] = newSize.h + units;
+        }
+        MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
+    },
+
+    /** @id MochiKit.Style.setDisplayForElement */
+    setDisplayForElement: function (display, element/*, ...*/) {
+        var elements = MochiKit.Base.extend(null, arguments, 1);
+        var getElement = MochiKit.DOM.getElement;
+        for (var i = 0; i < elements.length; i++) {
+            element = getElement(elements[i]);
+            if (element) {
+                element.style.display = display;
+            }
+        }
+    },
+
+    /** @id MochiKit.Style.getViewportDimensions */
+    getViewportDimensions: function () {
+        var d = new MochiKit.Style.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;
+    },
+
+    /** @id MochiKit.Style.getViewportPosition */
+    getViewportPosition: function () {
+        var c = new MochiKit.Style.Coordinates(0, 0);
+        var d = MochiKit.DOM._document;
+        var de = d.documentElement;
+        var db = d.body;
+        if (de && (de.scrollTop || de.scrollLeft)) {
+            c.x = de.scrollLeft;
+            c.y = de.scrollTop;
+        } else if (db) {
+            c.x = db.scrollLeft;
+            c.y = db.scrollTop;
+        }
+        return c;
+    },
+
+    __new__: function () {
+        var m = MochiKit.Base;
+
+        this.elementPosition = this.getElementPosition;
+        this.elementDimensions = this.getElementDimensions;
+
+        this.hideElement = m.partial(this.setDisplayForElement, 'none');
+        this.showElement = m.partial(this.setDisplayForElement, 'block');
+
+        this.EXPORT_TAGS = {
+            ':common': this.EXPORT,
+            ':all': m.concat(this.EXPORT, this.EXPORT_OK)
+        };
+
+        m.nameFunctions(this);
+    }
+});
+
+MochiKit.Style.__new__();
+MochiKit.Base._exportSymbols(this, MochiKit.Style);
diff --git a/mochikit_v14/MochiKit/Test.js b/mochikit_v14/MochiKit/Test.js
new file mode 100644 (file)
index 0000000..494a5b4
--- /dev/null
@@ -0,0 +1,181 @@
+/***
+
+MochiKit.Test 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Test');
+    dojo.require('MochiKit.Base');
+}
+
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use("MochiKit.Base", []);
+}
+
+try {
+    if (typeof(MochiKit.Base) == 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.Test depends on MochiKit.Base!";
+}
+
+if (typeof(MochiKit.Test) == 'undefined') {
+    MochiKit.Test = {};
+}
+
+MochiKit.Test.NAME = "MochiKit.Test";
+MochiKit.Test.VERSION = "1.4";
+MochiKit.Test.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Test.toString = function () {
+    return this.__repr__();
+};
+
+
+MochiKit.Test.EXPORT = ["runTests"];
+MochiKit.Test.EXPORT_OK = [];
+
+MochiKit.Test.runTests = function (obj) {
+    if (typeof(obj) == "string") {
+        obj = JSAN.use(obj);
+    }
+    var suite = new MochiKit.Test.Suite();
+    suite.run(obj);
+};
+
+MochiKit.Test.Suite = function () {
+    this.testIndex = 0;
+    MochiKit.Base.bindMethods(this);
+};
+
+MochiKit.Test.Suite.prototype = {
+    run: function (obj) {
+        try {
+            obj(this);
+        } catch (e) {
+            this.traceback(e);
+        }
+    },
+    traceback: function (e) {
+        var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
+        print("not ok " + this.testIndex + " - Error thrown");
+        for (var i = 0; i < items.length; i++) {
+            var kv = items[i];
+            if (kv[0] == "stack") {
+                kv[1] = kv[1].split(/\n/)[0];
+            }
+            this.print("# " + kv.join(": "));
+        }
+    },
+    print: function (s) {
+        print(s);
+    },
+    is: function (got, expected, /* optional */message) {
+        var res = 1;
+        var msg = null;
+        try {
+            res = MochiKit.Base.compare(got, expected);
+        } catch (e) {
+            msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
+        }
+        if (res) {
+            msg = "Expected value did not compare equal";
+        }
+        if (!res) {
+            return this.testResult(true, message);
+        }
+        return this.testResult(false, message,
+            [[msg], ["got:", got], ["expected:", expected]]);
+    },
+
+    testResult: function (pass, msg, failures) {
+        this.testIndex += 1;
+        if (pass) {
+            this.print("ok " + this.testIndex + " - " + msg);
+            return;
+        }
+        this.print("not ok " + this.testIndex + " - " + msg);
+        if (failures) {
+            for (var i = 0; i < failures.length; i++) {
+                this.print("# " + failures[i].join(" "));
+            }
+        }
+    },
+
+    isDeeply: function (got, expected, /* optional */message) {
+        var m = MochiKit.Base;
+        var res = 1;
+        try {
+            res = m.compare(got, expected);
+        } catch (e) {
+            // pass
+        }
+        if (res === 0) {
+            return this.ok(true, message);
+        }
+        var gk = m.keys(got);
+        var ek = m.keys(expected);
+        gk.sort();
+        ek.sort();
+        if (m.compare(gk, ek)) {
+            // differing keys
+            var cmp = {};
+            var i;
+            for (i = 0; i < gk.length; i++) {
+                cmp[gk[i]] = "got";
+            }
+            for (i = 0; i < ek.length; i++) {
+                if (ek[i] in cmp) {
+                    delete cmp[ek[i]];
+                } else {
+                    cmp[ek[i]] = "expected";
+                }
+            }
+            var diffkeys = m.keys(cmp);
+            diffkeys.sort();
+            var gotkeys = [];
+            var expkeys = [];
+            while (diffkeys.length) {
+                var k = diffkeys.shift();
+                if (k in Object.prototype) {
+                    continue;
+                }
+                (cmp[k] == "got" ? gotkeys : expkeys).push(k);
+            }
+
+
+        }
+
+        return this.testResult((!res), msg,
+            (msg ? [["got:", got], ["expected:", expected]] : undefined)
+        );
+    },
+
+    ok: function (res, message) {
+        return this.testResult(res, message);
+    }
+};
+
+MochiKit.Test.__new__ = function () {
+    var m = MochiKit.Base;
+
+    this.EXPORT_TAGS = {
+        ":common": this.EXPORT,
+        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+    };
+
+    m.nameFunctions(this);
+
+};
+
+MochiKit.Test.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Test);
diff --git a/mochikit_v14/MochiKit/Visual.js b/mochikit_v14/MochiKit/Visual.js
new file mode 100644 (file)
index 0000000..b7b9ff5
--- /dev/null
@@ -0,0 +1,1981 @@
+/***
+
+MochiKit.Visual 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito and others.  All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+    dojo.provide('MochiKit.Visual');
+    dojo.require('MochiKit.Base');
+    dojo.require('MochiKit.DOM');
+    dojo.require('MochiKit.Style');
+    dojo.require('MochiKit.Color');
+    dojo.require('MochiKit.Position');
+}
+
+if (typeof(JSAN) != 'undefined') {
+    JSAN.use("MochiKit.Base", []);
+    JSAN.use("MochiKit.DOM", []);
+    JSAN.use("MochiKit.Style", []);
+    JSAN.use("MochiKit.Color", []);
+    JSAN.use("MochiKit.Position", []);
+}
+
+try {
+    if (typeof(MochiKit.Base) === 'undefined' ||
+        typeof(MochiKit.DOM) === 'undefined' ||
+        typeof(MochiKit.Style) === 'undefined' ||
+        typeof(MochiKit.Position) === 'undefined' ||
+        typeof(MochiKit.Color) === 'undefined') {
+        throw "";
+    }
+} catch (e) {
+    throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style, MochiKit.Position and MochiKit.Color!";
+}
+
+if (typeof(MochiKit.Visual) == "undefined") {
+    MochiKit.Visual = {};
+}
+
+MochiKit.Visual.NAME = "MochiKit.Visual";
+MochiKit.Visual.VERSION = "1.4";
+
+MochiKit.Visual.__repr__ = function () {
+    return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Visual.toString = function () {
+    return this.__repr__();
+};
+
+MochiKit.Visual._RoundCorners = function (e, options) {
+    e = MochiKit.DOM.getElement(e);
+    this._setOptions(options);
+    if (this.options.__unstable__wrapElement) {
+        e = this._doWrap(e);
+    }
+
+    var color = this.options.color;
+    var C = MochiKit.Color.Color;
+    if (this.options.color === "fromElement") {
+        color = C.fromBackground(e);
+    } else if (!(color instanceof C)) {
+        color = C.fromString(color);
+    }
+    this.isTransparent = (color.asRGB().a <= 0);
+
+    var bgColor = this.options.bgColor;
+    if (this.options.bgColor === "fromParent") {
+        bgColor = C.fromBackground(e.offsetParent);
+    } else if (!(bgColor instanceof C)) {
+        bgColor = C.fromString(bgColor);
+    }
+
+    this._roundCornersImpl(e, color, bgColor);
+};
+
+MochiKit.Visual._RoundCorners.prototype = {
+    _doWrap: function (e) {
+        var parent = e.parentNode;
+        var doc = MochiKit.DOM.currentDocument();
+        if (typeof(doc.defaultView) === "undefined"
+            || doc.defaultView === null) {
+            return e;
+        }
+        var style = doc.defaultView.getComputedStyle(e, null);
+        if (typeof(style) === "undefined" || style === null) {
+            return e;
+        }
+        var wrapper = MochiKit.DOM.DIV({"style": {
+            display: "block",
+            // convert padding to margin
+            marginTop: style.getPropertyValue("padding-top"),
+            marginRight: style.getPropertyValue("padding-right"),
+            marginBottom: style.getPropertyValue("padding-bottom"),
+            marginLeft: style.getPropertyValue("padding-left"),
+            // remove padding so the rounding looks right
+            padding: "0px"
+            /*
+            paddingRight: "0px",
+            paddingLeft: "0px"
+            */
+        }});
+        wrapper.innerHTML = e.innerHTML;
+        e.innerHTML = "";
+        e.appendChild(wrapper);
+        return e;
+    },
+
+    _roundCornersImpl: function (e, color, bgColor) {
+        if (this.options.border) {
+            this._renderBorder(e, bgColor);
+        }
+        if (this._isTopRounded()) {
+            this._roundTopCorners(e, color, bgColor);
+        }
+        if (this._isBottomRounded()) {
+            this._roundBottomCorners(e, color, bgColor);
+        }
+    },
+
+    _renderBorder: function (el, bgColor) {
+        var borderValue = "1px solid " + this._borderColor(bgColor);
+        var borderL = "border-left: "  + borderValue;
+        var borderR = "border-right: " + borderValue;
+        var style = "style='" + borderL + ";" + borderR +  "'";
+        el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
+    },
+
+    _roundTopCorners: function (el, color, bgColor) {
+        var corner = this._createCorner(bgColor);
+        for (var i = 0; i < this.options.numSlices; i++) {
+            corner.appendChild(
+                this._createCornerSlice(color, bgColor, i, "top")
+            );
+        }
+        el.style.paddingTop = 0;
+        el.insertBefore(corner, el.firstChild);
+    },
+
+    _roundBottomCorners: function (el, color, bgColor) {
+        var corner = this._createCorner(bgColor);
+        for (var i = (this.options.numSlices - 1); i >= 0; i--) {
+            corner.appendChild(
+                this._createCornerSlice(color, bgColor, i, "bottom")
+            );
+        }
+        el.style.paddingBottom = 0;
+        el.appendChild(corner);
+    },
+
+    _createCorner: function (bgColor) {
+        var dom = MochiKit.DOM;
+        return dom.DIV({style: {backgroundColor: bgColor.toString()}});
+    },
+
+    _createCornerSlice: function (color, bgColor, n, position) {
+        var slice = MochiKit.DOM.SPAN();
+
+        var inStyle = slice.style;
+        inStyle.backgroundColor = color.toString();
+        inStyle.display = "block";
+        inStyle.height = "1px";
+        inStyle.overflow = "hidden";
+        inStyle.fontSize = "1px";
+
+        var borderColor = this._borderColor(color, bgColor);
+        if (this.options.border && n === 0) {
+            inStyle.borderTopStyle = "solid";
+            inStyle.borderTopWidth = "1px";
+            inStyle.borderLeftWidth = "0px";
+            inStyle.borderRightWidth = "0px";
+            inStyle.borderBottomWidth = "0px";
+            // assumes css compliant box model
+            inStyle.height = "0px";
+            inStyle.borderColor = borderColor.toString();
+        } else if (borderColor) {
+            inStyle.borderColor = borderColor.toString();
+            inStyle.borderStyle = "solid";
+            inStyle.borderWidth = "0px 1px";
+        }
+
+        if (!this.options.compact && (n == (this.options.numSlices - 1))) {
+            inStyle.height = "2px";
+        }
+
+        this._setMargin(slice, n, position);
+        this._setBorder(slice, n, position);
+
+        return slice;
+    },
+
+    _setOptions: function (options) {
+        this.options = {
+            corners: "all",
+            color: "fromElement",
+            bgColor: "fromParent",
+            blend: true,
+            border: false,
+            compact: false,
+            __unstable__wrapElement: false
+        };
+        MochiKit.Base.update(this.options, options);
+
+        this.options.numSlices = (this.options.compact ? 2 : 4);
+    },
+
+    _whichSideTop: function () {
+        var corners = this.options.corners;
+        if (this._hasString(corners, "all", "top")) {
+            return "";
+        }
+
+        var has_tl = (corners.indexOf("tl") != -1);
+        var has_tr = (corners.indexOf("tr") != -1);
+        if (has_tl && has_tr) {
+            return "";
+        }
+        if (has_tl) {
+            return "left";
+        }
+        if (has_tr) {
+            return "right";
+        }
+        return "";
+    },
+
+    _whichSideBottom: function () {
+        var corners = this.options.corners;
+        if (this._hasString(corners, "all", "bottom")) {
+            return "";
+        }
+
+        var has_bl = (corners.indexOf('bl') != -1);
+        var has_br = (corners.indexOf('br') != -1);
+        if (has_bl && has_br) {
+            return "";
+        }
+        if (has_bl) {
+            return "left";
+        }
+        if (has_br) {
+            return "right";
+        }
+        return "";
+    },
+
+    _borderColor: function (color, bgColor) {
+        if (color == "transparent") {
+            return bgColor;
+        } else if (this.options.border) {
+            return this.options.border;
+        } else if (this.options.blend) {
+            return bgColor.blendedColor(color);
+        }
+        return "";
+    },
+
+
+    _setMargin: function (el, n, corners) {
+        var marginSize = this._marginSize(n) + "px";
+        var whichSide = (
+            corners == "top" ? this._whichSideTop() : this._whichSideBottom()
+        );
+        var style = el.style;
+
+        if (whichSide == "left") {
+            style.marginLeft = marginSize;
+            style.marginRight = "0px";
+        } else if (whichSide == "right") {
+            style.marginRight = marginSize;
+            style.marginLeft = "0px";
+        } else {
+            style.marginLeft = marginSize;
+            style.marginRight = marginSize;
+        }
+    },
+
+    _setBorder: function (el, n, corners) {
+        var borderSize = this._borderSize(n) + "px";
+        var whichSide = (
+            corners == "top" ? this._whichSideTop() : this._whichSideBottom()
+        );
+
+        var style = el.style;
+        if (whichSide == "left") {
+            style.borderLeftWidth = borderSize;
+            style.borderRightWidth = "0px";
+        } else if (whichSide == "right") {
+            style.borderRightWidth = borderSize;
+            style.borderLeftWidth = "0px";
+        } else {
+            style.borderLeftWidth = borderSize;
+            style.borderRightWidth = borderSize;
+        }
+    },
+
+    _marginSize: function (n) {
+        if (this.isTransparent) {
+            return 0;
+        }
+
+        var o = this.options;
+        if (o.compact && o.blend) {
+            var smBlendedMarginSizes = [1, 0];
+            return smBlendedMarginSizes[n];
+        } else if (o.compact) {
+            var compactMarginSizes = [2, 1];
+            return compactMarginSizes[n];
+        } else if (o.blend) {
+            var blendedMarginSizes = [3, 2, 1, 0];
+            return blendedMarginSizes[n];
+        } else {
+            var marginSizes = [5, 3, 2, 1];
+            return marginSizes[n];
+        }
+    },
+
+    _borderSize: function (n) {
+        var o = this.options;
+        var borderSizes;
+        if (o.compact && (o.blend || this.isTransparent)) {
+            return 1;
+        } else if (o.compact) {
+            borderSizes = [1, 0];
+        } else if (o.blend) {
+            borderSizes = [2, 1, 1, 1];
+        } else if (o.border) {
+            borderSizes = [0, 2, 0, 0];
+        } else if (this.isTransparent) {
+            borderSizes = [5, 3, 2, 1];
+        } else {
+            return 0;
+        }
+        return borderSizes[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);
+    }
+};
+
+/** @id MochiKit.Visual.roundElement */
+MochiKit.Visual.roundElement = function (e, options) {
+    new MochiKit.Visual._RoundCorners(e, options);
+};
+
+/** @id MochiKit.Visual.roundClass */
+MochiKit.Visual.roundClass = function (tagName, className, options) {
+    var elements = MochiKit.DOM.getElementsByTagAndClassName(
+        tagName, className
+    );
+    for (var i = 0; i < elements.length; i++) {
+        MochiKit.Visual.roundElement(elements[i], options);
+    }
+};
+
+/** @id MochiKit.Visual.tagifyText */
+MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) {
+    /***
+
+    Change a node text to character in tags.
+
+    @param tagifyStyle: the style to apply to character nodes, default to
+    'position: relative'.
+
+    ***/
+    tagifyStyle = tagifyStyle || 'position:relative';
+    if (/MSIE/.test(navigator.userAgent)) {
+        tagifyStyle += ';zoom:1';
+    }
+    element = MochiKit.DOM.getElement(element);
+    var ma = MochiKit.Base.map;
+    ma(function (child) {
+        if (child.nodeType == 3) {
+            ma(function (character) {
+                element.insertBefore(
+                    MochiKit.DOM.SPAN({style: tagifyStyle},
+                        character == ' ' ? String.fromCharCode(160) : character), child);
+            }, child.nodeValue.split(''));
+            MochiKit.DOM.removeElement(child);
+        }
+    }, element.childNodes);
+};
+
+/** @id MochiKit.Visual.forceRerendering */
+MochiKit.Visual.forceRerendering = function (element) {
+    try {
+        element = MochiKit.DOM.getElement(element);
+        var n = document.createTextNode(' ');
+        element.appendChild(n);
+        element.removeChild(n);
+    } catch(e) {
+    }
+};
+
+/** @id MochiKit.Visual.multiple */
+MochiKit.Visual.multiple = function (elements, effect, /* optional */options) {
+    /***
+
+    Launch the same effect subsequently on given elements.
+
+    ***/
+    options = MochiKit.Base.update({
+        speed: 0.1, delay: 0.0
+    }, options || {});
+    var masterDelay = options.delay;
+    var index = 0;
+    MochiKit.Base.map(function (innerelement) {
+        options.delay = index * options.speed + masterDelay;
+        new effect(innerelement, options);
+        index += 1;
+    }, elements);
+};
+
+MochiKit.Visual.PAIRS = {
+    'slide': ['slideDown', 'slideUp'],
+    'blind': ['blindDown', 'blindUp'],
+    'appear': ['appear', 'fade'],
+    'size': ['grow', 'shrink']
+};
+
+/** @id MochiKit.Visual.toggle */
+MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) {
+    /***
+
+    Toggle an item between two state depending of its visibility, making
+    a effect between these states. Default  effect is 'appear', can be
+    'slide' or 'blind'.
+
+    ***/
+    element = MochiKit.DOM.getElement(element);
+    effect = (effect || 'appear').toLowerCase();
+    options = MochiKit.Base.update({
+        queue: {position: 'end', scope: (element.id || 'global'), limit: 1}
+    }, options || {});
+    var v = MochiKit.Visual;
+    v[element.style.display != 'none' ?
+      v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options);
+};
+
+/***
+
+Transitions: define functions calculating variations depending of a position.
+
+***/
+
+MochiKit.Visual.Transitions = {};
+
+/** @id MochiKit.Visual.Transitions.linear */
+MochiKit.Visual.Transitions.linear = function (pos) {
+    return pos;
+};
+
+/** @id MochiKit.Visual.Transitions.sinoidal */
+MochiKit.Visual.Transitions.sinoidal = function (pos) {
+    return (-Math.cos(pos*Math.PI)/2) + 0.5;
+};
+
+/** @id MochiKit.Visual.Transitions.reverse */
+MochiKit.Visual.Transitions.reverse = function (pos) {
+    return 1 - pos;
+};
+
+/** @id MochiKit.Visual.Transitions.flicker */
+MochiKit.Visual.Transitions.flicker = function (pos) {
+    return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+};
+
+/** @id MochiKit.Visual.Transitions.wobble */
+MochiKit.Visual.Transitions.wobble = function (pos) {
+    return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+};
+
+/** @id MochiKit.Visual.Transitions.pulse */
+MochiKit.Visual.Transitions.pulse = function (pos, pulses) {
+    if (!pulses) {
+        return (Math.floor(pos*10) % 2 === 0 ?
+            (pos*10 - Math.floor(pos*10)) : 1 - (pos*10 - Math.floor(pos*10)));
+    }
+    return (Math.round((pos % (1/pulses)) * pulses) == 0 ?
+            ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
+        1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2)));
+};
+
+/** @id MochiKit.Visual.Transitions.none */
+MochiKit.Visual.Transitions.none = function (pos) {
+    return 0;
+};
+
+/** @id MochiKit.Visual.Transitions.full */
+MochiKit.Visual.Transitions.full = function (pos) {
+    return 1;
+};
+
+/***
+
+Core effects
+
+***/
+
+MochiKit.Visual.ScopedQueue = function () {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls();
+    }
+    this.__init__();
+};
+
+MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, {
+    __init__: function () {
+        this.effects = [];
+        this.interval = null;
+    },
+
+    /** @id MochiKit.Visual.ScopedQueue.prototype.add */
+    add: function (effect) {
+        var timestamp = new Date().getTime();
+
+        var position = (typeof(effect.options.queue) == 'string') ?
+            effect.options.queue : effect.options.queue.position;
+
+        var ma = MochiKit.Base.map;
+        switch (position) {
+            case 'front':
+                // move unstarted effects after this effect
+                ma(function (e) {
+                    if (e.state == 'idle') {
+                        e.startOn += effect.finishOn;
+                        e.finishOn += effect.finishOn;
+                    }
+                }, this.effects);
+                break;
+            case 'end':
+                var finish;
+                // start effect after last queued effect has finished
+                ma(function (e) {
+                    var i = e.finishOn;
+                    if (i >= (finish || i)) {
+                        finish = i;
+                    }
+                }, this.effects);
+                timestamp = finish || timestamp;
+                break;
+            case 'break':
+                ma(function (e) {
+                    e.finalize();
+                }, this.effects);
+                break;
+        }
+
+        effect.startOn += timestamp;
+        effect.finishOn += timestamp;
+        if (!effect.options.queue.limit ||
+            this.effects.length < effect.options.queue.limit) {
+            this.effects.push(effect);
+        }
+
+        if (!this.interval) {
+            this.interval = this.startLoop(MochiKit.Base.bind(this.loop, this),
+                                        40);
+        }
+    },
+
+    /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */
+    startLoop: function (func, interval) {
+        return setInterval(func, interval);
+    },
+
+    /** @id MochiKit.Visual.ScopedQueue.prototype.remove */
+    remove: function (effect) {
+        this.effects = MochiKit.Base.filter(function (e) {
+            return e != effect;
+        }, this.effects);
+        if (!this.effects.length) {
+            this.stopLoop(this.interval);
+            this.interval = null;
+        }
+    },
+
+    /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */
+    stopLoop: function (interval) {
+        clearInterval(interval);
+    },
+
+    /** @id MochiKit.Visual.ScopedQueue.prototype.loop */
+    loop: function () {
+        var timePos = new Date().getTime();
+        MochiKit.Base.map(function (effect) {
+            effect.loop(timePos);
+        }, this.effects);
+    }
+});
+
+MochiKit.Visual.Queues = {
+    instances: {},
+
+    get: function (queueName) {
+        if (typeof(queueName) != 'string') {
+            return queueName;
+        }
+
+        if (!this.instances[queueName]) {
+            this.instances[queueName] = new MochiKit.Visual.ScopedQueue();
+        }
+        return this.instances[queueName];
+    }
+};
+
+MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global');
+
+MochiKit.Visual.DefaultOptions = {
+    transition: MochiKit.Visual.Transitions.sinoidal,
+    duration: 1.0,  // seconds
+    fps: 25.0,  // max. 25fps due to MochiKit.Visual.Queue implementation
+    sync: false,  // true for combining
+    from: 0.0,
+    to: 1.0,
+    delay: 0.0,
+    queue: 'parallel'
+};
+
+MochiKit.Visual.Base = function () {};
+
+MochiKit.Visual.Base.prototype = {
+    /***
+
+    Basic class for all Effects. Define a looping mechanism called for each step
+    of an effect. Don't instantiate it, only subclass it.
+
+    ***/
+
+    __class__ : MochiKit.Visual.Base,
+
+    /** @id MochiKit.Visual.Base.prototype.start */
+    start: function (options) {
+        var v = MochiKit.Visual;
+        this.options = MochiKit.Base.setdefault(options || {},
+                                                v.DefaultOptions);
+        this.currentFrame = 0;
+        this.state = 'idle';
+        this.startOn = this.options.delay*1000;
+        this.finishOn = this.startOn + (this.options.duration*1000);
+        this.event('beforeStart');
+        if (!this.options.sync) {
+            v.Queues.get(typeof(this.options.queue) == 'string' ?
+                'global' : this.options.queue.scope).add(this);
+        }
+    },
+
+    /** @id MochiKit.Visual.Base.prototype.loop */
+    loop: function (timePos) {
+        if (timePos >= this.startOn) {
+            if (timePos >= this.finishOn) {
+                return this.finalize();
+            }
+            var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
+            var frame =
+                Math.round(pos * this.options.fps * this.options.duration);
+            if (frame > this.currentFrame) {
+                this.render(pos);
+                this.currentFrame = frame;
+            }
+        }
+    },
+
+    /** @id MochiKit.Visual.Base.prototype.render */
+    render: function (pos) {
+        if (this.state == 'idle') {
+            this.state = 'running';
+            this.event('beforeSetup');
+            this.setup();
+            this.event('afterSetup');
+        }
+        if (this.state == 'running') {
+            if (this.options.transition) {
+                pos = this.options.transition(pos);
+            }
+            pos *= (this.options.to - this.options.from);
+            pos += this.options.from;
+            this.event('beforeUpdate');
+            this.update(pos);
+            this.event('afterUpdate');
+        }
+    },
+
+    /** @id MochiKit.Visual.Base.prototype.cancel */
+    cancel: function () {
+        if (!this.options.sync) {
+            MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ?
+                'global' : this.options.queue.scope).remove(this);
+        }
+        this.state = 'finished';
+    },
+
+    /** @id MochiKit.Visual.Base.prototype.finalize */
+    finalize: function () {
+        this.render(1.0);
+        this.cancel();
+        this.event('beforeFinish');
+        this.finish();
+        this.event('afterFinish');
+    },
+
+    setup: function () {
+    },
+
+    finish: function () {
+    },
+
+    update: function (position) {
+    },
+
+    /** @id MochiKit.Visual.Base.prototype.event */
+    event: function (eventName) {
+        if (this.options[eventName + 'Internal']) {
+            this.options[eventName + 'Internal'](this);
+        }
+        if (this.options[eventName]) {
+            this.options[eventName](this);
+        }
+    },
+
+    /** @id MochiKit.Visual.Base.prototype.repr */
+    repr: function () {
+        return '[' + this.__class__.NAME + ', options:' +
+               MochiKit.Base.repr(this.options) + ']';
+    }
+};
+
+    /** @id MochiKit.Visual.Parallel */
+MochiKit.Visual.Parallel = function (effects, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(effects, options);
+    }
+
+    this.__init__(effects, options);
+};
+
+MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, {
+    /***
+
+    Run multiple effects at the same time.
+
+    ***/
+
+    __class__ : MochiKit.Visual.Parallel,
+
+    __init__: function (effects, options) {
+        this.effects = effects || [];
+        this.start(options);
+    },
+
+    /** @id MochiKit.Visual.Parallel.prototype.update */
+    update: function (position) {
+        MochiKit.Base.map(function (effect) {
+            effect.render(position);
+        }, this.effects);
+    },
+
+    /** @id MochiKit.Visual.Parallel.prototype.finish */
+    finish: function () {
+        MochiKit.Base.map(function (effect) {
+            effect.finalize();
+        }, this.effects);
+    }
+});
+
+/** @id MochiKit.Visual.Opacity */
+MochiKit.Visual.Opacity = function (element, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, options);
+    }
+    this.__init__(element, options);
+};
+
+MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, {
+    /***
+
+    Change the opacity of an element.
+
+    @param options: 'from' and 'to' change the starting and ending opacities.
+    Must be between 0.0 and 1.0. Default to current opacity and 1.0.
+
+    ***/
+
+    __class__ : MochiKit.Visual.Opacity,
+
+    __init__: function (element, /* optional */options) {
+        var b = MochiKit.Base;
+        var s = MochiKit.Style;
+        this.element = MochiKit.DOM.getElement(element);
+        // make this work on IE on elements without 'layout'
+        if (this.element.currentStyle &&
+            (!this.element.currentStyle.hasLayout)) {
+            s.setStyle(this.element, {zoom: 1});
+        }
+        options = b.update({
+            from: s.getStyle(this.element, 'opacity') || 0.0,
+            to: 1.0
+        }, options || {});
+        this.start(options);
+    },
+
+    /** @id MochiKit.Visual.Opacity.prototype.update */
+    update: function (position) {
+        MochiKit.Style.setStyle(this.element, {'opacity': position});
+    }
+});
+
+/**  @id MochiKit.Visual.Move.prototype */
+MochiKit.Visual.Move = function (element, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, options);
+    }
+    this.__init__(element, options);
+};
+
+MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Move.prototype, {
+    /***
+
+    Move an element between its current position to a defined position
+
+    @param options: 'x' and 'y' for final positions, default to 0, 0.
+
+    ***/
+
+    __class__ : MochiKit.Visual.Move,
+
+    __init__: function (element, /* optional */options) {
+        this.element = MochiKit.DOM.getElement(element);
+        options = MochiKit.Base.update({
+            x: 0,
+            y: 0,
+            mode: 'relative'
+        }, options || {});
+        this.start(options);
+    },
+
+    /** @id MochiKit.Visual.Move.prototype.setup */
+    setup: function () {
+        // Bug in Opera: Opera returns the 'real' position of a static element
+        // or relative element that does not have top/left explicitly set.
+        // ==> Always set top and left for position relative elements in your
+        // stylesheets (to 0 if you do not need them)
+        MochiKit.DOM.makePositioned(this.element);
+
+        var s = this.element.style;
+        var originalVisibility = s.visibility;
+        var originalDisplay = s.display;
+        if (originalDisplay == 'none') {
+            s.visibility = 'hidden';
+            s.display = '';
+        }
+
+        this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0');
+        this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0');
+
+        if (this.options.mode == 'absolute') {
+            // absolute movement, so we need to calc deltaX and deltaY
+            this.options.x -= this.originalLeft;
+            this.options.y -= this.originalTop;
+        }
+        if (originalDisplay == 'none') {
+            s.visibility = originalVisibility;
+            s.display = originalDisplay;
+        }
+    },
+
+    /** @id MochiKit.Visual.Move.prototype.update */
+    update: function (position) {
+        MochiKit.Style.setStyle(this.element, {
+            left: Math.round(this.options.x * position + this.originalLeft) + 'px',
+            top: Math.round(this.options.y * position + this.originalTop) + 'px'
+        });
+    }
+});
+
+/** @id MochiKit.Visual.Scale */
+MochiKit.Visual.Scale = function (element, percent, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, percent, options);
+    }
+    this.__init__(element, percent, options);
+};
+
+MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Scale.prototype, {
+    /***
+
+    Change the size of an element.
+
+    @param percent: final_size = percent*original_size
+
+    @param options: several options changing scale behaviour
+
+    ***/
+
+    __class__ : MochiKit.Visual.Scale,
+
+    __init__: function (element, percent, /* optional */options) {
+        this.element = MochiKit.DOM.getElement(element);
+        options = MochiKit.Base.update({
+            scaleX: true,
+            scaleY: true,
+            scaleContent: true,
+            scaleFromCenter: false,
+            scaleMode: 'box',  // 'box' or 'contents' or {} with provided values
+            scaleFrom: 100.0,
+            scaleTo: percent
+        }, options || {});
+        this.start(options);
+    },
+
+    /** @id MochiKit.Visual.Scale.prototype.setup */
+    setup: function () {
+        this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+        this.elementPositioning = MochiKit.Style.getStyle(this.element,
+                                                        'position');
+
+        var ma = MochiKit.Base.map;
+        var b = MochiKit.Base.bind;
+        this.originalStyle = {};
+        ma(b(function (k) {
+                this.originalStyle[k] = this.element.style[k];
+            }, this), ['top', 'left', 'width', 'height', 'fontSize']);
+
+        this.originalTop = this.element.offsetTop;
+        this.originalLeft = this.element.offsetLeft;
+
+        var fontSize = MochiKit.Style.getStyle(this.element,
+                                             'font-size') || '100%';
+        ma(b(function (fontSizeType) {
+            if (fontSize.indexOf(fontSizeType) > 0) {
+                this.fontSize = parseFloat(fontSize);
+                this.fontSizeType = fontSizeType;
+            }
+        }, this), ['em', 'px', '%']);
+
+        this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+        if (/^content/.test(this.options.scaleMode)) {
+            this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+        } else if (this.options.scaleMode == 'box') {
+            this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+        } else {
+            this.dims = [this.options.scaleMode.originalHeight,
+                         this.options.scaleMode.originalWidth];
+        }
+    },
+
+    /** @id MochiKit.Visual.Scale.prototype.update */
+    update: function (position) {
+        var currentScale = (this.options.scaleFrom/100.0) +
+                           (this.factor * position);
+        if (this.options.scaleContent && this.fontSize) {
+            MochiKit.Style.setStyle(this.element, {
+                fontSize: this.fontSize * currentScale + this.fontSizeType
+            });
+        }
+        this.setDimensions(this.dims[0] * currentScale,
+                           this.dims[1] * currentScale);
+    },
+
+    /** @id MochiKit.Visual.Scale.prototype.finish */
+    finish: function () {
+        if (this.restoreAfterFinish) {
+            MochiKit.Style.setStyle(this.element, this.originalStyle);
+        }
+    },
+
+    /** @id MochiKit.Visual.Scale.prototype.setDimensions */
+    setDimensions: function (height, width) {
+        var d = {};
+        var r = Math.round;
+        if (/MSIE/.test(navigator.userAgent)) {
+            r = Math.ceil;
+        }
+        if (this.options.scaleX) {
+            d.width = r(width) + 'px';
+        }
+        if (this.options.scaleY) {
+            d.height = r(height) + 'px';
+        }
+        if (this.options.scaleFromCenter) {
+            var topd = (height - this.dims[0])/2;
+            var leftd = (width - this.dims[1])/2;
+            if (this.elementPositioning == 'absolute') {
+                if (this.options.scaleY) {
+                    d.top = this.originalTop - topd + 'px';
+                }
+                if (this.options.scaleX) {
+                    d.left = this.originalLeft - leftd + 'px';
+                }
+            } else {
+                if (this.options.scaleY) {
+                    d.top = -topd + 'px';
+                }
+                if (this.options.scaleX) {
+                    d.left = -leftd + 'px';
+                }
+            }
+        }
+        MochiKit.Style.setStyle(this.element, d);
+    }
+});
+
+/** @id MochiKit.Visual.Highlight */
+MochiKit.Visual.Highlight = function (element, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, options);
+    }
+    this.__init__(element, options);
+};
+
+MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, {
+    /***
+
+    Highlight an item of the page.
+
+    @param options: 'startcolor' for choosing highlighting color, default
+    to '#ffff99'.
+
+    ***/
+
+    __class__ : MochiKit.Visual.Highlight,
+
+    __init__: function (element, /* optional */options) {
+        this.element = MochiKit.DOM.getElement(element);
+        options = MochiKit.Base.update({
+            startcolor: '#ffff99'
+        }, options || {});
+        this.start(options);
+    },
+
+    /** @id MochiKit.Visual.Highlight.prototype.setup */
+    setup: function () {
+        var b = MochiKit.Base;
+        var s = MochiKit.Style;
+        // Prevent executing on elements not in the layout flow
+        if (s.getStyle(this.element, 'display') == 'none') {
+            this.cancel();
+            return;
+        }
+        // Disable background image during the effect
+        this.oldStyle = {
+            backgroundImage: s.getStyle(this.element, 'background-image')
+        };
+        s.setStyle(this.element, {
+            backgroundImage: 'none'
+        });
+
+        if (!this.options.endcolor) {
+            this.options.endcolor =
+                MochiKit.Color.Color.fromBackground(this.element).toHexString();
+        }
+        if (b.isUndefinedOrNull(this.options.restorecolor)) {
+            this.options.restorecolor = s.getStyle(this.element,
+                                                   'background-color');
+        }
+        // init color calculations
+        this._base = b.map(b.bind(function (i) {
+            return parseInt(
+                this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16);
+        }, this), [0, 1, 2]);
+        this._delta = b.map(b.bind(function (i) {
+            return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16)
+                - this._base[i];
+        }, this), [0, 1, 2]);
+    },
+
+    /** @id MochiKit.Visual.Highlight.prototype.update */
+    update: function (position) {
+        var m = '#';
+        MochiKit.Base.map(MochiKit.Base.bind(function (i) {
+            m += MochiKit.Color.toColorPart(Math.round(this._base[i] +
+                                            this._delta[i]*position));
+        }, this), [0, 1, 2]);
+        MochiKit.Style.setStyle(this.element, {
+            backgroundColor: m
+        });
+    },
+
+    /** @id MochiKit.Visual.Highlight.prototype.finish */
+    finish: function () {
+        MochiKit.Style.setStyle(this.element,
+            MochiKit.Base.update(this.oldStyle, {
+                backgroundColor: this.options.restorecolor
+        }));
+    }
+});
+
+/** @id MochiKit.Visual.ScrollTo */
+MochiKit.Visual.ScrollTo = function (element, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, options);
+    }
+    this.__init__(element, options);
+};
+
+MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, {
+    /***
+
+    Scroll to an element in the page.
+
+    ***/
+
+    __class__ : MochiKit.Visual.ScrollTo,
+
+    __init__: function (element, /* optional */options) {
+        this.element = MochiKit.DOM.getElement(element);
+        this.start(options || {});
+    },
+
+    /** @id MochiKit.Visual.ScrollTo.prototype.setup */
+    setup: function () {
+        var p = MochiKit.Position;
+        p.prepare();
+        var offsets = p.cumulativeOffset(this.element);
+        if (this.options.offset) {
+            offsets.y += this.options.offset;
+        }
+        var max;
+        if (window.innerHeight) {
+            max = window.innerHeight - window.height;
+        } else if (document.documentElement &&
+                   document.documentElement.clientHeight) {
+            max = document.documentElement.clientHeight -
+                  document.body.scrollHeight;
+        } else if (document.body) {
+            max = document.body.clientHeight - document.body.scrollHeight;
+        }
+        this.scrollStart = p.windowOffset.y;
+        this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart;
+    },
+
+    /** @id MochiKit.Visual.ScrollTo.prototype.update */
+    update: function (position) {
+        var p = MochiKit.Position;
+        p.prepare();
+        window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta));
+    }
+});
+
+MochiKit.Visual.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+MochiKit.Visual.Morph = function (element, options) {
+    var cls = arguments.callee;
+    if (!(this instanceof cls)) {
+        return new cls(element, options);
+    }
+    this.__init__(element, options);
+};
+
+MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Morph.prototype, {
+    /***
+
+    Morph effect: make a transformation from current style to the given style,
+    automatically making a transition between the two.
+
+    ***/
+
+    __class__ : MochiKit.Visual.Morph,
+
+    __init__: function (element, /* optional */options) {
+        this.element = MochiKit.DOM.getElement(element);
+        this.start(options || {});
+    },
+
+    /** @id MochiKit.Visual.Morph.prototype.setup */
+    setup: function () {
+        var b = MochiKit.Base;
+        var style = this.options.style;
+        this.styleStart = {};
+        this.styleEnd = {};
+        this.units = {};
+        var value, unit;
+        for (var s in style) {
+            value = style[s];
+            s = b.camelize(s);
+            if (MochiKit.Visual.CSS_LENGTH.test(value)) {
+                var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+                value = parseFloat(components[1]);
+                unit = (components.length == 3) ? components[2] : null;
+                this.styleEnd[s] = value;
+                this.units[s] = unit;
+                value = MochiKit.Style.getStyle(this.element, s);
+                components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+                value = parseFloat(components[1]);
+                this.styleStart[s] = value;
+            } else {
+                var c = MochiKit.Color.Color;
+                value = c.fromString(value);
+                if (value) {
+                    this.units[s] = "color";
+                    this.styleEnd[s] = value.toHexString();
+                    value = MochiKit.Style.getStyle(this.element, s);
+                    this.styleStart[s] = c.fromString(value).toHexString();
+
+                    this.styleStart[s] = b.map(b.bind(function (i) {
+                        return parseInt(
+                            this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16);
+                    }, this), [0, 1, 2]);
+                    this.styleEnd[s] = b.map(b.bind(function (i) {
+                        return parseInt(
+                            this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16);
+                    }, this), [0, 1, 2]);
+                }
+            }
+        }
+    },
+
+    /** @id MochiKit.Visual.Morph.prototype.update */
+    update: function (position) {
+        var value;
+        for (var s in this.styleStart) {
+            if (this.units[s] == "color") {
+                var m = '#';
+                var start = this.styleStart[s];
+                var end = this.styleEnd[s];
+                MochiKit.Base.map(MochiKit.Base.bind(function (i) {
+                    m += MochiKit.Color.toColorPart(Math.round(start[i] +
+                                                    (end[i] - start[i])*position));
+                }, this), [0, 1, 2]);
+                this.element.style[s] = m;
+            } else {
+                value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s];
+                this.element.style[s] = value;
+            }
+        }
+    }
+});
+
+/***
+
+Combination effects.
+
+***/
+
+/** @id MochiKit.Visual.fade */
+MochiKit.Visual.fade = function (element, /* optional */ options) {
+    /***
+
+    Fade a given element: change its opacity and hide it in the end.
+
+    @param options: 'to' and 'from' to change opacity.
+
+    ***/
+    var s = MochiKit.Style;
+    var oldOpacity = s.getStyle(element, 'opacity');
+    options = MochiKit.Base.update({
+        from: s.getStyle(element, 'opacity') || 1.0,
+        to: 0.0,
+        afterFinishInternal: function (effect) {
+            if (effect.options.to !== 0) {
+                return;
+            }
+            s.hideElement(effect.element);
+            s.setStyle(effect.element, {'opacity': oldOpacity});
+        }
+    }, options || {});
+    return new MochiKit.Visual.Opacity(element, options);
+};
+
+/** @id MochiKit.Visual.appear */
+MochiKit.Visual.appear = function (element, /* optional */ options) {
+    /***
+
+    Make an element appear.
+
+    @param options: 'to' and 'from' to change opacity.
+
+    ***/
+    var s = MochiKit.Style;
+    var v = MochiKit.Visual;
+    options = MochiKit.Base.update({
+        from: (s.getStyle(element, 'display') == 'none' ? 0.0 :
+               s.getStyle(element, 'opacity') || 0.0),
+        to: 1.0,
+        // force Safari to render floated elements properly
+        afterFinishInternal: function (effect) {
+            v.forceRerendering(effect.element);
+        },
+        beforeSetupInternal: function (effect) {
+            s.setStyle(effect.element, {'opacity': effect.options.from});
+            s.showElement(effect.element);
+        }
+    }, options || {});
+    return new v.Opacity(element, options);
+};
+
+/** @id MochiKit.Visual.puff */
+MochiKit.Visual.puff = function (element, /* optional */ options) {
+    /***
+
+    'Puff' an element: grow it to double size, fading it and make it hidden.
+
+    ***/
+    var s = MochiKit.Style;
+    var v = MochiKit.Visual;
+    element = MochiKit.DOM.getElement(element);
+    var oldStyle = {
+        position: s.getStyle(element, 'position'),
+        top: element.style.top,
+        left: element.style.left,
+        width: element.style.width,
+        height: element.style.height,
+        opacity: s.getStyle(element, 'opacity')
+    };
+    options = MochiKit.Base.update({
+        beforeSetupInternal: function (effect) {
+            MochiKit.Position.absolutize(effect.effects[0].element);
+        },
+        afterFinishInternal: function (effect) {
+            s.hideElement(effect.effects[0].element);
+            s.setStyle(effect.effects[0].element, oldStyle);
+        },
+        scaleContent: true,
+        scaleFromCenter: true
+    }, options || {});
+    return new v.Parallel(
+        [new v.Scale(element, 200,
+            {sync: true, scaleFromCenter: options.scaleFromCenter,
+             scaleContent: options.scaleContent, restoreAfterFinish: true}),
+         new v.Opacity(element, {sync: true, to: 0.0 })],
+        options);
+};
+
+/** @id MochiKit.Visual.blindUp */
+MochiKit.Visual.blindUp = function (element, /* optional */ options) {
+    /***
+
+    Blind an element up: change its vertical size to 0.
+
+    ***/
+    var d = MochiKit.DOM;
+    element = d.getElement(element);
+    var elemClip = d.makeClipping(element);
+    options = MochiKit.Base.update({
+        scaleContent: false,
+        scaleX: false,
+        restoreAfterFinish: true,
+        afterFinishInternal: function (effect) {
+            MochiKit.Style.hideElement(effect.element);
+            d.undoClipping(effect.element, elemClip);
+        }
+    }, options || {});
+
+    return new MochiKit.Visual.Scale(element, 0, options);
+};
+
+/** @id MochiKit.Visual.blindDown */
+MochiKit.Visual.blindDown = function (element, /* optional */ options) {
+    /***
+
+    Blind an element down: restore its vertical size.
+
+    ***/
+    var d = MochiKit.DOM;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    var elementDimensions = s.getElementDimensions(element);
+    var elemClip;
+    options = MochiKit.Base.update({
+        scaleContent: false,
+        scaleX: false,
+        scaleFrom: 0,
+        scaleMode: {originalHeight: elementDimensions.h,
+                    originalWidth: elementDimensions.w},
+        restoreAfterFinish: true,
+        afterSetupInternal: function (effect) {
+            elemClip = d.makeClipping(effect.element);
+            s.setStyle(effect.element, {height: '0px'});
+            s.showElement(effect.element);
+        },
+        afterFinishInternal: function (effect) {
+            d.undoClipping(effect.element, elemClip);
+        }
+    }, options || {});
+    return new MochiKit.Visual.Scale(element, 100, options);
+};
+
+/** @id MochiKit.Visual.switchOff */
+MochiKit.Visual.switchOff = function (element, /* optional */ options) {
+    /***
+
+    Apply a switch-off-like effect.
+
+    ***/
+    var d = MochiKit.DOM;
+    element = d.getElement(element);
+    var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
+    var elemClip;
+    options = MochiKit.Base.update({
+        duration: 0.3,
+        scaleFromCenter: true,
+        scaleX: false,
+        scaleContent: false,
+        restoreAfterFinish: true,
+        beforeSetupInternal: function (effect) {
+            d.makePositioned(effect.element);
+            elemClip = d.makeClipping(effect.element);
+        },
+        afterFinishInternal: function (effect) {
+            MochiKit.Style.hideElement(effect.element);
+            d.undoClipping(effect.element, elemClip);
+            d.undoPositioned(effect.element);
+            MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
+        }
+    }, options || {});
+    var v = MochiKit.Visual;
+    return new v.appear(element, {
+        duration: 0.4,
+        from: 0,
+        transition: v.Transitions.flicker,
+        afterFinishInternal: function (effect) {
+            new v.Scale(effect.element, 1, options);
+        }
+    });
+};
+
+/** @id MochiKit.Visual.dropOut */
+MochiKit.Visual.dropOut = function (element, /* optional */ options) {
+    /***
+
+    Make an element fall and disappear.
+
+    ***/
+    var d = MochiKit.DOM;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    var oldStyle = {
+        top: s.getStyle(element, 'top'),
+        left: s.getStyle(element, 'left'),
+        opacity: s.getStyle(element, 'opacity')
+    };
+
+    options = MochiKit.Base.update({
+        duration: 0.5,
+        distance: 100,
+        beforeSetupInternal: function (effect) {
+            d.makePositioned(effect.effects[0].element);
+        },
+        afterFinishInternal: function (effect) {
+            s.hideElement(effect.effects[0].element);
+            d.undoPositioned(effect.effects[0].element);
+            s.setStyle(effect.effects[0].element, oldStyle);
+        }
+    }, options || {});
+    var v = MochiKit.Visual;
+    return new v.Parallel(
+        [new v.Move(element, {x: 0, y: options.distance, sync: true}),
+         new v.Opacity(element, {sync: true, to: 0.0})],
+        options);
+};
+
+/** @id MochiKit.Visual.shake */
+MochiKit.Visual.shake = function (element, /* optional */ options) {
+    /***
+
+    Move an element from left to right several times.
+
+    ***/
+    var d = MochiKit.DOM;
+    var v = MochiKit.Visual;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    options = MochiKit.Base.update({
+        x: -20,
+        y: 0,
+        duration: 0.05,
+        afterFinishInternal: function (effect) {
+            d.undoPositioned(effect.element);
+            s.setStyle(effect.element, oldStyle);
+        }
+    }, options || {});
+    var oldStyle = {
+        top: s.getStyle(element, 'top'),
+        left: s.getStyle(element, 'left') };
+        return new v.Move(element,
+          {x: 20, y: 0, duration: 0.05, afterFinishInternal: function (effect) {
+        new v.Move(effect.element,
+          {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+        new v.Move(effect.element,
+           {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+        new v.Move(effect.element,
+          {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+        new v.Move(effect.element,
+           {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+        new v.Move(effect.element, options
+        ) }}) }}) }}) }}) }});
+};
+
+/** @id MochiKit.Visual.slideDown */
+MochiKit.Visual.slideDown = function (element, /* optional */ options) {
+    /***
+
+    Slide an element down.
+    It needs to have the content of the element wrapped in a container
+    element with fixed height.
+
+    ***/
+    var d = MochiKit.DOM;
+    var b = MochiKit.Base;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    if (!element.firstChild) {
+        throw "MochiKit.Visual.slideDown must be used on a element with a child";
+    }
+    d.removeEmptyTextNodes(element);
+    var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0;
+    var elementDimensions = s.getElementDimensions(element);
+    var elemClip;
+    options = b.update({
+        scaleContent: false,
+        scaleX: false,
+        scaleFrom: 0,
+        scaleMode: {originalHeight: elementDimensions.h,
+                    originalWidth: elementDimensions.w},
+        restoreAfterFinish: true,
+        afterSetupInternal: function (effect) {
+            d.makePositioned(effect.element);
+            d.makePositioned(effect.element.firstChild);
+            if (/Opera/.test(navigator.userAgent)) {
+                s.setStyle(effect.element, {top: ''});
+            }
+            elemClip = d.makeClipping(effect.element);
+            s.setStyle(effect.element, {height: '0px'});
+            s.showElement(effect.element);
+        },
+        afterUpdateInternal: function (effect) {
+            s.setStyle(effect.element.firstChild,
+               {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'});
+        },
+        afterFinishInternal: function (effect) {
+            d.undoClipping(effect.element, elemClip);
+            // IE will crash if child is undoPositioned first
+            if (/MSIE/.test(navigator.userAgent)) {
+                d.undoPositioned(effect.element);
+                d.undoPositioned(effect.element.firstChild);
+            } else {
+                d.undoPositioned(effect.element.firstChild);
+                d.undoPositioned(effect.element);
+            }
+            s.setStyle(effect.element.firstChild,
+                                  {bottom: oldInnerBottom});
+        }
+    }, options || {});
+
+    return new MochiKit.Visual.Scale(element, 100, options);
+};
+
+/** @id MochiKit.Visual.slideUp */
+MochiKit.Visual.slideUp = function (element, /* optional */ options) {
+    /***
+
+    Slide an element up.
+    It needs to have the content of the element wrapped in a container
+    element with fixed height.
+
+    ***/
+    var d = MochiKit.DOM;
+    var b = MochiKit.Base;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    if (!element.firstChild) {
+        throw "MochiKit.Visual.slideUp must be used on a element with a child";
+    }
+    d.removeEmptyTextNodes(element);
+    var oldInnerBottom = s.getStyle(element.firstChild, 'bottom');
+    var elemClip;
+    options = b.update({
+        scaleContent: false,
+        scaleX: false,
+        scaleMode: 'box',
+        scaleFrom: 100,
+        restoreAfterFinish: true,
+        beforeStartInternal: function (effect) {
+            d.makePositioned(effect.element);
+            d.makePositioned(effect.element.firstChild);
+            if (/Opera/.test(navigator.userAgent)) {
+                s.setStyle(effect.element, {top: ''});
+            }
+            elemClip = d.makeClipping(effect.element);
+            s.showElement(effect.element);
+        },
+        afterUpdateInternal: function (effect) {
+            s.setStyle(effect.element.firstChild,
+            {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'});
+        },
+        afterFinishInternal: function (effect) {
+            s.hideElement(effect.element);
+            d.undoClipping(effect.element, elemClip);
+            d.undoPositioned(effect.element.firstChild);
+            d.undoPositioned(effect.element);
+            s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
+        }
+    }, options || {});
+    return new MochiKit.Visual.Scale(element, 0, options);
+};
+
+// Bug in opera makes the TD containing this element expand for a instance
+// after finish
+/** @id MochiKit.Visual.squish */
+MochiKit.Visual.squish = function (element, /* optional */ options) {
+    /***
+
+    Reduce an element and make it disappear.
+
+    ***/
+    var d = MochiKit.DOM;
+    var b = MochiKit.Base;
+    var elemClip;
+    options = b.update({
+        restoreAfterFinish: true,
+        beforeSetupInternal: function (effect) {
+            elemClip = d.makeClipping(effect.element);
+        },
+        afterFinishInternal: function (effect) {
+            MochiKit.Style.hideElement(effect.element);
+            d.undoClipping(effect.element, elemClip);
+        }
+    }, options || {});
+
+    return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options);
+};
+
+/** @id MochiKit.Visual.grow */
+MochiKit.Visual.grow = function (element, /* optional */ options) {
+    /***
+
+    Grow an element to its original size. Make it zero-sized before
+    if necessary.
+
+    ***/
+    var d = MochiKit.DOM;
+    var v = MochiKit.Visual;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    options = MochiKit.Base.update({
+        direction: 'center',
+        moveTransition: v.Transitions.sinoidal,
+        scaleTransition: v.Transitions.sinoidal,
+        opacityTransition: v.Transitions.full,
+        scaleContent: true,
+        scaleFromCenter: false
+    }, options || {});
+    var oldStyle = {
+        top: element.style.top,
+        left: element.style.left,
+        height: element.style.height,
+        width: element.style.width,
+        opacity: s.getStyle(element, 'opacity')
+    };
+
+    var dims = s.getElementDimensions(element);
+    var initialMoveX, initialMoveY;
+    var moveX, moveY;
+
+    switch (options.direction) {
+        case 'top-left':
+            initialMoveX = initialMoveY = moveX = moveY = 0;
+            break;
+        case 'top-right':
+            initialMoveX = dims.w;
+            initialMoveY = moveY = 0;
+            moveX = -dims.w;
+            break;
+        case 'bottom-left':
+            initialMoveX = moveX = 0;
+            initialMoveY = dims.h;
+            moveY = -dims.h;
+            break;
+        case 'bottom-right':
+            initialMoveX = dims.w;
+            initialMoveY = dims.h;
+            moveX = -dims.w;
+            moveY = -dims.h;
+            break;
+        case 'center':
+            initialMoveX = dims.w / 2;
+            initialMoveY = dims.h / 2;
+            moveX = -dims.w / 2;
+            moveY = -dims.h / 2;
+            break;
+    }
+
+    var optionsParallel = MochiKit.Base.update({
+        beforeSetupInternal: function (effect) {
+            s.setStyle(effect.effects[0].element, {height: '0px'});
+            s.showElement(effect.effects[0].element);
+        },
+        afterFinishInternal: function (effect) {
+            d.undoClipping(effect.effects[0].element);
+            d.undoPositioned(effect.effects[0].element);
+            s.setStyle(effect.effects[0].element, oldStyle);
+        }
+    }, options || {});
+
+    return new v.Move(element, {
+        x: initialMoveX,
+        y: initialMoveY,
+        duration: 0.01,
+        beforeSetupInternal: function (effect) {
+            s.hideElement(effect.element);
+            d.makeClipping(effect.element);
+            d.makePositioned(effect.element);
+        },
+        afterFinishInternal: function (effect) {
+            new v.Parallel(
+                [new v.Opacity(effect.element, {
+                    sync: true, to: 1.0, from: 0.0,
+                    transition: options.opacityTransition
+                 }),
+                 new v.Move(effect.element, {
+                     x: moveX, y: moveY, sync: true,
+                     transition: options.moveTransition
+                 }),
+                 new v.Scale(effect.element, 100, {
+                        scaleMode: {originalHeight: dims.h,
+                                    originalWidth: dims.w},
+                        sync: true,
+                        scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0,
+                        transition: options.scaleTransition,
+                        scaleContent: options.scaleContent,
+                        scaleFromCenter: options.scaleFromCenter,
+                        restoreAfterFinish: true
+                })
+                ], optionsParallel
+            );
+        }
+    });
+};
+
+/** @id MochiKit.Visual.shrink */
+MochiKit.Visual.shrink = function (element, /* optional */ options) {
+    /***
+
+    Shrink an element and make it disappear.
+
+    ***/
+    var d = MochiKit.DOM;
+    var v = MochiKit.Visual;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    options = MochiKit.Base.update({
+        direction: 'center',
+        moveTransition: v.Transitions.sinoidal,
+        scaleTransition: v.Transitions.sinoidal,
+        opacityTransition: v.Transitions.none,
+        scaleContent: true,
+        scaleFromCenter: false
+    }, options || {});
+    var oldStyle = {
+        top: element.style.top,
+        left: element.style.left,
+        height: element.style.height,
+        width: element.style.width,
+        opacity: s.getStyle(element, 'opacity')
+    };
+
+    var dims = s.getElementDimensions(element);
+    var moveX, moveY;
+
+    switch (options.direction) {
+        case 'top-left':
+            moveX = moveY = 0;
+            break;
+        case 'top-right':
+            moveX = dims.w;
+            moveY = 0;
+            break;
+        case 'bottom-left':
+            moveX = 0;
+            moveY = dims.h;
+            break;
+        case 'bottom-right':
+            moveX = dims.w;
+            moveY = dims.h;
+            break;
+        case 'center':
+            moveX = dims.w / 2;
+            moveY = dims.h / 2;
+            break;
+    }
+    var elemClip;
+
+    var optionsParallel = MochiKit.Base.update({
+        beforeStartInternal: function (effect) {
+            elemClip = d.makePositioned(effect.effects[0].element);
+            d.makeClipping(effect.effects[0].element);
+        },
+        afterFinishInternal: function (effect) {
+            s.hideElement(effect.effects[0].element);
+            d.undoClipping(effect.effects[0].element, elemClip);
+            d.undoPositioned(effect.effects[0].element);
+            s.setStyle(effect.effects[0].element, oldStyle);
+        }
+    }, options || {});
+
+    return new v.Parallel(
+        [new v.Opacity(element, {
+            sync: true, to: 0.0, from: 1.0,
+            transition: options.opacityTransition
+         }),
+         new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
+             sync: true, transition: options.scaleTransition,
+             scaleContent: options.scaleContent,
+             scaleFromCenter: options.scaleFromCenter,
+             restoreAfterFinish: true
+         }),
+         new v.Move(element, {
+             x: moveX, y: moveY, sync: true, transition: options.moveTransition
+         })
+        ], optionsParallel
+    );
+};
+
+/** @id MochiKit.Visual.pulsate */
+MochiKit.Visual.pulsate = function (element, /* optional */ options) {
+    /***
+
+    Pulse an element between appear/fade.
+
+    ***/
+    var d = MochiKit.DOM;
+    var v = MochiKit.Visual;
+    var b = MochiKit.Base;
+    var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
+    options = b.update({
+        duration: 3.0,
+        from: 0,
+        afterFinishInternal: function (effect) {
+            MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
+        }
+    }, options || {});
+    var transition = options.transition || v.Transitions.sinoidal;
+    var reverser = b.bind(function (pos) {
+        return transition(1 - v.Transitions.pulse(pos, options.pulses));
+    }, transition);
+    b.bind(reverser, transition);
+    return new v.Opacity(element, b.update({
+        transition: reverser}, options));
+};
+
+/** @id MochiKit.Visual.fold */
+MochiKit.Visual.fold = function (element, /* optional */ options) {
+    /***
+
+    Fold an element, first vertically, then horizontally.
+
+    ***/
+    var d = MochiKit.DOM;
+    var v = MochiKit.Visual;
+    var s = MochiKit.Style;
+    element = d.getElement(element);
+    var oldStyle = {
+        top: element.style.top,
+        left: element.style.left,
+        width: element.style.width,
+        height: element.style.height
+    };
+    var elemClip = d.makeClipping(element);
+    options = MochiKit.Base.update({
+        scaleContent: false,
+        scaleX: false,
+        afterFinishInternal: function (effect) {
+            new v.Scale(element, 1, {
+                scaleContent: false,
+                scaleY: false,
+                afterFinishInternal: function (effect) {
+                    s.hideElement(effect.element);
+                    d.undoClipping(effect.element, elemClip);
+                    s.setStyle(effect.element, oldStyle);
+                }
+            });
+        }
+    }, options || {});
+    return new v.Scale(element, 5, options);
+};
+
+
+// Compatibility with MochiKit 1.0
+MochiKit.Visual.Color = MochiKit.Color.Color;
+MochiKit.Visual.getElementsComputedStyle = MochiKit.DOM.computedStyle;
+
+/* end of Rico adaptation */
+
+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",
+    "tagifyText",
+    "multiple",
+    "toggle",
+    "Parallel",
+    "Opacity",
+    "Move",
+    "Scale",
+    "Highlight",
+    "ScrollTo",
+    "Morph",
+    "fade",
+    "appear",
+    "puff",
+    "blindUp",
+    "blindDown",
+    "switchOff",
+    "dropOut",
+    "shake",
+    "slideDown",
+    "slideUp",
+    "squish",
+    "grow",
+    "shrink",
+    "pulsate",
+    "fold"
+];
+
+MochiKit.Visual.EXPORT_OK = [
+    "Base",
+    "PAIRS"
+];
+
+MochiKit.Visual.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Visual);
diff --git a/mochikit_v14/MochiKit/__package__.js b/mochikit_v14/MochiKit/__package__.js
new file mode 100644 (file)
index 0000000..8d644b1
--- /dev/null
@@ -0,0 +1,18 @@
+dojo.kwCompoundRequire({
+    "common": [
+        "MochiKit.Base",
+        "MochiKit.Iter",
+        "MochiKit.Logging",
+        "MochiKit.DateTime",
+        "MochiKit.Format",
+        "MochiKit.Async",
+        "MochiKit.DOM",
+        "MochiKit.Style",
+        "MochiKit.LoggingPane",
+        "MochiKit.Color",
+        "MochiKit.Signal",
+        "MochiKit.Position",
+        "MochiKit.Visual"
+    ]
+});
+dojo.provide("MochiKit.*");
diff --git a/mochikit_v14/doc/html/MochiKit/Async.html b/mochikit_v14/doc/html/MochiKit/Async.html
new file mode 100644 (file)
index 0000000..d9c26cf
--- /dev/null
@@ -0,0 +1,781 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Async - manage asynchronous tasks</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Async - manage asynchronous tasks</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+var url = &quot;/src/b/bo/bob/MochiKit.Async/META.json&quot;;
+/*
+
+    META.json looks something like this:
+
+    {&quot;name&quot;: &quot;MochiKit&quot;, &quot;version&quot;: &quot;0.5&quot;}
+
+*/
+var d = loadJSONDoc(url);
+var gotMetadata = function (meta) {
+    if (MochiKit.Async.VERSION == meta.version) {
+        alert(&quot;You have the newest MochiKit.Async!&quot;);
+    } else {
+        alert(&quot;MochiKit.Async &quot;
+            + meta.version
+            + &quot; is available, upgrade!&quot;);
+    }
+};
+var metadataFetchFailed = function (err) {
+  alert(&quot;The metadata for MochiKit.Async could not be fetched :(&quot;);
+};
+d.addCallbacks(gotMetadata, metadataFetchFailed);
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.Async provides facilities to manage asynchronous (as in AJAX
+<a class="footnote-reference" href="#id7" id="id1" name="id1">[1]</a>) tasks. The model for asynchronous computation used in this
+module is heavily inspired by Twisted <a class="footnote-reference" href="#id8" id="id2" name="id2">[2]</a>.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<div class="section">
+<h2><a id="deferred" name="deferred">Deferred</a></h2>
+<p>The Deferred constructor encapsulates a single value that is not
+available yet. The most important example of this in the context of a
+web browser would be an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to a server. The importance
+of the Deferred is that it allows a consistent API to be exposed for
+all asynchronous computations that occur exactly once.</p>
+<p>The producer of the Deferred is responsible for doing all of the
+complicated work behind the scenes. This often means waiting for a
+timer to fire, or waiting for an event (e.g. <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> of
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>).  It could also be coordinating several events
+(e.g.  <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> with a timeout, or several Deferreds
+(e.g. fetching a set of XML documents that should be processed at the
+same time).</p>
+<p>Since these sorts of tasks do not respond immediately, the producer of
+the Deferred does the following steps before returning to the
+consumer:</p>
+<ol class="arabic simple">
+<li>Create a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred();</a> object and keep a
+reference to it, because it will be needed later when the value is
+ready.</li>
+<li>Setup the conditions to create the value requested (e.g.  create a
+new <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>, set its <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt>).</li>
+<li>Return the <a class="mochiref reference" href="#fn-deferred">Deferred</a> object.</li>
+</ol>
+<p>Since the value is not yet ready, the consumer attaches a function to
+the Deferred that will be called when the value is ready. This is not
+unlike <tt class="docutils literal"><span class="pre">setTimeout</span></tt>, or other similar facilities you may already be
+familiar with.  The consumer can also attach an &quot;errback&quot; to the
+<a class="mochiref reference" href="#fn-deferred">Deferred</a>, which is a callback for error handling.</p>
+<p>When the value is ready, the producer simply calls
+<tt class="docutils literal"><span class="pre">myDeferred.callback(theValue)</span></tt>. If an error occurred, it should
+call <tt class="docutils literal"><span class="pre">myDeferred.errback(theValue)</span></tt> instead.  As soon as this
+happens, the callback that the consumer attached to the
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> is called with <tt class="docutils literal"><span class="pre">theValue</span></tt> as the only argument.</p>
+<p>There are quite a few additional &quot;advanced&quot; features baked into
+<a class="mochiref reference" href="#fn-deferred">Deferred</a>, such as cancellation and callback chains, so
+take a look at the API reference if you would like to know more!</p>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="errors" name="errors">Errors</a></h2>
+<p>
+<a name="fn-alreadycallederror"></a>
+<a class="mochidef reference" href="#fn-alreadycallederror">AlreadyCalledError</a>:</p>
+<blockquote>
+<p>Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> if <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt>
+are called more than once.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-browsercomplianceerror"></a>
+<a class="mochidef reference" href="#fn-browsercomplianceerror">BrowserComplianceError</a>:</p>
+<blockquote>
+<p>Thrown when the JavaScript runtime is not capable of performing
+the given function. Currently, this happens if the browser does
+not support <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-cancellederror"></a>
+<a class="mochidef reference" href="#fn-cancellederror">CancelledError</a>:</p>
+<blockquote>
+<p>Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> when it is cancelled, unless a
+canceller is present and throws something else.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-genericerror"></a>
+<a class="mochidef reference" href="#fn-genericerror">GenericError</a>:</p>
+<blockquote>
+<p>Results passed to <tt class="docutils literal"><span class="pre">.fail</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> of a
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> are wrapped by this <tt class="docutils literal"><span class="pre">Error</span></tt> if <tt class="docutils literal"><span class="pre">!(result</span>
+<span class="pre">instanceof</span> <span class="pre">Error)</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-xmlhttprequesterror"></a>
+<a class="mochidef reference" href="#fn-xmlhttprequesterror">XMLHttpRequestError</a>:</p>
+<blockquote>
+<p>Thrown when an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> does not complete successfully
+for any reason. The <tt class="docutils literal"><span class="pre">req</span></tt> property of the error is the failed
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object, and for convenience the <tt class="docutils literal"><span class="pre">number</span></tt>
+property corresponds to <tt class="docutils literal"><span class="pre">req.status</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="constructors" name="constructors">Constructors</a></h2>
+<p>
+<a name="fn-deferred"></a>
+<a class="mochidef reference" href="#fn-deferred">Deferred()</a>:</p>
+<blockquote>
+Encapsulates a sequence of callbacks in response to a value that
+may not yet be available. This is modeled after the Deferred class
+from Twisted <a class="footnote-reference" href="#id9" id="id3" name="id3">[3]</a>.</blockquote>
+<blockquote>
+<p>Why do we want this?  JavaScript has no threads, and even if it
+did, threads are hard. Deferreds are a way of abstracting
+non-blocking events, such as the final response to an
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</p>
+<p>The sequence of callbacks is internally represented as a list of
+2-tuples containing the callback/errback pair. For example, the
+following call sequence:</p>
+<pre class="literal-block">
+var d = new Deferred();
+d.addCallback(myCallback);
+d.addErrback(myErrback);
+d.addBoth(myBoth);
+d.addCallbacks(myCallback, myErrback);
+</pre>
+<p>is translated into a <a class="mochiref reference" href="#fn-deferred">Deferred</a> with the following
+internal representation:</p>
+<pre class="literal-block">
+[
+    [myCallback, null],
+    [null, myErrback],
+    [myBoth, myBoth],
+    [myCallback, myErrback]
+]
+</pre>
+<p>The <a class="mochiref reference" href="#fn-deferred">Deferred</a> also keeps track of its current status
+(fired).  Its status may be one of the following three values:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="14%" />
+<col width="86%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Value</th>
+<th class="head">Condition</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>-1</td>
+<td>no value yet (initial condition)</td>
+</tr>
+<tr><td>0</td>
+<td>success</td>
+</tr>
+<tr><td>1</td>
+<td>error</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>A <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the error state if one of the
+following conditions are met:</p>
+<ol class="arabic simple">
+<li>The result given to callback or errback is &quot;<tt class="docutils literal"><span class="pre">instanceof</span>
+<span class="pre">Error</span></tt>&quot;</li>
+<li>The callback or errback threw while executing. If the thrown
+object is not <tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Error</span></tt>, it will be wrapped with
+<a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</li>
+</ol>
+<p>Otherwise, the <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the success
+state. The state of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> determines the next
+element in the callback sequence to run.</p>
+<p>When a callback or errback occurs with the example deferred chain,
+something equivalent to the following will happen (imagine that
+exceptions are caught and returned as-is):</p>
+<pre class="literal-block">
+// d.callback(result) or d.errback(result)
+if (!(result instanceof Error)) {
+    result = myCallback(result);
+}
+if (result instanceof Error) {
+    result = myErrback(result);
+}
+result = myBoth(result);
+if (result instanceof Error) {
+    result = myErrback(result);
+} else {
+    result = myCallback(result);
+}
+</pre>
+<p>The result is then stored away in case another step is added to
+the callback sequence. Since the <a class="mochiref reference" href="#fn-deferred">Deferred</a> already has
+a value available, any new callbacks added will be called
+immediately.</p>
+<p>There are two other &quot;advanced&quot; details about this implementation
+that are useful:</p>
+<p>Callbacks are allowed to return <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances, so
+you can build complicated sequences of events with (relative)
+ease.</p>
+<p>The creator of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> may specify a
+canceller. The canceller is a function that will be called if
+<a class="mochiref reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel</a> is called before the
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> fires. You can use this to allow an
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to be cleanly cancelled, for example. Note that
+cancel will fire the <a class="mochiref reference" href="#fn-deferred">Deferred</a> with a
+<a class="mochiref reference" href="#fn-cancellederror">CancelledError</a> (unless your canceller throws or
+returns a different <tt class="docutils literal"><span class="pre">Error</span></tt>), so errbacks should be prepared to
+handle that <tt class="docutils literal"><span class="pre">Error</span></tt> gracefully for cancellable
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> instances.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferred.prototype.addboth"></a>
+<a class="mochidef reference" href="#fn-deferred.prototype.addboth">Deferred.prototype.addBoth(func)</a>:</p>
+<blockquote>
+<p>Add the same function as both a callback and an errback as the
+next element on the callback sequence. This is useful for code
+that you want to guarantee to run, e.g. a finalizer.</p>
+<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
+with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null,
+arguments)</a>. This differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of
+the callback or errback will be the <em>last</em> argument passed to
+<tt class="docutils literal"><span class="pre">func</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be
+chained (its value or error will be passed to the next
+callback). Note that once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it
+can no longer accept new callbacks.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferred.prototype.addcallback"></a>
+<a class="mochidef reference" href="#fn-deferred.prototype.addcallback">Deferred.prototype.addCallback(func[, ...])</a>:</p>
+<blockquote>
+<p>Add a single callback to the end of the callback sequence.</p>
+<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
+with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null,
+arguments)</a>. This differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of
+the callback will be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be
+chained (its value or error will be passed to the next
+callback). Note that once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it
+can no longer accept new callbacks.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferred.prototype.addcallbacks"></a>
+<a class="mochidef reference" href="#fn-deferred.prototype.addcallbacks">Deferred.prototype.addCallbacks(callback, errback)</a>:</p>
+<blockquote>
+<p>Add separate callback and errback to the end of the callback
+sequence. Either callback or errback may be <tt class="docutils literal"><span class="pre">null</span></tt>, but not
+both.</p>
+<p>If <tt class="docutils literal"><span class="pre">callback</span></tt> or <tt class="docutils literal"><span class="pre">errback</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>,
+then it will be chained (its value or error will be passed to the
+next callback). Note that once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is
+chained, it can no longer accept new callbacks.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferred.prototype.adderrback"></a>
+<a class="mochidef reference" href="#fn-deferred.prototype.adderrback">Deferred.prototype.addErrback(func)</a>:</p>
+<blockquote>
+<p>Add a single errback to the end of the callback sequence.</p>
+<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
+with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null,
+arguments)</a>. This differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of
+the errback will be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be
+chained (its value or error will be passed to the next
+callback). Note that once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it
+can no longer accept new callbacks.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferred.prototype.callback"></a>
+<a class="mochidef reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback([result])</a>:</p>
+<blockquote>
+<p>Begin the callback sequence with a non-<tt class="docutils literal"><span class="pre">Error</span></tt> result. Result
+may be any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
+<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should be called exactly once
+on a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferred.prototype.cancel"></a>
+<a class="mochidef reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel()</a>:</p>
+<blockquote>
+<p>Cancels a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has not yet received a value,
+or is waiting on another <a class="mochiref reference" href="#fn-deferred">Deferred</a> as its value.</p>
+<p>If a canceller is defined, the canceller is called.  If the
+canceller did not return an <tt class="docutils literal"><span class="pre">Error</span></tt>, or there was no canceller,
+then the errback chain is started with <a class="mochiref reference" href="#fn-cancellederror">CancelledError</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferred.prototype.errback"></a>
+<a class="mochidef reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback([result])</a>:</p>
+<blockquote>
+<p>Begin the callback sequence with an error result.  Result may be
+any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, but if <tt class="docutils literal"><span class="pre">!(result</span>
+<span class="pre">instanceof</span> <span class="pre">Error)</span></tt>, it will be wrapped with
+<a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</p>
+<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should be called exactly once
+on a 
+<a name="fn-deferred"></a>
+<a class="mochidef reference" href="#fn-deferred">Deferred</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferredlock"></a>
+<a class="mochidef reference" href="#fn-deferredlock">DeferredLock()</a>:</p>
+<blockquote>
+<p>A lock for asynchronous systems.</p>
+<p>The <tt class="docutils literal"><span class="pre">locked</span></tt> property of a <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> will be
+<tt class="docutils literal"><span class="pre">true</span></tt> if it locked, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise. Do not change this
+property.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferredlock.prototype.acquire"></a>
+<a class="mochidef reference" href="#fn-deferredlock.prototype.acquire">DeferredLock.prototype.acquire()</a>:</p>
+<blockquote>
+<p>Attempt to acquire the lock. Returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that
+fires on lock acquisition with the <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> as the
+value.  If the lock is locked, then the <a class="mochiref reference" href="#fn-deferred">Deferred</a> goes
+into a waiting list.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferredlock.prototype.release"></a>
+<a class="mochidef reference" href="#fn-deferredlock.prototype.release">DeferredLock.prototype.release()</a>:</p>
+<blockquote>
+<p>Release the lock. If there is a waiting list, then the first
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> in that waiting list will be called back.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-deferredlist"></a>
+<a class="mochidef reference" href="#fn-deferredlist">DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])</a>:</p>
+<blockquote>
+<p>Combine a list of <a class="mochiref reference" href="#fn-deferred">Deferred</a> into one. Track the
+callbacks and return a list of (success, result) tuples, 'success'
+being a boolean indicating whether result is a normal result or an
+error.</p>
+<p>Once created, you have access to all <a class="mochiref reference" href="#fn-deferred">Deferred</a> methods,
+like addCallback, addErrback, addBoth. The behaviour can be
+changed by the following options:</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">fireOnOneCallback</span></tt>:</dt>
+<dd>Flag for launching the callback once the first Deferred of the
+list has returned.</dd>
+<dt><tt class="docutils literal"><span class="pre">fireOnOneErrback</span></tt>:</dt>
+<dd>Flag for calling the errback at the first error of a Deferred.</dd>
+<dt><tt class="docutils literal"><span class="pre">consumeErrors</span></tt>:</dt>
+<dd>Flag indicating that any errors raised in the Deferreds should
+be consumed by the DeferredList.</dd>
+</dl>
+<p>Example:</p>
+<pre class="literal-block">
+// We need to fetch data from 2 different urls
+var d1 = loadJSONDoc(url1);
+var d2 = loadJSONDoc(url2);
+var l1 = new DeferredList([d1, d2], false, false, true);
+l1.addCallback(function (resultList) {
+    MochiKit.Base.map(function (result) {
+        if (result[0]) {
+            alert(&quot;Data is here: &quot; + result[1]);
+        } else {
+            alert(&quot;Got an error: &quot; + result[1]);
+        }
+    }, resultList);
+});
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-calllater"></a>
+<a class="mochidef reference" href="#fn-calllater">callLater(seconds, func[, args...])</a>:</p>
+<blockquote>
+<p>Call <tt class="docutils literal"><span class="pre">func(args...)</span></tt> after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have
+elapsed.  This is a convenience method for:</p>
+<pre class="literal-block">
+func = partial.apply(extend(null, arguments, 1));
+return wait(seconds).addCallback(function (res) { return func() });
+</pre>
+<p>Returns a cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-doxhr"></a>
+<a class="mochidef reference" href="#fn-doxhr">doXHR(url[, {option: value, ...}])</a>:</p>
+<blockquote>
+<p>Perform a customized <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> and wrap it with a
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> that may be cancelled.</p>
+<p>Note that only <tt class="docutils literal"><span class="pre">200</span></tt> (OK), <tt class="docutils literal"><span class="pre">201</span></tt> (CREATED),
+<tt class="docutils literal"><span class="pre">204</span></tt> (NO CONTENT) and <tt class="docutils literal"><span class="pre">304</span></tt> (NOT MODIFIED) are considered
+success codes. All other status codes will
+result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
+<dd>The URL for this request.</dd>
+</dl>
+<p>The following options are currently accepted:</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">method</span></tt>:</dt>
+<dd>The HTTP method. Default is <tt class="docutils literal"><span class="pre">'GET'</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">sendContent</span></tt>:</dt>
+<dd>The content to send (e.g. with POST). Default is no content.</dd>
+<dt><tt class="docutils literal"><span class="pre">queryString</span></tt>:</dt>
+<dd>If present it will be used to build a query string to append to
+the url using <a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a>. Default is
+no query string.</dd>
+<dt><tt class="docutils literal"><span class="pre">username</span></tt>:</dt>
+<dd>The username for the request. Default is no username.</dd>
+<dt><tt class="docutils literal"><span class="pre">password</span></tt>:</dt>
+<dd>The password for the request. Default is no password.</dd>
+<dt><tt class="docutils literal"><span class="pre">headers</span></tt>:</dt>
+<dd>Additional headers to set in the request, either as an object
+such as <tt class="docutils literal"><span class="pre">{'Accept':</span> <span class="pre">'text/xml'}</span></tt> or as an Array of 2-Arrays
+<tt class="docutils literal"><span class="pre">[['Accept',</span> <span class="pre">'text/xml']]</span></tt>. Default is no additional headers.</dd>
+<dt><tt class="docutils literal"><span class="pre">mimeType</span></tt>:</dt>
+<dd>An override mime type. The typical use of this is to pass
+'text/xml' to force XMLHttpRequest to attempt to parse responseXML.
+Default is no override.</dd>
+<dt><em>returns</em>:</dt>
+<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> instance on success</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+.</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-dosimplexmlhttprequest"></a>
+<a class="mochidef reference" href="#fn-dosimplexmlhttprequest">doSimpleXMLHttpRequest(url[, queryArguments...])</a>:</p>
+<blockquote>
+<p>Perform a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> and wrap it with a
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> that may be cancelled.</p>
+<p>Note that only <tt class="docutils literal"><span class="pre">200</span></tt> (OK), <tt class="docutils literal"><span class="pre">201</span></tt> (CREATED),
+<tt class="docutils literal"><span class="pre">204</span></tt> (NO CONTENT) and <tt class="docutils literal"><span class="pre">304</span></tt> (NOT MODIFIED) are considered
+success codes. All other status codes will
+result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
+<dd>The URL to GET</dd>
+<dt><tt class="docutils literal"><span class="pre">queryArguments</span></tt>:</dt>
+<dd><p class="first">If this function is called with more than one argument, a
+<tt class="docutils literal"><span class="pre">&quot;?&quot;</span></tt> and the result of
+<a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a> with the rest of the
+arguments are appended to the URL.</p>
+<p>For example, this will do a GET request to the URL
+<tt class="docutils literal"><span class="pre">http://example.com?bar=baz</span></tt>:</p>
+<pre class="last literal-block">
+doSimpleXMLHttpRequest(&quot;http://example.com&quot;, {bar: &quot;baz&quot;});
+</pre>
+</dd>
+<dt><em>returns</em>:</dt>
+<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> instance on success</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+. Support for 201 and 204 were added in
+MochiKit 1.4.</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-evaljsonrequest"></a>
+<a class="mochidef reference" href="#fn-evaljsonrequest">evalJSONRequest(req)</a>:</p>
+<blockquote>
+<p>Evaluate a JSON <a class="footnote-reference" href="#id10" id="id4" name="id4">[4]</a> <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
+<dd>The request whose <tt class="docutils literal"><span class="pre">.responseText</span></tt> property is to be
+evaluated</dd>
+<dt><em>returns</em>:</dt>
+<dd>A JavaScript object</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-fail"></a>
+<a class="mochidef reference" href="#fn-fail">fail([result])</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had
+<tt class="docutils literal"><span class="pre">.errback(result)</span></tt> called.</p>
+<p>See <tt class="docutils literal"><span class="pre">succeed</span></tt> documentation for rationale.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
+<dd>The result to give to
+<a class="mochiref reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback(result)</a>.</dd>
+<dt><em>returns</em>:</dt>
+<dd>A <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred()</a></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-gatherresults"></a>
+<a class="mochidef reference" href="#fn-gatherresults">gatherResults(deferreds)</a>:</p>
+<blockquote>
+<p>A convenience function that returns a <a class="mochiref reference" href="#fn-deferredlist">DeferredList</a>
+from the given <tt class="docutils literal"><span class="pre">Array</span></tt> of <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances that
+will callback with an <tt class="docutils literal"><span class="pre">Array</span></tt> of just results when they're
+available, or errback on the first array.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getxmlhttprequest"></a>
+<a class="mochidef reference" href="#fn-getxmlhttprequest">getXMLHttpRequest()</a>:</p>
+<blockquote>
+<p>Return an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> compliant object for the current
+platform.</p>
+<p>In order of preference:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">XMLHttpRequest()</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP')</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Microsoft.XMLHTTP')</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP.4.0')</span></tt></li>
+</ul>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-maybedeferred"></a>
+<a class="mochidef reference" href="#fn-maybedeferred">maybeDeferred(func[, argument...])</a>:</p>
+<blockquote>
+<p>Call a <tt class="docutils literal"><span class="pre">func</span></tt> with the given arguments and ensure the result is
+a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">func</span></tt>:</dt>
+<dd>The function to call.</dd>
+<dt><em>returns</em>:</dt>
+<dd>A new <a class="mochiref reference" href="#fn-deferred">Deferred</a> based on the call to <tt class="docutils literal"><span class="pre">func</span></tt>. If
+<tt class="docutils literal"><span class="pre">func</span></tt> does not naturally return a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, its
+result or error value will be wrapped by one.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-loadjsondoc"></a>
+<a class="mochidef reference" href="#fn-loadjsondoc">loadJSONDoc(url[, queryArguments...])</a>:</p>
+<blockquote>
+<p>Do a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to a URL and get the response as a
+JSON <a class="footnote-reference" href="#id10" id="id5" name="id5">[4]</a> document.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
+<dd>The URL to GET</dd>
+<dt><tt class="docutils literal"><span class="pre">queryArguments</span></tt>:</dt>
+<dd><p class="first">If this function is called with more than one argument, a
+<tt class="docutils literal"><span class="pre">&quot;?&quot;</span></tt> and the result of
+<a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a> with the rest of the
+arguments are appended to the URL.</p>
+<p>For example, this will do a GET request to the URL
+<tt class="docutils literal"><span class="pre">http://example.com?bar=baz</span></tt>:</p>
+<pre class="last literal-block">
+loadJSONDoc(&quot;http://example.com&quot;, {bar: &quot;baz&quot;});
+</pre>
+</dd>
+<dt><em>returns</em>:</dt>
+<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the evaluated
+JSON <a class="footnote-reference" href="#id10" id="id6" name="id6">[4]</a> response upon successful <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-sendxmlhttprequest"></a>
+<a class="mochidef reference" href="#fn-sendxmlhttprequest">sendXMLHttpRequest(req[, sendContent])</a>:</p>
+<blockquote>
+<p>Set an <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> handler on an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
+object and send it off. Will return a cancellable
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback on success.</p>
+<p>Note that only <tt class="docutils literal"><span class="pre">200</span></tt> (OK), <tt class="docutils literal"><span class="pre">201</span></tt> (CREATED),
+<tt class="docutils literal"><span class="pre">204</span></tt> (NO CONTENT) and <tt class="docutils literal"><span class="pre">304</span></tt> (NOT MODIFIED) are considered
+success codes. All other status codes will
+result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
+<dd>An preconfigured <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object (open has been
+called).</dd>
+<dt><tt class="docutils literal"><span class="pre">sendContent</span></tt>:</dt>
+<dd>Optional string or DOM content to send over the
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</dd>
+<dt><em>returns</em>:</dt>
+<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the
+<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> instance on success.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+. Support for 201 and 204 were added in
+MochiKit 1.4.</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-succeed"></a>
+<a class="mochidef reference" href="#fn-succeed">succeed([result])</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had
+<tt class="docutils literal"><span class="pre">.callback(result)</span></tt> called.</p>
+<p>This is useful when you're writing synchronous code to an
+asynchronous interface: i.e., some code is calling you expecting a
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> result, but you don't actually need to do
+anything asynchronous. Just return <tt class="docutils literal"><span class="pre">succeed(theResult)</span></tt>.</p>
+<p>See <tt class="docutils literal"><span class="pre">fail</span></tt> for a version of this function that uses a failing
+<a class="mochiref reference" href="#fn-deferred">Deferred</a> rather than a successful one.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
+<dd>The result to give to
+<a class="mochiref reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback(result)</a></dd>
+<dt><em>returns</em>:</dt>
+<dd>a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred</a></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-wait"></a>
+<a class="mochidef reference" href="#fn-wait">wait(seconds[, res])</a>:</p>
+<blockquote>
+<p>Return a new cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> that will
+<tt class="docutils literal"><span class="pre">.callback(res)</span></tt> after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have
+elapsed.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id7">[1]</a></td><td>AJAX, Asynchronous JavaScript and XML: <a class="reference" href="http://en.wikipedia.org/wiki/AJAX">http://en.wikipedia.org/wiki/AJAX</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2" name="id8">[2]</a></td><td>Twisted, an event-driven networking framework written in Python: <a class="reference" href="http://twistedmatrix.com/">http://twistedmatrix.com/</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id9" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id3" name="id9">[3]</a></td><td>Twisted Deferred Reference: <a class="reference" href="http://twistedmatrix.com/projects/core/documentation/howto/defer.html">http://twistedmatrix.com/projects/core/documentation/howto/defer.html</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id10" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id10">[4]</a></td><td><em>(<a class="fn-backref" href="#id4">1</a>, <a class="fn-backref" href="#id5">2</a>, <a class="fn-backref" href="#id6">3</a>)</em> JSON, JavaScript Object Notation: <a class="reference" href="http://json.org/">http://json.org/</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Base.html b/mochikit_v14/doc/html/MochiKit/Base.html
new file mode 100644 (file)
index 0000000..1fc71f6
--- /dev/null
@@ -0,0 +1,1665 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Base - functional programming and useful comparisons</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Base - functional programming and useful comparisons</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+myObjectRepr = function () {
+    // gives a nice, stable string representation for objects,
+    // ignoring any methods
+    var keyValuePairs = [];
+    for (var k in this) {
+        var v = this[k];
+        if (typeof(v) != 'function') {
+            keyValuePairs.push([k, v]);
+        }
+    };
+    keyValuePairs.sort(compare);
+    return &quot;{&quot; + map(
+        function (pair) {
+            return map(repr, pair).join(&quot;:&quot;);
+        },
+        keyValuePairs
+    ).join(&quot;, &quot;) + &quot;}&quot;;
+};
+
+// repr() will look for objects that have a repr method
+myObjectArray = [
+    {&quot;a&quot;: 3, &quot;b&quot;: 2, &quot;repr&quot;: myObjectRepr},
+    {&quot;a&quot;: 1, &quot;b&quot;: 2, &quot;repr&quot;: myObjectRepr}
+];
+
+// sort it by the &quot;a&quot; property, check to see if it matches
+myObjectArray.sort(keyComparator(&quot;a&quot;));
+expectedRepr = '[{&quot;a&quot;: 1, &quot;b&quot;: 2}, {&quot;a&quot;: 3, &quot;b&quot;: 2}]';
+assert( repr(myObjectArray) == expectedRepr );
+
+// get just the &quot;a&quot; values out into an array
+sortedAValues = map(itemgetter(&quot;a&quot;), myObjectArray);
+assert( compare(sortedAValues, [1, 3]) == 0 );
+
+// serialize an array as JSON, unserialize it, expect something equivalent
+myArray = [1, 2, &quot;3&quot;, null, undefined];
+assert( objEqual(evalJSON(serializeJSON(myArray)), myArray) );
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p><a class="mochiref reference" href="Base.html">MochiKit.Base</a> is the foundation for the MochiKit suite.
+It provides:</p>
+<ul class="simple">
+<li>An extensible comparison facility
+(<a class="mochiref reference" href="#fn-compare">compare</a>, <a class="mochiref reference" href="#fn-registercomparator">registerComparator</a>)</li>
+<li>An extensible programmer representation facility
+(<a class="mochiref reference" href="#fn-repr">repr</a>, <a class="mochiref reference" href="#fn-registerrepr">registerRepr</a>)</li>
+<li>An extensible JSON <a class="footnote-reference" href="#id7" id="id1" name="id1">[1]</a> serialization and evaluation facility
+(<a class="mochiref reference" href="#fn-serializejson">serializeJSON</a>, <a class="mochiref reference" href="#fn-evaljson">evalJSON</a>,
+<a class="mochiref reference" href="#fn-registerjson">registerJSON</a>)</li>
+<li>A simple adaptation facility (<a class="mochiref reference" href="#fn-adapterregistry">AdapterRegistry</a>)</li>
+<li>Convenience functions for manipulating objects and Arrays
+(<a class="mochiref reference" href="#fn-update">update</a>, <a class="mochiref reference" href="#fn-setdefault">setdefault</a>, <a class="mochiref reference" href="#fn-extend">extend</a>, etc.)</li>
+<li>Array-based functional programming
+(<a class="mochiref reference" href="#fn-map">map</a>, <a class="mochiref reference" href="#fn-filter">filter</a>, etc.)</li>
+<li>Bound and partially applied functions
+(<a class="mochiref reference" href="#fn-bind">bind</a>, <a class="mochiref reference" href="#fn-method">method</a>, <a class="mochiref reference" href="#fn-partial">partial</a>)</li>
+</ul>
+<p>Python users will feel at home with <a class="mochiref reference" href="Base.html">MochiKit.Base</a>, as the
+facilities are quite similar to those available as part of Python and
+the Python standard library.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<p>None.</p>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<div class="section">
+<h2><a id="comparison" name="comparison">Comparison</a></h2>
+<p>The comparators (operators for comparison) in JavaScript are deeply
+broken, and it is not possible to teach them new tricks.</p>
+<p>MochiKit exposes an extensible comparison facility as a simple
+<a class="mochiref reference" href="#fn-compare">compare(a, b)</a> function, which should be used in lieu of
+JavaScript's operators whenever comparing objects other than numbers
+or strings (though you can certainly use <a class="mochiref reference" href="#fn-compare">compare</a> for
+those, too!).</p>
+<p>The <a class="mochiref reference" href="#fn-compare">compare</a> function has the same signature and return
+value as a sort function for <tt class="docutils literal"><span class="pre">Array.prototype.sort</span></tt>, and is often
+used in that context.</p>
+<p>Defining new comparators for the <a class="mochiref reference" href="#fn-compare">compare</a> function to use
+is done by adding an entry to its <a class="mochiref reference" href="#fn-adapterregistry">AdapterRegistry</a> with the
+<a class="mochiref reference" href="#fn-registercomparator">registerComparator</a> function.</p>
+</div>
+<div class="section">
+<h2><a id="programmer-representation" name="programmer-representation">Programmer Representation</a></h2>
+<p>JavaScript's default representation mechanism, <tt class="docutils literal"><span class="pre">toString</span></tt>, is
+notorious for having terrible default behavior. It's also very unwise
+to change that default, as other JavaScript code you may be using may
+depend on it.</p>
+<p>It's also useful to separate the concept of a &quot;string representation&quot;
+and a &quot;string representation for programmers&quot;, much like Python does
+with its str and repr protocols.</p>
+<p><a class="mochiref reference" href="#fn-repr">repr</a> provides this programmer representation for
+JavaScript, in a way that doesn't require object prototype hacking:
+using an <a class="mochiref reference" href="#fn-adapterregistry">AdapterRegistry</a>.</p>
+<p>Objects that implement the repr protocol can either implement a
+<tt class="docutils literal"><span class="pre">.repr()</span></tt> or <tt class="docutils literal"><span class="pre">.__repr__()</span></tt> method, or they can simply have an
+adapter setup to generate programmer representations. By default, the
+registry provides nice representations for <tt class="docutils literal"><span class="pre">null</span></tt>, <tt class="docutils literal"><span class="pre">undefined</span></tt>,
+<tt class="docutils literal"><span class="pre">Array</span></tt>, and objects or functions with a <tt class="docutils literal"><span class="pre">NAME</span></tt> attribute that use
+the default <tt class="docutils literal"><span class="pre">toString</span></tt>. For objects that <tt class="docutils literal"><span class="pre">repr</span></tt> doesn't already
+understand, it simply defaults to <tt class="docutils literal"><span class="pre">toString</span></tt>, so it will integrate
+seamlessly with code that implements the idiomatic JavaScript
+<tt class="docutils literal"><span class="pre">toString</span></tt> method!</p>
+<p>To define a programmer representation for your own objects, simply add
+a <tt class="docutils literal"><span class="pre">.repr()</span></tt> or <tt class="docutils literal"><span class="pre">.__repr__()</span></tt> method that returns a string. For
+objects that you didn't create (e.g., from a script you didn't write,
+or a built-in object), it is instead recommended that you create an
+adapter with <a class="mochiref reference" href="#fn-registerrepr">registerRepr</a>.</p>
+</div>
+<div class="section">
+<h2><a id="json-serialization" name="json-serialization">JSON Serialization</a></h2>
+<p>JSON <a class="footnote-reference" href="#id7" id="id2" name="id2">[1]</a>, JavaScript Object Notation, is a widely used serialization
+format in the context of web development. It's extremely simple,
+lightweight, and fast. In its essence, JSON is a restricted subset of
+JavaScript syntax suitable for sending over the wire that can be
+unserialized with a simple eval. It's often used as an alternative to
+XML in &quot;AJAX&quot; contexts because it is compact, fast, and much simpler
+to use for most purposes.</p>
+<p>To create a JSON serialization of any object, simply call
+<a class="mochiref reference" href="#fn-serializejson">serializeJSON()</a> with that object. To unserialize a JSON
+string, simply call <a class="mochiref reference" href="#fn-evaljson">evalJSON()</a> with the serialization.</p>
+<p>In order of precedence, <a class="mochiref reference" href="#fn-serializejson">serializeJSON</a> coerces the given
+argument into a JSON serialization:</p>
+<ol class="arabic simple">
+<li>Primitive types are returned as their JSON representation:
+<tt class="docutils literal"><span class="pre">string</span></tt>, <tt class="docutils literal"><span class="pre">number</span></tt>, <tt class="docutils literal"><span class="pre">boolean</span></tt>, <tt class="docutils literal"><span class="pre">null</span></tt>.</li>
+<li>If the object has a <tt class="docutils literal"><span class="pre">__json__</span></tt> or <tt class="docutils literal"><span class="pre">json</span></tt> method, then it is
+called with no arguments. If the result of this method is not the
+object itself, then the new object goes through rule processing
+again (e.g. it may return a string, which is then serialized in
+JSON format).</li>
+<li>If the object is <tt class="docutils literal"><span class="pre">Array</span></tt>-like (has a <tt class="docutils literal"><span class="pre">length</span></tt> property that is
+a number, and is not a function), then it is serialized as a JSON
+array.  Each element will be processed according to these rules in
+order.  Elements that can not be serialized (e.g. functions) will
+be replaced with <tt class="docutils literal"><span class="pre">undefined</span></tt>.</li>
+<li>The <tt class="docutils literal"><span class="pre">jsonRegistry</span></tt> <a class="mochiref reference" href="#fn-adapterregistry">AdapterRegistry</a> is consulted for
+an adapter for this object. JSON adapters take one argument (the
+object), and are expected to behave like a <tt class="docutils literal"><span class="pre">__json__</span></tt> or
+<tt class="docutils literal"><span class="pre">json</span></tt> method (return another object to be serialized, or
+itself).</li>
+<li>If the object is <tt class="docutils literal"><span class="pre">undefined</span></tt>, a <tt class="docutils literal"><span class="pre">TypeError</span></tt> is thrown. If you
+wish to serialize <tt class="docutils literal"><span class="pre">undefined</span></tt> as <tt class="docutils literal"><span class="pre">null</span></tt> or some other value, you
+should create an adapter to do so.</li>
+<li>If no adapter is available, the object is enumerated and
+serialized as a JSON object (name:value pairs). All names are
+expected to be strings.  Each value is serialized according to
+these rules, and if it can not be serialized (e.g. methods), then
+that name:value pair will be skipped.</li>
+</ol>
+</div>
+<div class="section">
+<h2><a id="adapter-registries" name="adapter-registries">Adapter Registries</a></h2>
+<p>MochiKit makes extensive use of adapter registries, which enable you
+to implement object-specific behaviors for objects that you do not
+necessarily want to modify, such as built-in objects. This is
+especially useful because JavaScript does not provide a method for
+hiding user-defined properties from <tt class="docutils literal"><span class="pre">for</span> <span class="pre">propName</span> <span class="pre">in</span> <span class="pre">obj</span></tt>
+enumeration.</p>
+<p><a class="mochiref reference" href="#fn-adapterregistry">AdapterRegistry</a> is simply an encapsulation for an ordered
+list of &quot;check&quot; and &quot;wrap&quot; function pairs. Each
+<a class="mochiref reference" href="#fn-adapterregistry">AdapterRegistry</a> instance should perform one function, but
+may have multiple ways to achieve that function based upon the
+arguments. One way to think of it is as a poor man's generic function,
+or multiple dispatch (on arbitrary functions, not just type!).</p>
+<p>Check functions take one or more arguments, and return <tt class="docutils literal"><span class="pre">true</span></tt> if the
+argument list is suitable for the wrap function. Check functions
+should perform &quot;cheap&quot; checks of an object's type or contents, before
+the &quot;expensive&quot; wrap function is called.</p>
+<p>Wrap functions take the same arguments as check functions and do some
+operation, such as creating a programmer representation or comparing
+both arguments.</p>
+</div>
+<div class="section">
+<h2><a id="convenience-functions" name="convenience-functions">Convenience Functions</a></h2>
+<p>Much of <a class="mochiref reference" href="Base.html">MochiKit.Base</a> is there to simply remove the grunt
+work of doing generic JavaScript programming.</p>
+<p>Need to take every property from one object and set them on another?
+No problem, just call <a class="mochiref reference" href="#fn-update">update(dest, src)</a>! What if you just
+wanted to update keys that weren't already set? Look no further than
+<a class="mochiref reference" href="#fn-setdefault">setdefault(dest, src[, ...])</a>.</p>
+<p>Want to return a mutable object, but don't want to suffer the
+consequences if the user mutates it? Just <a class="mochiref reference" href="#fn-clone">clone(it)</a> and
+you'll get a copy-on-write clone. Cheaper than a copy!</p>
+<p>Need to extend an <tt class="docutils literal"><span class="pre">Array</span></tt> with another array? Or even an
+<tt class="docutils literal"><span class="pre">Array</span></tt>-like object such as a <tt class="docutils literal"><span class="pre">NodeList</span></tt> or the special
+<tt class="docutils literal"><span class="pre">arguments</span></tt> object? Even if you need to skip the first few elements
+of the source <tt class="docutils literal"><span class="pre">Array</span></tt>-like object, it's no problem with
+<a class="mochiref reference" href="#fn-extend">extend(dstArray, srcArrayLike[, skip])</a>!</p>
+<p>Wouldn't it be convenient to have all of the JavaScript operators were
+available as functions somewhere? That's what the
+<a class="mochiref reference" href="#fn-operators">operators</a> table is for, and it even comes with additional
+operators based on the <a class="mochiref reference" href="#fn-compare">compare</a> function.</p>
+<p>Need to walk some tree of objects and manipulate or find something in
+it?  A DOM element tree perhaps? Use <a class="mochiref reference" href="#fn-nodewalk">nodeWalk(node,
+visitor)</a>!</p>
+<p>There's plenty more, so check out the <a class="reference" href="#api-reference">API Reference</a> below.</p>
+</div>
+<div class="section">
+<h2><a id="functional-programming" name="functional-programming">Functional Programming</a></h2>
+<p>Functional programming constructs such as <a class="mochiref reference" href="#fn-map">map</a> and
+<a class="mochiref reference" href="#fn-filter">filter</a> can save you a lot of time, because JavaScript
+iteration is error-prone and arduous. Writing less code is the best
+way to prevent bugs, and functional programming can help you do that.</p>
+<p><a class="mochiref reference" href="Base.html">MochiKit.Base</a> ships with a few simple Array-based
+functional programming constructs, namely <a class="mochiref reference" href="#fn-map">map</a> and
+<a class="mochiref reference" href="#fn-filter">filter</a>, and their &quot;extended&quot; brethren, <a class="mochiref reference" href="#fn-xmap">xmap</a>
+and <a class="mochiref reference" href="#fn-xfilter">xfilter</a>.</p>
+<p><a class="mochiref reference" href="#fn-map">map(func, arrayLike[, ...])</a> takes a function and an
+<tt class="docutils literal"><span class="pre">Array</span></tt>-like object, and creates a new <tt class="docutils literal"><span class="pre">Array</span></tt>. The new <tt class="docutils literal"><span class="pre">Array</span></tt>
+is the result of <tt class="docutils literal"><span class="pre">func(element)</span></tt> for every element of <tt class="docutils literal"><span class="pre">arrayLike</span></tt>,
+much like the <tt class="docutils literal"><span class="pre">Array.prototype.map</span></tt> extension in Mozilla. However,
+<a class="mochiref reference" href="Base.html">MochiKit.Base</a> takes that a step further and gives you the
+full blown Python version of <a class="mochiref reference" href="#fn-map">map</a>, which will take several
+<tt class="docutils literal"><span class="pre">Array</span></tt>-like objects, and calls the function with one argument per
+given <tt class="docutils literal"><span class="pre">Array</span></tt>-like, e.g.:</p>
+<pre class="literal-block">
+var arrayOne = [1, 2, 3, 4, 5];
+var arrayTwo = [1, 5, 2, 4, 3];
+var arrayThree = [5, 2, 1, 3, 4];
+var biggestElements = map(objMax, arrayOne, arrayTwo, arrayThree);
+assert( objEqual(biggestElements, [5, 5, 3, 4, 5]) );
+</pre>
+<p><a class="mochiref reference" href="#fn-filter">filter(func, arrayLike[, self])</a> takes a function and an
+<tt class="docutils literal"><span class="pre">Array</span></tt>-like object, and returns a new <tt class="docutils literal"><span class="pre">Array</span></tt>.  This is basically
+identical to the <tt class="docutils literal"><span class="pre">Array.prototype.filter</span></tt> extension in
+Mozilla. self, if given, will be used as <tt class="docutils literal"><span class="pre">this</span></tt> in the context of
+func when called.</p>
+<p><a class="mochiref reference" href="#fn-xmap">xmap</a> and <a class="mochiref reference" href="#fn-xfilter">xfilter</a> are just special forms of
+<a class="mochiref reference" href="#fn-map">map</a> and <a class="mochiref reference" href="#fn-filter">filter</a> that accept a function as the
+first argument, and use the extra arguments as the <tt class="docutils literal"><span class="pre">Array</span></tt>-like. Not
+terribly interesting, but a definite time-saver in some cases.</p>
+<p>If you appreciate the functional programming facilities here, you
+should definitely check out <a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>, which provides
+full blown iterators, <a class="mochiref reference" href="Iter.html#fn-range">MochiKit.Iter.range</a>,
+<a class="mochiref reference" href="Iter.html#fn-reduce">MochiKit.Iter.reduce</a>, and a near-complete port of Python's
+itertools <a class="footnote-reference" href="#id8" id="id3" name="id3">[2]</a> module, with some extra stuff thrown in for good
+measure!</p>
+</div>
+<div class="section">
+<h2><a id="bound-and-partial-functions" name="bound-and-partial-functions">Bound and Partial Functions</a></h2>
+<p>JavaScript's method-calling special form and lack of bound functions
+(functions that know what <tt class="docutils literal"><span class="pre">this</span></tt> should be) are one of the first
+stumbling blocks that programmers new to JavaScript face. The
+<a class="mochiref reference" href="#fn-bind">bind(func, self)</a> method fixes that right up by returning a
+new function that calls func with the right <tt class="docutils literal"><span class="pre">this</span></tt>.</p>
+<p>In order to take real advantage of all this fancy functional
+programming stuff, you're probably going to want partial
+application. This allows you to create a new function from an existing
+function that remembers some of the arguments.  For example, if you
+wanted to compare a given object to a slew of other objects, you could
+do something like this:</p>
+<pre class="literal-block">
+compareWithOne = partial(compare, 1);
+results = map(compareWithOne, [0, 1, 2, 3]);
+assert( objEqual(results, [-1, 0, 1, 1]) );
+</pre>
+<p>One of the better uses of partial functions is in
+<a class="mochiref reference" href="DOM.html">MochiKit.DOM</a>, which is certainly a must-see for those of
+you creating lots of DOM elements with JavaScript!</p>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="errors" name="errors">Errors</a></h2>
+<p>
+<a name="fn-notfound"></a>
+<a class="mochidef reference" href="#fn-notfound">NotFound</a>:</p>
+<blockquote>
+<p>A singleton error raised when no suitable adapter is found</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="constructors" name="constructors">Constructors</a></h2>
+<p>
+<a name="fn-adapterregistry"></a>
+<a class="mochidef reference" href="#fn-adapterregistry">AdapterRegistry</a>:</p>
+<blockquote>
+<p>A registry to facilitate adaptation.</p>
+<p>All <tt class="docutils literal"><span class="pre">check</span></tt>/<tt class="docutils literal"><span class="pre">wrap</span></tt> function pairs in a given registry should
+take the same number of arguments.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-adapterregistry.prototype.register"></a>
+<a class="mochidef reference" href="#fn-adapterregistry.prototype.register">AdapterRegistry.prototype.register(name, check, wrap[, override])</a>:</p>
+<blockquote>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">name</span></tt>:</dt>
+<dd>a unique identifier used to identify this adapter so that it
+may be unregistered.</dd>
+<dt><tt class="docutils literal"><span class="pre">check</span></tt>:</dt>
+<dd>function that should return <tt class="docutils literal"><span class="pre">true</span></tt> if the given arguments
+are appropriate for the <tt class="docutils literal"><span class="pre">wrap</span></tt> function.</dd>
+<dt><tt class="docutils literal"><span class="pre">wrap</span></tt>:</dt>
+<dd>function that takes the same parameters as <tt class="docutils literal"><span class="pre">check</span></tt> and does
+the adaptation.  Every <tt class="docutils literal"><span class="pre">wrap</span></tt>/<tt class="docutils literal"><span class="pre">check</span></tt> function pair in the
+registry should have the same number of arguments.</dd>
+<dt><tt class="docutils literal"><span class="pre">override</span></tt>:</dt>
+<dd>if <tt class="docutils literal"><span class="pre">true</span></tt>, the <tt class="docutils literal"><span class="pre">check</span></tt> function will be
+given highest priority. Otherwise, the lowest.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-adapterregistry.prototype.match"></a>
+<a class="mochidef reference" href="#fn-adapterregistry.prototype.match">AdapterRegistry.prototype.match(obj[, ...])</a>:</p>
+<blockquote>
+<p>Find an adapter for the given arguments by calling every <tt class="docutils literal"><span class="pre">check</span></tt>
+function until one returns <tt class="docutils literal"><span class="pre">true</span></tt>.</p>
+<p>If no suitable adapter is found, throws <a class="mochiref reference" href="#fn-notfound">NotFound</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-adapterregistry.prototype.unregister"></a>
+<a class="mochidef reference" href="#fn-adapterregistry.prototype.unregister">AdapterRegistry.prototype.unregister(name)</a>:</p>
+<blockquote>
+<p>Remove a named adapter from the registry</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-namederror"></a>
+<a class="mochidef reference" href="#fn-namederror">NamedError</a>:</p>
+<blockquote>
+<p>Convenience constructor for creating new errors
+(e.g. <a class="mochiref reference" href="#fn-notfound">NotFound</a>)</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-arrayequal"></a>
+<a class="mochidef reference" href="#fn-arrayequal">arrayEqual(self, arr)</a>:</p>
+<blockquote>
+<p>Compare the arrays <tt class="docutils literal"><span class="pre">self</span></tt> and <tt class="docutils literal"><span class="pre">arr</span></tt> for equality using
+<tt class="docutils literal"><span class="pre">compare</span></tt> on each element. Uses a fast-path for length
+differences.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-average"></a>
+<a class="mochidef reference" href="#fn-average">average(lst[, ...])</a>:</p>
+<blockquote>
+<p>This function is an alias of <a class="mochiref reference" href="#fn-mean">mean()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-bind"></a>
+<a class="mochidef reference" href="#fn-bind">bind(func, self[, arg, ...])</a>:</p>
+<blockquote>
+<p>Return a copy of <tt class="docutils literal"><span class="pre">func</span></tt> bound to <tt class="docutils literal"><span class="pre">self</span></tt>. This means whenever
+and however the returned function is called, <tt class="docutils literal"><span class="pre">this</span></tt> will always
+reference the given <tt class="docutils literal"><span class="pre">self</span></tt>. <tt class="docutils literal"><span class="pre">func</span></tt> may be either a function
+object, or a string. If it is a string, then <tt class="docutils literal"><span class="pre">self[func]</span></tt> will
+be used, making these two statements equivalent:</p>
+<pre class="literal-block">
+bind(&quot;method&quot;, self);
+bind(self.method, self);
+</pre>
+<p>Calling <a class="mochiref reference" href="#fn-bind">bind(func, self)</a> on an already bound function
+will return a new function that is bound to the new <tt class="docutils literal"><span class="pre">self</span></tt>! If
+<tt class="docutils literal"><span class="pre">self</span></tt> is <tt class="docutils literal"><span class="pre">undefined</span></tt>, then the previous <tt class="docutils literal"><span class="pre">self</span></tt> is used.  If
+<tt class="docutils literal"><span class="pre">self</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, then the <tt class="docutils literal"><span class="pre">this</span></tt> object is used (which may
+or may not be the global object). To force binding to the global
+object, you should pass it explicitly.</p>
+<p>Additional arguments, if given, will be partially applied to the
+function. These three expressions are equivalent and return
+equally efficient functions (<a class="mochiref reference" href="#fn-bind">bind</a> and
+<a class="mochiref reference" href="#fn-partial">partial</a> share the same code path):</p>
+<ul class="simple">
+<li><a class="mochiref reference" href="#fn-bind">bind(oldfunc, self, arg1, arg2)</a></li>
+<li><a class="mochiref reference" href="#fn-bind">bind(partial(oldfunc, arg1, arg2), self)</a></li>
+<li><a class="mochiref reference" href="#fn-partial">partial(bind(oldfunc, self), arg1, arg2)</a></li>
+</ul>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-bindmethods"></a>
+<a class="mochidef reference" href="#fn-bindmethods">bindMethods(self)</a>:</p>
+<blockquote>
+<p>Replace all functions <tt class="docutils literal"><span class="pre">meth</span></tt> on <tt class="docutils literal"><span class="pre">self</span></tt> with
+<a class="mochiref reference" href="#fn-bind">bind(meth, self)</a>.  This emulates Python's bound
+instance methods, where there is no need to worry about preserving
+<tt class="docutils literal"><span class="pre">this</span></tt> when the method is used as a callback.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-camelize"></a>
+<a class="mochidef reference" href="#fn-camelize">camelize(str)</a>:</p>
+<blockquote>
+<p>Converts hyphenated strings to camelCase:</p>
+<pre class="literal-block">
+assert( camelize(&quot;border-left&quot;) == &quot;borderLeft&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-clone"></a>
+<a class="mochidef reference" href="#fn-clone">clone(obj)</a>:</p>
+<blockquote>
+<p>Return a new object using <tt class="docutils literal"><span class="pre">obj</span></tt> as its prototype. Use this if
+you want to return a mutable object (e.g. instance state), but
+don't want the user to mutate it. If they do, it won't have any
+effect on the original <tt class="docutils literal"><span class="pre">obj</span></tt>.</p>
+<p>Note that this is a shallow clone, so mutable properties will have
+to be cloned separately if you want to &quot;protect&quot; them.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-compare"></a>
+<a class="mochidef reference" href="#fn-compare">compare(a, b)</a>:</p>
+<blockquote>
+<p>Compare two objects in a sensible manner. Currently this is:</p>
+<ol class="arabic simple">
+<li><tt class="docutils literal"><span class="pre">undefined</span></tt> and <tt class="docutils literal"><span class="pre">null</span></tt> compare equal to each other</li>
+<li><tt class="docutils literal"><span class="pre">undefined</span></tt> and <tt class="docutils literal"><span class="pre">null</span></tt> are less than anything else</li>
+<li>If JavaScript says <tt class="docutils literal"><span class="pre">a</span> <span class="pre">==</span> <span class="pre">b</span></tt>, then we trust it</li>
+<li>comparators registered with registerComparator are used to
+find a good comparator. Built-in comparators are currently
+available for <tt class="docutils literal"><span class="pre">Array</span></tt>-like and <tt class="docutils literal"><span class="pre">Date</span></tt>-like objects.</li>
+<li>Otherwise hope that the built-in comparison operators do
+something useful, which should work for numbers and strings.</li>
+<li>If neither <tt class="docutils literal"><span class="pre">a</span> <span class="pre">&lt;</span> <span class="pre">b</span></tt> or <tt class="docutils literal"><span class="pre">a</span> <span class="pre">&gt;</span> <span class="pre">b</span></tt>, then throw a <tt class="docutils literal"><span class="pre">TypeError</span></tt></li>
+</ol>
+<p>Returns what one would expect from a comparison function:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="42%" />
+<col width="58%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Value</td>
+<td>Condition</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">0</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">==</span> <span class="pre">b</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">1</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&gt;</span> <span class="pre">b</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">-1</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&lt;</span> <span class="pre">b</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-compose"></a>
+<a class="mochidef reference" href="#fn-compose">compose(f1, f2, ..., fN)</a>:</p>
+<blockquote>
+<p>Return a new function as the combination of the given function
+arguments, equivalent to <tt class="docutils literal"><span class="pre">f1(f2(arguments))</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-concat"></a>
+<a class="mochidef reference" href="#fn-concat">concat(lst[, ...])</a>:</p>
+<blockquote>
+<p>Concatenates all given <tt class="docutils literal"><span class="pre">Array</span></tt>-like arguments and returns
+a new <tt class="docutils literal"><span class="pre">Array</span></tt>:</p>
+<pre class="literal-block">
+var lst = concat([&quot;1&quot;,&quot;3&quot;,&quot;5&quot;], [&quot;2&quot;,&quot;4&quot;,&quot;6&quot;]);
+assert( lst.toString() == &quot;1,3,5,2,4,6&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-counter"></a>
+<a class="mochidef reference" href="#fn-counter">counter(n=1)</a>:</p>
+<blockquote>
+<p>Returns a function that will return a number one greater than
+the previous returned value, starting at <tt class="docutils literal"><span class="pre">n</span></tt>. For example:</p>
+<pre class="literal-block">
+nextId = counter()
+assert( nextId() == 1 )
+assert( nextId() == 2 )
+</pre>
+<p>For an iterator with this behavior, see
+<a class="mochiref reference" href="Iter.html#fn-count">MochiKit.Iter.count</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-extend"></a>
+<a class="mochidef reference" href="#fn-extend">extend(self, obj, skip=0)</a>:</p>
+<blockquote>
+<p>Mutate the array <tt class="docutils literal"><span class="pre">self</span></tt> by extending it with an <tt class="docutils literal"><span class="pre">Array</span></tt>-like
+<tt class="docutils literal"><span class="pre">obj</span></tt>, starting from index <tt class="docutils literal"><span class="pre">skip</span></tt>. If <tt class="docutils literal"><span class="pre">null</span></tt> is given as the
+initial array, a new one will be created.</p>
+<p>This mutates <em>and returns</em> <tt class="docutils literal"><span class="pre">self</span></tt>, be warned.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-evaljson"></a>
+<a class="mochidef reference" href="#fn-evaljson">evalJSON(aJSONString)</a>:</p>
+<blockquote>
+<p>Unserialize a JSON <a class="footnote-reference" href="#id7" id="id4" name="id4">[1]</a> represenation of an object.</p>
+<p>Note that this uses the <tt class="docutils literal"><span class="pre">eval</span></tt> function of the interpreter, and
+therefore trusts the contents of <tt class="docutils literal"><span class="pre">aJSONString</span></tt> to be safe.  This
+is acceptable when the JSON and JavaScript application originate
+from the same server, but in other scenarios it may not be the
+appropriate security model. Currently, a validating JSON parser is
+beyond the scope of MochiKit, but there is one available from
+json.org <a class="footnote-reference" href="#id7" id="id5" name="id5">[1]</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-filter"></a>
+<a class="mochidef reference" href="#fn-filter">filter(fn, lst)</a>:</p>
+<blockquote>
+<p>Returns a new <tt class="docutils literal"><span class="pre">Array</span></tt> composed of all elements from <tt class="docutils literal"><span class="pre">lst</span></tt>
+where <tt class="docutils literal"><span class="pre">fn(lst[i])</span></tt> returns a true value.</p>
+<p>If <tt class="docutils literal"><span class="pre">fn</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, <tt class="docutils literal"><span class="pre">operator.truth</span></tt> will be used.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-findvalue"></a>
+<a class="mochidef reference" href="#fn-findvalue">findValue(lst, value, start=0, end=lst.length)</a>:</p>
+<blockquote>
+<p>Finds the index of <tt class="docutils literal"><span class="pre">value</span></tt> in the <tt class="docutils literal"><span class="pre">Array</span></tt>-like object <tt class="docutils literal"><span class="pre">lst</span></tt>
+using <a class="mochiref reference" href="#fn-compare">compare</a>. The search starts at the index
+<tt class="docutils literal"><span class="pre">start</span></tt>, and ends at the index <tt class="docutils literal"><span class="pre">end</span> <span class="pre">-</span> <span class="pre">1</span></tt>. If <tt class="docutils literal"><span class="pre">value</span></tt> is not
+found in <tt class="docutils literal"><span class="pre">lst</span></tt>, it will return <tt class="docutils literal"><span class="pre">-1</span></tt>.</p>
+<p>For example:</p>
+<pre class="literal-block">
+assert( findValue([1, 2, 3, 2, 1], 2) == 1 )
+assert( findValue([1, 2, 3, 2, 1], 2, 2) == 3 )
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-findidentical"></a>
+<a class="mochidef reference" href="#fn-findidentical">findIdentical(lst, value, start=0, end=lst.length)</a>:</p>
+<blockquote>
+<p>Finds the index of <tt class="docutils literal"><span class="pre">value</span></tt> in the <tt class="docutils literal"><span class="pre">Array</span></tt>-like object <tt class="docutils literal"><span class="pre">lst</span></tt>
+using the <tt class="docutils literal"><span class="pre">===</span></tt> operator. The search starts at the index
+<tt class="docutils literal"><span class="pre">start</span></tt>, and ends at the index <tt class="docutils literal"><span class="pre">end</span> <span class="pre">-</span> <span class="pre">1</span></tt>. If <tt class="docutils literal"><span class="pre">value</span></tt> is not
+found in <tt class="docutils literal"><span class="pre">lst</span></tt>, it will return <tt class="docutils literal"><span class="pre">-1</span></tt>.</p>
+<p>You should use this function instead of <a class="mochiref reference" href="#fn-findvalue">findValue</a> if
+<tt class="docutils literal"><span class="pre">lst</span></tt> may be comprised of objects for which no comparator is
+defined and all you care about is finding an identical object
+(e.g. the same instance), or if <tt class="docutils literal"><span class="pre">lst</span></tt> is comprised of just
+numbers or strings and performance is important.</p>
+<p>For example:</p>
+<pre class="literal-block">
+assert( findIdentical([1, 2, 3, 2, 1], 2) == 1 )
+assert( findIdentical([1, 2, 3, 2, 1], 2, 2) == 3 )
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-flattenarguments"></a>
+<a class="mochidef reference" href="#fn-flattenarguments">flattenArguments(arg[, ...])</a>:</p>
+<blockquote>
+<p>Given a bunch of arguments, return a single <tt class="docutils literal"><span class="pre">Array</span></tt> containing
+all of those arguments. Any <tt class="docutils literal"><span class="pre">Array</span></tt>-like argument will be extended
+in-place, e.g.:</p>
+<pre class="literal-block">
+compare(flattenArguments(1, [2, 3, [4, 5]]), [1, 2, 3, 4, 5]) == 0
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-flattenarray"></a>
+<a class="mochidef reference" href="#fn-flattenarray">flattenArray(lst)</a>:</p>
+<blockquote>
+<p>Return a new <tt class="docutils literal"><span class="pre">Array</span></tt> consisting of every item in lst with <tt class="docutils literal"><span class="pre">Array</span></tt>
+items expanded in-place recursively. This differs from
+<a class="mochiref reference" href="#fn-flattenarguments">flattenArguments</a> in that it only takes one argument and
+it only flattens items that are <tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Array</span></tt>.</p>
+<blockquote>
+compare(flattenArray([1, [2, 3, [4, 5]]]), [1, 2, 3, 4, 5]) == 0</blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-forwardcall"></a>
+<a class="mochidef reference" href="#fn-forwardcall">forwardCall(name)</a>:</p>
+<blockquote>
+<p>Returns a function that forwards a method call to
+<tt class="docutils literal"><span class="pre">this.name(...)</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isarraylike"></a>
+<a class="mochidef reference" href="#fn-isarraylike">isArrayLike(obj[, ...])</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> if all given arguments are <tt class="docutils literal"><span class="pre">Array</span></tt>-like (have a
+<tt class="docutils literal"><span class="pre">.length</span></tt> property and <tt class="docutils literal"><span class="pre">typeof(obj)</span> <span class="pre">==</span> <span class="pre">'object'</span></tt>)</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isdatelike"></a>
+<a class="mochidef reference" href="#fn-isdatelike">isDateLike(obj[, ...])</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> if all given arguments are <tt class="docutils literal"><span class="pre">Date</span></tt>-like (have a
+<tt class="docutils literal"><span class="pre">.getTime()</span></tt> method)</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isempty"></a>
+<a class="mochidef reference" href="#fn-isempty">isEmpty(obj[, ...])</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> if all the given <tt class="docutils literal"><span class="pre">Array</span></tt>-like or string
+arguments are empty <tt class="docutils literal"><span class="pre">(obj.length</span> <span class="pre">==</span> <span class="pre">0)</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isnotempty"></a>
+<a class="mochidef reference" href="#fn-isnotempty">isNotEmpty(obj[, ...])</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> if all the given <tt class="docutils literal"><span class="pre">Array</span></tt>-like or string
+arguments are not empty <tt class="docutils literal"><span class="pre">(obj.length</span> <span class="pre">&gt;</span> <span class="pre">0)</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isnull"></a>
+<a class="mochidef reference" href="#fn-isnull">isNull(obj[, ...])</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> if all arguments are <tt class="docutils literal"><span class="pre">null</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isundefinedornull"></a>
+<a class="mochidef reference" href="#fn-isundefinedornull">isUndefinedOrNull(obj[, ...])</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> if all arguments are undefined or <tt class="docutils literal"><span class="pre">null</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-itemgetter"></a>
+<a class="mochidef reference" href="#fn-itemgetter">itemgetter(name)</a>:</p>
+<blockquote>
+<p>Returns a <tt class="docutils literal"><span class="pre">function(obj)</span></tt> that returns <tt class="docutils literal"><span class="pre">obj[name]</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-items"></a>
+<a class="mochidef reference" href="#fn-items">items(obj)</a>:</p>
+<blockquote>
+<p>Return an <tt class="docutils literal"><span class="pre">Array</span></tt> of <tt class="docutils literal"><span class="pre">[propertyName,</span> <span class="pre">propertyValue]</span></tt> pairs for
+the given <tt class="docutils literal"><span class="pre">obj</span></tt> (in the order determined by <tt class="docutils literal"><span class="pre">for</span> <span class="pre">propName</span> <span class="pre">in</span>
+<span class="pre">obj</span></tt>).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-keycomparator"></a>
+<a class="mochidef reference" href="#fn-keycomparator">keyComparator(key[, ...])</a>:</p>
+<blockquote>
+<p>A comparator factory that compares <tt class="docutils literal"><span class="pre">a[key]</span></tt> with <tt class="docutils literal"><span class="pre">b[key]</span></tt>.
+e.g.:</p>
+<pre class="literal-block">
+var lst = [&quot;a&quot;, &quot;bbb&quot;, &quot;cc&quot;];
+lst.sort(keyComparator(&quot;length&quot;));
+assert( lst.toString() == &quot;a,cc,bbb&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-keys"></a>
+<a class="mochidef reference" href="#fn-keys">keys(obj)</a>:</p>
+<blockquote>
+<p>Return an <tt class="docutils literal"><span class="pre">Array</span></tt> of the property names of an object (in the
+order determined by <tt class="docutils literal"><span class="pre">for</span> <span class="pre">propName</span> <span class="pre">in</span> <span class="pre">obj</span></tt>).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-listmax"></a>
+<a class="mochidef reference" href="#fn-listmax">listMax(lst)</a>:</p>
+<blockquote>
+<p>Return the largest element of an <tt class="docutils literal"><span class="pre">Array</span></tt>-like object, as
+determined by <a class="mochiref reference" href="#fn-compare">compare</a>. This is a special form of
+<a class="mochiref reference" href="#fn-listminmax">listMinMax</a>, specifically
+<a class="mochiref reference" href="#fn-partial">partial(listMinMax, 1)</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-listmin"></a>
+<a class="mochidef reference" href="#fn-listmin">listMin(lst)</a>:</p>
+<blockquote>
+<p>Return the smallest element of an <tt class="docutils literal"><span class="pre">Array</span></tt>-like object, as
+determined by <a class="mochiref reference" href="#fn-compare">compare</a>. This is a special form of
+<a class="mochiref reference" href="#fn-listminmax">listMinMax</a>, specifically
+<a class="mochiref reference" href="#fn-partial">partial(listMinMax, -1)</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-listminmax"></a>
+<a class="mochidef reference" href="#fn-listminmax">listMinMax(which, lst)</a>:</p>
+<blockquote>
+<p>If <tt class="docutils literal"><span class="pre">which</span> <span class="pre">==</span> <span class="pre">-1</span></tt> then it will return the smallest element of the
+<tt class="docutils literal"><span class="pre">Array</span></tt>-like <tt class="docutils literal"><span class="pre">lst</span></tt>. This is also available as
+<a class="mochiref reference" href="#fn-listmin">listMin(lst)</a>.</p>
+<p>If <tt class="docutils literal"><span class="pre">which</span> <span class="pre">==</span> <span class="pre">1</span></tt> then it will return the largest element of the
+<tt class="docutils literal"><span class="pre">Array</span></tt>-like <tt class="docutils literal"><span class="pre">lst</span></tt>. This is also available as
+<a class="mochiref reference" href="#fn-listmax">listMax(list)</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-map"></a>
+<a class="mochidef reference" href="#fn-map">map(fn, lst[, ...])</a>:</p>
+<blockquote>
+<p>Return a new array composed of the results of <tt class="docutils literal"><span class="pre">fn(x)</span></tt> for every
+<tt class="docutils literal"><span class="pre">x</span></tt> in <tt class="docutils literal"><span class="pre">lst</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">fn</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, and only one sequence argument is given the
+identity function is used.</p>
+<blockquote>
+<a class="mochiref reference" href="#fn-map">map(null, lst)</a> -&gt; <tt class="docutils literal"><span class="pre">lst.slice()</span></tt>;</blockquote>
+<p>If <tt class="docutils literal"><span class="pre">fn</span></tt> is not <tt class="docutils literal"><span class="pre">null</span></tt> and more than one sequence argument is
+given, then one element from each sequence is used to build the
+argument list for <tt class="docutils literal"><span class="pre">fn</span></tt>.</p>
+<blockquote>
+<dl class="docutils">
+<dt><a class="mochiref reference" href="#fn-map">map(fn, p, q, ...)</a></dt>
+<dd>-&gt;  <tt class="docutils literal"><span class="pre">[fn(p[0],</span> <span class="pre">q[0],</span> <span class="pre">..),</span> <span class="pre">fn(p[1],</span> <span class="pre">q[1],</span> <span class="pre">...),</span> <span class="pre">...]</span></tt></dd>
+</dl>
+</blockquote>
+<p>If <tt class="docutils literal"><span class="pre">fn</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, and more than one sequence is given as
+arguments, then the <tt class="docutils literal"><span class="pre">Array</span></tt> function is used, making it
+equivalent to <a class="mochiref reference" href="Iter.html#fn-zip">MochiKit.Iter.zip</a>.</p>
+<blockquote>
+<dl class="docutils">
+<dt><a class="mochiref reference" href="#fn-map">map(null, p, q, ...)</a></dt>
+<dd>-&gt; <a class="mochiref reference" href="Iter.html#fn-zip">MochiKit.Iter.zip(p, q, ...)</a>
+-&gt; <tt class="docutils literal"><span class="pre">[[p0,</span> <span class="pre">q0,</span> <span class="pre">...],</span> <span class="pre">[p1,</span> <span class="pre">q1,</span> <span class="pre">...],</span> <span class="pre">...];</span></tt></dd>
+</dl>
+</blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-mean"></a>
+<a class="mochidef reference" href="#fn-mean">mean(lst[, ...])</a>:</p>
+<blockquote>
+<p>Returns the arithmetic mean (average) of the argument list, or an array.
+This function applies <a class="mochiref reference" href="#fn-flattenarguments">flattenArguments()</a> to the argument list.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-median"></a>
+<a class="mochidef reference" href="#fn-median">median(lst[, ...])</a>:</p>
+<blockquote>
+<p>Returns the median of the argument list, or an array. This function
+applies <a class="mochiref reference" href="#fn-flattenarguments">flattenArguments()</a> to the argument list.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-merge"></a>
+<a class="mochidef reference" href="#fn-merge">merge(obj[, ...])</a>:</p>
+<blockquote>
+<p>Create a new instance of <tt class="docutils literal"><span class="pre">Object</span></tt> that contains every property
+from all given objects. If a property is defined on more than one
+of the objects, the last property is used.</p>
+<p>This is a special form of <a class="mochiref reference" href="#fn-update">update(self, obj[, ...])</a>,
+specifically, it is defined as <a class="mochiref reference" href="#fn-partial">partial(update, null)</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-method"></a>
+<a class="mochidef reference" href="#fn-method">method(self, func, ...)</a>:</p>
+<blockquote>
+<p>Alternate form of <a class="mochiref reference" href="#fn-bind">bind</a> that takes the object before
+the function. These two calls are equivalent:</p>
+<pre class="literal-block">
+bind(&quot;method&quot;, myobject)
+method(myobject, &quot;method&quot;)
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-methodcaller"></a>
+<a class="mochidef reference" href="#fn-methodcaller">methodcaller(name[, args...])</a>:</p>
+<blockquote>
+<p>Return a new function that calls a method on its argument,
+for example:</p>
+<pre class="literal-block">
+lst = map(methodcaller(&quot;toLowerCase&quot;), [&quot;THIS&quot;, &quot;is&quot;, &quot;LoWeRCaSe&quot;]);
+assert( lst.join(&quot; &quot;) == &quot;this is lowercase&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-namefunctions"></a>
+<a class="mochidef reference" href="#fn-namefunctions">nameFunctions(namespace)</a>:</p>
+<blockquote>
+<p>Given a <tt class="docutils literal"><span class="pre">namespace</span></tt> (object or function) with a <tt class="docutils literal"><span class="pre">NAME</span></tt>
+property, find all methods in it and give them nice <tt class="docutils literal"><span class="pre">NAME</span></tt>
+properties too (for use with <a class="mochiref reference" href="#fn-repr">repr</a>). e.g.:</p>
+<pre class="literal-block">
+namespace = {
+    NAME: &quot;Awesome&quot;,
+    Dude: function () {}
+}
+nameFunctions(namespace);
+assert( namespace.Dude.NAME == 'Awesome.Dude' );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-noop"></a>
+<a class="mochidef reference" href="#fn-noop">noop()</a>:</p>
+<blockquote>
+<p>A function that performs no operation. Use this where you would
+otherwise use <tt class="docutils literal"><span class="pre">(function</span> <span class="pre">()</span> <span class="pre">{})</span></tt> in order to avoid Internet
+Explorer cyclic garbage leakage.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-objequal"></a>
+<a class="mochidef reference" href="#fn-objequal">objEqual(a, b)</a>:</p>
+<blockquote>
+<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">compare(a,</span> <span class="pre">b)</span> <span class="pre">==</span> <span class="pre">0</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-nodewalk"></a>
+<a class="mochidef reference" href="#fn-nodewalk">nodeWalk(node, visitor)</a>:</p>
+<blockquote>
+<p>Non-recursive generic node walking function (e.g. for a DOM).</p>
+<p>The walk order for nodeWalk is breadth first, meaning that all
+siblings will be visited before any children.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>The initial node to be searched.</dd>
+<dt><tt class="docutils literal"><span class="pre">visitor</span></tt>:</dt>
+<dd>The visitor function, will be called as <tt class="docutils literal"><span class="pre">visitor(node)</span></tt>, and
+should return an <tt class="docutils literal"><span class="pre">Array</span></tt>-like of nodes to be searched next
+(e.g. <tt class="docutils literal"><span class="pre">node.childNodes</span></tt>).  Leaf nodes may return <tt class="docutils literal"><span class="pre">null</span></tt> or
+<tt class="docutils literal"><span class="pre">undefined</span></tt>.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-objmax"></a>
+<a class="mochidef reference" href="#fn-objmax">objMax(obj[, ...])</a>:</p>
+<blockquote>
+<p>Return the maximum object according to <a class="mochiref reference" href="#fn-compare">compare</a> out of
+the given arguments. This is similar to <a class="mochiref reference" href="#fn-listmax">listMax</a>,
+except is uses the arguments instead of a given <tt class="docutils literal"><span class="pre">Array</span></tt>-like.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-objmin"></a>
+<a class="mochidef reference" href="#fn-objmin">objMin(obj[, ...])</a>:</p>
+<blockquote>
+<p>Return the minimum object according to <a class="mochiref reference" href="#fn-compare">compare</a> out of
+the given arguments. This is similar to <a class="mochiref reference" href="#fn-listmin">listMin</a>,
+except it uses the arguments instead of a given <tt class="docutils literal"><span class="pre">Array</span></tt>-like.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-operator"></a>
+<a class="mochidef reference" href="#fn-operator">operator</a>:</p>
+<blockquote>
+<p>A table of JavaScript's operators for usage with <a class="mochiref reference" href="#fn-map">map</a>,
+<a class="mochiref reference" href="#fn-filter">filter</a>, etc.</p>
+<p>Unary Logic Operators:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="31%" />
+<col width="40%" />
+<col width="29%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Operator</th>
+<th class="head">Implementation</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">truth(a)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">!!a</span></tt></td>
+<td>Logical truth</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">lognot(a)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">!a</span></tt></td>
+<td>Logical not</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">identity(a)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span></tt></td>
+<td>Logical identity</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>Unary Math Operators:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="33%" />
+<col width="43%" />
+<col width="25%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Operator</th>
+<th class="head">Implementation</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">not(a)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">~a</span></tt></td>
+<td>Bitwise not</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">neg(a)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">-a</span></tt></td>
+<td>Negation</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>Binary Operators:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="28%" />
+<col width="28%" />
+<col width="45%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Operator</th>
+<th class="head">Implementation</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">add(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">+</span> <span class="pre">b</span></tt></td>
+<td>Addition</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">sub(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">-</span> <span class="pre">b</span></tt></td>
+<td>Subtraction</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">div(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">/</span> <span class="pre">b</span></tt></td>
+<td>Division</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">mod(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">%</span> <span class="pre">b</span></tt></td>
+<td>Modulus</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">mul(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">*</span> <span class="pre">b</span></tt></td>
+<td>Multiplication</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">and(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&amp;</span> <span class="pre">b</span></tt></td>
+<td>Bitwise and</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">or(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">|</span> <span class="pre">b</span></tt></td>
+<td>Bitwise or</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">xor(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">^</span> <span class="pre">b</span></tt></td>
+<td>Bitwise exclusive or</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">lshift(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&lt;&lt;</span> <span class="pre">b</span></tt></td>
+<td>Bitwise left shift</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">rshift(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&gt;&gt;</span> <span class="pre">b</span></tt></td>
+<td>Bitwise signed right shift</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">zrshift(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&gt;&gt;&gt;</span> <span class="pre">b</span></tt></td>
+<td>Bitwise unsigned right shift</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>Built-in Comparators:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="25%" />
+<col width="31%" />
+<col width="44%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Operator</th>
+<th class="head">Implementation</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">eq(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">==</span> <span class="pre">b</span></tt></td>
+<td>Equals</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">ne(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">!=</span> <span class="pre">b</span></tt></td>
+<td>Not equals</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">gt(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&gt;</span> <span class="pre">b</span></tt></td>
+<td>Greater than</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">ge(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&gt;=</span> <span class="pre">b</span></tt></td>
+<td>Greater than or equal to</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">lt(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&lt;</span> <span class="pre">b</span></tt></td>
+<td>Less than</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">le(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&lt;=</span> <span class="pre">b</span></tt></td>
+<td>Less than or equal to</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>Strict Built-in Comparators:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="25%" />
+<col width="31%" />
+<col width="44%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Operator</th>
+<th class="head">Implementation</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">seq(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">===</span> <span class="pre">b</span></tt></td>
+<td>Strict equals</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">sne(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">!==</span> <span class="pre">b</span></tt></td>
+<td>Strict not equals</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>Extended Comparators (uses <a class="mochiref reference" href="#fn-compare">compare</a>):</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="22%" />
+<col width="39%" />
+<col width="39%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Operator</th>
+<th class="head">Implementation</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">ceq(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">compare(a,</span> <span class="pre">b)</span> <span class="pre">==</span> <span class="pre">0</span></tt></td>
+<td>Equals</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">cne(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">compare(a,</span> <span class="pre">b)</span> <span class="pre">!=</span> <span class="pre">0</span></tt></td>
+<td>Not equals</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">cgt(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">compare(a,</span> <span class="pre">b)</span> <span class="pre">==</span> <span class="pre">1</span></tt></td>
+<td>Greater than</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">cge(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">compare(a,</span> <span class="pre">b)</span> <span class="pre">!=</span> <span class="pre">-1</span></tt></td>
+<td>Greater than or equal to</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">clt(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">compare(a,</span> <span class="pre">b)</span> <span class="pre">==</span> <span class="pre">-1</span></tt></td>
+<td>Less than</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">cle(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">compare(a,</span> <span class="pre">b)</span> <span class="pre">!=</span> <span class="pre">1</span></tt></td>
+<td>Less than or equal to</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>Binary Logical Operators:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="33%" />
+<col width="28%" />
+<col width="39%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Operator</th>
+<th class="head">Implementation</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">logand(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">&amp;&amp;</span> <span class="pre">b</span></tt></td>
+<td>Logical and</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">logor(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">a</span> <span class="pre">||</span> <span class="pre">b</span></tt></td>
+<td>Logical or</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">contains(a,</span> <span class="pre">b)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">b</span> <span class="pre">in</span> <span class="pre">a</span></tt></td>
+<td>Has property (note order)</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-parsequerystring"></a>
+<a class="mochidef reference" href="#fn-parsequerystring">parseQueryString(encodedString[, useArrays=false])</a>:</p>
+<blockquote>
+<p>Parse a name=value pair URL query string into an object with a
+property for each pair. e.g.:</p>
+<pre class="literal-block">
+var args = parseQueryString(&quot;foo=value%20one&amp;bar=two&quot;);
+assert( args.foo == &quot;value one&quot; &amp;&amp; args.bar == &quot;two&quot; );
+</pre>
+<p>If you expect that the query string will reuse the same name, then
+give <tt class="docutils literal"><span class="pre">true</span></tt> as a second argument, which will use arrays to store
+the values. e.g.:</p>
+<pre class="literal-block">
+var args = parseQueryString(&quot;foo=one&amp;foo=two&quot;, true);
+assert( args.foo[0] == &quot;one&quot; &amp;&amp; args.foo[1] == &quot;two&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-partial"></a>
+<a class="mochidef reference" href="#fn-partial">partial(func, arg[, ...])</a>:</p>
+<blockquote>
+<p>Return a partially applied function, e.g.:</p>
+<pre class="literal-block">
+addNumbers = function (a, b) {
+    return a + b;
+}
+
+addOne = partial(addNumbers, 1);
+
+assert(addOne(2) == 3);
+</pre>
+<p><a class="mochiref reference" href="#fn-partial">partial</a> is a special form of <a class="mochiref reference" href="#fn-bind">bind</a> that
+does not alter the bound <tt class="docutils literal"><span class="pre">self</span></tt> (if any). It is equivalent to
+calling:</p>
+<pre class="literal-block">
+bind(func, undefined, arg[, ...]);
+</pre>
+<p>See the documentation for <a class="mochiref reference" href="#fn-bind">bind</a> for more details about
+this facility.</p>
+<p>This could be used to implement, but is NOT currying.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-querystring"></a>
+<a class="mochidef reference" href="#fn-querystring">queryString(names, values)</a>:</p>
+<blockquote>
+<p>Creates a URL query string from a pair of <tt class="docutils literal"><span class="pre">Array</span></tt>-like objects
+representing <tt class="docutils literal"><span class="pre">names</span></tt> and <tt class="docutils literal"><span class="pre">values</span></tt>. Each name=value pair will
+be URL encoded by <a class="mochiref reference" href="#fn-urlencode">urlEncode</a>. name=value pairs with a
+value of <tt class="docutils literal"><span class="pre">undefined</span></tt> or <tt class="docutils literal"><span class="pre">null</span></tt> will be skipped. e.g.:</p>
+<pre class="literal-block">
+var keys = [&quot;foo&quot;, &quot;bar&quot;];
+var values = [&quot;value one&quot;, &quot;two&quot;];
+assert( queryString(keys, values) == &quot;foo=value%20one&amp;bar=two&quot; );
+</pre>
+<dl class="docutils">
+<dt>Alternate form 1:</dt>
+<dd><a class="mochiref reference" href="#fn-querystring">queryString(domElement)</a></dd>
+</dl>
+<p>If <a class="mochiref reference" href="DOM.html">MochiKit.DOM</a> is loaded, one argument is given, and
+that argument is either a string or has a <tt class="docutils literal"><span class="pre">nodeType</span></tt> property
+greater than zero, then <tt class="docutils literal"><span class="pre">names</span></tt> and <tt class="docutils literal"><span class="pre">values</span></tt> will be the
+result of <a class="mochiref reference" href="DOM.html#fn-formcontents">MochiKit.DOM.formContents(domElement)</a>.</p>
+<dl class="docutils">
+<dt>Alternate form 2:</dt>
+<dd><a class="mochiref reference" href="#fn-querystring">queryString({name: value, ...})</a></dd>
+</dl>
+<p>Note that when using the alternate form, the order of the
+name=value pairs in the resultant query string is dependent on how
+the particular JavaScript implementation handles <tt class="docutils literal"><span class="pre">for</span> <span class="pre">(..in..)</span></tt>
+property enumeration.</p>
+<p>When using the second alternate form, name=value pairs with
+<tt class="docutils literal"><span class="pre">typeof(value)</span> <span class="pre">==</span> <span class="pre">&quot;function&quot;</span></tt> are ignored. This is a workaround
+for the case where a poorly designed library has modified
+<tt class="docutils literal"><span class="pre">Object.prototype</span></tt> and inserted &quot;convenience functions&quot;.</p>
+<p>Values that are Array-like will be expanded as if they were multiply
+defined HTML elements. For example:</p>
+<pre class="literal-block">
+assert( queryString({a: [1,2]}) === &quot;a=1&amp;a=2&quot; );
+</pre>
+<dl class="docutils">
+<dt>Alternate form 2 (MochiKit 1.4+):</dt>
+<dd><a class="mochiref reference" href="#fn-querystring">queryString([names, values])</a></dd>
+</dl>
+<p>This form behaves identically to <a class="mochiref reference" href="#fn-querystring">queryString(names, values)</a>,
+except it takes both arguments as a single Array. This mirrors the
+return value of <a class="mochiref reference" href="DOM.html#fn-formcontents">MochiKit.DOM.formContents</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-registercomparator"></a>
+<a class="mochidef reference" href="#fn-registercomparator">registerComparator(name, check, comparator[, override])</a>:</p>
+<blockquote>
+<p>Register a comparator for use with <a class="mochiref reference" href="#fn-compare">compare</a>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">name</span></tt>:</dt>
+<dd>unique identifier describing the comparator.</dd>
+<dt><tt class="docutils literal"><span class="pre">check</span></tt>:</dt>
+<dd><tt class="docutils literal"><span class="pre">function(a,</span> <span class="pre">b)</span></tt> that returns <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">a</span></tt> and <tt class="docutils literal"><span class="pre">b</span></tt>
+can be compared with <tt class="docutils literal"><span class="pre">comparator</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">comparator</span></tt>:</dt>
+<dd><p class="first"><tt class="docutils literal"><span class="pre">function(a,</span> <span class="pre">b)</span></tt> that returns:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="39%" />
+<col width="61%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Value</td>
+<td>Condition</td>
+</tr>
+<tr><td>0</td>
+<td>a == b</td>
+</tr>
+<tr><td>1</td>
+<td>a &gt; b</td>
+</tr>
+<tr><td>-1</td>
+<td>a &lt; b</td>
+</tr>
+</tbody>
+</table>
+<p class="last"><tt class="docutils literal"><span class="pre">comparator</span></tt> is guaranteed to only be called if <tt class="docutils literal"><span class="pre">check(a,</span>
+<span class="pre">b)</span></tt> returns a <tt class="docutils literal"><span class="pre">true</span></tt> value.</p>
+</dd>
+<dt><tt class="docutils literal"><span class="pre">override</span></tt>:</dt>
+<dd>if <tt class="docutils literal"><span class="pre">true</span></tt>, then this will be made the highest precedence
+comparator.  Otherwise, the lowest.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-registerjson"></a>
+<a class="mochidef reference" href="#fn-registerjson">registerJSON(name, check, simplifier[, override])</a>:</p>
+<blockquote>
+<p>Register a simplifier function for use with
+<a class="mochiref reference" href="#fn-serializejson">serializeJSON</a>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">name</span></tt>:</dt>
+<dd>unique identifier describing the serialization.</dd>
+<dt><tt class="docutils literal"><span class="pre">check</span></tt>:</dt>
+<dd><tt class="docutils literal"><span class="pre">function(obj)</span></tt> that returns <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">obj</span></tt> can
+can be simplified for serialization by <tt class="docutils literal"><span class="pre">simplifier</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">simplifier</span></tt>:</dt>
+<dd><p class="first"><tt class="docutils literal"><span class="pre">function(obj)</span></tt> that returns a simpler object that can be
+further serialized by <a class="mochiref reference" href="#fn-serializejson">serializeJSON</a>. For example,
+you could simplify <tt class="docutils literal"><span class="pre">Date</span></tt>-like objects to ISO 8601 timestamp
+strings with the following simplifier:</p>
+<pre class="literal-block">
+var simplifyDateAsISO = function (obj) {
+    return toISOTimestamp(obj, true);
+};
+registerJSON(&quot;DateLike&quot;, isDateLike, simplifyDateAsISO);
+</pre>
+<p class="last"><tt class="docutils literal"><span class="pre">simplifier</span></tt> is guaranteed to only be called if
+<tt class="docutils literal"><span class="pre">check(obj)</span></tt> returns a <tt class="docutils literal"><span class="pre">true</span></tt> value.</p>
+</dd>
+<dt><tt class="docutils literal"><span class="pre">override</span></tt>:</dt>
+<dd>if <tt class="docutils literal"><span class="pre">true</span></tt>, then this will be made the highest precedence
+serialization. Otherwise, the lowest.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-registerrepr"></a>
+<a class="mochidef reference" href="#fn-registerrepr">registerRepr(name, check, wrap[, override])</a>:</p>
+<blockquote>
+<p>Register a programmer representation function.  <a class="mochiref reference" href="#fn-repr">repr</a>
+functions should take one argument and return a string
+representation of it suitable for developers, primarily used when
+debugging.</p>
+<p>If <tt class="docutils literal"><span class="pre">override</span></tt> is given, it is used as the highest priority repr,
+otherwise it will be used as the lowest.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-repr"></a>
+<a class="mochidef reference" href="#fn-repr">repr(obj)</a>:</p>
+<blockquote>
+<p>Return a programmer representation for <tt class="docutils literal"><span class="pre">obj</span></tt>. See the
+<a class="reference" href="#programmer-representation">Programmer Representation</a> overview for more information about
+this function.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-reversekeycomparator"></a>
+<a class="mochidef reference" href="#fn-reversekeycomparator">reverseKeyComparator(key)</a>:</p>
+<blockquote>
+<p>A comparator factory that compares <tt class="docutils literal"><span class="pre">a[key]</span></tt> with <tt class="docutils literal"><span class="pre">b[key]</span></tt> in
+reverse.  e.g.:</p>
+<pre class="literal-block">
+var lst = [&quot;a&quot;, &quot;bbb&quot;, &quot;cc&quot;];
+lst.sort(reverseKeyComparator(&quot;length&quot;));
+assert(lst.toString() == &quot;bbb,cc,a&quot;);
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-serializejson"></a>
+<a class="mochidef reference" href="#fn-serializejson">serializeJSON(anObject)</a>:</p>
+<blockquote>
+<p>Serialize <tt class="docutils literal"><span class="pre">anObject</span></tt> in the JSON <a class="footnote-reference" href="#id7" id="id6" name="id6">[1]</a> format, see <a class="reference" href="#json-serialization">JSON
+Serialization</a> for the coercion rules. For unserializable objects
+(functions that do not have an adapter, <tt class="docutils literal"><span class="pre">__json__</span></tt> method, or
+<tt class="docutils literal"><span class="pre">json</span></tt> method), this will return <tt class="docutils literal"><span class="pre">undefined</span></tt>.</p>
+<p>For those familiar with Python, JSON is similar in scope to
+pickle, but it can not handle recursive object graphs.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setdefault"></a>
+<a class="mochidef reference" href="#fn-setdefault">setdefault(self, obj[, ...])</a>:</p>
+<blockquote>
+<p>Mutate <tt class="docutils literal"><span class="pre">self</span></tt> by adding all properties from other object(s) that
+it does not already have set.</p>
+<p>If <tt class="docutils literal"><span class="pre">self</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, a new <tt class="docutils literal"><span class="pre">Object</span></tt> instance will be created
+and returned.</p>
+<p>This mutates <em>and returns</em> <tt class="docutils literal"><span class="pre">self</span></tt>, be warned.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-typematcher"></a>
+<a class="mochidef reference" href="#fn-typematcher">typeMatcher(typ[, ...])</a>:</p>
+<blockquote>
+<p>Given a set of types (as string arguments), returns a
+<tt class="docutils literal"><span class="pre">function(obj[,</span> <span class="pre">...])</span></tt> that will return <tt class="docutils literal"><span class="pre">true</span></tt> if the types of
+the given arguments are all members of that set.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-update"></a>
+<a class="mochidef reference" href="#fn-update">update(self, obj[, ...])</a>:</p>
+<blockquote>
+<p>Mutate <tt class="docutils literal"><span class="pre">self</span></tt> by replacing its key:value pairs with those from
+other object(s). Key:value pairs from later objects will overwrite
+those from earlier objects.</p>
+<p>If <tt class="docutils literal"><span class="pre">self</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, a new <tt class="docutils literal"><span class="pre">Object</span></tt> instance will be created
+and returned.</p>
+<p>This mutates <em>and returns</em> <tt class="docutils literal"><span class="pre">self</span></tt>, be warned.</p>
+<p>A version of this function that creates a new object is available
+as <a class="mochiref reference" href="#fn-merge">merge(a, b[, ...])</a></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-updatetree"></a>
+<a class="mochidef reference" href="#fn-updatetree">updatetree(self, obj[, ...])</a>:</p>
+<blockquote>
+<p>Mutate <tt class="docutils literal"><span class="pre">self</span></tt> by replacing its key:value pairs with those from
+other object(s). If a given key has an object value in both
+<tt class="docutils literal"><span class="pre">self</span></tt> and <tt class="docutils literal"><span class="pre">obj</span></tt>, then this function will be called
+recursively, updating instead of replacing that object.</p>
+<p>If <tt class="docutils literal"><span class="pre">self</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, a new <tt class="docutils literal"><span class="pre">Object</span></tt> instance will be created
+and returned.</p>
+<p>This mutates <em>and returns</em> <tt class="docutils literal"><span class="pre">self</span></tt>, be warned.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-urlencode"></a>
+<a class="mochidef reference" href="#fn-urlencode">urlEncode(unencoded)</a>:</p>
+<blockquote>
+<p>Converts <tt class="docutils literal"><span class="pre">unencoded</span></tt> into a URL-encoded string. In this
+implementation, spaces are converted to %20 instead of &quot;+&quot;. e.g.:</p>
+<pre class="literal-block">
+assert( URLencode(&quot;1+2=2&quot;) == &quot;1%2B2%3D2&quot;);
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-values"></a>
+<a class="mochidef reference" href="#fn-values">values(obj)</a>:</p>
+<blockquote>
+<p>Return an <tt class="docutils literal"><span class="pre">Array</span></tt> of the property values of an object (in the
+order determined by <tt class="docutils literal"><span class="pre">for</span> <span class="pre">propName</span> <span class="pre">in</span> <span class="pre">obj</span></tt>).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-xfilter"></a>
+<a class="mochidef reference" href="#fn-xfilter">xfilter(fn, obj[, ...])</a>:</p>
+<blockquote>
+<p>Returns a new <tt class="docutils literal"><span class="pre">Array</span></tt> composed of the arguments where
+<tt class="docutils literal"><span class="pre">fn(obj)</span></tt> returns a true value.</p>
+<p>If <tt class="docutils literal"><span class="pre">fn</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, <tt class="docutils literal"><span class="pre">operator.truth</span></tt> will be used.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-xmap"></a>
+<a class="mochidef reference" href="#fn-xmap">xmap(fn, obj[, ...)</a>:</p>
+<blockquote>
+<p>Return a new <tt class="docutils literal"><span class="pre">Array</span></tt> composed of <tt class="docutils literal"><span class="pre">fn(obj)</span></tt> for every <tt class="docutils literal"><span class="pre">obj</span></tt>
+given as an argument.</p>
+<p>If <tt class="docutils literal"><span class="pre">fn</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, <tt class="docutils literal"><span class="pre">operator.identity</span></tt> is used.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id7">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id2">2</a>, <a class="fn-backref" href="#id4">3</a>, <a class="fn-backref" href="#id5">4</a>, <a class="fn-backref" href="#id6">5</a>)</em> JSON, JavaScript Object Notation: <a class="reference" href="http://json.org/">http://json.org/</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id3" name="id8">[2]</a></td><td>Python's itertools
+module: <a class="reference" href="http://docs.python.org/lib/module-itertools.html">http://docs.python.org/lib/module-itertools.html</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Color.html b/mochikit_v14/doc/html/MochiKit/Color.html
new file mode 100644 (file)
index 0000000..de50c0b
--- /dev/null
@@ -0,0 +1,753 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Color - color abstraction with CSS3 support</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Color - color abstraction with CSS3 support</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+// RGB color expressions are supported
+assert(
+    objEqual(Color.whiteColor(), Color.fromString(&quot;rgb(255,100%, 255)&quot;))
+);
+
+// So is instantiating directly from HSL or RGB values.
+// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
+assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
+
+// Or even SVG color keyword names, as per CSS3!
+assert( Color.fromString(&quot;aquamarine&quot;), &quot;#7fffd4&quot; );
+
+// NSColor-like colors built in
+assert( Color.whiteColor().toHexString() == &quot;#ffffff&quot; );
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.Color is an abstraction for handling colors and strings that
+represent colors.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
+<li><a class="mochiref reference" href="Style.html">MochiKit.Style</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<p>MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with
+alpha.  It supports parsing and generating of CSS3 colors, and has a
+full CSS3 (SVG) color table.</p>
+<p>All of the functionality in this module is exposed through a Color
+constructor and its prototype, but a few of its internals are
+available for direct use at module level.</p>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="constructors" name="constructors">Constructors</a></h2>
+<p>
+<a name="fn-color"></a>
+<a class="mochidef reference" href="#fn-color">Color()</a>:</p>
+<blockquote>
+<p>Represents a color. Component values should be integers between
+<tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>. You should use one of the <a class="mochiref reference" href="#fn-color">Color</a>
+factory functions such as <a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB</a>,
+<a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL</a>, etc. instead of constructing
+<a class="mochiref reference" href="#fn-color">Color</a> objects directly.</p>
+<p><a class="mochiref reference" href="#fn-color">Color</a> instances can be compared with
+<a class="mochiref reference" href="Base.html#fn-compare">MochiKit.Base.compare</a> (though ordering is on RGB, so
+is not particularly meaningful except for equality), and the
+default <tt class="docutils literal"><span class="pre">toString</span></tt> implementation returns
+<a class="mochiref reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>.</p>
+<p><a class="mochiref reference" href="#fn-color">Color</a> instances are immutable, and much of the
+architecture is inspired by AppKit's NSColor <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.frombackground"></a>
+<a class="mochidef reference" href="#fn-color.frombackground">Color.fromBackground(elem)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the background of the
+provided element. Equivalent to:</p>
+<pre class="literal-block">
+c = Color.fromComputedStyle(
+    elem, &quot;backgroundColor&quot;, &quot;background-color&quot;) || Color.whiteColor();
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromcomputedstyle"></a>
+<a class="mochidef reference" href="#fn-color.fromcomputedstyle">Color.fromComputedStyle(elem, style)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the result of
+<a class="mochiref reference" href="Style.html#fn-getstyle">MochiKit.Style.getStyle(elem, style)</a> or <tt class="docutils literal"><span class="pre">null</span></tt> if not
+found.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromhexstring"></a>
+<a class="mochidef reference" href="#fn-color.fromhexstring">Color.fromHexString(hexString)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given hexadecimal
+color string.  For example, <tt class="docutils literal"><span class="pre">&quot;#FFFFFF&quot;</span></tt> would return a
+<a class="mochiref reference" href="#fn-color">Color</a> with RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt>
+(white).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromhsl"></a>
+<a class="mochidef reference" href="#fn-color.fromhsl">Color.fromHSL(hue, saturation, lightness, alpha=1.0)</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>,
+<tt class="docutils literal"><span class="pre">saturation</span></tt>, <tt class="docutils literal"><span class="pre">lightness</span></tt> values. Values should be numbers
+between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will
+be used.</p>
+<dl class="docutils">
+<dt>Alternate form:</dt>
+<dd><a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL({h: hue, s: saturation, l: lightness,
+a: alpha})</a></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromhslstring"></a>
+<a class="mochidef reference" href="#fn-color.fromhslstring">Color.fromHSLString(hslString)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal hsl
+color string.  For example, <tt class="docutils literal"><span class="pre">&quot;hsl(0,0%,100%)&quot;</span></tt> would return a
+<a class="mochiref reference" href="#fn-color">Color</a> with HSL values <tt class="docutils literal"><span class="pre">[0/360,</span> <span class="pre">0/360,</span> <span class="pre">360/360]</span></tt>
+(white).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromhsv"></a>
+<a class="mochidef reference" href="#fn-color.fromhsv">Color.fromHSV(hue, saturation, value, alpha=1.0)</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>,
+<tt class="docutils literal"><span class="pre">saturation</span></tt>, <tt class="docutils literal"><span class="pre">value</span></tt> values. Values should be numbers between
+<tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will
+be used.</p>
+<dl class="docutils">
+<dt>Alternate form:</dt>
+<dd><a class="mochiref reference" href="#fn-color.fromhsv">Color.fromHSV({h: hue, s: saturation, v: value, a:
+alpha})</a></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromname"></a>
+<a class="mochidef reference" href="#fn-color.fromname">Color.fromName(colorName)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object corresponding to the given SVG
+1.0 color keyword name <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> as per the W3C CSS3 Color Module
+<a class="footnote-reference" href="#id8" id="id3" name="id3">[3]</a>. <tt class="docutils literal"><span class="pre">&quot;transparent&quot;</span></tt> is also accepted as a color name, and will
+return <a class="mochiref reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromrgb"></a>
+<a class="mochidef reference" href="#fn-color.fromrgb">Color.fromRGB(red, green, blue, alpha=1.0)</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">red</span></tt>,
+<tt class="docutils literal"><span class="pre">green</span></tt>, <tt class="docutils literal"><span class="pre">blue</span></tt>, and <tt class="docutils literal"><span class="pre">alpha</span></tt> values. Values should be
+numbers between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will
+be used.</p>
+<dl class="docutils">
+<dt>Alternate form:</dt>
+<dd><a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB({r: red, g: green, b: blue, a:
+alpha})</a></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromrgbstring"></a>
+<a class="mochidef reference" href="#fn-color.fromrgbstring">Color.fromRGBString(rgbString)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal rgb
+color string.  For example, <tt class="docutils literal"><span class="pre">&quot;rgb(255,255,255)&quot;</span></tt> would return a
+<a class="mochiref reference" href="#fn-color">Color</a> with RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt>
+(white).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromtext"></a>
+<a class="mochidef reference" href="#fn-color.fromtext">Color.fromText(elem)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the text color of the
+provided element. Equivalent to:</p>
+<pre class="literal-block">
+c = Color.fromComputedStyle(elem, &quot;color&quot;) || Color.whiteColor();
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.fromstring"></a>
+<a class="mochidef reference" href="#fn-color.fromstring">Color.fromString(rgbOrHexString)</a>:</p>
+<blockquote>
+<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given RGB, HSL, hex,
+or name.  Will return <tt class="docutils literal"><span class="pre">null</span></tt> if the string can not be parsed by
+any of these methods.</p>
+<p>See <a class="mochiref reference" href="#fn-color.fromhexstring">Color.fromHexString</a>,
+<a class="mochiref reference" href="#fn-color.fromrgbstring">Color.fromRGBString</a>, <a class="mochiref reference" href="#fn-color.fromhslstring">Color.fromHSLString</a>
+and <a class="mochiref reference" href="#fn-color.fromname">Color.fromName</a> more information.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.namedcolors"></a>
+<a class="mochidef reference" href="#fn-color.namedcolors">Color.namedColors()</a>:</p>
+<blockquote>
+<p>Returns an object with properties for each SVG 1.0 color keyword
+name <a class="footnote-reference" href="#id7" id="id4" name="id4">[2]</a> supported by CSS3 <a class="footnote-reference" href="#id8" id="id5" name="id5">[3]</a>. Property names are the color
+keyword name in lowercase, and the value is a string suitable for
+<a class="mochiref reference" href="#fn-color.fromstring">Color.fromString()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.colorwithalpha"></a>
+<a class="mochidef reference" href="#fn-color.prototype.colorwithalpha">Color.prototype.colorWithAlpha(alpha)</a>:</p>
+<blockquote>
+<p>Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the
+provided <tt class="docutils literal"><span class="pre">alpha</span></tt> value.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.colorwithhue"></a>
+<a class="mochidef reference" href="#fn-color.prototype.colorwithhue">Color.prototype.colorWithHue(hue)</a>:</p>
+<blockquote>
+<p>Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the
+provided <tt class="docutils literal"><span class="pre">hue</span></tt> value.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.colorwithsaturation"></a>
+<a class="mochidef reference" href="#fn-color.prototype.colorwithsaturation">Color.prototype.colorWithSaturation(saturation)</a>:</p>
+<blockquote>
+<p>Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the
+provided <tt class="docutils literal"><span class="pre">saturation</span></tt> value (using the HSL color model).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.colorwithlightness"></a>
+<a class="mochidef reference" href="#fn-color.prototype.colorwithlightness">Color.prototype.colorWithLightness(lightness)</a>:</p>
+<blockquote>
+<p>Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the
+provided <tt class="docutils literal"><span class="pre">lightness</span></tt> value.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.darkercolorwithlevel"></a>
+<a class="mochidef reference" href="#fn-color.prototype.darkercolorwithlevel">Color.prototype.darkerColorWithLevel(level)</a>:</p>
+<blockquote>
+<p>Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but darker by
+the given <tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.lightercolorwithlevel"></a>
+<a class="mochidef reference" href="#fn-color.prototype.lightercolorwithlevel">Color.prototype.lighterColorWithLevel(level)</a>:</p>
+<blockquote>
+<p>Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but lighter by
+the given <tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.blendedcolor"></a>
+<a class="mochidef reference" href="#fn-color.prototype.blendedcolor">Color.prototype.blendedColor(other, fraction=0.5)</a>:</p>
+<blockquote>
+<p>Return a new <a class="mochiref reference" href="#fn-color">Color</a> whose RGBA component values are a
+weighted sum of this color and <tt class="docutils literal"><span class="pre">other</span></tt>. Each component of the
+returned color is the <tt class="docutils literal"><span class="pre">fraction</span></tt> of other's value plus <tt class="docutils literal"><span class="pre">1</span> <span class="pre">-</span>
+<span class="pre">fraction</span></tt> of this color's.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.islight"></a>
+<a class="mochidef reference" href="#fn-color.prototype.islight">Color.prototype.isLight()</a>:</p>
+<blockquote>
+<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is greater
+than <tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
+<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color
+components are not premultiplied).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.isdark"></a>
+<a class="mochidef reference" href="#fn-color.prototype.isdark">Color.prototype.isDark()</a>:</p>
+<blockquote>
+<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is less than
+or equal to <tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
+<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color
+components are not premultiplied).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.torgbstring"></a>
+<a class="mochidef reference" href="#fn-color.prototype.torgbstring">Color.prototype.toRGBString()</a>:</p>
+<blockquote>
+<p>Return the decimal <tt class="docutils literal"><span class="pre">&quot;rgb(red,</span> <span class="pre">green,</span> <span class="pre">blue)&quot;</span></tt> string
+representation of this color.</p>
+<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
+<tt class="docutils literal"><span class="pre">&quot;rgba(red,</span> <span class="pre">green,</span> <span class="pre">blue,</span> <span class="pre">alpha)&quot;</span></tt> string representation will be
+used.</p>
+<p>For example:</p>
+<pre class="literal-block">
+assert( Color.whiteColor().toRGBString() == &quot;rgb(255,255,255)&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.tohslstring"></a>
+<a class="mochidef reference" href="#fn-color.prototype.tohslstring">Color.prototype.toHSLString()</a>:</p>
+<blockquote>
+<p>Return the decimal <tt class="docutils literal"><span class="pre">&quot;hsl(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness)&quot;</span></tt> string
+representation of this color.</p>
+<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
+<tt class="docutils literal"><span class="pre">&quot;hsla(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness,</span> <span class="pre">alpha)&quot;</span></tt> string
+representation will be used.</p>
+<p>For example:</p>
+<pre class="literal-block">
+assert( Color.whiteColor().toHSLString() == &quot;hsl(0,0,360)&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.tohexstring"></a>
+<a class="mochidef reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>:</p>
+<blockquote>
+<p>Return the hexadecimal <tt class="docutils literal"><span class="pre">&quot;#RRGGBB&quot;</span></tt> string representation of this
+color.</p>
+<p>Note that the alpha component is completely ignored for
+hexadecimal string representations!</p>
+<p>For example:</p>
+<pre class="literal-block">
+assert( Color.whiteColor().toHexString() == &quot;#FFFFFF&quot; );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.asrgb"></a>
+<a class="mochidef reference" href="#fn-color.prototype.asrgb">Color.prototype.asRGB()</a>:</p>
+<blockquote>
+<p>Return the RGB (red, green, blue, alpha) components of this color
+as an object with <tt class="docutils literal"><span class="pre">r</span></tt>, <tt class="docutils literal"><span class="pre">g</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, and <tt class="docutils literal"><span class="pre">a</span></tt> properties that
+have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.ashsl"></a>
+<a class="mochidef reference" href="#fn-color.prototype.ashsl">Color.prototype.asHSL()</a>:</p>
+<blockquote>
+<p>Return the HSL (hue, saturation, lightness, alpha) components of
+this color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">l</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt>
+properties that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.prototype.ashsv"></a>
+<a class="mochidef reference" href="#fn-color.prototype.ashsv">Color.prototype.asHSV()</a>:</p>
+<blockquote>
+<p>Return the HSV (hue, saturation, value, alpha) components of this
+color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">v</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt> properties
+that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.blackcolor"></a>
+<a class="mochidef reference" href="#fn-color.blackcolor">Color.blackColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 0
+(#000000).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.bluecolor"></a>
+<a class="mochidef reference" href="#fn-color.bluecolor">Color.blueColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 1
+(#0000ff).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.browncolor"></a>
+<a class="mochidef reference" href="#fn-color.browncolor">Color.brownColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.6, 0.4,
+0.2 (#996633).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.cyancolor"></a>
+<a class="mochidef reference" href="#fn-color.cyancolor">Color.cyanColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 1
+(#00ffff).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.darkgraycolor"></a>
+<a class="mochidef reference" href="#fn-color.darkgraycolor">Color.darkGrayColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1/3, 1/3,
+1/3 (#555555).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.graycolor"></a>
+<a class="mochidef reference" href="#fn-color.graycolor">Color.grayColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0.5,
+0.5 (#808080).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.greencolor"></a>
+<a class="mochidef reference" href="#fn-color.greencolor">Color.greenColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 0.
+(#00ff00).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.lightgraycolor"></a>
+<a class="mochidef reference" href="#fn-color.lightgraycolor">Color.lightGrayColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 2/3, 2/3,
+2/3 (#aaaaaa).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.magentacolor"></a>
+<a class="mochidef reference" href="#fn-color.magentacolor">Color.magentaColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 1
+(#ff00ff).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.orangecolor"></a>
+<a class="mochidef reference" href="#fn-color.orangecolor">Color.orangeColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0.5, 0
+(#ff8000).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.purplecolor"></a>
+<a class="mochidef reference" href="#fn-color.purplecolor">Color.purpleColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0, 0.5
+(#800080).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.redcolor"></a>
+<a class="mochidef reference" href="#fn-color.redcolor">Color.redColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 0
+(#ff0000).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.whitecolor"></a>
+<a class="mochidef reference" href="#fn-color.whitecolor">Color.whiteColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 1
+(#ffffff).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.yellowcolor"></a>
+<a class="mochidef reference" href="#fn-color.yellowcolor">Color.yellowColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 0
+(#ffff00).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-color.transparentcolor"></a>
+<a class="mochidef reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>:</p>
+<blockquote>
+<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object that is completely transparent
+(has alpha component of 0).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-clampcolorcomponent"></a>
+<a class="mochidef reference" href="#fn-clampcolorcomponent">clampColorComponent(num, scale)</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">num</span> <span class="pre">*</span> <span class="pre">scale</span></tt> clamped between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">scale</span></tt>.</p>
+<p><a class="mochiref reference" href="#fn-clampcolorcomponent">clampColorComponent</a> is not exported by default when
+using JSAN.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-hsltorgb"></a>
+<a class="mochidef reference" href="#fn-hsltorgb">hslToRGB(hue, saturation, lightness, alpha)</a>:</p>
+<blockquote>
+<p>Computes RGB values from the provided HSL values. The return value
+is a mapping with <tt class="docutils literal"><span class="pre">&quot;r&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;g&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;b&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt> keys.</p>
+<dl class="docutils">
+<dt>Alternate form:</dt>
+<dd><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB({h: hue, s: saturation, l: lightness, a:
+alpha})</a>.</dd>
+</dl>
+<p><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB</a> is not exported by default when using JSAN.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-hsvtorgb"></a>
+<a class="mochidef reference" href="#fn-hsvtorgb">hsvToRGB(hue, saturation, value, alpha)</a>:</p>
+<blockquote>
+<p>Computes RGB values from the provided HSV values. The return value
+is a mapping with <tt class="docutils literal"><span class="pre">&quot;r&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;g&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;b&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt> keys.</p>
+<dl class="docutils">
+<dt>Alternate form:</dt>
+<dd><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB({h: hue, s: saturation, v: value, a:
+alpha})</a>.</dd>
+</dl>
+<p><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB</a> is not exported by default when using JSAN.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-tocolorpart"></a>
+<a class="mochidef reference" href="#fn-tocolorpart">toColorPart(num)</a>:</p>
+<blockquote>
+<p>Convert num to a zero padded hexadecimal digit for use in a
+hexadecimal color string. Num should be an integer between <tt class="docutils literal"><span class="pre">0</span></tt>
+and <tt class="docutils literal"><span class="pre">255</span></tt>.</p>
+<p><a class="mochiref reference" href="#fn-tocolorpart">toColorPart</a> is not exported by default when using
+JSAN.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-rgbtohsl"></a>
+<a class="mochidef reference" href="#fn-rgbtohsl">rgbToHSL(red, green, blue, alpha)</a>:</p>
+<blockquote>
+<p>Computes HSL values based on the provided RGB values. The return
+value is a mapping with <tt class="docutils literal"><span class="pre">&quot;h&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;s&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;l&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt>
+keys.</p>
+<dl class="docutils">
+<dt>Alternate form:</dt>
+<dd><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL({r: red, g: green, b: blue, a: alpha})</a>.</dd>
+</dl>
+<p><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL</a> is not exported by default when using JSAN.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-rgbtohsv"></a>
+<a class="mochidef reference" href="#fn-rgbtohsv">rgbToHSV(red, green, blue, alpha)</a>:</p>
+<blockquote>
+<p>Computes HSV values based on the provided RGB values. The return
+value is a mapping with <tt class="docutils literal"><span class="pre">&quot;h&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;s&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;v&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt>
+keys.</p>
+<dl class="docutils">
+<dt>Alternate form:</dt>
+<dd><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV({r: red, g: green, b: blue, a: alpha})</a>.</dd>
+</dl>
+<p><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV</a> is not exported by default when using JSAN.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id7">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id8">[3]</a></td><td><em>(<a class="fn-backref" href="#id3">1</a>, <a class="fn-backref" href="#id5">2</a>)</em> W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/DOM.html b/mochikit_v14/doc/html/MochiKit/DOM.html
new file mode 100644 (file)
index 0000000..a61ec34
--- /dev/null
@@ -0,0 +1,1186 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.DOM - painless DOM manipulation API</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.DOM - painless DOM manipulation API</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+var rows = [
+    [&quot;dataA1&quot;, &quot;dataA2&quot;, &quot;dataA3&quot;],
+    [&quot;dataB1&quot;, &quot;dataB2&quot;, &quot;dataB3&quot;]
+];
+row_display = function (row) {
+    return TR(null, map(partial(TD, null), row));
+}
+var newTable = TABLE({'class': 'prettytable'},
+    THEAD(null,
+        row_display([&quot;head1&quot;, &quot;head2&quot;, &quot;head3&quot;])),
+    TFOOT(null,
+        row_display([&quot;foot1&quot;, &quot;foot2&quot;, &quot;foot3&quot;])),
+    TBODY(null,
+        map(row_display, rows)));
+// put that in your document.createElement and smoke it!
+swapDOM(oldTable, newTable);
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>As you probably know, the DOM APIs are some of the most painful
+Java-inspired APIs you'll run across from a highly dynamic
+language. Don't worry about that though, because they provide a
+reasonable basis to build something that sucks a lot less.</p>
+<p>MochiKit.DOM takes much of its inspiration from Nevow's <a class="footnote-reference" href="#id5" id="id1" name="id1">[1]</a> stan
+<a class="footnote-reference" href="#id6" id="id2" name="id2">[2]</a>.  This means you choose a tag, give it some attributes, then
+stuff it full of <em>whatever objects you want</em>. MochiKit.DOM isn't
+stupid, it knows that a string should be a text node, and that you
+want functions to be called, and that <tt class="docutils literal"><span class="pre">Array</span></tt>-like objects should be
+expanded, and stupid <tt class="docutils literal"><span class="pre">null</span></tt> values should be skipped.</p>
+<p>Hell, it will let you return strings from functions, and use iterators
+from <a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>. If that's not enough, just teach it
+new tricks with <a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>. If you have never
+used an API like this for creating DOM elements, you've been wasting
+your damn time. Get with it!</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="Style.html">MochiKit.Style</a> (optional since MochiKit 1.4 for
+backwards-compatibility)</li>
+<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a> (optional since MochiKit 1.4)</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<div class="section">
+<h2><a id="dom-coercion-rules" name="dom-coercion-rules">DOM Coercion Rules</a></h2>
+<p>In order of precedence, <a class="mochiref reference" href="#fn-createdom">createDOM</a> coerces given arguments
+to DOM nodes using the following rules:</p>
+<ol class="arabic simple">
+<li>Functions are called with a <tt class="docutils literal"><span class="pre">this</span></tt> and first argument of the
+parent node and their return value is subject to the following
+rules (even this one).</li>
+<li><tt class="docutils literal"><span class="pre">undefined</span></tt> and <tt class="docutils literal"><span class="pre">null</span></tt> are ignored.</li>
+<li>If <a class="mochiref reference" href="Iter.html">MochiKit.Iter</a> is loaded, iterables are flattened
+(as if they were passed in-line as nodes) and each return value is
+subject to these rules.</li>
+<li>Values that look like DOM nodes (objects with a <tt class="docutils literal"><span class="pre">.nodeType</span> <span class="pre">&gt;</span> <span class="pre">0</span></tt>)
+are <tt class="docutils literal"><span class="pre">.appendChild</span></tt>'ed to the created DOM fragment.</li>
+<li>Strings are wrapped up with <tt class="docutils literal"><span class="pre">document.createTextNode</span></tt></li>
+<li>Objects that have a <tt class="docutils literal"><span class="pre">.dom(node)</span></tt> or <tt class="docutils literal"><span class="pre">.__dom__(node)</span></tt> method
+are called with the parent node and their result is coerced using
+these rules.  (MochiKit 1.4+).</li>
+<li>Objects that are not strings are run through the <tt class="docutils literal"><span class="pre">domConverters</span></tt>
+<a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a> (see
+<a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>).  The adapted value is subject
+to these same rules (e.g.  if the adapter returns a string, it
+will be coerced to a text node).</li>
+<li>If no adapter is available, <tt class="docutils literal"><span class="pre">.toString()</span></tt> is used to create a
+text node.</li>
+</ol>
+</div>
+<div class="section">
+<h2><a id="creating-dom-element-trees" name="creating-dom-element-trees">Creating DOM Element Trees</a></h2>
+<p><a class="mochiref reference" href="#fn-createdom">createDOM</a> provides you with an excellent facility for
+creating DOM trees that is easy on the wrists. One of the best ways to
+understand how to use it is to take a look at an example:</p>
+<pre class="literal-block">
+var rows = [
+    [&quot;dataA1&quot;, &quot;dataA2&quot;, &quot;dataA3&quot;],
+    [&quot;dataB1&quot;, &quot;dataB2&quot;, &quot;dataB3&quot;]
+];
+row_display = function (row) {
+    return TR(null, map(partial(TD, null), row));
+}
+var newTable = TABLE({'class': 'prettytable'},
+    THEAD(null,
+        row_display([&quot;head1&quot;, &quot;head2&quot;, &quot;head3&quot;])),
+    TFOOT(null,
+        row_display([&quot;foot1&quot;, &quot;foot2&quot;, &quot;foot3&quot;])),
+    TBODY(null,
+        map(row_display, rows)));
+</pre>
+<p>This will create a table with the following visual layout (if it were
+inserted into the document DOM):</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">head1</th>
+<th class="head">head2</th>
+<th class="head">head3</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>dataA1</td>
+<td>dataA2</td>
+<td>dataA3</td>
+</tr>
+<tr><td>dataB1</td>
+<td>dataB2</td>
+<td>dataB3</td>
+</tr>
+<tr><td>foot1</td>
+<td>foot2</td>
+<td>foot3</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>Corresponding to the following HTML:</p>
+<pre class="literal-block">
+&lt;table class=&quot;prettytable&quot;&gt;
+    &lt;thead&gt;
+        &lt;tr&gt;
+            &lt;td&gt;head1&lt;/td&gt;
+            &lt;td&gt;head2&lt;/td&gt;
+            &lt;td&gt;head3&lt;/td&gt;
+        &lt;/tr&gt;
+    &lt;/thead&gt;
+    &lt;tfoot&gt;
+        &lt;tr&gt;
+            &lt;td&gt;foot1&lt;/td&gt;
+            &lt;td&gt;foot2&lt;/td&gt;
+            &lt;td&gt;foot3&lt;/td&gt;
+        &lt;/tr&gt;
+    &lt;/tfoot&gt;
+    &lt;tbody&gt;
+        &lt;tr&gt;
+            &lt;td&gt;dataA1&lt;/td&gt;
+            &lt;td&gt;dataA2&lt;/td&gt;
+            &lt;td&gt;dataA3&lt;/td&gt;
+        &lt;/tr&gt;
+        &lt;tr&gt;
+            &lt;td&gt;dataB1&lt;/td&gt;
+            &lt;td&gt;dataB2&lt;/td&gt;
+            &lt;td&gt;dataB3&lt;/td&gt;
+        &lt;/tr&gt;
+    &lt;/tbody&gt;
+&lt;/table&gt;
+</pre>
+</div>
+<div class="section">
+<h2><a id="dom-context" name="dom-context">DOM Context</a></h2>
+<p>In order to prevent having to pass a <tt class="docutils literal"><span class="pre">window</span></tt> and/or <tt class="docutils literal"><span class="pre">document</span></tt>
+variable to every MochiKit.DOM function (e.g. when working with a
+child window), MochiKit.DOM maintains a context variable for each of
+them. They are managed with the <a class="mochiref reference" href="#fn-withwindow">withWindow</a> and
+<a class="mochiref reference" href="#fn-withdocument">withDocument</a> functions, and can be acquired with
+<a class="mochiref reference" href="#fn-currentwindow">currentWindow()</a> and <a class="mochiref reference" href="#fn-currentdocument">currentDocument()</a></p>
+<p>For example, if you are creating DOM nodes in a child window, you
+could do something like this:</p>
+<pre class="literal-block">
+withWindow(child, function () {
+    var doc = currentDocument();
+    appendChildNodes(doc.body, H1(null, &quot;This is in the child!&quot;));
+});
+</pre>
+<p>Note that <a class="mochiref reference" href="#fn-withwindow">withWindow(win, ...)</a> also implies
+<a class="mochiref reference" href="#fn-withdocument">withDocument(win.document, ...)</a>.</p>
+</div>
+<div class="section">
+<h2><a id="dom-gotchas" name="dom-gotchas">DOM Gotchas</a></h2>
+<dl class="docutils">
+<dt>Performance Tradeoff:</dt>
+<dd>DOM is much easier to get correct and more flexible than working
+directly with markup as strings. Modifying <tt class="docutils literal"><span class="pre">innerHTML</span></tt> is still
+the fastest way to make document changes.</dd>
+<dt>Internet Explorer:</dt>
+<dd>Internet Explorer's DOM implementation is quite poor in comparison
+to the other popular implementations. In order to avoid memory
+leaks due to circular references, you should use
+<a class="mochiref reference" href="Signal.html#fn-connect">MochiKit.Signal.connect</a> for all of your event handling
+needs. Additionally, when creating tables with DOM, it is required
+to use a <tt class="docutils literal"><span class="pre">TBODY</span></tt> tag (see <a class="reference" href="#creating-dom-element-trees">Creating DOM Element Trees</a> for an
+example of this).</dd>
+</dl>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-$"></a>
+<a class="mochidef reference" href="#fn-$">$(id[, ...])</a>:</p>
+<blockquote>
+<p>An alias for <a class="mochiref reference" href="#fn-getelement">getElement(id[, ...])</a></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-addelementclass"></a>
+<a class="mochidef reference" href="#fn-addelementclass">addElementClass(element, className)</a>:</p>
+<blockquote>
+<p>Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> has <tt class="docutils literal"><span class="pre">className</span></tt> set as part of
+its class attribute. This will not disturb other class names.
+<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string
+identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-addloadevent"></a>
+<a class="mochidef reference" href="#fn-addloadevent">addLoadEvent(func)</a>:</p>
+<blockquote>
+<p>Note that <a class="mochiref reference" href="#fn-addloadevent">addLoadEvent</a> can not be used in combination
+with <a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> if the <tt class="docutils literal"><span class="pre">onload</span></tt> event is
+connected.  Once an event is connected with
+<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs may be used for that
+same event.</p>
+<p>This will stack <tt class="docutils literal"><span class="pre">window.onload</span></tt> functions on top of each other.
+Each function added will be called after <tt class="docutils literal"><span class="pre">onload</span></tt> in the order
+that they were added.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-addtocallstack"></a>
+<a class="mochidef reference" href="#fn-addtocallstack">addToCallStack(target, path, func[, once])</a>:</p>
+<blockquote>
+<p>Note that <a class="mochiref reference" href="#fn-addtocallstack">addToCallStack</a> is not compatible with
+<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>. Once an event is connected with
+<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs may be used for that
+same event.</p>
+<p>Set the property <tt class="docutils literal"><span class="pre">path</span></tt> of <tt class="docutils literal"><span class="pre">target</span></tt> to a function that calls
+the existing function at that property (if any), then calls
+<tt class="docutils literal"><span class="pre">func</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">target[path]()</span></tt> returns exactly <tt class="docutils literal"><span class="pre">false</span></tt>, then <tt class="docutils literal"><span class="pre">func</span></tt>
+will not be called.</p>
+<p>If <tt class="docutils literal"><span class="pre">once</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then <tt class="docutils literal"><span class="pre">target[path]</span></tt> is set to <tt class="docutils literal"><span class="pre">null</span></tt>
+after the function call stack has completed.</p>
+<p>If called several times for the same <tt class="docutils literal"><span class="pre">target[path]</span></tt>, it will
+create a stack of functions (instead of just a pair).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-appendchildnodes"></a>
+<a class="mochidef reference" href="#fn-appendchildnodes">appendChildNodes(node[, childNode[, ...]])</a>:</p>
+<blockquote>
+<p>Append children to a DOM element using the <a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element to add children to (if a string
+is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate
+the node)</dd>
+<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
+<dd>All additional arguments, if any, will be coerced into DOM
+nodes that are appended as children using the <a class="reference" href="#dom-coercion-rules">DOM Coercion
+Rules</a>.</dd>
+<dt><em>returns</em>:</dt>
+<dd>The given DOM element</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-insertsiblingnodesbefore"></a>
+<a class="mochidef reference" href="#fn-insertsiblingnodesbefore">insertSiblingNodesBefore(node[, siblingNode[, ...]])</a>:</p>
+<blockquote>
+<p>Insert children into the DOM structure using the <a class="reference" href="#dom-coercion-rules">DOM Coercion
+Rules</a>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element you want to insert children
+before (if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
+will be used to locate the node)</dd>
+<dt><tt class="docutils literal"><span class="pre">siblingNode</span></tt>...:</dt>
+<dd>All additional arguments, if any, will be coerced into DOM
+nodes that are inserted as siblings using the <a class="reference" href="#dom-coercion-rules">DOM Coercion
+Rules</a>.</dd>
+<dt><em>returns</em>:</dt>
+<dd>The parent of the given DOM element</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-insertsiblingnodesafter"></a>
+<a class="mochidef reference" href="#fn-insertsiblingnodesafter">insertSiblingNodesAfter(node[, siblingNode[, ...]])</a>:</p>
+<blockquote>
+<p>Insert children into the DOM structure using the <a class="reference" href="#dom-coercion-rules">DOM Coercion
+Rules</a>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element you want to insert children
+after (if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
+will be used to locate the node)</dd>
+<dt><tt class="docutils literal"><span class="pre">siblingNode</span></tt>...:</dt>
+<dd>All additional arguments, if any, will be coerced into DOM
+nodes that are inserted as siblings using the <a class="reference" href="#dom-coercion-rules">DOM Coercion
+Rules</a>.</dd>
+<dt><em>returns</em>:</dt>
+<dd>The parent of the given DOM element</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-createdom"></a>
+<a class="mochidef reference" href="#fn-createdom">createDOM(name[, attrs[, node[, ...]]])</a>:</p>
+<blockquote>
+<p>Create a DOM fragment in a really convenient manner, much like
+Nevow`s <a class="footnote-reference" href="#id5" id="id3" name="id3">[1]</a> stan <a class="footnote-reference" href="#id6" id="id4" name="id4">[2]</a>.</p>
+<p>Partially applied versions of this function for common tags are
+available as aliases:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">A</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">BUTTON</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">BR</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">CANVAS</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">DIV</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">FIELDSET</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">FORM</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">H1</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">H2</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">H3</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">HR</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">IMG</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">INPUT</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">LABEL</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">LEGEND</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">LI</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">OL</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">OPTGROUP</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">OPTION</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">P</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">PRE</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">SELECT</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">SPAN</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">STRONG</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TABLE</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TBODY</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TD</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TEXTAREA</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TFOOT</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TH</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">THEAD</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TR</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TT</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">UL</span></tt></li>
+</ul>
+<p>See <a class="reference" href="#creating-dom-element-trees">Creating DOM Element Trees</a> for a comprehensive example.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">name</span></tt>:</dt>
+<dd>The kind of fragment to create (e.g. 'span'), such as you
+would pass to <tt class="docutils literal"><span class="pre">document.createElement</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
+<dd><p class="first">An object whose properties will be used as the attributes
+(e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">'display:block'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
+attributes need to be set.</p>
+<p>See <a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a> for more information.</p>
+<p class="last">For convenience, if <tt class="docutils literal"><span class="pre">attrs</span></tt> is a string, <tt class="docutils literal"><span class="pre">null</span></tt> is used
+and the string will be considered the first <tt class="docutils literal"><span class="pre">node</span></tt>.</p>
+</dd>
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
+<dd>All additional arguments, if any, will be coerced into DOM
+nodes that are appended as children using the <a class="reference" href="#dom-coercion-rules">DOM Coercion
+Rules</a>.</dd>
+<dt><em>returns</em>:</dt>
+<dd>A DOM element</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-createdomfunc"></a>
+<a class="mochidef reference" href="#fn-createdomfunc">createDOMFunc(tag[, attrs[, node[, ...]]])</a>:</p>
+<blockquote>
+<p>Convenience function to create a partially applied createDOM
+function. You'd want to use this if you add additional convenience
+functions for creating tags, or if you find yourself creating a
+lot of tags with a bunch of the same attributes or contents.</p>
+<p>See <a class="mochiref reference" href="#fn-createdom">createDOM</a> for more detailed descriptions of the
+arguments.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">tag</span></tt>:</dt>
+<dd>The name of the tag</dd>
+<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
+<dd>Optionally specify the attributes to apply</dd>
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
+<dd>Optionally specify any children nodes it should have</dd>
+<dt><em>returns</em>:</dt>
+<dd>function that takes additional arguments and calls
+<a class="mochiref reference" href="#fn-createdom">createDOM</a></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-currentdocument"></a>
+<a class="mochidef reference" href="#fn-currentdocument">currentDocument()</a>:</p>
+<blockquote>
+<p>Return the current <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always
+be the same as the global <tt class="docutils literal"><span class="pre">document</span></tt> unless
+<a class="mochiref reference" href="#fn-withdocument">withDocument</a> or <a class="mochiref reference" href="#fn-withwindow">withWindow</a> is currently
+executing.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-currentwindow"></a>
+<a class="mochidef reference" href="#fn-currentwindow">currentWindow()</a>:</p>
+<blockquote>
+<p>Return the current <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always be
+the same as the global <tt class="docutils literal"><span class="pre">window</span></tt> unless <a class="mochiref reference" href="#fn-withwindow">withWindow</a> is
+currently executing.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-emithtml"></a>
+<a class="mochidef reference" href="#fn-emithtml">emitHTML(dom[, lst])</a>:</p>
+<blockquote>
+<p>Convert a DOM tree to an <tt class="docutils literal"><span class="pre">Array</span></tt> of HTML string fragments. This should
+be used for debugging/testing purposes only.</p>
+<p>The DOM property <tt class="docutils literal"><span class="pre">innerHTML</span></tt> or <tt class="docutils literal"><span class="pre">cloneNode(true)</span></tt> method should
+be used for most purposes.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-escapehtml"></a>
+<a class="mochidef reference" href="#fn-escapehtml">escapeHTML(s)</a>:</p>
+<blockquote>
+<p>Make a string safe for HTML, converting the usual suspects (lt,
+gt, quot, amp)</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-focusonload"></a>
+<a class="mochidef reference" href="#fn-focusonload">focusOnLoad(element)</a>:</p>
+<blockquote>
+<p>Note that <a class="mochiref reference" href="#fn-focusonload">focusOnLoad</a> can not be used in combination
+with <a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> if the <tt class="docutils literal"><span class="pre">onload</span></tt> event is
+connected.  Once an event is connected with
+<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs may be used for that
+same event.</p>
+<p>This adds an onload event to focus the given element.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-formcontents"></a>
+<a class="mochidef reference" href="#fn-formcontents">formContents(elem=document.body)</a>:</p>
+<blockquote>
+<p>Search the DOM tree, starting at <tt class="docutils literal"><span class="pre">elem</span></tt>, for any elements with a
+<tt class="docutils literal"><span class="pre">name</span></tt> and <tt class="docutils literal"><span class="pre">value</span></tt> attribute. Return a 2-element <tt class="docutils literal"><span class="pre">Array</span></tt> of
+<tt class="docutils literal"><span class="pre">names</span></tt> and <tt class="docutils literal"><span class="pre">values</span></tt> suitable for use with
+<a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getelement"></a>
+<a class="mochidef reference" href="#fn-getelement">getElement(id[, ...])</a>:</p>
+<blockquote>
+<p>A small quick little function to encapsulate the
+<tt class="docutils literal"><span class="pre">getElementById</span></tt> method. It includes a check to ensure we can
+use that method.</p>
+<p>If the id isn't a string, it will be returned as-is.</p>
+<p>Also available as <a class="mochiref reference" href="#fn-$">$(...)</a> for convenience and
+compatibility with other JavaScript frameworks.</p>
+<p>If multiple arguments are given, an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getelementsbytagandclassname"></a>
+<a class="mochidef reference" href="#fn-getelementsbytagandclassname">getElementsByTagAndClassName(tagName, className, parent=document)</a>:</p>
+<blockquote>
+<p>Returns an array of elements in <tt class="docutils literal"><span class="pre">parent</span></tt> that match the tag name
+and class name provided. If <tt class="docutils literal"><span class="pre">parent</span></tt> is a string, it will be
+looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<p>If <tt class="docutils literal"><span class="pre">tagName</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt> or <tt class="docutils literal"><span class="pre">&quot;*&quot;</span></tt>, all elements will be
+searched for the matching class.</p>
+<p>If <tt class="docutils literal"><span class="pre">className</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, all elements matching the provided
+tag are returned.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getfirstelementbytagandclassname"></a>
+<a class="mochidef reference" href="#fn-getfirstelementbytagandclassname">getFirstElementByTagAndClassName(tagName, className, parent=document)</a>:</p>
+<blockquote>
+<p>Return the first element in <tt class="docutils literal"><span class="pre">parent</span></tt> that matches the tag name
+and class name provided. If <tt class="docutils literal"><span class="pre">parent</span></tt> is a string, it will be
+looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<p>If <tt class="docutils literal"><span class="pre">tagName</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt> or <tt class="docutils literal"><span class="pre">&quot;*&quot;</span></tt>, all elements will be searched
+for the matching class.</p>
+<p>If <tt class="docutils literal"><span class="pre">className</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, the first element matching the provided
+tag will be returned.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getfirstparentbytagandclassname"></a>
+<a class="mochidef reference" href="#fn-getfirstparentbytagandclassname">getFirstParentByTagAndClassName(elem, tagName='*', className=null)</a>:</p>
+<blockquote>
+<p>Returns the first parent of <tt class="docutils literal"><span class="pre">elem</span></tt> matches the tag name and class name
+provided. If parent is a string, it will be looked up using
+<a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<p>If <tt class="docutils literal"><span class="pre">tagName</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt> or <tt class="docutils literal"><span class="pre">&quot;*&quot;</span></tt>, all elements will be searched
+for the matching class.</p>
+<p>If <tt class="docutils literal"><span class="pre">className</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, the first element matching the provided
+tag will be returned.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getnodeattribute"></a>
+<a class="mochidef reference" href="#fn-getnodeattribute">getNodeAttribute(node, attr)</a>:</p>
+<blockquote>
+<p>Get the value of the given attribute for a DOM element without
+ever raising an exception (will return <tt class="docutils literal"><span class="pre">null</span></tt> on exception).</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element to update (if a string is
+given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the
+node)</dd>
+<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
+<dd><p class="first">The name of the attribute</p>
+<p class="last">Note that it will do the right thing for IE, so don't do
+the <tt class="docutils literal"><span class="pre">class</span></tt> -&gt; <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
+</dd>
+<dt><em>returns</em>:</dt>
+<dd>The attribute's value, or <tt class="docutils literal"><span class="pre">null</span></tt></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-haselementclass"></a>
+<a class="mochidef reference" href="#fn-haselementclass">hasElementClass(element, className[, ...])</a>:</p>
+<blockquote>
+<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">className</span></tt> is found on the <tt class="docutils literal"><span class="pre">element</span></tt>.
+<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string
+identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-ischildnode"></a>
+<a class="mochidef reference" href="#fn-ischildnode">isChildNode(node, maybeParent)</a>:</p>
+<blockquote>
+<p>Determine whether <tt class="docutils literal"><span class="pre">node</span></tt> is a child node of <tt class="docutils literal"><span class="pre">maybeParent</span></tt>.
+Returns <tt class="docutils literal"><span class="pre">true</span></tt> if so, and <tt class="docutils literal"><span class="pre">false</span></tt> if not. A node is considered
+a child node of itself for the purposes of this function.</p>
+<p>If either <tt class="docutils literal"><span class="pre">node</span></tt> or <tt class="docutils literal"><span class="pre">maybeParent</span></tt> are strings, the related
+nodes will be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isparent"></a>
+<a class="mochidef reference" href="#fn-isparent">isParent(child, element)</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt> contains <tt class="docutils literal"><span class="pre">child</span></tt>. Returns <tt class="docutils literal"><span class="pre">false</span></tt>
+if <tt class="docutils literal"><span class="pre">element</span> <span class="pre">==</span> <span class="pre">child</span></tt> or <tt class="docutils literal"><span class="pre">child</span></tt> is not contained in <tt class="docutils literal"><span class="pre">element</span></tt>.
+If <tt class="docutils literal"><span class="pre">child</span></tt> or <tt class="docutils literal"><span class="pre">element</span></tt> are strings, they will be looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-makeclipping"></a>
+<a class="mochidef reference" href="#fn-makeclipping">makeClipping(element)</a>:</p>
+<blockquote>
+<p>Ensure that <tt class="docutils literal"><span class="pre">element.style.overflow</span> <span class="pre">=</span> <span class="pre">'hidden'</span></tt>. If <tt class="docutils literal"><span class="pre">element</span></tt> is a
+string, then it will be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<p>Returns the original value of <tt class="docutils literal"><span class="pre">element.style.overflow</span></tt>, so that it
+may be restored with <a class="mochiref reference" href="#fn-undoclipping">undoClipping(element, overflow)</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-makepositioned"></a>
+<a class="mochidef reference" href="#fn-makepositioned">makePositioned(element)</a>:</p>
+<blockquote>
+<p>Ensure that <tt class="docutils literal"><span class="pre">element.style.position</span></tt> is set to <tt class="docutils literal"><span class="pre">&quot;relative&quot;</span></tt> if it
+is not set or is <tt class="docutils literal"><span class="pre">&quot;static&quot;</span></tt>. If <tt class="docutils literal"><span class="pre">element</span></tt> is a
+string, then it will be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<p>Returns the original value of <tt class="docutils literal"><span class="pre">element.style.position</span></tt>, so that it
+may be restored with <a class="mochiref reference" href="#fn-undopositioned">undoPositioned(element, position)</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-registerdomconverter"></a>
+<a class="mochidef reference" href="#fn-registerdomconverter">registerDOMConverter(name, check, wrap[, override])</a>:</p>
+<blockquote>
+<p>Register an adapter to convert objects that match <tt class="docutils literal"><span class="pre">check(obj,</span>
+<span class="pre">ctx)</span></tt> to a DOM element, or something that can be converted to a
+DOM element (i.e. number, bool, string, function, iterable).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-removeelement"></a>
+<a class="mochidef reference" href="#fn-removeelement">removeElement(node)</a>:</p>
+<blockquote>
+<p>Remove and return <tt class="docutils literal"><span class="pre">node</span></tt> from a DOM tree.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>the DOM element (or string id of one) to be removed</dd>
+<dt><em>returns</em></dt>
+<dd>The removed element</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-removeelementclass"></a>
+<a class="mochidef reference" href="#fn-removeelementclass">removeElementClass(element, className)</a>:</p>
+<blockquote>
+<p>Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> does not have <tt class="docutils literal"><span class="pre">className</span></tt> set
+as part of its class attribute. This will not disturb other class
+names.  <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so
+string identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-removeemptytextnodes"></a>
+<a class="mochidef reference" href="#fn-removeemptytextnodes">removeEmptyTextNodes(node)</a>:</p>
+<blockquote>
+<p>Remove all text node children that contain only whitespace from
+<tt class="docutils literal"><span class="pre">node</span></tt>. Useful in situations where such empty text nodes can
+interfere with DOM traversal.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>the DOM element (or string id of one) to remove whitespace child
+nodes from.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-replacechildnodes"></a>
+<a class="mochidef reference" href="#fn-replacechildnodes">replaceChildNodes(node[, childNode[, ...]])</a>:</p>
+<blockquote>
+<p>Remove all children from the given DOM element, then append any
+given childNodes to it (by calling <a class="mochiref reference" href="#fn-appendchildnodes">appendChildNodes</a>).</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element to add children to (if a string
+is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate
+the node)</dd>
+<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
+<dd>All additional arguments, if any, will be coerced into DOM
+nodes that are appended as children using the <a class="reference" href="#dom-coercion-rules">DOM Coercion
+Rules</a>.</dd>
+<dt><em>returns</em>:</dt>
+<dd>The given DOM element</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-scrapetext"></a>
+<a class="mochidef reference" href="#fn-scrapetext">scrapeText(node[, asArray=false])</a>:</p>
+<blockquote>
+<p>Walk a DOM tree in-order and scrape all of the text out of it as a
+<tt class="docutils literal"><span class="pre">string</span></tt>.</p>
+<p>If <tt class="docutils literal"><span class="pre">asArray</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned
+with each individual text node. These two are equivalent:</p>
+<pre class="literal-block">
+assert( scrapeText(node) == scrapeText(node, true).join(&quot;&quot;) );
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setelementclass"></a>
+<a class="mochidef reference" href="#fn-setelementclass">setElementClass(element, className)</a>:</p>
+<blockquote>
+<p>Set the entire class attribute of <tt class="docutils literal"><span class="pre">element</span></tt> to <tt class="docutils literal"><span class="pre">className</span></tt>.
+<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string
+identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setnodeattribute"></a>
+<a class="mochidef reference" href="#fn-setnodeattribute">setNodeAttribute(node, attr, value)</a>:</p>
+<blockquote>
+<p>Set the value of the given attribute for a DOM element without
+ever raising an exception (will return null on exception). If
+setting more than one attribute, you should use
+<a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element to update (if a string is
+given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the
+node)</dd>
+<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
+<dd><p class="first">The name of the attribute</p>
+<p class="last">Note that it will do the right thing for IE, so don't do the
+<tt class="docutils literal"><span class="pre">class</span></tt> -&gt; <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
+</dd>
+<dt><tt class="docutils literal"><span class="pre">value</span></tt>:</dt>
+<dd>The value of the attribute, may be an object to be merged
+(e.g. for setting style).</dd>
+<dt><em>returns</em>:</dt>
+<dd>The given DOM element or <tt class="docutils literal"><span class="pre">null</span></tt> on failure</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-swapdom"></a>
+<a class="mochidef reference" href="#fn-swapdom">swapDOM(dest, src)</a>:</p>
+<blockquote>
+<p>Replace <tt class="docutils literal"><span class="pre">dest</span></tt> in a DOM tree with <tt class="docutils literal"><span class="pre">src</span></tt>, returning <tt class="docutils literal"><span class="pre">src</span></tt>.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">dest</span></tt>:</dt>
+<dd>a DOM element (or string id of one) to be replaced</dd>
+<dt><tt class="docutils literal"><span class="pre">src</span></tt>:</dt>
+<dd>the DOM element (or string id of one) to replace it with, or
+<tt class="docutils literal"><span class="pre">null</span></tt> if <tt class="docutils literal"><span class="pre">dest</span></tt> is to be removed (replaced with nothing).</dd>
+<dt><em>returns</em>:</dt>
+<dd>a DOM element (<tt class="docutils literal"><span class="pre">src</span></tt>)</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-swapelementclass"></a>
+<a class="mochidef reference" href="#fn-swapelementclass">swapElementClass(element, fromClass, toClass)</a>:</p>
+<blockquote>
+<p>If <tt class="docutils literal"><span class="pre">fromClass</span></tt> is set on <tt class="docutils literal"><span class="pre">element</span></tt>, replace it with
+<tt class="docutils literal"><span class="pre">toClass</span></tt>.  This will not disturb other classes on that element.
+<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string
+identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-toggleelementclass"></a>
+<a class="mochidef reference" href="#fn-toggleelementclass">toggleElementClass(className[, element[, ...]])</a>:</p>
+<blockquote>
+<p>Toggle the presence of a given <tt class="docutils literal"><span class="pre">className</span></tt> in the class
+attribute of all given elements. All elements will be looked up
+with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-tohtml"></a>
+<a class="mochidef reference" href="#fn-tohtml">toHTML(dom)</a>:</p>
+<blockquote>
+<p>Convert a DOM tree to a HTML string using <a class="mochiref reference" href="#fn-emithtml">emitHTML</a>.
+This should be used for debugging/testing purposes only.</p>
+<p>The DOM property <tt class="docutils literal"><span class="pre">innerHTML</span></tt> or <tt class="docutils literal"><span class="pre">cloneNode(true)</span></tt> method should
+be used for most purposes.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-undoclipping"></a>
+<a class="mochidef reference" href="#fn-undoclipping">undoClipping(element, overflow)</a>:</p>
+<blockquote>
+<p>Restore the setting of <tt class="docutils literal"><span class="pre">element.style.overflow</span></tt> set by
+<a class="mochiref reference" href="#fn-makeclipping">makeClipping(element)</a>. If <tt class="docutils literal"><span class="pre">element</span></tt> is a string, then
+it will be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-undopositioned"></a>
+<a class="mochidef reference" href="#fn-undopositioned">undoPositioned(element, overflow)</a>:</p>
+<blockquote>
+<p>Restore the setting of <tt class="docutils literal"><span class="pre">element.style.position</span></tt> set by
+<a class="mochiref reference" href="#fn-makepositioned">makePositioned(element)</a>. If <tt class="docutils literal"><span class="pre">element</span></tt> is a string, then
+it will be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-updatenodeattributes"></a>
+<a class="mochidef reference" href="#fn-updatenodeattributes">updateNodeAttributes(node, attrs)</a>:</p>
+<blockquote>
+<p>Update the attributes of a DOM element from a given object.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element to update (if a string is
+given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the
+node)</dd>
+<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
+<dd><p class="first">An object whose properties will be used to set the attributes
+(e.g. <tt class="docutils literal"><span class="pre">{'class':</span> <span class="pre">'invisible'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
+attributes need to be set. If an object is given for the
+attribute value (e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">{'display':</span> <span class="pre">'block'}}</span></tt>)
+then <a class="mochiref reference" href="Base.html#fn-updatetree">MochiKit.Base.updatetree</a> will be used to set
+that attribute.</p>
+<p class="last">Note that it will do the right thing for IE, so don't do the
+<tt class="docutils literal"><span class="pre">class</span></tt> -&gt; <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself, and it deals with
+setting &quot;on...&quot; event handlers correctly.</p>
+</dd>
+<dt><em>returns</em>:</dt>
+<dd>The given DOM element</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-withwindow"></a>
+<a class="mochidef reference" href="#fn-withwindow">withWindow(win, func)</a>:</p>
+<blockquote>
+<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win</span></tt>
+and the <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win.document</span></tt>. When
+<tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a> will be
+restored to its previous state.</p>
+<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-withdocument"></a>
+<a class="mochidef reference" href="#fn-withdocument">withDocument(doc, func)</a>:</p>
+<blockquote>
+<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">doc</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">doc</span></tt>.
+When <tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a>
+will be restored to its previous state.</p>
+<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="style-functions" name="style-functions">Style Functions</a></h2>
+<p>These functions are available in MochiKit 1.3.1, but have been moved to
+<a class="mochiref reference" href="Style.html">MochiKit.Style</a> in 1.4+.</p>
+<p>
+<a name="fn-computedstyle"></a>
+<a class="mochidef reference" href="#fn-computedstyle">computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)</a>:</p>
+<blockquote>
+<p>Looks up a CSS property for the given element. The element can be
+specified as either a string with the element's ID or the element
+object itself.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">cssProperty</span></tt>:</dt>
+<dd>MochiKit 1.3.1 expects camel case, e.g. <tt class="docutils literal"><span class="pre">backgroundColor</span></tt>.
+MochiKit 1.4+ expects CSS selector case, e.g. <tt class="docutils literal"><span class="pre">background-color</span></tt>,
+but will accept camel case for backwards-compatibility.</dd>
+<dt><tt class="docutils literal"><span class="pre">mozillaEquivalentCSS</span></tt>:</dt>
+<dd>MochiKit 1.3.1 expects selector case.
+MochiKit 1.4+ ignores this argument.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, deprecated in favor of
+<a class="mochiref reference" href="Style.html#fn-getstyle">MochiKit.Style.getStyle</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-elementdimensions"></a>
+<a class="mochidef reference" href="#fn-elementdimensions">elementDimensions(element)</a>:</p>
+<blockquote>
+<p>Return the absolute pixel width and height (including padding and border,
+but not margins) of <tt class="docutils literal"><span class="pre">element</span></tt> as an object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt>
+properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt> is not in the document.
+<tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to be looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object with
+<tt class="docutils literal"><span class="pre">w</span></tt> and/or <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, deprecated in favor of
+<a class="mochiref reference" href="Style.html#fn-getelementdimensions">MochiKit.Style.getElementDimensions</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-elementposition"></a>
+<a class="mochidef reference" href="#fn-elementposition">elementPosition(element[, relativeTo={x: 0, y: 0}])</a>:</p>
+<blockquote>
+<p>Return the absolute pixel position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document
+as an object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if
+<tt class="docutils literal"><span class="pre">element</span></tt> is not in the document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified
+as a string to be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM
+element, or trivially as an object with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt>
+properties.</p>
+<p>If <tt class="docutils literal"><span class="pre">relativeTo</span></tt> is given, then its coordinates are subtracted from
+the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt>, e.g.:</p>
+<pre class="literal-block">
+var elemPos = elementPosition(elem);
+var anotherElemPos = elementPosition(anotherElem);
+var relPos = elementPosition(elem, anotherElem);
+assert( relPos.x == (elemPos.x - anotherElemPos.x) );
+assert( relPos.y == (elemPos.y - anotherElemPos.y) );
+</pre>
+<p><tt class="docutils literal"><span class="pre">relativeTo</span></tt> may be specified as a string to be looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object
+with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, deprecated in favor of
+<a class="mochiref reference" href="Style.html#fn-getelementposition">MochiKit.Style.getElementPosition</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getviewportdimensions"></a>
+<a class="mochidef reference" href="#fn-getviewportdimensions">getViewportDimensions()</a>:</p>
+<blockquote>
+<p>Return the pixel width and height of the viewport as an object
+with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties. <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-getviewportdimensions">MochiKit.Style.getViewportDimensions</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-hideelement"></a>
+<a class="mochidef reference" href="#fn-hideelement">hideElement(element, ...)</a>:</p>
+<blockquote>
+<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
+<pre class="literal-block">
+partial(setDisplayForElement, &quot;none&quot;)
+</pre>
+<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt>
+based show/hide mechanism, and a CSS based alternative, see
+<a class="reference" href="Style.html#element-visibility">Element Visibility</a>.</p>
+</blockquote>
+<blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-hideelement">MochiKit.Style.hideElement</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setelementdimensions"></a>
+<a class="mochidef reference" href="#fn-setelementdimensions">setElementDimensions(element, dimensions[, units='px'])</a>:</p>
+<blockquote>
+<p>Sets the dimensions of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an object
+with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element to update (if a string is
+given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the
+node)</dd>
+<dt><tt class="docutils literal"><span class="pre">dimensions</span></tt>:</dt>
+<dd>An object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties</dd>
+<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
+<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-setelementdimensions">MochiKit.Style.setElementDimensions</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setelementposition"></a>
+<a class="mochidef reference" href="#fn-setelementposition">setElementPosition(element, position[, units='px'])</a>:</p>
+<blockquote>
+<p>Sets the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
+object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
+<dd>A reference to the DOM element to update (if a string is
+given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the
+node)</dd>
+<dt><tt class="docutils literal"><span class="pre">position</span></tt>:</dt>
+<dd>An object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties</dd>
+<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
+<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-setelementposition">MochiKit.Style.setElementPosition</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setdisplayforelement"></a>
+<a class="mochidef reference" href="#fn-setdisplayforelement">setDisplayForElement(display, element[, ...])</a>:</p>
+<blockquote>
+<p>Change the <tt class="docutils literal"><span class="pre">style.display</span></tt> for the given element(s). Usually
+used as the partial forms:</p>
+<ul class="simple">
+<li><a class="mochiref reference" href="#fn-showelement">showElement(element, ...)</a></li>
+<li><a class="mochiref reference" href="#fn-hideelement">hideElement(element, ...)</a></li>
+</ul>
+<p>Elements are looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string
+identifiers are acceptable.</p>
+<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt>
+based show/hide mechanism, and a CSS based alternative, see
+<a class="reference" href="Style.html#element-visibility">Element Visibility</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-setdisplayforelement">MochiKit.Style.setDisplayForElement</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setopacity"></a>
+<a class="mochidef reference" href="#fn-setopacity">setOpacity(element, opacity)</a>:</p>
+<blockquote>
+<p>Sets <tt class="docutils literal"><span class="pre">opacity</span></tt> for <tt class="docutils literal"><span class="pre">element</span></tt>. Valid <tt class="docutils literal"><span class="pre">opacity</span></tt> values range
+from 0 (invisible) to 1 (opaque). <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-setopacity">MochiKit.Style.setOpacity</a> in 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-showelement"></a>
+<a class="mochidef reference" href="#fn-showelement">showElement(element, ...)</a>:</p>
+<blockquote>
+<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
+<pre class="literal-block">
+partial(setDisplayForElement, &quot;block&quot;)
+</pre>
+<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt>
+based show/hide mechanism, and a CSS based alternative, see
+<a class="reference" href="Style.html#element-visibility">Element Visibility</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-showelement">MochiKit.Style.showElement</a> in 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="style-objects" name="style-objects">Style Objects</a></h2>
+<p>These objects are available in MochiKit 1.3.1, but have been moved to
+<a class="mochiref reference" href="Style.html">MochiKit.Style</a> in 1.4+.</p>
+<p>
+<a name="fn-coordinates"></a>
+<a class="mochidef reference" href="#fn-coordinates">Coordinates(x, y)</a>:</p>
+<blockquote>
+<p>Constructs an object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties. <tt class="docutils literal"><span class="pre">obj.toString()</span></tt>
+returns something like <tt class="docutils literal"><span class="pre">{x:</span> <span class="pre">0,</span> <span class="pre">y:</span> <span class="pre">42}</span></tt> for debugging.</p>
+<p><em>Availability</em>:
+Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-coordinates">MochiKit.Style.Coordinates</a> in 1.4+</p>
+</blockquote>
+<p>
+<a name="fn-dimensions"></a>
+<a class="mochidef reference" href="#fn-dimensions">Dimensions(w, h)</a>:</p>
+<blockquote>
+<p>Constructs an object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties. <tt class="docutils literal"><span class="pre">obj.toString()</span></tt>
+returns something like <tt class="docutils literal"><span class="pre">{w:</span> <span class="pre">0,</span> <span class="pre">h:</span> <span class="pre">42}</span></tt> for debugging.</p>
+<p><em>Availability</em>:
+Available in MochiKit 1.3.1, moved to
+<a class="mochiref reference" href="Style.html#fn-dimensions">MochiKit.Style.Dimensions</a> in 1.4+</p>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id5" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id5">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> Nevow, a web application construction kit for Python:
+<a class="reference" href="http://divmod.org/trac/wiki/DivmodNevow">http://divmod.org/trac/wiki/DivmodNevow</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id6">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> nevow.stan is a domain specific language for Python (read as
+&quot;crazy getitem/call overloading abuse&quot;) that Donovan and I
+schemed up at PyCon 2003 at this super ninja Python/C++
+programmer's (David Abrahams) hotel room. Donovan later
+inflicted this upon the masses in Nevow. Check out the Nevow
+Guide for some examples:
+<a class="reference" href="http://divmod.org/trac/wiki/DivmodNevow">http://divmod.org/trac/wiki/DivmodNevow</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/DateTime.html b/mochikit_v14/doc/html/MochiKit/DateTime.html
new file mode 100644 (file)
index 0000000..eab793f
--- /dev/null
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.DateTime - &quot;what time is it anyway?&quot;</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.DateTime - &quot;what time is it anyway?&quot;</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+stringDate = toISOTimestamp(new Date());
+dateObject = isoTimestamp(stringDate);
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>Remote servers don't give you JavaScript Date objects, and they
+certainly don't want them from you, so you need to deal with string
+representations of dates and timestamps. MochiKit.Date does that.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<p>None.</p>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-isodate"></a>
+<a class="mochidef reference" href="#fn-isodate">isoDate(str)</a>:</p>
+<blockquote>
+<p>Convert an ISO 8601 date (YYYY-MM-DD) to a <tt class="docutils literal"><span class="pre">Date</span></tt> object.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-isotimestamp"></a>
+<a class="mochidef reference" href="#fn-isotimestamp">isoTimestamp(str)</a>:</p>
+<blockquote>
+<p>Convert any ISO 8601 <a class="footnote-reference" href="#id3" id="id1" name="id1">[1]</a> timestamp (or something reasonably close
+to it) to a <tt class="docutils literal"><span class="pre">Date</span></tt> object. Will accept the &quot;de facto&quot; form:</p>
+<blockquote>
+YYYY-MM-DD hh:mm:ss</blockquote>
+<p>or (the proper form):</p>
+<blockquote>
+YYYY-MM-DDThh:mm:ssZ</blockquote>
+<p>If a time zone designator (&quot;Z&quot; or &quot;[+-]HH:MM&quot;) is not present,
+then the local timezone is used.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-toisotime"></a>
+<a class="mochidef reference" href="#fn-toisotime">toISOTime(date)</a>:</p>
+<blockquote>
+<p>Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to a string in the form of hh:mm:ss</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-toisotimestamp"></a>
+<a class="mochidef reference" href="#fn-toisotimestamp">toISOTimestamp(date, realISO=false)</a>:</p>
+<blockquote>
+<p>Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to something that's ALMOST but not quite
+an ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it
+would be:</p>
+<blockquote>
+YYYY-MM-DDThh:mm:ssZ</blockquote>
+<p>However, we see junk in SQL and other places that looks like this:</p>
+<blockquote>
+YYYY-MM-DD hh:mm:ss</blockquote>
+<p>So, this function returns the latter form, despite its name,
+unless you pass <tt class="docutils literal"><span class="pre">true</span></tt> for <tt class="docutils literal"><span class="pre">realISO</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-toisodate"></a>
+<a class="mochidef reference" href="#fn-toisodate">toISODate(date)</a>:</p>
+<blockquote>
+<p>Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an ISO 8601 <a class="footnote-reference" href="#id3" id="id2" name="id2">[1]</a> date string
+(YYYY-MM-DD)</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-americandate"></a>
+<a class="mochidef reference" href="#fn-americandate">americanDate(str)</a>:</p>
+<blockquote>
+<p>Converts a MM/DD/YYYY date to a <tt class="docutils literal"><span class="pre">Date</span></tt> object</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-topaddedamericandate"></a>
+<a class="mochidef reference" href="#fn-topaddedamericandate">toPaddedAmericanDate(date)</a>:</p>
+<blockquote>
+<p>Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an MM/DD/YYYY date, e.g. 01/01/2001</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-toamericandate"></a>
+<a class="mochidef reference" href="#fn-toamericandate">toAmericanDate(date)</a>:</p>
+<blockquote>
+<p>Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an M/D/YYYY date, e.g. 1/1/2001</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id3">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id2">2</a>)</em> W3C profile of ISO 8601: <a class="reference" href="http://www.w3.org/TR/NOTE-datetime">http://www.w3.org/TR/NOTE-datetime</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/DragAndDrop.html b/mochikit_v14/doc/html/MochiKit/DragAndDrop.html
new file mode 100644 (file)
index 0000000..7ccc41c
--- /dev/null
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.DragAndDrop - drag and drop elements with MochiKit</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.DragAndDrop - drag and drop elements with MochiKit</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+// Create a draggable
+new Draggable('mydrag');
+
+// Create a corresponding droppable
+new Droppable('mydrop', {
+    accept: ['drag-class'],
+    ondrop: function (element) {
+        alert('&quot;' + element.id + '&quot; was dropped on me');
+    }
+});
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.DragAndDrop enables you the power of dragging elements
+through your pages, for richer interfaces.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
+<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a></li>
+<li><a class="mochiref reference" href="Visual.html">MochiKit.Visual</a></li>
+<li><a class="mochiref reference" href="Signal.html">MochiKit.Signal</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<p>The implementation was adapted from <a class="reference" href="http://script.aculo.us">Scriptaculous</a>.</p>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="constructors" name="constructors">Constructors</a></h2>
+<p>
+<a name="fn-draggable"></a>
+<a class="mochidef reference" href="#fn-draggable">Draggable(element[, options])</a>:</p>
+<blockquote>
+<p>A object that can be drag with the mouse.</p>
+<p>You have the following options, with corresponding default values:</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">handle</span> <span class="pre">(false)</span></tt>:</dt>
+<dd>Option for giving the element where starting the drag. By
+default it's the element itself, but you can either put a
+class of a subelement or the id of another element as handle.</dd>
+<dt><tt class="docutils literal"><span class="pre">starteffect</span> <span class="pre">(MochiKit.Visual.Opacity)</span></tt>:</dt>
+<dd>Function called once the drag has begun, taking the dragged
+element as argument. It's an effect by default but you can
+define any callback.</dd>
+<dt><tt class="docutils literal"><span class="pre">reverteffect</span> <span class="pre">(MochiKit.Visual.Move)</span></tt>:</dt>
+<dd>Effect applied when drag is cancelled. You have to define the
+<tt class="docutils literal"><span class="pre">revert</span></tt> option to enable the call. By default it brings the
+element back to its initial position, so you should know what
+you want when you modify this. The function should return an
+effect that can be cancelled.</dd>
+<dt><tt class="docutils literal"><span class="pre">endeffect</span> <span class="pre">(MochiKit.Visual.Opacity)</span></tt>:</dt>
+<dd>Pending part of starteffect. If you have modified your element
+during start, you'd usually want to revert it in the function.</dd>
+<dt><tt class="docutils literal"><span class="pre">zindex</span> <span class="pre">(1000)</span></tt>:</dt>
+<dd>Zindex of the drag element. By default it brings it to front.</dd>
+<dt><tt class="docutils literal"><span class="pre">revert</span> <span class="pre">(false)</span></tt>:</dt>
+<dd>Indicate if the reverteffect function should be called. If you
+define a function here, this function will be called before
+reverteffect, with the element as first argument.</dd>
+<dt><tt class="docutils literal"><span class="pre">snap</span> <span class="pre">(false)</span></tt>:</dt>
+<dd>Define the behaviour of the drag element when moving. It can
+either be a function, a value or an array of two values. If
+it's a function, it should take the (x, y) position of the
+element as arguments, and return the position draw in the
+browser. If its a value, it's used as a modulo for each
+coordinates. If it's an array, each value is applied for the
+corresponding coordinate.</dd>
+<dt><tt class="docutils literal"><span class="pre">selectclass</span> <span class="pre">(null)</span></tt>:</dt>
+<dd>If defined, name of CSS class applied during the drag.</dd>
+<dt><tt class="docutils literal"><span class="pre">ghosting</span> <span class="pre">(null)</span></tt>:</dt>
+<dd>Make a ghost from the draggable: clone it at start, then
+remove the clone at end.</dd>
+<dt><tt class="docutils literal"><span class="pre">onchange</span>&nbsp; <span class="pre">(MochiKit.Base.noop)</span></tt>:</dt>
+<dd>Function called when updates are made on the draggable object.</dd>
+<dt><tt class="docutils literal"><span class="pre">scroll</span> <span class="pre">(false)</span></tt>:</dt>
+<dd>Element to scroll around, if precised. For example, 'window'
+will allow the draggable to scroll in the page.</dd>
+<dt><tt class="docutils literal"><span class="pre">scrollSensitivity</span> <span class="pre">(20)</span></tt>:</dt>
+<dd>Scroll sensitivity, used when scroll is used.</dd>
+<dt><tt class="docutils literal"><span class="pre">scrollSpeed</span> <span class="pre">(15)</span></tt>:</dt>
+<dd>Scroll speed, used when scroll is used.</dd>
+</dl>
+<p>A draggable generates some signals during its lifetime: start, drag and
+end. They are available through the Draggables handler, and are called
+with a draggable as argument. You can register a callback for these events
+like this:</p>
+<pre class="literal-block">
+onStart = function (draggable) {
+    // Do some stuff
+};
+
+connect(Draggables, 'start', onStart);
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-droppable"></a>
+<a class="mochidef reference" href="#fn-droppable">Droppable(element[, options])</a>:</p>
+<blockquote>
+<p>A object where you can drop a draggable.</p>
+<p>You have the following options, with corresponding default values:</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">greedy</span> <span class="pre">(true)</span></tt>:</dt>
+<dd>Stop on this droppable when a draggable drops over it.</dd>
+<dt><tt class="docutils literal"><span class="pre">hoverclass</span> <span class="pre">(null)</span></tt>:</dt>
+<dd>If defined, name of CSS class applied when a draggable is
+hover the droppable element (hover state).</dd>
+<dt><tt class="docutils literal"><span class="pre">hoverfunc</span> <span class="pre">(MochiKit.Base.noop)</span></tt>:</dt>
+<dd>Function called on hover state.</dd>
+<dt><tt class="docutils literal"><span class="pre">accept</span> <span class="pre">(null)</span></tt>:</dt>
+<dd>Array of CSS classes allowed to drop on this.</dd>
+<dt><tt class="docutils literal"><span class="pre">activeclass</span> <span class="pre">(null)</span></tt>:</dt>
+<dd>If defined, name of CSS class applied if a possible draggable
+begins its start (active state).</dd>
+<dt><tt class="docutils literal"><span class="pre">onactive</span> <span class="pre">(MochiKit.Base.noop)</span></tt>:</dt>
+<dd>Function called on active state.</dd>
+<dt><tt class="docutils literal"><span class="pre">containment</span> <span class="pre">([])</span></tt>:</dt>
+<dd>Specify a list of elements to check for active state: only the
+children of the specified elements can be dropped. Mainly
+useful for Sortable.</dd>
+<dt><tt class="docutils literal"><span class="pre">onhover</span> <span class="pre">(MochiKit.Base.noop)</span></tt>:</dt>
+<dd>Specific hover function, mainly used for Sortable.</dd>
+<dt><tt class="docutils literal"><span class="pre">ondrop</span> <span class="pre">(MochiKit.Base.noop)</span></tt>:</dt>
+<dd>Function called when a draggable is dropped. The function
+takes three arguments: the draggable element, the droppable
+element, and the event that raised the drop.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Thomas Herve &lt;<a class="reference" href="mailto:therve&#64;gmail.com">therve&#64;gmail.com</a>&gt;</li>
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+<li>Originally adapted from Script.aculo.us &lt;<a class="reference" href="http://script.aculo.us/">http://script.aculo.us/</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;.  This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+<p>Portions adapted from <a class="reference" href="http://script.aculo.us">Scriptaculous</a> are available under the terms
+of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Format.html b/mochikit_v14/doc/html/MochiKit/Format.html
new file mode 100644 (file)
index 0000000..e192bef
--- /dev/null
@@ -0,0 +1,290 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Format - string formatting goes here</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Format - string formatting goes here</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+assert( truncToFixed(0.12345, 4) == &quot;0.1234&quot; );
+assert( roundToFixed(0.12345, 4) == &quot;0.1235&quot; );
+assert( twoDigitAverage(1, 0) == &quot;0&quot; );
+assert( twoDigitFloat(1.2345) == &quot;1.23&quot; );
+assert( twoDigitFloat(1) == &quot;1&quot; );
+assert( percentFormat(1.234567) == &quot;123.46%&quot; );
+assert( numberFormatter(&quot;###,###%&quot;)(125) == &quot;12,500%&quot; );
+assert( numberFormatter(&quot;##.000&quot;)(1.25) == &quot;1.250&quot; );
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>Formatting strings and stringifying numbers is boring, so a couple
+useful functions in that domain live here.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<p>None.</p>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<div class="section">
+<h2><a id="formatting-numbers" name="formatting-numbers">Formatting Numbers</a></h2>
+<p>MochiKit provides an extensible number formatting facility, modeled
+loosely after the Number Format Pattern Syntax <a class="footnote-reference" href="#id2" id="id1" name="id1">[1]</a> from Java.
+<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(pattern[, placeholder=&quot;&quot;[,
+locale=&quot;default&quot;])</a> returns a function that converts Number to string
+using the given information.  <tt class="docutils literal"><span class="pre">pattern</span></tt> is a string consisting of
+the following symbols:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="15%" />
+<col width="85%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Symbol</th>
+<th class="head">Meaning</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">-</span></tt></td>
+<td>If given, used as the position of the minus sign
+for negative numbers. If not given, the position
+to the left of the first number placeholder is used.</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">#</span></tt></td>
+<td>The placeholder for a number that does not imply zero
+padding.</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">0</span></tt></td>
+<td>The placeholder for a number that implies zero padding.
+If it is used to the right of a decimal separator, it
+implies trailing zeros, otherwise leading zeros.</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">,</span></tt></td>
+<td>The placeholder for a &quot;thousands separator&quot;. May be used
+at most once, and it must be to the left of a decimal
+separator. Will be replaced by <tt class="docutils literal"><span class="pre">locale.separator</span></tt> in the
+result (the default is also <tt class="docutils literal"><span class="pre">,</span></tt>).</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">.</span></tt></td>
+<td>The decimal separator. The quantity of <tt class="docutils literal"><span class="pre">#</span></tt> or <tt class="docutils literal"><span class="pre">0</span></tt>
+after the decimal separator will determine the precision of
+the result. If no decimal separator is present, the
+fractional precision is <tt class="docutils literal"><span class="pre">0</span></tt> -- meaning that it will be
+rounded to the nearest integer.</td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">%</span></tt></td>
+<td>If present, the number will be multiplied by <tt class="docutils literal"><span class="pre">100</span></tt> and
+the <tt class="docutils literal"><span class="pre">%</span></tt> will be replaced by <tt class="docutils literal"><span class="pre">locale.percent</span></tt>.</td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-formatlocale"></a>
+<a class="mochidef reference" href="#fn-formatlocale">formatLocale(locale=&quot;default&quot;)</a>:</p>
+<blockquote>
+<p>Return a locale object for the given locale. <tt class="docutils literal"><span class="pre">locale</span></tt> may be
+either a string, which is looked up in the
+<tt class="docutils literal"><span class="pre">MochiKit.Format.LOCALE</span></tt> object, or a locale object. If no
+locale is given, <tt class="docutils literal"><span class="pre">LOCALE.default</span></tt> is used (equivalent to
+<tt class="docutils literal"><span class="pre">LOCALE.en_US</span></tt>).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-lstrip"></a>
+<a class="mochidef reference" href="#fn-lstrip">lstrip(str, chars=&quot;\s&quot;)</a>:</p>
+<blockquote>
+<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading whitespace
+stripped.</p>
+<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead
+of whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a
+<tt class="docutils literal"><span class="pre">RegExp</span></tt> <tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-numberformatter"></a>
+<a class="mochidef reference" href="#fn-numberformatter">numberFormatter(pattern, placeholder=&quot;&quot;, locale=&quot;default&quot;)</a>:</p>
+<blockquote>
+<p>Return a function <tt class="docutils literal"><span class="pre">formatNumber(aNumber)</span></tt> that formats numbers
+as a string according to the given pattern, placeholder and
+locale.</p>
+<p><tt class="docutils literal"><span class="pre">pattern</span></tt> is a string that describes how the numbers should be
+formatted, for more information see <a class="reference" href="#formatting-numbers">Formatting Numbers</a>.</p>
+<p><tt class="docutils literal"><span class="pre">locale</span></tt> is a string of a known locale (en_US, de_DE, fr_FR,
+default) or an object with the following fields:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="16%" />
+<col width="84%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>separator</td>
+<td>The &quot;thousands&quot; separator for this locale (en_US is &quot;,&quot;)</td>
+</tr>
+<tr><td>decimal</td>
+<td>The decimal separator for this locale (en_US is &quot;.&quot;)</td>
+</tr>
+<tr><td>percent</td>
+<td>The percent symbol for this locale (en_US is &quot;%&quot;)</td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-percentformat"></a>
+<a class="mochidef reference" href="#fn-percentformat">percentFormat(someFloat)</a>:</p>
+<blockquote>
+<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf(&quot;%.2f%%&quot;,</span> <span class="pre">someFloat</span> <span class="pre">*</span> <span class="pre">100)</span></tt></p>
+<p>In new code, you probably want to use:
+<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(&quot;#.##%&quot;)(someFloat)</a> instead.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-roundtofixed"></a>
+<a class="mochidef reference" href="#fn-roundtofixed">roundToFixed(aNumber, precision)</a>:</p>
+<blockquote>
+<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, rounded to
+<tt class="docutils literal"><span class="pre">precision</span></tt> digits with trailing zeros. This is similar to
+<tt class="docutils literal"><span class="pre">Number.toFixed(aNumber,</span> <span class="pre">precision)</span></tt>, but this has
+implementation consistent rounding behavior (some versions of
+Safari round 0.5 down!)  and also includes preceding <tt class="docutils literal"><span class="pre">0</span></tt> for
+numbers less than <tt class="docutils literal"><span class="pre">1</span></tt> (Safari, again).</p>
+<p>For example, <a class="mochiref reference" href="#fn-roundtofixed">roundToFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.14</span></tt>
+on every supported platform, where some return <tt class="docutils literal"><span class="pre">.13</span></tt> for
+<tt class="docutils literal"><span class="pre">(0.1357).toFixed(2)</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-rstrip"></a>
+<a class="mochidef reference" href="#fn-rstrip">rstrip(str, chars=&quot;\s&quot;)</a>:</p>
+<blockquote>
+<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with trailing whitespace stripped.</p>
+<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead
+of whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a
+<tt class="docutils literal"><span class="pre">RegExp</span></tt> <tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-strip"></a>
+<a class="mochidef reference" href="#fn-strip">strip(str, chars=&quot;\s&quot;)</a>:</p>
+<blockquote>
+<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading and trailing
+whitespace stripped (equivalent to <a class="mochiref reference" href="#fn-lstrip">lstrip(rstrip(str,
+chars), chars)</a>).</p>
+<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead
+of whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a
+<tt class="docutils literal"><span class="pre">RegExp</span></tt> <tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-trunctofixed"></a>
+<a class="mochidef reference" href="#fn-trunctofixed">truncToFixed(aNumber, precision)</a>:</p>
+<blockquote>
+<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, truncated to
+<tt class="docutils literal"><span class="pre">precision</span></tt> digits with trailing zeros. This is similar to
+<tt class="docutils literal"><span class="pre">aNumber.toFixed(precision)</span></tt>, but this truncates rather than
+rounds and has implementation consistent behavior for numbers less
+than 1.  Specifically, <a class="mochiref reference" href="#fn-trunctofixed">truncToFixed(aNumber,
+precision)</a> will always have a preceding <tt class="docutils literal"><span class="pre">0</span></tt> for numbers less
+than <tt class="docutils literal"><span class="pre">1</span></tt>.</p>
+<p>For example, <a class="mochiref reference" href="#fn-trunctofixed">truncToFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.13</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-twodigitaverage"></a>
+<a class="mochidef reference" href="#fn-twodigitaverage">twoDigitAverage(numerator, denominator)</a>:</p>
+<blockquote>
+<p>Calculate an average from a numerator and a denominator and return
+it as a string with two digits of precision (e.g. &quot;1.23&quot;).</p>
+<p>If the denominator is 0, &quot;0&quot; will be returned instead of <tt class="docutils literal"><span class="pre">NaN</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-twodigitfloat"></a>
+<a class="mochidef reference" href="#fn-twodigitfloat">twoDigitFloat(someFloat)</a>:</p>
+<blockquote>
+<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf(&quot;%.2f&quot;,</span> <span class="pre">someFloat)</span></tt></p>
+<p>In new code, you probably want to use
+<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(&quot;#.##&quot;)(someFloat)</a> instead.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id2">[1]</a></td><td>Java Number Format Pattern Syntax:
+<a class="reference" href="http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html">http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Iter.html b/mochikit_v14/doc/html/MochiKit/Iter.html
new file mode 100644 (file)
index 0000000..a96aa7c
--- /dev/null
@@ -0,0 +1,522 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and
+then easy</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+theSum = sum(takewhile(
+        partial(operator.gt, 10),
+        imap(
+            partial(operator.mul, 2),
+            count()
+        )
+    )
+));
+
+assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) );
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>All of the functional programming missing from
+<a class="mochiref reference" href="Base.html">MochiKit.Base</a> lives here. The functionality in this module
+is largely inspired by Python's iteration protocol <a class="footnote-reference" href="#id4" id="id1" name="id1">[1]</a>, and the
+itertools module <a class="footnote-reference" href="#id5" id="id2" name="id2">[2]</a>.</p>
+<p>MochiKit.Iter defines a standard way to iterate over anything, that
+you can extend with <a class="mochiref reference" href="#fn-registeriterator">registerIterator</a>, or by implementing
+the <tt class="docutils literal"><span class="pre">.iter()</span></tt> or <tt class="docutils literal"><span class="pre">.__iterator__()</span></tt> (in MochiKit 1.4+) protocol.
+Iterators are lazy, so it can potentially be
+cheaper to build a filter chain of iterators than to build lots of
+intermediate arrays.  Especially when the data set is very large, but
+the result is not.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<div class="section">
+<h2><a id="iteration-for-javascript" name="iteration-for-javascript">Iteration for JavaScript</a></h2>
+<p>The best overview right now is in my Iteration for JavaScript <a class="footnote-reference" href="#id6" id="id3" name="id3">[3]</a>
+blog entry.  This information will migrate here eventually.</p>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="errors" name="errors">Errors</a></h2>
+<p>
+<a name="fn-stopiteration"></a>
+<a class="mochidef reference" href="#fn-stopiteration">StopIteration</a>:</p>
+<blockquote>
+<p>The singleton <a class="mochiref reference" href="Base.html#fn-namederror">MochiKit.Base.NamedError</a> that signifies
+the end of an iterator</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-applymap"></a>
+<a class="mochidef reference" href="#fn-applymap">applymap(fun, seq[, self])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">applymap(fun,</span> <span class="pre">seq)</span></tt> --&gt;
+fun.apply(self, seq0), fun.apply(self, seq1), ...</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-chain"></a>
+<a class="mochidef reference" href="#fn-chain">chain(p, q[, ...])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">chain(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --&gt; p0, p1, ... plast, q0, q1, ...</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-count"></a>
+<a class="mochidef reference" href="#fn-count">count(n=0)</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">count(n=0)</span></tt> --&gt; n, n + 1, n + 2, ...</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-cycle"></a>
+<a class="mochidef reference" href="#fn-cycle">cycle(p)</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">cycle(p)</span></tt> --&gt; p0, p1, ... plast, p0, p1, ...</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-dropwhile"></a>
+<a class="mochidef reference" href="#fn-dropwhile">dropwhile(pred, seq)</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">dropwhile(pred,</span> <span class="pre">seq)</span></tt> --&gt; seq[n], seq[n + 1], starting when
+pred(seq[n]) fails</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-every"></a>
+<a class="mochidef reference" href="#fn-every">every(iterable, func)</a>:</p>
+<blockquote>
+<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for every item in
+<tt class="docutils literal"><span class="pre">iterable</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-exhaust"></a>
+<a class="mochidef reference" href="#fn-exhaust">exhaust(iterable)</a>:</p>
+<blockquote>
+<p>Exhausts an iterable without saving the results anywhere, like
+<a class="mochiref reference" href="#fn-list">list(iterable)</a> when you don't care what the output is.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-foreach"></a>
+<a class="mochidef reference" href="#fn-foreach">forEach(iterable, func[, self])</a>:</p>
+<blockquote>
+<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> for each item in <tt class="docutils literal"><span class="pre">iterable</span></tt>, and don't save the
+results.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-groupby"></a>
+<a class="mochidef reference" href="#fn-groupby">groupby(iterable[, keyfunc])</a>:</p>
+<blockquote>
+<p>Make an iterator that returns consecutive keys and groups from the
+iterable. The key is a function computing a key value for each
+element.  If not specified or is None, key defaults to an identity
+function and returns the element unchanged. Generally, the
+iterable needs to already be sorted on the same key function.</p>
+<p>The returned group is itself an iterator that shares the
+underlying iterable with <a class="mochiref reference" href="#fn-groupby">groupby()</a>. Because the source
+is shared, when the groupby object is advanced, the previous group
+is no longer visible.  So, if that data is needed later, it should
+be stored as an array:</p>
+<pre class="literal-block">
+var groups = [];
+var uniquekeys = [];
+forEach(groupby(data, keyfunc), function (key_group) {
+    groups.push(list(key_group[1]));
+    uniquekeys.push(key_group[0]);
+});
+</pre>
+<p>As a convenience, <a class="mochiref reference" href="#fn-groupby_as_array">groupby_as_array()</a> is provided to
+suit the above use case.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-groupby_as_array"></a>
+<a class="mochidef reference" href="#fn-groupby_as_array">groupby_as_array(iterable[, keyfunc])</a>:</p>
+<blockquote>
+<p>Perform the same task as <a class="mochiref reference" href="#fn-groupby">groupby()</a>, except return an
+array of arrays instead of an iterator of iterators.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-iextend"></a>
+<a class="mochidef reference" href="#fn-iextend">iextend(lst, iterable)</a>:</p>
+<blockquote>
+<p>Just like <a class="mochiref reference" href="#fn-list">list(iterable)</a>, except it pushes results on
+<tt class="docutils literal"><span class="pre">lst</span></tt> rather than creating a new one.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-ifilter"></a>
+<a class="mochidef reference" href="#fn-ifilter">ifilter(pred, seq)</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">ifilter(pred,</span> <span class="pre">seq)</span></tt> --&gt; elements of seq where <tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is
+<tt class="docutils literal"><span class="pre">true</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-ifilterfalse"></a>
+<a class="mochidef reference" href="#fn-ifilterfalse">ifilterfalse(pred, seq)</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">ifilterfalse(pred,</span> <span class="pre">seq)</span></tt> --&gt; elements of seq where
+<tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is <tt class="docutils literal"><span class="pre">false</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-imap"></a>
+<a class="mochidef reference" href="#fn-imap">imap(fun, p, q[, ...])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">imap(fun,</span> <span class="pre">p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --&gt; fun(p0, q0, ...), fun(p1, q1, ...),
+...</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-islice"></a>
+<a class="mochidef reference" href="#fn-islice">islice(seq, [start,] stop[, step])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">islice(seq,</span> <span class="pre">[start,]</span> <span class="pre">stop[,</span> <span class="pre">step])</span></tt> --&gt; elements from
+seq[start:stop:step] (in Python slice syntax)</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-iter"></a>
+<a class="mochidef reference" href="#fn-iter">iter(iterable[, sentinel])</a>:</p>
+<blockquote>
+<p>Convert the given argument to an iterator (object implementing
+<tt class="docutils literal"><span class="pre">.next()</span></tt>).</p>
+<ol class="arabic simple">
+<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator (implements <tt class="docutils literal"><span class="pre">.next()</span></tt>), then
+it will be returned as-is.</li>
+<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator factory (implements
+<tt class="docutils literal"><span class="pre">.iter()</span></tt>), then the result of <tt class="docutils literal"><span class="pre">iterable.iter()</span></tt> will be
+returned.</li>
+<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is a JavaScript 1.7 iterator factory (implements
+<tt class="docutils literal"><span class="pre">.__iterable__()</span></tt>), then the result of <tt class="docutils literal"><span class="pre">iterable.__iterable__()</span></tt>
+will be returned (MochiKit 1.4+).</li>
+<li>Otherwise, the iterator factory
+<a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a> is used to find a
+match.</li>
+<li>If no factory is found, it will throw <tt class="docutils literal"><span class="pre">TypeError</span></tt></li>
+</ol>
+<p>Built-in iterator factories are present for Array-like objects,
+and objects that implement the <tt class="docutils literal"><span class="pre">iterateNext</span></tt> protocol (e.g. the
+result of Mozilla's <tt class="docutils literal"><span class="pre">document.evaluate</span></tt>).</p>
+<p>When used directly, using an iterator should look like this:</p>
+<pre class="literal-block">
+var it = iter(iterable);
+try {
+    while (var o = it.next()) {
+        // use o
+    }
+} catch (e) {
+    if (e != StopIteration) {
+        throw e;
+    }
+    // pass
+}
+</pre>
+<p>This is ugly, so you should use the higher order functions to work
+with iterators whenever possible.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-izip"></a>
+<a class="mochidef reference" href="#fn-izip">izip(p, q[, ...])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">izip(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --&gt; [p0, q0, ...], [p1, q1, ...], ...</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-list"></a>
+<a class="mochidef reference" href="#fn-list">list(iterable)</a>:</p>
+<blockquote>
+<p>Convert <tt class="docutils literal"><span class="pre">iterable</span></tt> to a new <tt class="docutils literal"><span class="pre">Array</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-next"></a>
+<a class="mochidef reference" href="#fn-next">next(iterator)</a>:</p>
+<blockquote>
+<p>Return <tt class="docutils literal"><span class="pre">iterator.next()</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-range"></a>
+<a class="mochidef reference" href="#fn-range">range([start,] stop[, step])</a>:</p>
+<blockquote>
+<p>Return an iterator containing an arithmetic progression of integers.</p>
+<p><tt class="docutils literal"><span class="pre">range(i,</span> <span class="pre">j)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([i, i + 1, i + 2, ..., j -
+1])</a></p>
+<p><tt class="docutils literal"><span class="pre">start</span></tt> (!) defaults to <tt class="docutils literal"><span class="pre">0</span></tt>. When <tt class="docutils literal"><span class="pre">step</span></tt> is given, it
+specifies the increment (or decrement). The end point is omitted!</p>
+<p>For example, <tt class="docutils literal"><span class="pre">range(4)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([0, 1, 2, 3])</a>.
+This iterates over exactly the valid indexes for an array of 4
+elements.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-reduce"></a>
+<a class="mochidef reference" href="#fn-reduce">reduce(fn, iterable[, initial])</a>:</p>
+<blockquote>
+<p>Apply <tt class="docutils literal"><span class="pre">fn(a,</span> <span class="pre">b)</span></tt> cumulatively to the items of an iterable from
+left to right, so as to reduce the iterable to a single value.</p>
+<p>For example:</p>
+<pre class="literal-block">
+reduce(function (a, b) { return x + y; }, [1, 2, 3, 4, 5])
+</pre>
+<p>calculates:</p>
+<pre class="literal-block">
+((((1 + 2) + 3) + 4) + 5).
+</pre>
+<p>If initial is given, it is placed before the items of the sequence
+in the calculation, and serves as a default when the sequence is
+empty.</p>
+<p>Note that the above example could be written more clearly as:</p>
+<pre class="literal-block">
+reduce(operator.add, [1, 2, 3, 4, 5])
+</pre>
+<p>Or even simpler:</p>
+<pre class="literal-block">
+sum([1, 2, 3, 4, 5])
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-registeriteratorfactory"></a>
+<a class="mochidef reference" href="#fn-registeriteratorfactory">registerIteratorFactory(name, check, iterfactory[, override])</a>:</p>
+<blockquote>
+<p>Register an iterator factory for use with the iter function.</p>
+<p><tt class="docutils literal"><span class="pre">check</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">a</span></tt> can
+be converted into an iterator with <tt class="docutils literal"><span class="pre">iterfactory</span></tt>.</p>
+<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns an object with a
+<tt class="docutils literal"><span class="pre">.next()</span></tt> method that returns the next value in the sequence.</p>
+<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is guaranteed to only be called if <tt class="docutils literal"><span class="pre">check(a)</span></tt>
+returns a true value.</p>
+<p>If <tt class="docutils literal"><span class="pre">override</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then it will be made the
+highest precedence iterator factory. Otherwise, the lowest.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-repeat"></a>
+<a class="mochidef reference" href="#fn-repeat">repeat(elem[, n])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">repeat(elem,</span> <span class="pre">[,n])</span></tt> --&gt; elem, elem, elem, ... endlessly or up
+to n times</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-reversed"></a>
+<a class="mochidef reference" href="#fn-reversed">reversed(iterable)</a>:</p>
+<blockquote>
+<p>Return a reversed array from iterable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-some"></a>
+<a class="mochidef reference" href="#fn-some">some(iterable, func)</a>:</p>
+<blockquote>
+<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for at least one
+item in <tt class="docutils literal"><span class="pre">iterable</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-sorted"></a>
+<a class="mochidef reference" href="#fn-sorted">sorted(iterable[, cmp])</a>:</p>
+<blockquote>
+<p>Return a sorted array from iterable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-sum"></a>
+<a class="mochidef reference" href="#fn-sum">sum(iterable, start=0)</a>:</p>
+<blockquote>
+<p>Returns the sum of a sequence of numbers plus the value of
+parameter <tt class="docutils literal"><span class="pre">start</span></tt> (with a default of 0). When the sequence is
+empty, returns start.</p>
+<p>Equivalent to:</p>
+<pre class="literal-block">
+reduce(operator.add, iterable, start);
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-takewhile"></a>
+<a class="mochidef reference" href="#fn-takewhile">takewhile(pred, seq)</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">takewhile(pred,</span> <span class="pre">seq)</span></tt> --&gt; seq[0], seq[1], ... until
+pred(seq[n]) fails</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-tee"></a>
+<a class="mochidef reference" href="#fn-tee">tee(iterable, n=2)</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">tee(it,</span> <span class="pre">n=2)</span></tt> --&gt; [it1, it2, it3, ... itn] splits one iterator
+into n</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id4" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id4">[1]</a></td><td>The iteration protocol is described in
+PEP 234 - Iterators: <a class="reference" href="http://www.python.org/peps/pep-0234.html">http://www.python.org/peps/pep-0234.html</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id5" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2" name="id5">[2]</a></td><td>Python's itertools
+module: <a class="reference" href="http://docs.python.org/lib/module-itertools.html">http://docs.python.org/lib/module-itertools.html</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id3" name="id6">[3]</a></td><td>Iteration in JavaScript: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Logging.html b/mochikit_v14/doc/html/MochiKit/Logging.html
new file mode 100644 (file)
index 0000000..d547e77
--- /dev/null
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Logging - we're all tired of alert()</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Logging - we're all tired of alert()</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+log(&quot;INFO messages are so boring&quot;);
+logDebug(&quot;DEBUG messages are even worse&quot;);
+log(&quot;good thing I can pass&quot;, objects, &quot;conveniently&quot;);
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.Logging steals some ideas from Python's logging module <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a>,
+but completely forgot about the Java <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> inspiration. This is a KISS
+module for logging that provides enough flexibility to do just about
+anything via listeners, but without all the cruft.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<div class="section">
+<h2><a id="native-console-logging" name="native-console-logging">Native Console Logging</a></h2>
+<p>As of MochiKit 1.3, the default logger will log all messages to your
+browser's native console. This is currently supported in Safari, Opera
+9, and Firefox when the <a class="reference" href="http://www.joehewitt.com/software/firebug/">FireBug</a> extension is installed. MochiKit
+1.4 adds support for the relevant APIs for Internet Explorer (the
+Debugger and the Atlas framework, see <a class="reference" href="http://www.nikhilk.net/Entry.aspx?id=93">here</a>).</p>
+<p>To disable this behavior:</p>
+<pre class="literal-block">
+MochiKit.Logging.logger.useNativeConsole = false;
+</pre>
+</div>
+<div class="section">
+<h2><a id="bookmarklet-based-debugging" name="bookmarklet-based-debugging">Bookmarklet Based Debugging</a></h2>
+<p>JavaScript is at a serious disadvantage without a standard console for
+&quot;print&quot; statements. Everything else has one. The closest thing that
+you get in a browser environment is the <tt class="docutils literal"><span class="pre">alert</span></tt> function, which is
+absolutely evil.</p>
+<p>This leaves you with one reasonable solution: do your logging in the
+page somehow. The problem here is that you don't want to clutter the
+page with debugging tools. The solution to that problem is what we
+call BBD, or Bookmarklet Based Debugging <a class="footnote-reference" href="#id8" id="id4" name="id4">[3]</a>.</p>
+<p>Simply create a bookmarklet for
+<a class="reference" href="javascript:MochiKit.Logging.logger.debuggingBookmarklet()">javascript:MochiKit.Logging.logger.debuggingBookmarklet()</a>, and
+whack it whenever you want to see what's in the logger. Of course,
+this means you must drink the MochiKit.Logging kool-aid. It's tangy
+and sweet, don't worry.</p>
+<p>Currently this is an ugly <tt class="docutils literal"><span class="pre">alert</span></tt>, but we'll have something spiffy
+Real Soon Now, and when we do, you only have to upgrade
+MochiKit.Logging, not your bookmarklet!</p>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="constructors" name="constructors">Constructors</a></h2>
+<p>
+<a name="fn-logmessage"></a>
+<a class="mochidef reference" href="#fn-logmessage">LogMessage(num, level, info)</a>:</p>
+<blockquote>
+<p>Properties:</p>
+<blockquote>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
+<dd>Identifier for the log message</dd>
+<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
+<dd>Level of the log message (<tt class="docutils literal"><span class="pre">&quot;INFO&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;WARN&quot;</span></tt>,
+<tt class="docutils literal"><span class="pre">&quot;DEBUG&quot;</span></tt>, etc.)</dd>
+<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
+<dd>All other arguments passed to log function as an <tt class="docutils literal"><span class="pre">Array</span></tt></dd>
+<dt><tt class="docutils literal"><span class="pre">timestamp</span></tt>:</dt>
+<dd><tt class="docutils literal"><span class="pre">Date</span></tt> object timestamping the log message</dd>
+</dl>
+</blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger"></a>
+<a class="mochidef reference" href="#fn-logger">Logger([maxSize])</a>:</p>
+<blockquote>
+<p>A basic logger object that has a buffer of recent messages plus a
+listener dispatch mechanism for &quot;real-time&quot; logging of important
+messages.</p>
+<p><tt class="docutils literal"><span class="pre">maxSize</span></tt> is the maximum number of entries in the log.  If
+<tt class="docutils literal"><span class="pre">maxSize</span> <span class="pre">&gt;=</span> <span class="pre">0</span></tt>, then the log will not buffer more than that many
+messages. So if you don't like logging at all, be sure to pass
+<tt class="docutils literal"><span class="pre">0</span></tt>.</p>
+<p>There is a default logger available named &quot;logger&quot;, and several of
+its methods are also global functions:</p>
+<blockquote>
+<tt class="docutils literal"><span class="pre">logger.log</span></tt>      -&gt; <tt class="docutils literal"><span class="pre">log</span></tt>
+<tt class="docutils literal"><span class="pre">logger.debug</span></tt>    -&gt; <tt class="docutils literal"><span class="pre">logDebug</span></tt>
+<tt class="docutils literal"><span class="pre">logger.warning</span></tt>  -&gt; <tt class="docutils literal"><span class="pre">logWarning</span></tt>
+<tt class="docutils literal"><span class="pre">logger.error</span></tt>    -&gt; <tt class="docutils literal"><span class="pre">logError</span></tt>
+<tt class="docutils literal"><span class="pre">logger.fatal</span></tt>    -&gt; <tt class="docutils literal"><span class="pre">logFatal</span></tt></blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.addlistener"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener(ident, filter, listener)</a>:</p>
+<blockquote>
+<p>Add a listener for log messages.</p>
+<p><tt class="docutils literal"><span class="pre">ident</span></tt> is a unique identifier that may be used to remove the
+listener later on.</p>
+<p><tt class="docutils literal"><span class="pre">filter</span></tt> can be one of the following:</p>
+<blockquote>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">null</span></tt>:</dt>
+<dd><tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called for every log message
+received.</dd>
+<dt><tt class="docutils literal"><span class="pre">string</span></tt>:</dt>
+<dd><a class="mochiref reference" href="#fn-loglevelatleast">logLevelAtLeast(filter)</a> will be used as the
+function (see below).</dd>
+<dt><tt class="docutils literal"><span class="pre">function</span></tt>:</dt>
+<dd><tt class="docutils literal"><span class="pre">filter(msg)</span></tt> will be called for every msg, if it
+returns true then <tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called.</dd>
+</dl>
+</blockquote>
+<p><tt class="docutils literal"><span class="pre">listener</span></tt> is a function that takes one argument, a log
+message. A log message is an object (<a class="mochiref reference" href="#fn-logmessage">LogMessage</a>
+instance) that has at least these properties:</p>
+<blockquote>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
+<dd>A counter that uniquely identifies a log message
+(per-logger)</dd>
+<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
+<dd>A string or number representing the log level. If string,
+you may want to use <tt class="docutils literal"><span class="pre">LogLevel[level]</span></tt> for comparison.</dd>
+<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
+<dd>An Array of objects passed as additional arguments to the
+<tt class="docutils literal"><span class="pre">log</span></tt> function.</dd>
+</dl>
+</blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.baselog"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.baselog">Logger.prototype.baseLog(level, message[, ...])</a>:</p>
+<blockquote>
+<p>The base functionality behind all of the log functions.  The first
+argument is the log level as a string or number, and all other
+arguments are used as the info list.</p>
+<p>This function is available partially applied as:</p>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="61%" />
+<col width="39%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Logger.debug</td>
+<td>'DEBUG'</td>
+</tr>
+<tr><td>Logger.log</td>
+<td>'INFO'</td>
+</tr>
+<tr><td>Logger.error</td>
+<td>'ERROR'</td>
+</tr>
+<tr><td>Logger.fatal</td>
+<td>'FATAL'</td>
+</tr>
+<tr><td>Logger.warning</td>
+<td>'WARNING'</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<p>For the default logger, these are also available as global
+functions, see the <a class="mochiref reference" href="#fn-logger">Logger</a> constructor documentation
+for more info.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.clear"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.clear">Logger.prototype.clear()</a>:</p>
+<blockquote>
+<p>Clear all messages from the message buffer.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.debuggingbookmarklet"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.debuggingbookmarklet">Logger.prototype.debuggingBookmarklet()</a>:</p>
+<blockquote>
+<p>Display the contents of the logger in a useful way for browsers.</p>
+<p>Currently, if <a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> is loaded, then a
+pop-up <a class="mochiref reference" href="LoggingPane.html#fn-loggingpane">MochiKit.LoggingPane.LoggingPane</a> will be
+used. Otherwise, it will be an alert with
+<a class="mochiref reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.dispatchlisteners"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.dispatchlisteners">Logger.prototype.dispatchListeners(msg)</a>:</p>
+<blockquote>
+<p>Dispatch a log message to all listeners.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.getmessages"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages(howMany)</a>:</p>
+<blockquote>
+<p>Return a list of up to <tt class="docutils literal"><span class="pre">howMany</span></tt> messages from the message
+buffer.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.getmessagetext"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText(howMany)</a>:</p>
+<blockquote>
+<p>Get a string representing up to the last <tt class="docutils literal"><span class="pre">howMany</span></tt> messages in
+the message buffer. The default is <tt class="docutils literal"><span class="pre">30</span></tt>.</p>
+<p>The message looks like this:</p>
+<pre class="literal-block">
+LAST {messages.length} MESSAGES:
+  [{msg.num}] {msg.level}: {m.info.join(' ')}
+  [{msg.num}] {msg.level}: {m.info.join(' ')}
+  ...
+</pre>
+<p>If you want some other format, use
+<a class="mochiref reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages</a> and do it yourself.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logger.prototype.removelistener"></a>
+<a class="mochidef reference" href="#fn-logger.prototype.removelistener">Logger.prototype.removeListener(ident)</a>:</p>
+<blockquote>
+<p>Remove a listener using the ident given to
+<a class="mochiref reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener</a></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-alertlistener"></a>
+<a class="mochidef reference" href="#fn-alertlistener">alertListener(msg)</a>:</p>
+<blockquote>
+<p>Ultra-obnoxious <tt class="docutils literal"><span class="pre">alert(...)</span></tt> listener</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-log"></a>
+<a class="mochidef reference" href="#fn-log">log(message[, info[, ...]])</a>:</p>
+<blockquote>
+<p>Log an INFO message to the default logger</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logdebug"></a>
+<a class="mochidef reference" href="#fn-logdebug">logDebug(message[, info[, ...]])</a>:</p>
+<blockquote>
+<p>Log a DEBUG message to the default logger</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logerror"></a>
+<a class="mochidef reference" href="#fn-logerror">logError(message[, info[, ...]])</a>:</p>
+<blockquote>
+<p>Log an ERROR message to the default logger</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logfatal"></a>
+<a class="mochidef reference" href="#fn-logfatal">logFatal(message[, info[, ...]])</a>:</p>
+<blockquote>
+<p>Log a FATAL message to the default logger</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-loglevelatleast"></a>
+<a class="mochidef reference" href="#fn-loglevelatleast">logLevelAtLeast(minLevel)</a>:</p>
+<blockquote>
+<p>Return a function that will match log messages whose level is at
+least minLevel</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-logwarning"></a>
+<a class="mochidef reference" href="#fn-logwarning">logWarning(message[, info[, ...]])</a>:</p>
+<blockquote>
+<p>Log a WARNING message to the default logger</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Python's logging module: <a class="reference" href="http://docs.python.org/lib/module-logging.html">http://docs.python.org/lib/module-logging.html</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2" name="id7">[2]</a></td><td>PEP 282, where they admit all of the Java influence: <a class="reference" href="http://www.python.org/peps/pep-0282.html">http://www.python.org/peps/pep-0282.html</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id4" name="id8">[3]</a></td><td>Original Bookmarklet Based Debugging blather: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/">http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/LoggingPane.html b/mochikit_v14/doc/html/MochiKit/LoggingPane.html
new file mode 100644 (file)
index 0000000..ed19860
--- /dev/null
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+// open a pop-up window
+createLoggingPane()
+// use a div at the bottom of the document
+createLoggingPane(true);
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.Logging does not have any browser dependencies and is
+completely unobtrusive. MochiKit.LoggingPane is a browser-based
+colored viewing pane for your <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> output that
+can be used as a pop-up or inline.</p>
+<p>It also allows for regex and level filtering!  MochiKit.LoggingPane is
+used as the default
+<a class="mochiref reference" href="Logging.html#fn-debuggingbookmarklet">MochiKit.Logging.debuggingBookmarklet()</a> if it is loaded.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="constructors" name="constructors">Constructors</a></h2>
+<p>
+<a name="fn-loggingpane"></a>
+<a class="mochidef reference" href="#fn-loggingpane">LoggingPane(inline=false, logger=MochiKit.Logging.logger)</a>:</p>
+<blockquote>
+<p>A listener for a <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> logger with an
+interactive DOM representation.</p>
+<p>If <tt class="docutils literal"><span class="pre">inline</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> will be a
+<tt class="docutils literal"><span class="pre">DIV</span></tt> at the bottom of the document. Otherwise, it will be in a
+pop-up window with a name based on the calling page's URL. If
+there is an element in the document with an id of
+<tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt>, it will be used instead of appending a
+new <tt class="docutils literal"><span class="pre">DIV</span></tt> to the body.</p>
+<p><tt class="docutils literal"><span class="pre">logger</span></tt> is the reference to the
+<a class="mochiref reference" href="Logging.html#fn-logger">MochiKit.Logging.Logger</a> to listen to. If not
+specified, the global default logger is used.</p>
+<p>Properties:</p>
+<blockquote>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">win</span></tt>:</dt>
+<dd>Reference to the pop-up window (<tt class="docutils literal"><span class="pre">undefined</span></tt> if
+<tt class="docutils literal"><span class="pre">inline</span></tt>)</dd>
+<dt><tt class="docutils literal"><span class="pre">inline</span></tt>:</dt>
+<dd><tt class="docutils literal"><span class="pre">true</span></tt> if the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> is inline</dd>
+<dt><tt class="docutils literal"><span class="pre">colorTable</span></tt>:</dt>
+<dd><p class="first">An object with property-&gt;value mappings for each log level
+and its color. May also be mutated on
+<tt class="docutils literal"><span class="pre">LoggingPane.prototype</span></tt> to affect all instances. For
+example:</p>
+<pre class="last literal-block">
+MochiKit.LoggingPane.LoggingPane.prototype.colorTable = {
+    DEBUG: &quot;green&quot;,
+    INFO: &quot;black&quot;,
+    WARNING: &quot;blue&quot;,
+    ERROR: &quot;red&quot;,
+    FATAL: &quot;darkred&quot;
+};
+</pre>
+</dd>
+</dl>
+</blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-loggingpane.prototype.closepane"></a>
+<a class="mochidef reference" href="#fn-loggingpane.prototype.closepane">LoggingPane.prototype.closePane()</a>:</p>
+<blockquote>
+<p>Close the <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> (close the child window, or
+remove the <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> <tt class="docutils literal"><span class="pre">DIV</span></tt> from the document).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-createloggingpane"></a>
+<a class="mochidef reference" href="#fn-createloggingpane">createLoggingPane(inline=false)</a>:</p>
+<blockquote>
+<p>Create or return an existing <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> for this
+document with the given inline setting. This is preferred over
+using <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> directly, as only one
+<a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> should be present in a given document.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Position.html b/mochikit_v14/doc/html/MochiKit/Position.html
new file mode 100644 (file)
index 0000000..319285e
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Position - DOM Position manipulation API</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Position - DOM Position manipulation API</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<p>This module is experimental and is present in MochiKit 1.4+ only. No
+functions are currently exported from this module. Documentation is
+forthcoming.</p>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005-2006 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;, and others.
+This program is dual-licensed free
+software; you can redistribute it and/or modify it under the terms of
+the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Selector.html b/mochikit_v14/doc/html/MochiKit/Selector.html
new file mode 100644 (file)
index 0000000..e3e5f14
--- /dev/null
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Selector - Selecting elements by CSS selector syntax</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Selector - Selecting elements by CSS selector syntax</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+MochiKit.Base.map(MochiKit.Visual.fade, $$('p.fademe'));
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.Selector provides utilities to select elements by CSS
+selector syntax. In particular it provides the <a class="mochiref reference" href="#fn-$$">$$</a>
+function.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
+<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<p>This module provides facilities to select childs of a DOM node by
+using CSS selector syntax. In particular, it provides the
+<a class="mochiref reference" href="#fn-$$">$$</a> function, which performs such a selection on the
+current document.</p>
+<p>Many of CSS3 <a class="footnote-reference" href="#id3" id="id1" name="id1">[1]</a> selectors are supported:</p>
+<ul>
+<li><p class="first">Select by tag name (<tt class="docutils literal"><span class="pre">A</span></tt>)</p>
+</li>
+<li><p class="first">Select by class (<tt class="docutils literal"><span class="pre">.theclass</span></tt>)</p>
+</li>
+<li><p class="first">Select by id (<tt class="docutils literal"><span class="pre">#someid</span></tt>)</p>
+</li>
+<li><dl class="first docutils">
+<dt>Combinators</dt>
+<dd><ul class="first last simple">
+<li>Descendant: <tt class="docutils literal"><span class="pre">E</span> <span class="pre">F</span></tt></li>
+<li>Child: <tt class="docutils literal"><span class="pre">E</span> <span class="pre">&gt;</span> <span class="pre">F</span></tt></li>
+<li>Immediate following sibling: <tt class="docutils literal"><span class="pre">E</span> <span class="pre">+</span> <span class="pre">F</span></tt></li>
+<li>Following sibling: <tt class="docutils literal"><span class="pre">E</span> <span class="pre">~</span> <span class="pre">F</span></tt></li>
+</ul>
+</dd>
+</dl>
+</li>
+<li><dl class="first docutils">
+<dt>Attribute selectors</dt>
+<dd><ul class="first last simple">
+<li>simple &quot;has attribute&quot; (without operator)</li>
+<li><tt class="docutils literal"><span class="pre">=</span></tt> equal</li>
+<li><tt class="docutils literal"><span class="pre">!=</span></tt> not equal (not in CSS std.)</li>
+<li><tt class="docutils literal"><span class="pre">~=</span></tt> word containment</li>
+<li><tt class="docutils literal"><span class="pre">^=</span></tt> starts-with</li>
+<li><tt class="docutils literal"><span class="pre">$=</span></tt> ends-with</li>
+<li><tt class="docutils literal"><span class="pre">*=</span></tt> substring containment</li>
+<li><tt class="docutils literal"><span class="pre">|=</span></tt> first part of hyphen deleimited (eg. lang|=&quot;en&quot; matches lang=&quot;en-US&quot;)</li>
+</ul>
+</dd>
+</dl>
+</li>
+<li><dl class="first docutils">
+<dt>Pseudo-classes</dt>
+<dd><ul class="first last simple">
+<li><tt class="docutils literal"><span class="pre">:root</span></tt>, <tt class="docutils literal"><span class="pre">:nth-child</span></tt>, <tt class="docutils literal"><span class="pre">:nth-last-child</span></tt>, <tt class="docutils literal"><span class="pre">:nth-of-type</span></tt>, <tt class="docutils literal"><span class="pre">:nth-last-of-type</span></tt>, <tt class="docutils literal"><span class="pre">:first-child</span></tt>, <tt class="docutils literal"><span class="pre">:last-child</span></tt>, <tt class="docutils literal"><span class="pre">:first-of-type</span></tt>, <tt class="docutils literal"><span class="pre">:last-of-type</span></tt>, <tt class="docutils literal"><span class="pre">:only-child</span></tt>, <tt class="docutils literal"><span class="pre">:only-of-type</span></tt>, <tt class="docutils literal"><span class="pre">:empty</span></tt>, <tt class="docutils literal"><span class="pre">:enabled</span></tt>, <tt class="docutils literal"><span class="pre">:disabled</span></tt>, <tt class="docutils literal"><span class="pre">:checked</span></tt>, <tt class="docutils literal"><span class="pre">:not(&lt;any</span> <span class="pre">other</span> <span class="pre">selector&gt;)</span></tt></li>
+</ul>
+</dd>
+</dl>
+</li>
+</ul>
+<p>Multiple selectors can be concatenated, like this: <tt class="docutils literal"><span class="pre">P.quote[author~='Torvalds']</span></tt>,
+in which case elements matching <em>all</em> the selectors are returned. Furthermore, such
+concatenations can be <em>combined</em> by joining them with spaces and combinators.
+This invokes the regular CSS behaviour of matching parts of the combination in
+sequence, starting off each part from the elements returned by the preceeding part.</p>
+<p>For the <tt class="docutils literal"><span class="pre">:nth-*</span></tt> pseudoclasses, the <tt class="docutils literal"><span class="pre">an+b</span></tt> syntax is partially
+supported, specifically a and b must be non-negative and only a is
+optional (this differs from the CSS std.) Also, <tt class="docutils literal"><span class="pre">odd</span></tt> and <tt class="docutils literal"><span class="pre">even</span></tt>
+are supported, e.g. <tt class="docutils literal"><span class="pre">table</span> <span class="pre">tr:nth-child(odd)</span></tt> gives you every
+other row of table starting with the first one.</p>
+<p>For further documentation of CSS selectors, refer to the W3C CSS standard. <a class="footnote-reference" href="#id3" id="id2" name="id2">[1]</a></p>
+<p>The original version of this module was ported from Prototype.</p>
+<p><strong>Note:</strong> Due to how Internet Explorer handles node attributes, some attribute
+selectors may not work as expected. In particular <tt class="docutils literal"><span class="pre">a[title]</span></tt> will not work
+as all <tt class="docutils literal"><span class="pre">A</span></tt> elements in the Internet Explorer DOM model have a title attribute
+regardless of whether it's specified in the markup or not.</p>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-$$"></a>
+<a class="mochidef reference" href="#fn-$$">$$(expression[, ...])</a>:</p>
+<blockquote>
+<p>Performs a selection on the active document. Equivalent
+to <tt class="docutils literal"><span class="pre">findChildElements(MochiKit.DOM.currentDocument(),</span> <span class="pre">[expression,</span> <span class="pre">...])</span></tt></p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-findchildelements"></a>
+<a class="mochidef reference" href="#fn-findchildelements">findChildElements(element, expressions)</a>:</p>
+<blockquote>
+<p>Traverses the child nodes of <tt class="docutils literal"><span class="pre">element</span></tt> and returns the subset
+of those that match any of the selector expressions in <tt class="docutils literal"><span class="pre">expressions</span></tt>.</p>
+<p>Each expression can be a combination of simple expressions, by concatenating
+them with spaces or combinators. In that case, normal CSS rules apply, each
+simple expression is evaluated in turn and the results of that one is used
+as the scope for the succeeding expression (see <a class="mochiref reference" href="#fn-selector.findelements">Selector.findElements</a>).
+Finally, the results of the last simple expression is returned as the search result.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="constructors" name="constructors">Constructors</a></h2>
+<p>
+<a name="fn-selector"></a>
+<a class="mochidef reference" href="#fn-selector">Selector(simpleExpression)</a>:</p>
+<blockquote>
+<p>An object storing the parsed version of a simple CSS selector expression
+and providing functions for executing searches.</p>
+<p><em>Simple</em> means that the expression is not a combination of expressions,
+i.e. it does not contain any spaces.</p>
+<p>Usually the user would not instantiate or use this object directly, but
+heres how:</p>
+<pre class="literal-block">
+var selector = MochiKit.Selector.Selector('#someelementid');
+var searchResults = selector.findElements(rootElement);
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-selector.findelements"></a>
+<a class="mochidef reference" href="#fn-selector.findelements">Selector.findElements(scope[, axis=&quot;&quot;])</a>:</p>
+<blockquote>
+<p>Performs a search on <tt class="docutils literal"><span class="pre">scope</span></tt>. The value of axis controls what relatives
+of <tt class="docutils literal"><span class="pre">scope</span></tt> are considered.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">scope</span></tt>:</dt>
+<dd>A DOM node that acts as a starting point for the search.</dd>
+<dt><tt class="docutils literal"><span class="pre">axis</span></tt>:</dt>
+<dd>One of <tt class="docutils literal"><span class="pre">&quot;&gt;&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;+&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;~&quot;</span></tt> or the empty string (default).
+If the empty string, all descendant nodes of <tt class="docutils literal"><span class="pre">scope</span></tt> are tested against
+the expression. If <tt class="docutils literal"><span class="pre">&gt;</span></tt> only direct child nodes of <tt class="docutils literal"><span class="pre">scope</span></tt> are tested,
+if <tt class="docutils literal"><span class="pre">+</span></tt> only the next sibling (if any) of <tt class="docutils literal"><span class="pre">scope</span></tt> is tested and if
+<tt class="docutils literal"><span class="pre">~</span></tt> all succeeding siblings of <tt class="docutils literal"><span class="pre">scope</span></tt> are tested.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id3">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id2">2</a>)</em> CSS Selectors Level 3 (Last Call, oct. 2006):
+<a class="reference" href="http://www.w3.org/TR/2005/WD-css3-selectors-20051215/">http://www.w3.org/TR/2005/WD-css3-selectors-20051215/</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Arnar Birgisson &lt;<a class="reference" href="mailto:arnarbi&#64;gmail.com">arnarbi&#64;gmail.com</a>&gt;</li>
+<li>Thomas Herve &lt;<a class="reference" href="mailto:therve&#64;gmail.com">therve&#64;gmail.com</a>&gt;</li>
+<li>Originally ported from Prototype &lt;<a class="reference" href="http://prototype.conio.net/">http://prototype.conio.net/</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+<p>Based on Prototype, (c) 2005 Sam Stephenson, available under the <a class="reference" href="http://dev.rubyonrails.org/browser/spinoffs/prototype/LICENSE?rev=3362">Prototype
+license</a></p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Signal.html b/mochikit_v14/doc/html/MochiKit/Signal.html
new file mode 100644 (file)
index 0000000..8b4d47e
--- /dev/null
@@ -0,0 +1,476 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Signal - Simple universal event handling</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Signal - Simple universal event handling</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<p>Signal for DOM events:</p>
+<pre class="literal-block">
+// DOM events are also signals. Connect freely! The functions will be
+// called with the custom event as a parameter.
+
+// calls myClicked.apply(getElement('myID'), [event])
+connect('myID', 'onclick', myClicked);
+
+// calls wasClicked.apply(myObject, [event])
+connect('myID', 'onclick', myObject, wasClicked);
+
+// calls myObject.wasClicked(event)
+connect('myID', 'onclick', myObject, 'wasClicked');
+
+// the event is normalized, no more e = e || window.event!
+myObject.wasClicked = function(e) {
+    var crossBrowserCoordinates = e.mouse().page;
+    // e.mouse().page is a MochiKit.Style.Coordinates object
+}
+</pre>
+<p>Signal for non-DOM events:</p>
+<pre class="literal-block">
+// otherObject.gotFlash() will be called when 'flash' signalled.
+connect(myObject, 'flash', otherObject, 'gotFlash');
+
+// gotBang.apply(otherObject, [...]) will be called when 'bang' signalled.
+// You can access otherObject from within gotBang as 'this'.
+connect(myObject, 'bang', otherObject, gotBang);
+
+// myFunc.apply(myObject, [...]) will be called when 'flash' signalled.
+// You can access myObject from within myFunc as 'this'.
+var ident = connect(myObject, 'flash', myFunc);
+
+// You may disconnect with the return value from connect
+disconnect(ident);
+
+// Signal can take parameters. These will be passed along to the
+// connected functions.
+signal(myObject, 'flash');
+signal(myObject, 'bang', 'BANG!');
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>Event handling was never so easy!</p>
+<p>This module takes care of all the hard work—figuring out which
+event model to use, trying to retrieve the event object, and handling
+your own internal events, as well as cleanup when the page is unloaded
+to clean up IE's nasty memory leakage.</p>
+<p>This event system is largely based on Qt's signal/slot system. Read
+more on how that is handled and also how it is used in model/view
+programming at: <a class="reference" href="http://doc.trolltech.com/">http://doc.trolltech.com/</a></p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<div class="section">
+<h2><a id="using-signal-for-dom-events" name="using-signal-for-dom-events">Using Signal for DOM Events</a></h2>
+<p>When using MochiKit.Signal, do not use the browser's native event
+API. That means, no <tt class="docutils literal"><span class="pre">onclick=&quot;blah&quot;</span></tt>, no
+<tt class="docutils literal"><span class="pre">elem.addEventListener(...)</span></tt>, and certainly no
+<tt class="docutils literal"><span class="pre">elem.attachEvent(...)</span></tt>. This also means that
+<a class="mochiref reference" href="DOM.html#fn-addtocallstack">MochiKit.DOM.addToCallStack</a> and
+<a class="mochiref reference" href="DOM.html#fn-addloadevent">MochiKit.DOM.addLoadEvent</a> should not be used in
+combination with this module.</p>
+<p>Signals for DOM objects are named with the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix, e.g.:
+<tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>, etc.</p>
+<p>When the signal fires, your slot will be called with one parameter,
+the custom event object.</p>
+</div>
+<div class="section">
+<h2><a id="custom-event-objects-for-dom-events" name="custom-event-objects-for-dom-events">Custom Event Objects for DOM events</a></h2>
+<p>Signals triggered by DOM events are called with a custom event object
+as a parameter. The custom event object presents a consistent view of
+the event across all supported platforms and browsers, and provides
+many conveniences not available even in a correct W3C implementation.</p>
+<p>See the <a class="reference" href="#dom-custom-event-object-reference">DOM Custom Event Object Reference</a> for a detailed API
+description of this object.</p>
+<p>If you find that you're accessing the native event for any reason,
+create a <a class="reference" href="http://trac.mochikit.com/newticket">new ticket</a> and we'll look into normalizing the behavior
+you're looking for.</p>
+</div>
+<div class="section">
+<h2><a id="memory-usage" name="memory-usage">Memory Usage</a></h2>
+<p>Any object that has connected slots (via <a class="mochiref reference" href="#fn-connect">connect()</a>) is
+referenced by the Signal mechanism until it is disconnected via
+<a class="mochiref reference" href="#fn-disconnect">disconnect()</a> or <a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a>.</p>
+<p>Signal does not leak. It registers an <tt class="docutils literal"><span class="pre">'onunload'</span></tt> event that
+disconnects all objects on the page when the browser leaves the
+page. However, memory usage will grow during the page view for every
+connection made until it is disconnected. Even if the DOM object is
+removed from the document, it will still be referenced by Signal until
+it is explicitly disconnected.</p>
+<p>In order to conserve memory during the page view,
+<a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a> any DOM elements that are about to be
+removed from the document.</p>
+</div>
+<div class="section">
+<h2><a id="synthesized-events" name="synthesized-events">Synthesized Events</a></h2>
+<p>Certain events supported by MochiKit are not generated natively by all
+browsers. MochiKit can synthesize these events even for non-supporting
+browsers, however, by watching for related events and triggering the
+appropriate signals at the right times.</p>
+<p>These events include:</p>
+<p><tt class="docutils literal"><span class="pre">onmouseenter</span></tt></p>
+<blockquote>
+<p>Similar to <tt class="docutils literal"><span class="pre">'onmouseover'</span></tt>, but does not &quot;bubble&quot; up to parent
+nodes. Such bubbling is often a cause of confusion. On an
+<tt class="docutils literal"><span class="pre">'onmouseenter'</span></tt> event, you can be certain that the mouse has
+left the node attached to the event.</p>
+<dl class="docutils">
+<dt><em>Availability:</em></dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p><tt class="docutils literal"><span class="pre">onmouseleave</span></tt></p>
+<blockquote>
+<p>Similar to <tt class="docutils literal"><span class="pre">'onmouseout'</span></tt>, but does not &quot;bubble&quot; up to parent
+nodes. This is the analog to <tt class="docutils literal"><span class="pre">'onmouseenter'</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability:</em></dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="using-signal-for-non-dom-objects" name="using-signal-for-non-dom-objects">Using Signal for non-DOM objects</a></h2>
+<p>Signals are triggered with the <a class="mochiref reference" href="#fn-signal">signal(src, 'signal', ...)</a>
+function. Additional parameters passed to this are passed onto the
+connected slots. Explicit signals are not required for DOM events.</p>
+<p>Slots that are connected to a signal are called in the following
+manner when that signal is signalled:</p>
+<ul class="simple">
+<li>If the slot was a single function, then it is called with <tt class="docutils literal"><span class="pre">this</span></tt>
+set to the object originating the signal with whatever parameters
+it was signalled with.</li>
+<li>If the slot was an object and a function, then it is called with
+<tt class="docutils literal"><span class="pre">this</span></tt> set to the object, and with whatever parameters it was
+signalled with.</li>
+<li>If the slot was an object and a string, then <tt class="docutils literal"><span class="pre">object[string]</span></tt> is
+called with the parameters to the signal.</li>
+</ul>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="signal-api-reference" name="signal-api-reference">Signal API Reference</a></h2>
+<p>
+<a name="fn-connect"></a>
+<a class="mochidef reference" href="#fn-connect">connect(src, signal, dest[, func])</a>:</p>
+<blockquote>
+<p>Connects a signal to a slot, and return a unique identifier that
+can be used to disconnect that signal.</p>
+<p><tt class="docutils literal"><span class="pre">src</span></tt> is the object that has the signal. You may pass in a
+string, in which case, it is interpreted as an id for an HTML
+element.</p>
+<p><tt class="docutils literal"><span class="pre">signal</span></tt> is a string that represents a signal name. If 'src' is
+an HTML Element, <tt class="docutils literal"><span class="pre">window</span></tt>, or the <tt class="docutils literal"><span class="pre">document</span></tt>, then it can be
+one of the 'on-XYZ' events. You must include the 'on' prefix, and
+it must be all lower-case.</p>
+<p><tt class="docutils literal"><span class="pre">dest</span></tt> and <tt class="docutils literal"><span class="pre">func</span></tt> describe the slot, or the action to take
+when the signal is triggered.</p>
+<blockquote>
+<ul class="simple">
+<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a string, then
+<tt class="docutils literal"><span class="pre">dest[func].apply(dest,</span> <span class="pre">[...])</span></tt> will be called when the
+signal is signalled.</li>
+<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a function, then
+<tt class="docutils literal"><span class="pre">func.apply(dest,</span> <span class="pre">[...])</span></tt> will be called when the signal
+is signalled.</li>
+<li>If <tt class="docutils literal"><span class="pre">func</span></tt> is undefined and <tt class="docutils literal"><span class="pre">dest</span></tt> is a function, then
+<tt class="docutils literal"><span class="pre">dest.apply(src,</span> <span class="pre">[...])</span></tt> will be called when the signal is
+signalled.</li>
+</ul>
+</blockquote>
+<p>No other combinations are allowed and will raise an exception.</p>
+<p>The return value can be passed to <a class="mochiref reference" href="#fn-disconnect">disconnect</a> to
+disconnect the signal.</p>
+<p>In MochiKit 1.4+, if <tt class="docutils literal"><span class="pre">src</span></tt> is an object that has a <tt class="docutils literal"><span class="pre">__connect__</span></tt>
+method, then <tt class="docutils literal"><span class="pre">src.__connect__(ident,</span> <span class="pre">signal,</span> <span class="pre">objOrFunc,</span> <span class="pre">funcOrStr)</span></tt>
+will be called. This method may be used to disconnect the signal.
+DOM objects can not implement this feature.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-disconnect"></a>
+<a class="mochidef reference" href="#fn-disconnect">disconnect(ident)</a>:</p>
+<blockquote>
+<p>To disconnect a signal, pass its ident returned by
+<a class="mochiref reference" href="#fn-connect">connect()</a>.  This is similar to how the browser's
+<tt class="docutils literal"><span class="pre">setTimeout</span></tt> and <tt class="docutils literal"><span class="pre">clearTimeout</span></tt> works.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-disconnectall"></a>
+<a class="mochidef reference" href="#fn-disconnectall">disconnectAll(src[, signal, ...])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">disconnectAll(src)</span></tt> removes all signals from src.</p>
+<p><tt class="docutils literal"><span class="pre">disconnectAll(src,</span> <span class="pre">'onmousedown',</span> <span class="pre">'mySignal')</span></tt> will remove all
+<tt class="docutils literal"><span class="pre">'onmousedown'</span></tt> and <tt class="docutils literal"><span class="pre">'mySignal'</span></tt> signals from src.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-disconnectallto"></a>
+<a class="mochidef reference" href="#fn-disconnectallto">disconnectAllTo(dest[, func])</a>:</p>
+<blockquote>
+<p><tt class="docutils literal"><span class="pre">disconnectAllTo(dest)</span></tt> removes all signals connected to dest.</p>
+<p><tt class="docutils literal"><span class="pre">disconnectAllTo(dest,</span> <span class="pre">func)</span></tt> will remove all
+signals connected to dest using func.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-signal"></a>
+<a class="mochidef reference" href="#fn-signal">signal(src, signal, ...)</a>:</p>
+<blockquote>
+<p>This will signal a signal, passing whatever additional parameters
+on to the connected slots. <tt class="docutils literal"><span class="pre">src</span></tt> and <tt class="docutils literal"><span class="pre">signal</span></tt> are the same as
+for <a class="mochiref reference" href="#fn-connect">connect()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="dom-custom-event-object-reference" name="dom-custom-event-object-reference">DOM Custom Event Object Reference</a></h2>
+<p>
+<a name="fn-event"></a>
+<a class="mochidef reference" href="#fn-event">event()</a>:</p>
+<blockquote>
+<p>The native event produced by the browser. You should not need to
+use this.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-src"></a>
+<a class="mochidef reference" href="#fn-src">src()</a>:</p>
+<blockquote>
+<p>The element that this signal is connected to.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-type"></a>
+<a class="mochidef reference" href="#fn-type">type()</a>:</p>
+<blockquote>
+<p>The event type (<tt class="docutils literal"><span class="pre">'click'</span></tt>, <tt class="docutils literal"><span class="pre">'mouseover'</span></tt>, <tt class="docutils literal"><span class="pre">'keypress'</span></tt>,
+etc.) as a string. Does not include the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-target"></a>
+<a class="mochidef reference" href="#fn-target">target()</a>:</p>
+<blockquote>
+<p>The element that triggered the event. This may be a child of
+<a class="mochiref reference" href="#fn-src">src()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-modifier"></a>
+<a class="mochidef reference" href="#fn-modifier">modifier()</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">{shift,</span> <span class="pre">ctrl,</span> <span class="pre">meta,</span> <span class="pre">alt,</span> <span class="pre">any}</span></tt>, where each property is
+<tt class="docutils literal"><span class="pre">true</span></tt> if its respective modifier key was pressed, <tt class="docutils literal"><span class="pre">false</span></tt>
+otherwise. <tt class="docutils literal"><span class="pre">any</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> if any modifier is pressed,
+<tt class="docutils literal"><span class="pre">false</span></tt> otherwise.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-stoppropagation"></a>
+<a class="mochidef reference" href="#fn-stoppropagation">stopPropagation()</a>:</p>
+<blockquote>
+<p>Works like W3C's <a class="reference" href="http://developer.mozilla.org/en/docs/DOM:event.stopPropagation">stopPropagation()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-preventdefault"></a>
+<a class="mochidef reference" href="#fn-preventdefault">preventDefault()</a>:</p>
+<blockquote>
+<p>Works like W3C's <a class="reference" href="http://developer.mozilla.org/en/docs/DOM:event.preventDefault">preventDefault()</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-stop"></a>
+<a class="mochidef reference" href="#fn-stop">stop()</a>:</p>
+<blockquote>
+<p>Shortcut that calls <tt class="docutils literal"><span class="pre">stopPropagation()</span></tt> and
+<tt class="docutils literal"><span class="pre">preventDefault()</span></tt>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-key"></a>
+<a class="mochidef reference" href="#fn-key">key()</a>:</p>
+<blockquote>
+<p>Returns <tt class="docutils literal"><span class="pre">{code,</span> <span class="pre">string}</span></tt>.</p>
+<p>Use <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> handlers to detect control
+characters such as <tt class="docutils literal"><span class="pre">'KEY_F1'</span></tt>. Use the <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>
+handler to detect &quot;printable&quot; characters, such as <tt class="docutils literal"><span class="pre">'é'</span></tt>.</p>
+<p>When a user presses F1, in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> this
+method returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">122,</span> <span class="pre">string:</span> <span class="pre">'KEY_F1'}</span></tt>. In
+<tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">0,</span> <span class="pre">string:</span> <span class="pre">''}</span></tt>.</p>
+<p>If a user presses Shift+2 on a US keyboard, this method returns
+<tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">50,</span> <span class="pre">string:</span> <span class="pre">'KEY_2'}</span></tt> in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and
+<tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>.  In <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">64,</span>
+<span class="pre">string:</span> <span class="pre">'&#64;'}</span></tt>.</p>
+<p>See <tt class="docutils literal"><span class="pre">_specialKeys</span></tt> in the source code for a comprehensive list
+of control characters.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-mouse"></a>
+<a class="mochidef reference" href="#fn-mouse">mouse()</a>:</p>
+<blockquote>
+<p>Properties for <tt class="docutils literal"><span class="pre">'onmouse*'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>,
+and <tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">page</span></tt> is a <a class="mochiref reference" href="Style.html#fn-coordinates">MochiKit.Style.Coordinates</a> object
+that represents the cursor position relative to the HTML
+document.  Equivalent to <tt class="docutils literal"><span class="pre">pageX</span></tt> and <tt class="docutils literal"><span class="pre">pageY</span></tt> in
+Safari, Mozilla, and Opera.</li>
+<li><tt class="docutils literal"><span class="pre">client</span></tt> is a <a class="mochiref reference" href="Style.html#fn-coordinates">MochiKit.Style.Coordinates</a>
+object that represents the cursor position relative to the
+visible portion of the HTML document. Equivalent to
+<tt class="docutils literal"><span class="pre">clientX</span></tt> and <tt class="docutils literal"><span class="pre">clientY</span></tt> on all browsers. Current versions of
+Safari incorrectly return clientX as relative to the canvas
+instead of relative to the viewport (<a class="reference" href="http://bugs.webkit.org/show_bug.cgi?id=8707">Safari Bug 8707</a>).</li>
+</ul>
+</blockquote>
+<p>Properties for <tt class="docutils literal"><span class="pre">'onmouseup'</span></tt>, <tt class="docutils literal"><span class="pre">'onmousedown'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>,
+and <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">mouse().button</span></tt> returns <tt class="docutils literal"><span class="pre">{left,</span> <span class="pre">right,</span> <span class="pre">middle}</span></tt> where
+each property is <tt class="docutils literal"><span class="pre">true</span></tt> if the mouse button was pressed,
+<tt class="docutils literal"><span class="pre">false</span></tt> otherwise.</li>
+</ul>
+</blockquote>
+<p>Known browser bugs:</p>
+<blockquote>
+<ul>
+<li><p class="first">Current versions of Safari won't signal <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>
+when attached via <tt class="docutils literal"><span class="pre">connect()</span></tt> (<a class="reference" href="http://bugs.webkit.org/show_bug.cgi?id=7790">Safari Bug 7790</a>).</p>
+</li>
+<li><p class="first">In Safari &lt; 2.0.4, calling <tt class="docutils literal"><span class="pre">preventDefault()</span></tt> or <tt class="docutils literal"><span class="pre">stop()</span></tt>
+in <tt class="docutils literal"><span class="pre">'onclick'</span></tt> events signalled from <tt class="docutils literal"><span class="pre">&lt;a&gt;</span></tt> tags does not
+prevent the browser from following those links.</p>
+</li>
+<li><p class="first">Mac browsers don't report right-click consistently. Firefox
+signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().ctrl</span></tt> to true,
+Opera signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().meta</span></tt> to
+<tt class="docutils literal"><span class="pre">true</span></tt>, and Safari doesn't signal the slot at all
+(<a class="reference" href="http://bugs.webkit.org/show_bug.cgi?id=6595">Safari Bug 6595</a>).</p>
+<p>To find a right-click in Safari, Firefox, and IE, you can
+connect an element to <tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>. This doesn't
+work in Opera.</p>
+</li>
+</ul>
+</blockquote>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-relatedtarget"></a>
+<a class="mochidef reference" href="#fn-relatedtarget">relatedTarget()</a>:</p>
+<blockquote>
+<p>Returns the document element that the mouse has moved to. This is
+generated for <tt class="docutils literal"><span class="pre">'onmouseover'</span></tt> and <tt class="docutils literal"><span class="pre">'onmouseout'</span></tt> events.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-confirmunload"></a>
+<a class="mochidef reference" href="#fn-confirmunload">confirmUnload(msg)</a>:</p>
+<blockquote>
+<p>In browsers that support the <tt class="docutils literal"><span class="pre">'onbeforeunload'</span></tt> event (IE and
+Firefox), calling this in the event handler will show a dialog box
+that allows the user to confirm or cancel the navigation away from
+the page.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Jonathan Gardner &lt;<a class="reference" href="mailto:jgardner&#64;jonathangardner.net">jgardner&#64;jonathangardner.net</a>&gt;</li>
+<li>Beau Hartshorne &lt;<a class="reference" href="mailto:beau&#64;hartshornesoftware.com">beau&#64;hartshornesoftware.com</a>&gt;</li>
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2006 Jonathan Gardner &lt;<a class="reference" href="mailto:jgardner&#64;jonathangardner.net">jgardner&#64;jonathangardner.net</a>&gt;, Beau
+Hartshorne &lt;<a class="reference" href="mailto:beau&#64;hartshornesoftware.com">beau&#64;hartshornesoftware.com</a>&gt;, and Bob Ippolito
+&lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;.  This program is dual-licensed free software; you
+can redistribute it and/or modify it under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT
+License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Sortable.html b/mochikit_v14/doc/html/MochiKit/Sortable.html
new file mode 100644 (file)
index 0000000..d3ddaa4
--- /dev/null
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit.Sortable - sortable with drag and drop lists</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Sortable - sortable with drag and drop lists</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+&lt;ul id=&quot;dnd_sortable&quot;&gt;
+    &lt;li&gt;mochibot.com&lt;/li&gt;
+    &lt;li&gt;pythonmac.org&lt;/li&gt;
+    &lt;li&gt;undefined.org&lt;/li&gt;
+    &lt;li&gt;python.org&lt;/li&gt;
+&lt;/ul&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+  MochiKit.Sortable.Sortable.create('dnd_sortable');
+&lt;/script&gt;
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.Sortable add a new Sortable object to manipulate easily
+drag&amp;drop in lists.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
+<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a></li>
+<li><a class="mochiref reference" href="Visual.html">MochiKit.Visual</a></li>
+<li><a class="mochiref reference" href="Signal.html">MochiKit.Signal</a></li>
+<li><a class="mochiref reference" href="DragAndDrop.html">MochiKit.DragAndDrop</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<p>MochiKit.Sortable mainly contains the Sortable object offering
+facilities to manipulate a list and drag its items to reorder it. It
+can also be serialized for being send to server. It is ported from
+<a class="reference" href="http://script.aculo.us">Scriptaculous</a>.</p>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="objects-defined" name="objects-defined">Objects defined</a></h2>
+<p>
+<a name="fn-sortableobserver"></a>
+<a class="mochidef reference" href="#fn-sortableobserver">SortableObserver</a>:</p>
+<blockquote>
+<p>Observer for DragAndDrop object. You normally don't have to access
+this, only for customization purpose.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-sortable.create"></a>
+<a class="mochidef reference" href="#fn-sortable.create">Sortable.create(element [, options])</a>:</p>
+<blockquote>
+<p>Create a new Sortable. Usually you'll call it with a UL element,
+but it can be customized with options to use something else.</p>
+<p>You have the following options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="49%" />
+<col width="51%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>element</td>
+<td>element</td>
+</tr>
+<tr><td>tag</td>
+<td>'li'</td>
+</tr>
+<tr><td>dropOnEmpty</td>
+<td>false</td>
+</tr>
+<tr><td>overlap</td>
+<td>'vertical'</td>
+</tr>
+<tr><td>constraint</td>
+<td>'vertical'</td>
+</tr>
+<tr><td>containment</td>
+<td>element</td>
+</tr>
+<tr><td>handle</td>
+<td>false</td>
+</tr>
+<tr><td>only</td>
+<td>false</td>
+</tr>
+<tr><td>hoverclass</td>
+<td>null</td>
+</tr>
+<tr><td>ghosting</td>
+<td>false</td>
+</tr>
+<tr><td>scroll</td>
+<td>false</td>
+</tr>
+<tr><td>scrollSensitivity</td>
+<td>20</td>
+</tr>
+<tr><td>scrollSpeed</td>
+<td>15</td>
+</tr>
+<tr><td>format</td>
+<td>/^[^_]*_(.*)$/</td>
+</tr>
+<tr><td>onChange</td>
+<td>MochiKit.Base.noop</td>
+</tr>
+<tr><td>onUpdate</td>
+<td>MochiKit.Base.noop</td>
+</tr>
+<tr><td>tree</td>
+<td>false</td>
+</tr>
+<tr><td>treeTag</td>
+<td>'ul'</td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">tag</span></tt>:</dt>
+<dd>Name of the tag used to make the draggable elements. It matches all
+the childNodes of the Sortable element with this tag.</dd>
+<dt><tt class="docutils literal"><span class="pre">only</span></tt>:</dt>
+<dd>Class or array of classes used to filter the children, combined with
+the tag criteria.</dd>
+<dt><tt class="docutils literal"><span class="pre">format</span></tt>:</dt>
+<dd>Regular expression which serves as a match filter for serialization,
+on children' ids. For example, with the default value, you'll get
+['1', '2', '3', '4'] with ids ['sort_1', 'sort_2', 'sort_3', 'sort_4'].</dd>
+<dt><tt class="docutils literal"><span class="pre">onChange</span></tt>:</dt>
+<dd>Callback called when an element moves between others in the Sortable.
+It's called for <em>each</em> movements, even if you don't release the mouse.</dd>
+<dt><tt class="docutils literal"><span class="pre">onUpdate</span></tt>:</dt>
+<dd>Callback called when the order changes in the Sortable. It's called
+only if the Sortable is modified, after you dropped an element.</dd>
+<dt><tt class="docutils literal"><span class="pre">tree</span></tt>:</dt>
+<dd>Option for creating a Sortable tree. It's an experimental
+setting, that can be very slow even with a few elements. You
+can customize its behaviour with the <tt class="docutils literal"><span class="pre">treeTag</span></tt> option, that
+defines the node used to make branches in your tree (that
+contains leaves).</dd>
+</dl>
+<p>Other options are passed to the Draggables and Droppables objects created.
+Refer to <a class="mochiref reference" href="DragAndDrop.html">MochiKit.DragAndDrop</a> for more information.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-sortable.destroy"></a>
+<a class="mochidef reference" href="#fn-sortable.destroy">Sortable.destroy(element)</a>:</p>
+<blockquote>
+<p>Destroy a previously created sortable. It prevents further use of
+the Sortable functionnality on the element, unless recreated.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-sortable.serialize"></a>
+<a class="mochidef reference" href="#fn-sortable.serialize">Sortable.serialize(element [, options])</a>:</p>
+<blockquote>
+<p>Serialize the content of a Sortable. Useful to send this content
+through a XMLHTTPRequest. The options overrides the ones of the Sortable
+only for the serialization.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="13%" />
+<col width="88%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>tag</td>
+<td>tag from the Sortable</td>
+</tr>
+<tr><td>only</td>
+<td>only from the Sortable</td>
+</tr>
+<tr><td>name</td>
+<td>id of the element</td>
+</tr>
+<tr><td>format</td>
+<td>format of the Sortable or /^[^_]*_(.*)$</td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Thomas Herve &lt;<a class="reference" href="mailto:therve&#64;gmail.com">therve&#64;gmail.com</a>&gt;</li>
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+<li>Originally adapted from Script.aculo.us &lt;<a class="reference" href="http://script.aculo.us/">http://script.aculo.us/</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;.  This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+<p>Portions adapted from <a class="reference" href="http://script.aculo.us">Scriptaculous</a> are available under the terms
+of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Style.html b/mochikit_v14/doc/html/MochiKit/Style.html
new file mode 100644 (file)
index 0000000..51bffe6
--- /dev/null
@@ -0,0 +1,332 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4.1: http://docutils.sourceforge.net/" />
+<title>MochiKit.Style - painless Style manipulation API</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Style - painless Style manipulation API</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+var messagePos = getElementPosition('message');
+var messageSize = getElementDimensions('message');
+
+var notifyPos = new MochiKit.Style.Coordinates(
+     messagePos.x + messageSize.w + 10,
+     messagePos.y);
+
+setElementPosition('notify', notifyPos);
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>Refactored from <a class="mochiref reference" href="DOM.html">MochiKit.DOM</a>.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<p>Refactored from <a class="mochiref reference" href="DOM.html">MochiKit.DOM</a>.</p>
+<div class="section">
+<h2><a id="element-visibility" name="element-visibility">Element Visibility</a></h2>
+<p>The <a class="mochiref reference" href="#fn-hideelement">hideElement</a> and <a class="mochiref reference" href="#fn-showelement">showElement</a> functions are
+provided as a convenience, but only work for elements that are
+<tt class="docutils literal"><span class="pre">display:</span> <span class="pre">block</span></tt>. For a general solution to showing, hiding, and
+checking the explicit visibility of elements, we recommend using a
+solution that involves a little CSS. Here's an example:</p>
+<pre class="literal-block">
+&lt;style type=&quot;text/css&quot;&gt;
+    .invisible { display: none; }
+&lt;/style&gt;
+
+&lt;script type=&quot;text/javascript&quot;&gt;
+    function toggleVisible(elem) {
+        toggleElementClass(&quot;invisible&quot;, elem);
+    }
+
+    function makeVisible(elem) {
+        removeElementClass(elem, &quot;invisible&quot;);
+    }
+
+    function makeInvisible(elem) {
+        addElementClass(elem, &quot;invisible&quot;);
+    }
+
+    function isVisible(elem) {
+        // you may also want to check for
+        // getElement(elem).style.display == &quot;none&quot;
+        return !hasElementClass(elem, &quot;invisible&quot;);
+    };
+&lt;/script&gt;
+</pre>
+<p>MochiKit doesn't ship with such a solution, because there is no
+reliable and portable method for adding CSS rules on the fly with
+JavaScript.</p>
+</div>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-getstyle"></a>
+<a class="mochidef reference" href="#fn-getstyle">getStyle(element, cssSelector)</a>:</p>
+<blockquote>
+<p>Looks up a CSS property for the given element. The element can be
+specified as either a string with the element's ID or the element
+object itself.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">cssSelector</span></tt>:</dt>
+<dd>The CSS selector, e.g. <tt class="docutils literal"><span class="pre">background-color</span></tt>.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setstyle"></a>
+<a class="mochidef reference" href="#fn-setstyle">setStyle(element, styles)</a>:</p>
+<blockquote>
+<p>Set CSS properties on a the given element. The element can be
+specified as either a string with the element's ID or the element
+object itself.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">styles</span></tt>:</dt>
+<dd>Dictionnary holding CSS properties to set, e.g.
+<tt class="docutils literal"><span class="pre">{'background-color':</span> <span class="pre">'red',</span> <span class="pre">'opacity':</span> <span class="pre">0.5}</span></tt>.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setopacity"></a>
+<a class="mochidef reference" href="#fn-setopacity">setOpacity(element, opacity)</a>:</p>
+<blockquote>
+<p>Sets <tt class="docutils literal"><span class="pre">opacity</span></tt> for <tt class="docutils literal"><span class="pre">element</span></tt>. Valid <tt class="docutils literal"><span class="pre">opacity</span></tt> values range
+from 0 (invisible) to 1 (opaque). <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getelementdimensions"></a>
+<a class="mochidef reference" href="#fn-getelementdimensions">getElementDimensions(element)</a>:</p>
+<blockquote>
+<p>Return the absolute pixel width and height (including padding and border,
+but not margins) of <tt class="docutils literal"><span class="pre">element</span></tt> as an object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt>
+properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt> is not in the document.
+<tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to be looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object with
+<tt class="docutils literal"><span class="pre">w</span></tt> and/or <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setelementdimensions"></a>
+<a class="mochidef reference" href="#fn-setelementdimensions">setElementDimensions(element, dimensions[, units='px'])</a>:</p>
+<blockquote>
+<p>Sets the dimensions of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an object
+with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
+<p>Warning: IE in quirks-mode seems to behave strange when you set
+the height off an element containing text to 0. You can workaround this
+by setting the value of visibly/display.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">element</span></tt>:</dt>
+<dd>A reference to the DOM element to update (if a string is
+given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the
+node)</dd>
+<dt><tt class="docutils literal"><span class="pre">dimensions</span></tt>:</dt>
+<dd>An object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties. You can also specify only
+one property.</dd>
+<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
+<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getelementposition"></a>
+<a class="mochidef reference" href="#fn-getelementposition">getElementPosition(element[, relativeTo={x: 0, y: 0}])</a>:</p>
+<blockquote>
+<p>Return the absolute pixel position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document
+as an object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if
+<tt class="docutils literal"><span class="pre">element</span></tt> is not in the document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified
+as a string to be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM
+element, or trivially as an object with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt>
+properties.</p>
+<p>If <tt class="docutils literal"><span class="pre">relativeTo</span></tt> is given, then its coordinates are subtracted
+from the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt>, e.g.:</p>
+<pre class="literal-block">
+var elemPos = getElementPosition(elem);
+var anotherElemPos = getElementPosition(anotherElem);
+var relPos = getElementPosition(elem, anotherElem);
+assert( relPos.x == (elemPos.x - anotherElemPos.x) );
+assert( relPos.y == (elemPos.y - anotherElemPos.y) );
+</pre>
+<p><tt class="docutils literal"><span class="pre">relativeTo</span></tt> may be specified as a string to be looked up with
+<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object
+with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setelementposition"></a>
+<a class="mochidef reference" href="#fn-setelementposition">setElementPosition(element, position[, units='px'])</a>:</p>
+<blockquote>
+<p>Sets the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
+object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">element</span></tt>:</dt>
+<dd>A reference to the DOM element to update (if a string is
+given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the
+node)</dd>
+<dt><tt class="docutils literal"><span class="pre">position</span></tt>:</dt>
+<dd>An object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties. You can also specify only
+one property.</dd>
+<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
+<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-setdisplayforelement"></a>
+<a class="mochidef reference" href="#fn-setdisplayforelement">setDisplayForElement(display, element[, ...])</a>:</p>
+<blockquote>
+<p>Change the <tt class="docutils literal"><span class="pre">style.display</span></tt> for the given element(s). Usually
+used as the partial forms:</p>
+<ul class="simple">
+<li><a class="mochiref reference" href="#fn-showelement">showElement(element, ...)</a></li>
+<li><a class="mochiref reference" href="#fn-hideelement">hideElement(element, ...)</a></li>
+</ul>
+<p>Elements are looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string
+identifiers are acceptable.</p>
+<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt>
+based show/hide mechanism, and a CSS based alternative, see
+<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-showelement"></a>
+<a class="mochidef reference" href="#fn-showelement">showElement(element, ...)</a>:</p>
+<blockquote>
+<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
+<pre class="literal-block">
+partial(setDisplayForElement, &quot;block&quot;)
+</pre>
+<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt>
+based show/hide mechanism, and a CSS based alternative, see
+<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-hideelement"></a>
+<a class="mochidef reference" href="#fn-hideelement">hideElement(element, ...)</a>:</p>
+<blockquote>
+<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
+<pre class="literal-block">
+partial(setDisplayForElement, &quot;none&quot;)
+</pre>
+<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt>
+based show/hide mechanism, and a CSS based alternative, see
+<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getviewportdimensions"></a>
+<a class="mochidef reference" href="#fn-getviewportdimensions">getViewportDimensions()</a>:</p>
+<blockquote>
+<p>Return the pixel width and height of the viewport as an object
+with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-getviewportposition"></a>
+<a class="mochidef reference" href="#fn-getviewportposition">getViewportPosition()</a>:</p>
+<blockquote>
+<p>Return the pixel position of the viewport inside the window, as a
+<a class="mochiref reference" href="#fn-coordinates">Coordinates</a> object.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="objects" name="objects">Objects</a></h2>
+<p>
+<a name="fn-coordinates"></a>
+<a class="mochidef reference" href="#fn-coordinates">Coordinates(x, y)</a>:</p>
+<blockquote>
+<p>Constructs an object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties. <tt class="docutils literal"><span class="pre">obj.toString()</span></tt>
+returns something like <tt class="docutils literal"><span class="pre">{x:</span> <span class="pre">0,</span> <span class="pre">y:</span> <span class="pre">42}</span></tt> for debugging.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-dimensions"></a>
+<a class="mochidef reference" href="#fn-dimensions">Dimensions(w, h)</a>:</p>
+<blockquote>
+<p>Constructs an object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties. <tt class="docutils literal"><span class="pre">obj.toString()</span></tt>
+returns something like <tt class="docutils literal"><span class="pre">{w:</span> <span class="pre">0,</span> <span class="pre">h:</span> <span class="pre">42}</span></tt> for debugging.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+<li>Beau Hartshorne &lt;<a class="reference" href="mailto:beau&#64;hartshornesoftware.com">beau&#64;hartshornesoftware.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005-2006 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;, and Beau Hartshorne
+&lt;<a class="reference" href="mailto:beau&#64;hartshornesoftware.com">beau&#64;hartshornesoftware.com</a>&gt;. This program is dual-licensed free
+software; you can redistribute it and/or modify it under the terms of
+the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/VersionHistory.html b/mochikit_v14/doc/html/MochiKit/VersionHistory.html
new file mode 100644 (file)
index 0000000..db7f459
--- /dev/null
@@ -0,0 +1,331 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title></title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<p>2006-XX-XX      v1.4</p>
+<ul class="simple">
+<li>MochiKit.Color's HSV to RGB conversion code fixed to return the correct
+value (hsv.v for RGB values) in cases where saturation === 0.</li>
+<li>doXHR workaround for a Mozilla bug when calling XMLHttpRequest in certain
+situations. Always wraps call in a callLater(0, doXHR, url, opts).</li>
+<li>parseQueryString will now parse values with embedded &quot;=&quot;</li>
+<li>Workaround for a Safari DOM crash when using MochiKit.Iter.list.
+<a class="reference" href="http://bugs.webkit.org/show_bug.cgi?id=12191">http://bugs.webkit.org/show_bug.cgi?id=12191</a></li>
+<li>New removeNodeAttribute function in MochiKit.DOM.</li>
+<li>MochiKit.Async.doXHR and dependent functions now accept 201 CREATED and
+204 NO CONTENT as valid.</li>
+<li>MochiKit.DOM.formContents now treats option tags the same way that
+form posts do in the case of missing and empty string value attributes,
+even in IE.</li>
+<li>MochiKit.Base.queryString now accepts third queryString([names, values])
+form.</li>
+<li>MochiKit.DOM.formContents now defaults to document.body if no element is
+given.</li>
+<li>New MochiKit.Selector module</li>
+<li>MochiKit.LoggingPane fixes for Internet Explorer</li>
+<li>MochiKit.DOM now creates XHTML nodes in XUL documents.</li>
+<li>MochiKit.LoggingPane now works on pages with '#' in the URL on IE</li>
+<li>New MochiKit.Async.doXHR as a convenient method for doing custom
+XMLHttpRequests (e.g. extra headers, overrideMimeType, etc.)</li>
+<li>New __connect__ protocol for MochiKit.Signal.connect source notifications</li>
+<li>Added colSpan, bgColor to the list of DOM renames for Internet Explorer</li>
+<li>New MochiKit.Signal.disconnectAllTo function</li>
+<li>MochiKit.Base.parseQueryString now accepts leading question mark</li>
+<li>New MochiKit.Base.values function</li>
+<li>Fixed MochiKit.Signal.disconnect when called from a signal handler invoked
+by MochiKit.Signal.signal</li>
+<li>parseQueryString now splits on HTML entities equivalent to ampersand as well</li>
+<li>Better XHTML compatibility (removed obvious cases where uppercase tagName or
+nodeName was assumed)</li>
+<li>MochiKit.Base.queryString now handles array values in the same way HTML
+forms handle multiple elements of the same name.</li>
+<li>MochiKit.Base.parseQueryString now returns {} for empty query string instead
+of {&quot;&quot;: &quot;undefined&quot;}</li>
+<li>MochiKit.DOM.formContents now handles option value=&quot;&quot; correctly.</li>
+<li>MochiKit.DOM now checks for undefined className.</li>
+<li>MochiKit.Iter.groupby() now uses compare() to group rather than == and !=</li>
+<li>serializeJSON no longer serializes undefined, as per the JSON spec</li>
+<li>Fixed an infinite recursion bug in serializeJSON if an adapter
+returns the object itself.</li>
+<li>New MochiKit.Base.operator.seq and sne to support strict comparison</li>
+<li>MochiKit.Base.isArrayLike no longer returns true for DOM text nodes</li>
+<li>Added readonly-readOnly to the list of DOM renames for Internet Explorer</li>
+<li>New MochiKit.Signal event method: confirmUnload (sets returnValue for
+onbeforeunload)</li>
+<li>Fix interpreter help() function for Firefox and IE</li>
+<li>API version compatibility notes added</li>
+<li>New MochiKit.Base functions methodcaller and compose</li>
+<li>Support IE-based native console logging (Debugger, Atlas)</li>
+<li>Refactored style functions from MochiKit.DOM to MochiKit.Style</li>
+<li>MochiKit.Async.DeferredList is now a proper Deferred</li>
+<li>MochiKit.DOM.formContents now supports SELECT multiple tags</li>
+<li>Re-use StopIteration Error if the browser already has it</li>
+<li>Workaround IE type=&quot;&quot; bug for INPUT elements</li>
+<li>Allow LoggingPane to work in IE with hyphen-containing URLs</li>
+<li>Replace percents for Safari native logging to avoid crashing</li>
+<li>New MochiKit.DOM.coerceToDOM .dom(node) / .__dom__(node) protocol</li>
+<li>MochiKit.DOM's MochiKit.Iter dependency is now optional</li>
+<li>Added expand all link to the documentation index</li>
+<li>Added MochiKit.DOM.isChildNode</li>
+<li>Added synthesizing for onmouseenter/onmouseleave</li>
+</ul>
+<p>2006-04-29      v1.3.1 (bug fix release)</p>
+<ul class="simple">
+<li>Fix sendXMLHttpRequest sendContent regression</li>
+<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
+<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
+</ul>
+<p>2006-04-26      v1.3 &quot;warp zone&quot;</p>
+<ul class="simple">
+<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
+<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
+<li>New MochiKit.Base.method as a convenience form of bind that takes the
+object before the method</li>
+<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
+a single Array</li>
+<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
+<li>New key_events example demonstrating use of MochiKit.Signal's key handling
+capabilities.</li>
+<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
+null is used and the string will be considered the first node. This
+allows for the more natural P(&quot;foo&quot;) rather than P(null, &quot;foo&quot;).</li>
+<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
+provides multi-line input and a help() function to get MochiKit function
+signature from the documentation.</li>
+<li>Native Console Logging for the default MochiKit.Logging logger</li>
+<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
+<li>New MochiKit.Signal example: draggable</li>
+<li>Added sanity checking to Deferred to ensure that errors happen when chaining
+is used incorrectly</li>
+<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
+<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
+component values smaller than 16/255.</li>
+<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
+maximum size</li>
+<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
+Error, so that the errback chain is used instead of the callback chain.</li>
+<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
+in the correct order.</li>
+<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
+<li>MochiKit.Base.isNull no longer matches undefined</li>
+<li>example doctypes changed to HTML4</li>
+<li>isDateLike no longer throws error on null</li>
+<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
+<li>updated elementDimensions to calculate width from offsetWidth instead
+of clientWidth</li>
+<li>formContents now works with FORM tags that have a name attribute</li>
+<li>Documentation now uses MochiKit to generate a function index</li>
+</ul>
+<p>2006-01-26      v1.2 &quot;the ocho&quot;</p>
+<ul class="simple">
+<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
+<li>Added new MochiKit.Base.findIdentical function to find the index of an
+element in an Array-like object. Uses === for identity comparison.</li>
+<li>Added new MochiKit.Base.find function to find the index of an element in
+an Array-like object. Uses compare for rich comparison.</li>
+<li>MochiKit.Base.bind will accept a string for func, which will be immediately
+looked up as self[func].</li>
+<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
+compatibility</li>
+<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
+<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
+height of an element in the document</li>
+<li>MochiKit.DOM's initialization is now compatible with
+HTMLUnit + JWebUnit + Rhino</li>
+<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
+currently in the document instead of always creating one.</li>
+<li>MochiKit.Base now has operator.mul</li>
+<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
+a custom value attribute</li>
+<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
+<li>MochiKit.DOM.setNodeAttribute should work now</li>
+<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
+property to a string</li>
+<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
+name and for properties</li>
+<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
+<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
+<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
+<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
+<li>Added new MochiKit.DOM documentation on element visibility</li>
+<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
+for determining the position of an element in the document</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
+</ul>
+<p>2005-11-14      v1.1</p>
+<ul class="simple">
+<li>Fixed a bug in numberFormatter with large numbers</li>
+<li>Massively overhauled documentation</li>
+<li>Fast-path for primitives in MochiKit.Base.compare</li>
+<li>New groupby and groupby_as_array in MochiKit.Iter</li>
+<li>Added iterator factory adapter for objects that implement iterateNext()</li>
+<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
+LEGEND, FIELDSET</li>
+<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
+<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
+<li>MochiKit.LoggingPane now uses named windows based on the URL so that
+a given URL will get the same LoggingPane window after a reload
+(at the same position, etc.)</li>
+<li>MochiKit.DOM now has currentWindow() and currentDocument() context
+variables that are set with withWindow() and withDocument(). These
+context variables affect all MochiKit.DOM functionality (getElement,
+createDOM, etc.)</li>
+<li>MochiKit.Base.items will now catch and ignore exceptions for properties
+that are enumerable but not accessible (e.g. permission denied)</li>
+<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
+now accept additional arguments that are used to create a partially
+applied function. This differs from Twisted in that the callback/errback
+result becomes the <em>last</em> argument, not the first when this feature
+is used.</li>
+<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
+arguments which are used to create a GET query string</li>
+<li>Did some refactoring to reduce the footprint of MochiKit by a few
+kilobytes</li>
+<li>escapeHTML to longer escapes ' (apos) and now uses
+String.replace instead of iterating over every char.</li>
+<li>Added DeferredLock to Async</li>
+<li>Renamed getElementsComputedStyle to computedStyle and moved
+it from MochiKit.Visual to MochiKit.DOM</li>
+<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
+<li>Fixed range() to accept a negative step</li>
+<li>New alias to MochiKit.swapDOM called removeElement</li>
+<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
+an attribute on a node without raising, roughly equivalent to:
+updateNodeAttributes(node, {attr: value})</li>
+<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
+a node's attribute or returns null without raising</li>
+<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
+directly (addLoadEvent did not leak, since it clears the handler)</li>
+</ul>
+<p>2005-10-24      v1.0</p>
+<ul class="simple">
+<li>New interpreter example that shows usage of MochiKit.DOM  to make
+an interactive JavaScript interpreter</li>
+<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
+debuggingBookmarklet, with logging_pane example to show its usage</li>
+<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
+in order to provide a live regular expression matching tool</li>
+<li>Added advanced number formatting capabilities to MochiKit.Format:
+numberFormatter(pattern, placeholder=&quot;&quot;, locale=&quot;default&quot;) and
+formatLocale(locale=&quot;default&quot;)</li>
+<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
+MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
+<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
+to MochiKit.Format</li>
+<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
+isoTimestamp(isoString) will convert them to Date objects, and
+toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
+<li>Fixed missing errback for sendXMLHttpRequest when the server does not
+respond</li>
+<li>Fixed infinite recusion bug when using roundClass(&quot;DIV&quot;, ...)</li>
+<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
+from being cancelled properly</li>
+<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
+have an apply method, such as alert</li>
+<li>Reliably return null from the string parsing/manipulation functions if
+the input can't be coerced to a string (s + &quot;&quot;) or the input makes no sense;
+e.g. isoTimestamp(null) and isoTimestamp(&quot;&quot;) return null</li>
+</ul>
+<p>2005-10-08      v0.90</p>
+<ul class="simple">
+<li>Fixed ISO compliance with toISODate</li>
+<li>Added missing operator.sub</li>
+<li>Placated Mozilla's strict warnings a bit</li>
+<li>Added JSON serialization and unserialization support to MochiKit.Base:
+serializeJSON, evalJSON, registerJSON. This is very similar to the repr
+API.</li>
+<li>Fixed a bug in the script loader that failed in some scenarios when a script
+tag did not have a &quot;src&quot; attribute (thanks Ian!)</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
+P, FORM</li>
+<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
+and parseQueryString, when available.</li>
+</ul>
+<p>2005-08-12      v0.80</p>
+<ul class="simple">
+<li>Source highlighting in all examples, moved to a view-source example</li>
+<li>Added some experimental syntax highlighting for the Rounded Corners example,
+via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
+<li>Use an indirect binding for the logger conveniences, so that the global
+logger could be replaced by setting MochiKit.Logger.logger to something else
+(though an observer is probably a better choice).</li>
+<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
+which will be looked up with getElement</li>
+<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
+node.parentNode)</li>
+<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
+<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
+<li>Possible workaround for Safari issue with swapDOM, where it would get
+confused because two elements were in the DOM at the same time with the
+same id</li>
+<li>Added missing THEAD convenience function to MochiKit.DOM</li>
+<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
+<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
+MochiKit.DOM</li>
+<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
+<li>Added HSV color space support to MochiKit.Visual</li>
+<li>Fixed a bug in the sortable_tables example, it now converts types
+correctly</li>
+<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
+scope</li>
+</ul>
+<p>2005-08-04      v0.70</p>
+<ul class="simple">
+<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
+a little TAL-ish DOM templating attribute language.</li>
+<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
+ignore requests with status == 0, which seems to happen for cached or local
+requests</li>
+<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
+<li>Changed scrapeText API to return a string by default. This is API-breaking!
+It was dumb to have the default return value be the form you almost never
+want. Sorry.</li>
+<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
+(where previously you'd likely get a DOM exception).</li>
+<li>Added three new functions to MochiKit.Base for dealing with URL query
+strings: urlEncode, queryString, parseQueryString</li>
+<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
+starts with &quot;on&quot; (e.g. &quot;onclick&quot;). If v is a string, it will set it to
+new Function(v).</li>
+<li>Another workaround for Internet &quot;worst browser ever&quot; Explorer's setAttribute
+usage in MochiKit.DOM.createDOM (checked -&gt; defaultChecked).</li>
+<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
+<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
+now!</li>
+</ul>
+<p>2005-07-29      v0.60</p>
+<ul class="simple">
+<li>Beefed up the MochiKit.DOM test suite</li>
+<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
+false unexpectedly before</li>
+<li>Added an optional &quot;parent&quot; argument to
+MochiKit.DOM.getElementsByTagAndClassName</li>
+<li>Added a &quot;packed&quot; version in packed/MochiKit/MochiKit.js</li>
+<li>Changed build script to rewrite the URLs in tests to account for the
+JSAN-required reorganization</li>
+<li>MochiKit.Compat to potentially work around IE 5.5 issues
+(5.0 still not supported). Test.Simple doesn't seem to work there,
+though.</li>
+<li>Several minor documentation corrections</li>
+</ul>
+<p>2005-07-27      v0.50</p>
+<ul class="simple">
+<li>Initial Release</li>
+</ul>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/Visual.html b/mochikit_v14/doc/html/MochiKit/Visual.html
new file mode 100644 (file)
index 0000000..234c82f
--- /dev/null
@@ -0,0 +1,699 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4.1: http://docutils.sourceforge.net/" />
+<title>MochiKit.Visual - visual effects</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="name" name="name">Name</a></h1>
+<p>MochiKit.Visual - visual effects</p>
+</div>
+<div class="section">
+<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
+<pre class="literal-block">
+// round the corners of all h1 elements
+roundClass(&quot;h1&quot;, null);
+
+// round the top left corner of the element with the id &quot;title&quot;
+roundElement(&quot;title&quot;, {corners: &quot;tl&quot;});
+
+// Add an fade effect to an element
+fade('myelement');
+</pre>
+</div>
+<div class="section">
+<h1><a id="description" name="description">Description</a></h1>
+<p>MochiKit.Visual provides visual effects and support functions for
+visuals.</p>
+</div>
+<div class="section">
+<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
+<ul class="simple">
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
+<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
+<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a></li>
+<li><a class="mochiref reference" href="Position.html">MochiKit.Position</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<p>MochiKit.Visual provides different visual effect: rounded corners and
+animations for your HTML elements. Rounded corners are created
+completely through CSS manipulations and require no external images or
+style sheets.  This implementation was adapted from <a class="reference" href="http://www.openrico.org">Rico</a>. Dynamic
+effects are ported from <a class="reference" href="http://script.aculo.us">Scriptaculous</a>.</p>
+</div>
+<div class="section">
+<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
+<div class="section">
+<h2><a id="functions" name="functions">Functions</a></h2>
+<p>
+<a name="fn-roundclass"></a>
+<a class="mochidef reference" href="#fn-roundclass">roundClass(tagName[, className[, options]])</a>:</p>
+<blockquote>
+<p>Rounds all of the elements that match the <tt class="docutils literal"><span class="pre">tagName</span></tt> and
+<tt class="docutils literal"><span class="pre">className</span></tt> specifiers, using the options provided.  <tt class="docutils literal"><span class="pre">tagName</span></tt>
+or <tt class="docutils literal"><span class="pre">className</span></tt> can be <tt class="docutils literal"><span class="pre">null</span></tt> to match all tags or classes.
+For more information about the options, see the
+<a class="mochiref reference" href="#fn-roundelement">roundElement</a> function.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-roundelement"></a>
+<a class="mochidef reference" href="#fn-roundelement">roundElement(element[, options])</a>:</p>
+<blockquote>
+<p>Immediately round the corners of the specified element.  The
+element can be given as either a string with the element ID, or as
+an element object.</p>
+<p>The options mapping has the following defaults:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="35%" />
+<col width="65%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>corners</td>
+<td><tt class="docutils literal"><span class="pre">&quot;all&quot;</span></tt></td>
+</tr>
+<tr><td>color</td>
+<td><tt class="docutils literal"><span class="pre">&quot;fromElement&quot;</span></tt></td>
+</tr>
+<tr><td>bgColor</td>
+<td><tt class="docutils literal"><span class="pre">&quot;fromParent&quot;</span></tt></td>
+</tr>
+<tr><td>blend</td>
+<td><tt class="docutils literal"><span class="pre">true</span></tt></td>
+</tr>
+<tr><td>border</td>
+<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
+</tr>
+<tr><td>compact</td>
+<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
+</tr>
+</tbody>
+</table>
+<p>corners:</p>
+<blockquote>
+<p>specifies which corners of the element should be rounded.
+Choices are:</p>
+<ul class="simple">
+<li>all</li>
+<li>top</li>
+<li>bottom</li>
+<li>tl (top left)</li>
+<li>bl (bottom left)</li>
+<li>tr (top right)</li>
+<li>br (bottom right)</li>
+</ul>
+<dl class="docutils">
+<dt>Example:</dt>
+<dd><tt class="docutils literal"><span class="pre">&quot;tl</span> <span class="pre">br&quot;</span></tt>: top-left and bottom-right corners are rounded</dd>
+</dl>
+</blockquote>
+<dl class="docutils">
+<dt>blend:</dt>
+<dd>specifies whether the color and background color should be
+blended together to produce the border color.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.3.1+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-toggle"></a>
+<a class="mochidef reference" href="#fn-toggle">toggle(element[, effect[, options]])</a>:</p>
+<blockquote>
+<p>Toggle an element between visible and invisible state using an effect.</p>
+<dl class="docutils">
+<dt>effect:</dt>
+<dd>One of the visual pairs to use, between 'slide', 'blind',
+'appear', and 'size'.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-tagifytext"></a>
+<a class="mochidef reference" href="#fn-tagifytext">tagifyText(element[, tagifyStyle])</a>:</p>
+<blockquote>
+<p>Transform a node text into nodes containing one letter by tag.</p>
+<dl class="docutils">
+<dt>tagifyStyle:</dt>
+<dd>style to apply to character nodes, default to 'position:
+relative'.</dd>
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-multiple"></a>
+<a class="mochidef reference" href="#fn-multiple">multiple(elements, effect[, options])</a>:</p>
+<blockquote>
+<p>Launch the same effect on a list of elements.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="basic-effects-classes" name="basic-effects-classes">Basic Effects classes</a></h2>
+<p>
+<a name="fn-defaultoptions"></a>
+<a class="mochidef reference" href="#fn-defaultoptions">DefaultOptions</a>:</p>
+<blockquote>
+<p>Default options for all Effect creation.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="22%" />
+<col width="78%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>transition</td>
+<td><tt class="docutils literal"><span class="pre">MochiKit.Visual.Transitions.sinoidal</span></tt></td>
+</tr>
+<tr><td>duration</td>
+<td><tt class="docutils literal"><span class="pre">1.0</span></tt></td>
+</tr>
+<tr><td>fps</td>
+<td><tt class="docutils literal"><span class="pre">25.0</span></tt></td>
+</tr>
+<tr><td>sync</td>
+<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
+</tr>
+<tr><td>from</td>
+<td><tt class="docutils literal"><span class="pre">0.0</span></tt></td>
+</tr>
+<tr><td>to</td>
+<td><tt class="docutils literal"><span class="pre">1.0</span></tt></td>
+</tr>
+<tr><td>delay</td>
+<td><tt class="docutils literal"><span class="pre">0.0</span></tt></td>
+</tr>
+<tr><td>queue</td>
+<td><tt class="docutils literal"><span class="pre">'parallel'</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-base"></a>
+<a class="mochidef reference" href="#fn-base">Base()</a>:</p>
+<blockquote>
+<p>Base class to all effects. Define a basic looping service, use it
+for creating new effects.</p>
+<p>You can override the methods <tt class="docutils literal"><span class="pre">setup</span></tt>, <tt class="docutils literal"><span class="pre">update</span></tt> and <tt class="docutils literal"><span class="pre">finish`</span></tt>.</p>
+<p>The class defines a number of events that will be called during effect
+life. The events are:</p>
+<ul class="simple">
+<li>beforeStart</li>
+<li>beforeSetup</li>
+<li>beforeUpdate</li>
+<li>afterUpdate</li>
+<li>beforeFinish</li>
+<li>afterFinish</li>
+</ul>
+<p>If you want to define your own callbacks, define it in the options
+parameter of the effect. Example:</p>
+<pre class="literal-block">
+// I slide it up and then down again
+slideUp('myelement', {afterFinish: function () {
+    slideDown('myelement');
+});
+</pre>
+<p>Specific <tt class="docutils literal"><span class="pre">internal</span></tt> events are also available: for each one abone the
+same exists with 'Internal' (example: 'beforeStartInternal'). Their purpose
+is mainly for creating your own effect and keep the user access to event
+callbacks (not overriding the library ones).</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-parallel"></a>
+<a class="mochidef reference" href="#fn-parallel">Parallel(effects [, options])</a>:</p>
+<blockquote>
+<p>Launch effects in parallel.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-opacity"></a>
+<a class="mochidef reference" href="#fn-opacity">Opacity(element [, options])</a>:</p>
+<blockquote>
+<p>Change the opacity of an element progressively.</p>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="43%" />
+<col width="57%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>from</td>
+<td><tt class="docutils literal"><span class="pre">0.0</span></tt></td>
+</tr>
+<tr><td>to</td>
+<td><tt class="docutils literal"><span class="pre">1.0</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-move"></a>
+<a class="mochidef reference" href="#fn-move">Move(element [, options])</a>:</p>
+<blockquote>
+<p>Change the position of an element in small steps, creating a
+moving effect.</p>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="36%" />
+<col width="64%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>x</td>
+<td><tt class="docutils literal"><span class="pre">0</span></tt></td>
+</tr>
+<tr><td>y</td>
+<td><tt class="docutils literal"><span class="pre">0</span></tt></td>
+</tr>
+<tr><td>position</td>
+<td><tt class="docutils literal"><span class="pre">'relative'</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-scale"></a>
+<a class="mochidef reference" href="#fn-scale">Scale(element, percent [, options])</a>:</p>
+<blockquote>
+<p>Change the size of an element.</p>
+<dl class="docutils">
+<dt>percent:</dt>
+<dd>Final wanted size in percent of current size. The size will be
+reduced if the value is between 0 and 100, and raised if the
+value is above 100.</dd>
+</dl>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="57%" />
+<col width="43%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>scaleX</td>
+<td><tt class="docutils literal"><span class="pre">true</span></tt></td>
+</tr>
+<tr><td>scaleY</td>
+<td><tt class="docutils literal"><span class="pre">true</span></tt></td>
+</tr>
+<tr><td>scaleContent</td>
+<td><tt class="docutils literal"><span class="pre">true</span></tt></td>
+</tr>
+<tr><td>scaleFromCenter</td>
+<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
+</tr>
+<tr><td>scaleMode</td>
+<td><tt class="docutils literal"><span class="pre">'box'</span></tt></td>
+</tr>
+<tr><td>scaleFrom</td>
+<td><tt class="docutils literal"><span class="pre">100.0</span></tt></td>
+</tr>
+<tr><td>scaleTo</td>
+<td><tt class="docutils literal"><span class="pre">percent</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-highlight"></a>
+<a class="mochidef reference" href="#fn-highlight">Highlight(element [, options])</a>:</p>
+<blockquote>
+<p>Highlight an element, flashing with one color.</p>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="44%" />
+<col width="56%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>startcolor</td>
+<td><tt class="docutils literal"><span class="pre">'#ffff99'</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-scrollto"></a>
+<a class="mochidef reference" href="#fn-scrollto">ScrollTo(element [, options])</a>:</p>
+<blockquote>
+<p>Scroll the window to the position of the given element.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-morph"></a>
+<a class="mochidef reference" href="#fn-morph">Morph(element [, options])</a>:</p>
+<blockquote>
+<p>Make a transformation to the given element. It's called with the option
+<tt class="docutils literal"><span class="pre">style</span></tt> with an array holding the styles to change. It works with
+properties for size (<tt class="docutils literal"><span class="pre">font-size</span></tt>, <tt class="docutils literal"><span class="pre">border-width</span></tt>, ...) and properties
+for color (<tt class="docutils literal"><span class="pre">color</span></tt>, <tt class="docutils literal"><span class="pre">background-color</span></tt>, ...).</p>
+<p>For size, it's better to have defined the original style. You <em>must</em>
+use the same unit in the call to Morph (no translation exists between two
+different units).</p>
+<p>Parsed length are postfixed with: em, ex, px, in, cm, mm, pt, pc.</p>
+<p>Example:</p>
+<pre class="literal-block">
+&lt;div id=&quot;foo&quot; style=&quot;font-size: 1em&quot;&gt;MyDiv&lt;/div&gt;
+...
+Morph(&quot;foo&quot;, {&quot;style&quot;: {&quot;font-size&quot;: &quot;2em&quot;}});
+</pre>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="combination-effects" name="combination-effects">Combination Effects</a></h2>
+<p>
+<a name="fn-fade"></a>
+<a class="mochidef reference" href="#fn-fade">fade(element [, options])</a>:</p>
+<blockquote>
+<p>Change the opacity of an element until making it disappear.</p>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="12%" />
+<col width="88%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>from</td>
+<td><tt class="docutils literal"><span class="pre">element.opacity</span> <span class="pre">||</span> <span class="pre">1.0</span></tt></td>
+</tr>
+<tr><td>to</td>
+<td><tt class="docutils literal"><span class="pre">0.0</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-appear"></a>
+<a class="mochidef reference" href="#fn-appear">appear(element [, options])</a>:</p>
+<blockquote>
+<p>Slowly show an invisible element.</p>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="36%" />
+<col width="64%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>from</td>
+<td><tt class="docutils literal"><span class="pre">0.0</span></tt></td>
+</tr>
+<tr><td>to</td>
+<td><tt class="docutils literal"><span class="pre">1.0</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-puff"></a>
+<a class="mochidef reference" href="#fn-puff">puff(element [, options])</a>:</p>
+<blockquote>
+<p>Make an element double size, and then make it disappear.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-blindup"></a>
+<a class="mochidef reference" href="#fn-blindup">blindUp(element [, options])</a>:</p>
+<blockquote>
+<p>Blind an element up, changing its vertical size to 0.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-blinddown"></a>
+<a class="mochidef reference" href="#fn-blinddown">blindDown(element [, options])</a>:</p>
+<blockquote>
+<p>Blind an element down, restoring its vertical size.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-switchoff"></a>
+<a class="mochidef reference" href="#fn-switchoff">switchOff(element [, options])</a>:</p>
+<blockquote>
+<p>A switch-off like effect, making the element disappear.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-dropout"></a>
+<a class="mochidef reference" href="#fn-dropout">dropOut(element [, options])</a>:</p>
+<blockquote>
+<p>Make the element fall and fade.</p>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="53%" />
+<col width="47%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>distance</td>
+<td><tt class="docutils literal"><span class="pre">100</span></tt></td>
+</tr>
+</tbody>
+</table>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-shake"></a>
+<a class="mochidef reference" href="#fn-shake">shake(element [, options])</a>:</p>
+<blockquote>
+<p>Shake an element from left to right.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-slidedown"></a>
+<a class="mochidef reference" href="#fn-slidedown">slideDown(element [, options])</a>:</p>
+<blockquote>
+<p>Slide an element down.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-slideup"></a>
+<a class="mochidef reference" href="#fn-slideup">slideUp(element [, options])</a>:</p>
+<blockquote>
+<p>Slide an element up.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-squish"></a>
+<a class="mochidef reference" href="#fn-squish">squish(element [, options])</a>:</p>
+<blockquote>
+<p>Reduce the horizontal and vertical sizes at the same time, using
+the top left corner.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-grow"></a>
+<a class="mochidef reference" href="#fn-grow">grow(element [, options])</a>:</p>
+<blockquote>
+<p>Restore the size of an element.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-shrink"></a>
+<a class="mochidef reference" href="#fn-shrink">shrink(element [, options])</a>:</p>
+<blockquote>
+<p>Shrink an element to its center.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-pulsate"></a>
+<a class="mochidef reference" href="#fn-pulsate">pulsate(element [, options])</a>:</p>
+<blockquote>
+<p>Switch an element between appear and fade.</p>
+<p>options:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="43%" />
+<col width="57%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>pulses</td>
+<td><tt class="docutils literal"><span class="pre">null</span></tt></td>
+</tr>
+</tbody>
+</table>
+<p>pulses controls the number of pulses made during the effect.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+<p>
+<a name="fn-fold"></a>
+<a class="mochidef reference" href="#fn-fold">fold(element [, options])</a>:</p>
+<blockquote>
+<p>Reduce first the vertical size, and then the horizontal size.</p>
+<dl class="docutils">
+<dt><em>Availability</em>:</dt>
+<dd>Available in MochiKit 1.4+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="the-effects-queue" name="the-effects-queue">The Effects Queue</a></h2>
+<p>When you create effects based on user input (mouse clicks for example), it can
+create conflicts between the effects if multiple effects are running at the
+same time. To manage this problem, the Queue mechanism has been introduced:
+it's responsible for running the effects as you desired.</p>
+<p>By default, you have one Queue called 'global', and the effects run in 'parallel'
+(see default options). Every effects have a queue option to customize this.
+It can be a string, the scope is then global:</p>
+<ul class="simple">
+<li><cite>start</cite>: the effect will be run before any other;</li>
+<li><cite>end</cite>: the effect will be run after any other;</li>
+<li><cite>break</cite>: every other effects break when the the effect start;</li>
+<li><cite>parallel</cite>: the effect run normally with others.</li>
+</ul>
+<p>But you have even more control if you use an array with the following keys:</p>
+<ul class="simple">
+<li><cite>position</cite> takes a value listed above;</li>
+<li><cite>scope</cite> manages how the information has to be taken. If it's <cite>global</cite>
+then it's the same information for every effects. Otherwise you can define
+your own scode. For example, if you add an effect on a specified element,
+you may use the element id as scode;</li>
+<li><cite>limit</cite> defines how many effects can run in the current scode. If an
+effect is added whereas the limit is reached, it will never be run (it's
+lost).</li>
+</ul>
+</div>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<table class="docutils footnote" frame="void" id="id1" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id1">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id2">[2]</a></td><td>SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id3">[3]</a></td><td>W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="authors" name="authors">Authors</a></h1>
+<ul class="simple">
+<li>Kevin Dangoor &lt;<a class="reference" href="mailto:dangoor&#64;gmail.com">dangoor&#64;gmail.com</a>&gt;</li>
+<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
+<li>Thomas Herve &lt;<a class="reference" href="mailto:therve&#64;gmail.com">therve&#64;gmail.com</a>&gt;</li>
+<li>Round corners originally adapted from Rico &lt;<a class="reference" href="http://openrico.org/">http://openrico.org/</a>&gt;
+(though little remains)</li>
+<li>Effects originally adapted from Script.aculo.us
+&lt;<a class="reference" href="http://script.aculo.us/">http://script.aculo.us/</a>&gt;</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;.  This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+<p>Portions adapted from <a class="reference" href="http://www.openrico.org">Rico</a> are available under the terms of the
+<a class="reference" href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, Version 2.0</a>.</p>
+<p>Portions adapted from <a class="reference" href="http://script.aculo.us">Scriptaculous</a> are available under the terms
+of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/html/MochiKit/index.html b/mochikit_v14/doc/html/MochiKit/index.html
new file mode 100644 (file)
index 0000000..ca62d38
--- /dev/null
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>MochiKit Documentation Index</title>
+
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+<div class="document">
+<div class="section">
+<h1><a id="distribution" name="distribution">Distribution</a></h1>
+<p>MochiKit - makes JavaScript suck a bit less</p>
+<ul class="simple">
+<li><a class="mochiref reference" href="Async.html">MochiKit.Async</a> - manage asynchronous tasks</li>
+<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a> - functional programming and useful comparisons</li>
+<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a> - painless DOM manipulation API</li>
+<li><a class="mochiref reference" href="DragAndDrop.html">MochiKit.DragAndDrop</a> - drag and drop</li>
+<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a> - color abstraction with CSS3 support</li>
+<li><a class="mochiref reference" href="DateTime.html">MochiKit.DateTime</a> - &quot;what time is it anyway?&quot;</li>
+<li><a class="mochiref reference" href="Format.html">MochiKit.Format</a> - string formatting goes here</li>
+<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a> - itertools for JavaScript; iteration made HARD,
+and then easy</li>
+<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> - we're all tired of <tt class="docutils literal"><span class="pre">alert()</span></tt></li>
+<li><a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> - interactive <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a>
+pane</li>
+<li><a class="mochiref reference" href="Selector.html">MochiKit.Selector</a> - selecting elements by CSS selector syntax</li>
+<li><a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> - simple universal event handling</li>
+<li><a class="mochiref reference" href="Style.html">MochiKit.Style</a> - painless CSS manipulation API</li>
+<li><a class="mochiref reference" href="Sortable.html">MochiKit.Sortable</a> - sortable</li>
+<li><a class="mochiref reference" href="Visual.html">MochiKit.Visual</a> - visual effects</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="notes" name="notes">Notes</a></h1>
+<p>To turn off MochiKit's export feature (which may be necessary for
+compatibility with some existing code), do this before loading
+MochiKit:</p>
+<pre class="literal-block">
+&lt;script type=&quot;text/javascript&quot;&gt;MochiKit = {__export__: false};&lt;/script&gt;
+</pre>
+<p>When export mode is off, you must use fully qualified names for
+all MochiKit functions (e.g. <tt class="docutils literal"><span class="pre">MochiKit.Base.map(...)</span></tt>).</p>
+</div>
+<div class="section">
+<h1><a id="screencasts" name="screencasts">Screencasts</a></h1>
+<ul class="simple">
+<li><a class="reference" href="http://mochikit.com/screencasts/MochiKit_Intro-1">MochiKit 1.1 Intro</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="see-also" name="see-also">See Also</a></h1>
+<ul class="simple">
+<li><a class="reference" href="http://groups.google.com/group/mochikit">Google Groups: MochiKit</a>: The official mailing list for discussions
+related to development of and with MochiKit</li>
+<li><a class="reference" href="http://mochikit.com/">mochikit.com</a>: MochiKit's home on the web</li>
+<li><a class="reference" href="http://bob.pythonmac.org/">from __future__ import *</a>: Bob Ippolito's blog</li>
+<li><a class="reference" href="http://openjsan.org/doc/b/bo/bob/MochiKit/">MochiKit on JSAN</a>: the JSAN distribution page for MochiKit</li>
+<li><a class="reference" href="http://del.icio.us/tag/mochikit">MochiKit tag on del.icio.us</a>: Recent bookmarks related to MochiKit</li>
+<li><a class="reference" href="http://technorati.com/tag/mochikit">MochiKit tag on Technorati</a>: Recent blog entries related to MochiKit</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="version-history" name="version-history">Version History</a></h1>
+<p>2006-XX-XX      v1.4</p>
+<ul class="simple">
+<li>MochiKit.Color's HSV to RGB conversion code fixed to return the correct
+value (hsv.v for RGB values) in cases where saturation === 0.</li>
+<li>doXHR workaround for a Mozilla bug when calling XMLHttpRequest in certain
+situations. Always wraps call in a callLater(0, doXHR, url, opts).</li>
+<li>parseQueryString will now parse values with embedded &quot;=&quot;</li>
+<li>Workaround for a Safari DOM crash when using MochiKit.Iter.list.
+<a class="reference" href="http://bugs.webkit.org/show_bug.cgi?id=12191">http://bugs.webkit.org/show_bug.cgi?id=12191</a></li>
+<li>New removeNodeAttribute function in MochiKit.DOM.</li>
+<li>MochiKit.Async.doXHR and dependent functions now accept 201 CREATED and
+204 NO CONTENT as valid.</li>
+<li>MochiKit.DOM.formContents now treats option tags the same way that
+form posts do in the case of missing and empty string value attributes,
+even in IE.</li>
+<li>MochiKit.Base.queryString now accepts third queryString([names, values])
+form.</li>
+<li>MochiKit.DOM.formContents now defaults to document.body if no element is
+given.</li>
+<li>New MochiKit.Selector module</li>
+<li>MochiKit.LoggingPane fixes for Internet Explorer</li>
+<li>MochiKit.DOM now creates XHTML nodes in XUL documents.</li>
+<li>MochiKit.LoggingPane now works on pages with '#' in the URL on IE</li>
+<li>New MochiKit.Async.doXHR as a convenient method for doing custom
+XMLHttpRequests (e.g. extra headers, overrideMimeType, etc.)</li>
+<li>New __connect__ protocol for MochiKit.Signal.connect source notifications</li>
+<li>Added colSpan, bgColor to the list of DOM renames for Internet Explorer</li>
+<li>New MochiKit.Signal.disconnectAllTo function</li>
+<li>MochiKit.Base.parseQueryString now accepts leading question mark</li>
+<li>New MochiKit.Base.values function</li>
+<li>Fixed MochiKit.Signal.disconnect when called from a signal handler invoked
+by MochiKit.Signal.signal</li>
+<li>parseQueryString now splits on HTML entities equivalent to ampersand as well</li>
+<li>Better XHTML compatibility (removed obvious cases where uppercase tagName or
+nodeName was assumed)</li>
+<li>MochiKit.Base.queryString now handles array values in the same way HTML
+forms handle multiple elements of the same name.</li>
+<li>MochiKit.Base.parseQueryString now returns {} for empty query string instead
+of {&quot;&quot;: &quot;undefined&quot;}</li>
+<li>MochiKit.DOM.formContents now handles option value=&quot;&quot; correctly.</li>
+<li>MochiKit.DOM now checks for undefined className.</li>
+<li>MochiKit.Iter.groupby() now uses compare() to group rather than == and !=</li>
+<li>serializeJSON no longer serializes undefined, as per the JSON spec</li>
+<li>Fixed an infinite recursion bug in serializeJSON if an adapter
+returns the object itself.</li>
+<li>New MochiKit.Base.operator.seq and sne to support strict comparison</li>
+<li>MochiKit.Base.isArrayLike no longer returns true for DOM text nodes</li>
+<li>Added readonly-readOnly to the list of DOM renames for Internet Explorer</li>
+<li>New MochiKit.Signal event method: confirmUnload (sets returnValue for
+onbeforeunload)</li>
+<li>Fix interpreter help() function for Firefox and IE</li>
+<li>API version compatibility notes added</li>
+<li>New MochiKit.Base functions methodcaller and compose</li>
+<li>Support IE-based native console logging (Debugger, Atlas)</li>
+<li>Refactored style functions from MochiKit.DOM to MochiKit.Style</li>
+<li>MochiKit.Async.DeferredList is now a proper Deferred</li>
+<li>MochiKit.DOM.formContents now supports SELECT multiple tags</li>
+<li>Re-use StopIteration Error if the browser already has it</li>
+<li>Workaround IE type=&quot;&quot; bug for INPUT elements</li>
+<li>Allow LoggingPane to work in IE with hyphen-containing URLs</li>
+<li>Replace percents for Safari native logging to avoid crashing</li>
+<li>New MochiKit.DOM.coerceToDOM .dom(node) / .__dom__(node) protocol</li>
+<li>MochiKit.DOM's MochiKit.Iter dependency is now optional</li>
+<li>Added expand all link to the documentation index</li>
+<li>Added MochiKit.DOM.isChildNode</li>
+<li>Added synthesizing for onmouseenter/onmouseleave</li>
+</ul>
+<p>2006-04-29      v1.3.1 (bug fix release)</p>
+<ul class="simple">
+<li>Fix sendXMLHttpRequest sendContent regression</li>
+<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
+<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
+</ul>
+<p>2006-04-26      v1.3 &quot;warp zone&quot;</p>
+<ul class="simple">
+<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
+<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
+<li>New MochiKit.Base.method as a convenience form of bind that takes the
+object before the method</li>
+<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
+a single Array</li>
+<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
+<li>New key_events example demonstrating use of MochiKit.Signal's key handling
+capabilities.</li>
+<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
+null is used and the string will be considered the first node. This
+allows for the more natural P(&quot;foo&quot;) rather than P(null, &quot;foo&quot;).</li>
+<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
+provides multi-line input and a help() function to get MochiKit function
+signature from the documentation.</li>
+<li>Native Console Logging for the default MochiKit.Logging logger</li>
+<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
+<li>New MochiKit.Signal example: draggable</li>
+<li>Added sanity checking to Deferred to ensure that errors happen when chaining
+is used incorrectly</li>
+<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
+<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
+component values smaller than 16/255.</li>
+<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
+maximum size</li>
+<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
+Error, so that the errback chain is used instead of the callback chain.</li>
+<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
+in the correct order.</li>
+<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
+<li>MochiKit.Base.isNull no longer matches undefined</li>
+<li>example doctypes changed to HTML4</li>
+<li>isDateLike no longer throws error on null</li>
+<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
+<li>updated elementDimensions to calculate width from offsetWidth instead
+of clientWidth</li>
+<li>formContents now works with FORM tags that have a name attribute</li>
+<li>Documentation now uses MochiKit to generate a function index</li>
+</ul>
+<p>2006-01-26      v1.2 &quot;the ocho&quot;</p>
+<ul class="simple">
+<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
+<li>Added new MochiKit.Base.findIdentical function to find the index of an
+element in an Array-like object. Uses === for identity comparison.</li>
+<li>Added new MochiKit.Base.find function to find the index of an element in
+an Array-like object. Uses compare for rich comparison.</li>
+<li>MochiKit.Base.bind will accept a string for func, which will be immediately
+looked up as self[func].</li>
+<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
+compatibility</li>
+<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
+<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
+height of an element in the document</li>
+<li>MochiKit.DOM's initialization is now compatible with
+HTMLUnit + JWebUnit + Rhino</li>
+<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
+currently in the document instead of always creating one.</li>
+<li>MochiKit.Base now has operator.mul</li>
+<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
+a custom value attribute</li>
+<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
+<li>MochiKit.DOM.setNodeAttribute should work now</li>
+<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
+property to a string</li>
+<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
+name and for properties</li>
+<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
+<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
+<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
+<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
+<li>Added new MochiKit.DOM documentation on element visibility</li>
+<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
+for determining the position of an element in the document</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
+</ul>
+<p>2005-11-14      v1.1</p>
+<ul class="simple">
+<li>Fixed a bug in numberFormatter with large numbers</li>
+<li>Massively overhauled documentation</li>
+<li>Fast-path for primitives in MochiKit.Base.compare</li>
+<li>New groupby and groupby_as_array in MochiKit.Iter</li>
+<li>Added iterator factory adapter for objects that implement iterateNext()</li>
+<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
+LEGEND, FIELDSET</li>
+<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
+<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
+<li>MochiKit.LoggingPane now uses named windows based on the URL so that
+a given URL will get the same LoggingPane window after a reload
+(at the same position, etc.)</li>
+<li>MochiKit.DOM now has currentWindow() and currentDocument() context
+variables that are set with withWindow() and withDocument(). These
+context variables affect all MochiKit.DOM functionality (getElement,
+createDOM, etc.)</li>
+<li>MochiKit.Base.items will now catch and ignore exceptions for properties
+that are enumerable but not accessible (e.g. permission denied)</li>
+<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
+now accept additional arguments that are used to create a partially
+applied function. This differs from Twisted in that the callback/errback
+result becomes the <em>last</em> argument, not the first when this feature
+is used.</li>
+<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
+arguments which are used to create a GET query string</li>
+<li>Did some refactoring to reduce the footprint of MochiKit by a few
+kilobytes</li>
+<li>escapeHTML to longer escapes ' (apos) and now uses
+String.replace instead of iterating over every char.</li>
+<li>Added DeferredLock to Async</li>
+<li>Renamed getElementsComputedStyle to computedStyle and moved
+it from MochiKit.Visual to MochiKit.DOM</li>
+<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
+<li>Fixed range() to accept a negative step</li>
+<li>New alias to MochiKit.swapDOM called removeElement</li>
+<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
+an attribute on a node without raising, roughly equivalent to:
+updateNodeAttributes(node, {attr: value})</li>
+<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
+a node's attribute or returns null without raising</li>
+<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
+directly (addLoadEvent did not leak, since it clears the handler)</li>
+</ul>
+<p>2005-10-24      v1.0</p>
+<ul class="simple">
+<li>New interpreter example that shows usage of MochiKit.DOM  to make
+an interactive JavaScript interpreter</li>
+<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
+debuggingBookmarklet, with logging_pane example to show its usage</li>
+<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
+in order to provide a live regular expression matching tool</li>
+<li>Added advanced number formatting capabilities to MochiKit.Format:
+numberFormatter(pattern, placeholder=&quot;&quot;, locale=&quot;default&quot;) and
+formatLocale(locale=&quot;default&quot;)</li>
+<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
+MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
+<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
+to MochiKit.Format</li>
+<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
+isoTimestamp(isoString) will convert them to Date objects, and
+toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
+<li>Fixed missing errback for sendXMLHttpRequest when the server does not
+respond</li>
+<li>Fixed infinite recusion bug when using roundClass(&quot;DIV&quot;, ...)</li>
+<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
+from being cancelled properly</li>
+<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
+have an apply method, such as alert</li>
+<li>Reliably return null from the string parsing/manipulation functions if
+the input can't be coerced to a string (s + &quot;&quot;) or the input makes no sense;
+e.g. isoTimestamp(null) and isoTimestamp(&quot;&quot;) return null</li>
+</ul>
+<p>2005-10-08      v0.90</p>
+<ul class="simple">
+<li>Fixed ISO compliance with toISODate</li>
+<li>Added missing operator.sub</li>
+<li>Placated Mozilla's strict warnings a bit</li>
+<li>Added JSON serialization and unserialization support to MochiKit.Base:
+serializeJSON, evalJSON, registerJSON. This is very similar to the repr
+API.</li>
+<li>Fixed a bug in the script loader that failed in some scenarios when a script
+tag did not have a &quot;src&quot; attribute (thanks Ian!)</li>
+<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
+P, FORM</li>
+<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
+and parseQueryString, when available.</li>
+</ul>
+<p>2005-08-12      v0.80</p>
+<ul class="simple">
+<li>Source highlighting in all examples, moved to a view-source example</li>
+<li>Added some experimental syntax highlighting for the Rounded Corners example,
+via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
+<li>Use an indirect binding for the logger conveniences, so that the global
+logger could be replaced by setting MochiKit.Logger.logger to something else
+(though an observer is probably a better choice).</li>
+<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
+which will be looked up with getElement</li>
+<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
+node.parentNode)</li>
+<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
+<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
+<li>Possible workaround for Safari issue with swapDOM, where it would get
+confused because two elements were in the DOM at the same time with the
+same id</li>
+<li>Added missing THEAD convenience function to MochiKit.DOM</li>
+<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
+<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
+MochiKit.DOM</li>
+<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
+<li>Added HSV color space support to MochiKit.Visual</li>
+<li>Fixed a bug in the sortable_tables example, it now converts types
+correctly</li>
+<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
+scope</li>
+</ul>
+<p>2005-08-04      v0.70</p>
+<ul class="simple">
+<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
+a little TAL-ish DOM templating attribute language.</li>
+<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
+ignore requests with status == 0, which seems to happen for cached or local
+requests</li>
+<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
+<li>Changed scrapeText API to return a string by default. This is API-breaking!
+It was dumb to have the default return value be the form you almost never
+want. Sorry.</li>
+<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
+(where previously you'd likely get a DOM exception).</li>
+<li>Added three new functions to MochiKit.Base for dealing with URL query
+strings: urlEncode, queryString, parseQueryString</li>
+<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
+starts with &quot;on&quot; (e.g. &quot;onclick&quot;). If v is a string, it will set it to
+new Function(v).</li>
+<li>Another workaround for Internet &quot;worst browser ever&quot; Explorer's setAttribute
+usage in MochiKit.DOM.createDOM (checked -&gt; defaultChecked).</li>
+<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
+<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
+now!</li>
+</ul>
+<p>2005-07-29      v0.60</p>
+<ul class="simple">
+<li>Beefed up the MochiKit.DOM test suite</li>
+<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
+false unexpectedly before</li>
+<li>Added an optional &quot;parent&quot; argument to
+MochiKit.DOM.getElementsByTagAndClassName</li>
+<li>Added a &quot;packed&quot; version in packed/MochiKit/MochiKit.js</li>
+<li>Changed build script to rewrite the URLs in tests to account for the
+JSAN-required reorganization</li>
+<li>MochiKit.Compat to potentially work around IE 5.5 issues
+(5.0 still not supported). Test.Simple doesn't seem to work there,
+though.</li>
+<li>Several minor documentation corrections</li>
+</ul>
+<p>2005-07-27      v0.50</p>
+<ul class="simple">
+<li>Initial Release</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="copyright" name="copyright">Copyright</a></h1>
+<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License
+v2.1</a>.</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/doc/js/toc.js b/mochikit_v14/doc/js/toc.js
new file mode 100644 (file)
index 0000000..46b0fc8
--- /dev/null
@@ -0,0 +1,113 @@
+function function_ref(fn) {
+    return A({"href": fn[1], "class": "mochiref reference"}, fn[0], BR());
+};
+
+function toggle_docs() {
+    toggleElementClass("invisible", "show_index", "function_index");
+    return false;
+};
+
+function create_toc() {
+    if (getElement("distribution")) {
+        return global_index();
+    } 
+    if (getElement("api-reference")) {
+        return module_index();
+    }
+};
+
+function doXHTMLRequest(url) {
+    var d = doXHR(url, {mimeType: 'text/xml'});
+    return d.addCallback(function (res) {
+        if (res.responseXML.documentElement) {
+            return res.responseXML.documentElement;
+        } else {
+            var container = document.createElement('div');
+            container.innerHTML = res.responseText;
+            return container;
+        }
+    });
+};
+
+function load_request(href, div, doc) {
+    var functions = withDocument(doc, spider_doc);
+    forEach(functions, function (func) {
+        // fix anchors
+        if (func[1].charAt(0) == "#") {
+            func[1] = href + func[1];
+        } else if (func[1].lastIndexOf("#") != -1) {
+            func[1] = href + "#" + func[1].split("#")[1];
+        }
+    });
+    var showLink = A({"class": "force-pointer"}, "[+]");
+    var hideLink = A({"class": "force-pointer"}, "[\u2013]");
+    var functionIndex = DIV({"id": "function_index", "class": "invisible"},
+        hideLink,
+        P(null, map(function_ref, functions))
+    );
+    var toggleFunc = function (e) {
+        toggleElementClass("invisible", showLink, functionIndex);
+    };
+    connect(showLink, "onclick", toggleFunc);
+    connect(hideLink, "onclick", toggleFunc);
+    replaceChildNodes(div,
+        showLink,
+        functionIndex
+    );
+    return [showLink, toggleFunc];
+};
+
+function global_index() {
+    var distList = getElementsByTagAndClassName("ul")[0];
+    var bullets = getElementsByTagAndClassName("li", null, distList);
+    var lst = [];
+    for (var i = 0; i < bullets.length; i++) {
+        var tag = bullets[i];
+        var firstLink = getElementsByTagAndClassName("a", "mochiref", tag)[0];
+        var href = getNodeAttribute(firstLink, "href");
+        var div = DIV(null, "[\u2026]");
+        appendChildNodes(tag, BR(), div);
+        lst.push(doXHTMLRequest(href).addCallback(load_request, href, div));
+    }
+    
+    var loadingNode = DIV(null, "[loading index\u2026]");
+    distList.parentNode.insertBefore(P(null, loadingNode), distList);
+    
+    var dl = gatherResults(lst).addCallback(function (res) {
+        var toggleFunc = function (e) {
+            for (var i = 0; i < res.length; i++) {
+                var item = res[i];
+                if (!hasElementClass(item[0], "invisible")) {
+                    item[1]();
+                }
+            }
+        };
+        var node = A({"class": "force-pointer"}, "[click to expand all]");
+        swapDOM(loadingNode, node);
+        connect(node, "onclick", toggleFunc);
+    });
+};
+
+function spider_doc() {
+    return map(
+        function (tag) {
+            return [scrapeText(tag), getNodeAttribute(tag, "href")];
+        },
+        getElementsByTagAndClassName("a", "mochidef")
+    );
+};
+
+function module_index() {
+    var sections = getElementsByTagAndClassName("div", "section");
+    var ptr = sections[1];
+    var ref = DIV({"class": "section"},
+        H1(null, "Function Index"),
+        A({"id": "show_index", "href": "#", "onclick": toggle_docs}, "[show]"),
+        DIV({"id": "function_index", "class": "invisible"},
+            A({"href":"#", "onclick": toggle_docs}, "[hide]"),
+            P(null, map(function_ref, spider_doc()))));
+    ptr.parentNode.insertBefore(ref, ptr);
+};
+
+connect(window, 'onload', create_toc);
+
diff --git a/mochikit_v14/doc/rst/MochiKit/Async.rst b/mochikit_v14/doc/rst/MochiKit/Async.rst
new file mode 100755 (executable)
index 0000000..d1f7b94
--- /dev/null
@@ -0,0 +1,735 @@
+.. title:: MochiKit.Async - manage asynchronous tasks
+
+Name
+====
+
+MochiKit.Async - manage asynchronous tasks
+
+
+Synopsis
+========
+
+::
+
+    var url = "/src/b/bo/bob/MochiKit.Async/META.json";
+    /*
+
+        META.json looks something like this:
+
+        {"name": "MochiKit", "version": "0.5"}
+
+    */
+    var d = loadJSONDoc(url);
+    var gotMetadata = function (meta) {
+        if (MochiKit.Async.VERSION == meta.version) {
+            alert("You have the newest MochiKit.Async!");
+        } else {
+            alert("MochiKit.Async "
+                + meta.version
+                + " is available, upgrade!");
+        }
+    };
+    var metadataFetchFailed = function (err) {
+      alert("The metadata for MochiKit.Async could not be fetched :(");
+    };
+    d.addCallbacks(gotMetadata, metadataFetchFailed);
+
+
+Description
+===========
+
+MochiKit.Async provides facilities to manage asynchronous (as in AJAX
+[1]_) tasks. The model for asynchronous computation used in this
+module is heavily inspired by Twisted [2]_.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+
+
+Overview
+========
+
+Deferred
+--------
+
+The Deferred constructor encapsulates a single value that is not
+available yet. The most important example of this in the context of a
+web browser would be an ``XMLHttpRequest`` to a server. The importance
+of the Deferred is that it allows a consistent API to be exposed for
+all asynchronous computations that occur exactly once.
+
+The producer of the Deferred is responsible for doing all of the
+complicated work behind the scenes. This often means waiting for a
+timer to fire, or waiting for an event (e.g. ``onreadystatechange`` of
+``XMLHttpRequest``).  It could also be coordinating several events
+(e.g.  ``XMLHttpRequest`` with a timeout, or several Deferreds
+(e.g. fetching a set of XML documents that should be processed at the
+same time).
+
+Since these sorts of tasks do not respond immediately, the producer of
+the Deferred does the following steps before returning to the
+consumer:
+
+1. Create a ``new`` :mochiref:`Deferred();` object and keep a
+   reference to it, because it will be needed later when the value is
+   ready.
+2. Setup the conditions to create the value requested (e.g.  create a
+   new ``XMLHttpRequest``, set its ``onreadystatechange``).
+3. Return the :mochiref:`Deferred` object.
+
+Since the value is not yet ready, the consumer attaches a function to
+the Deferred that will be called when the value is ready. This is not
+unlike ``setTimeout``, or other similar facilities you may already be
+familiar with.  The consumer can also attach an "errback" to the
+:mochiref:`Deferred`, which is a callback for error handling.
+
+When the value is ready, the producer simply calls
+``myDeferred.callback(theValue)``. If an error occurred, it should
+call ``myDeferred.errback(theValue)`` instead.  As soon as this
+happens, the callback that the consumer attached to the
+:mochiref:`Deferred` is called with ``theValue`` as the only argument.
+
+There are quite a few additional "advanced" features baked into
+:mochiref:`Deferred`, such as cancellation and callback chains, so
+take a look at the API reference if you would like to know more!
+
+API Reference
+=============
+
+Errors
+------
+
+:mochidef:`AlreadyCalledError`:
+
+    Thrown by a :mochiref:`Deferred` if ``.callback`` or ``.errback``
+    are called more than once.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`BrowserComplianceError`:
+
+    Thrown when the JavaScript runtime is not capable of performing
+    the given function. Currently, this happens if the browser does
+    not support ``XMLHttpRequest``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`CancelledError`:
+
+    Thrown by a :mochiref:`Deferred` when it is cancelled, unless a
+    canceller is present and throws something else.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`GenericError`:
+
+    Results passed to ``.fail`` or ``.errback`` of a
+    :mochiref:`Deferred` are wrapped by this ``Error`` if ``!(result
+    instanceof Error)``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`XMLHttpRequestError`:
+
+    Thrown when an ``XMLHttpRequest`` does not complete successfully
+    for any reason. The ``req`` property of the error is the failed
+    ``XMLHttpRequest`` object, and for convenience the ``number``
+    property corresponds to ``req.status``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Constructors
+------------
+
+:mochidef:`Deferred()`:
+
+    Encapsulates a sequence of callbacks in response to a value that
+    may not yet be available. This is modeled after the Deferred class
+    from Twisted [3]_.
+
+.. _`Twisted`: http://twistedmatrix.com/
+
+    Why do we want this?  JavaScript has no threads, and even if it
+    did, threads are hard. Deferreds are a way of abstracting
+    non-blocking events, such as the final response to an
+    ``XMLHttpRequest``.
+
+    The sequence of callbacks is internally represented as a list of
+    2-tuples containing the callback/errback pair. For example, the
+    following call sequence::
+
+        var d = new Deferred();
+        d.addCallback(myCallback);
+        d.addErrback(myErrback);
+        d.addBoth(myBoth);
+        d.addCallbacks(myCallback, myErrback);
+
+    is translated into a :mochiref:`Deferred` with the following
+    internal representation::
+
+        [
+            [myCallback, null],
+            [null, myErrback],
+            [myBoth, myBoth],
+            [myCallback, myErrback]
+        ]
+
+    The :mochiref:`Deferred` also keeps track of its current status
+    (fired).  Its status may be one of the following three values:
+
+
+        ===== ================================
+        Value Condition
+        ===== ================================
+        -1    no value yet (initial condition)
+        0     success
+        1     error
+        ===== ================================
+
+    A :mochiref:`Deferred` will be in the error state if one of the
+    following conditions are met:
+
+    1. The result given to callback or errback is "``instanceof
+       Error``"
+    2. The callback or errback threw while executing. If the thrown
+       object is not ``instanceof Error``, it will be wrapped with
+       :mochiref:`GenericError`.
+
+    Otherwise, the :mochiref:`Deferred` will be in the success
+    state. The state of the :mochiref:`Deferred` determines the next
+    element in the callback sequence to run.
+
+    When a callback or errback occurs with the example deferred chain,
+    something equivalent to the following will happen (imagine that
+    exceptions are caught and returned as-is)::
+
+        // d.callback(result) or d.errback(result)
+        if (!(result instanceof Error)) {
+            result = myCallback(result);
+        }
+        if (result instanceof Error) {
+            result = myErrback(result);
+        }
+        result = myBoth(result);
+        if (result instanceof Error) {
+            result = myErrback(result);
+        } else {
+            result = myCallback(result);
+        }
+
+    The result is then stored away in case another step is added to
+    the callback sequence. Since the :mochiref:`Deferred` already has
+    a value available, any new callbacks added will be called
+    immediately.
+
+    There are two other "advanced" details about this implementation
+    that are useful:
+
+    Callbacks are allowed to return :mochiref:`Deferred` instances, so
+    you can build complicated sequences of events with (relative)
+    ease.
+
+    The creator of the :mochiref:`Deferred` may specify a
+    canceller. The canceller is a function that will be called if
+    :mochiref:`Deferred.prototype.cancel` is called before the
+    :mochiref:`Deferred` fires. You can use this to allow an
+    ``XMLHttpRequest`` to be cleanly cancelled, for example. Note that
+    cancel will fire the :mochiref:`Deferred` with a
+    :mochiref:`CancelledError` (unless your canceller throws or
+    returns a different ``Error``), so errbacks should be prepared to
+    handle that ``Error`` gracefully for cancellable
+    :mochiref:`Deferred` instances.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Deferred.prototype.addBoth(func)`:
+
+    Add the same function as both a callback and an errback as the
+    next element on the callback sequence. This is useful for code
+    that you want to guarantee to run, e.g. a finalizer.
+
+    If additional arguments are given, then ``func`` will be replaced
+    with :mochiref:`MochiKit.Base.partial.apply(null,
+    arguments)`. This differs from `Twisted`_, because the result of
+    the callback or errback will be the *last* argument passed to
+    ``func``.
+
+    If ``func`` returns a :mochiref:`Deferred`, then it will be
+    chained (its value or error will be passed to the next
+    callback). Note that once the returned ``Deferred`` is chained, it
+    can no longer accept new callbacks.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Deferred.prototype.addCallback(func[, ...])`:
+
+    Add a single callback to the end of the callback sequence.
+
+    If additional arguments are given, then ``func`` will be replaced
+    with :mochiref:`MochiKit.Base.partial.apply(null,
+    arguments)`. This differs from `Twisted`_, because the result of
+    the callback will be the *last* argument passed to ``func``.
+
+    If ``func`` returns a :mochiref:`Deferred`, then it will be
+    chained (its value or error will be passed to the next
+    callback). Note that once the returned ``Deferred`` is chained, it
+    can no longer accept new callbacks.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Deferred.prototype.addCallbacks(callback, errback)`:
+
+    Add separate callback and errback to the end of the callback
+    sequence. Either callback or errback may be ``null``, but not
+    both.
+
+    If ``callback`` or ``errback`` returns a :mochiref:`Deferred`,
+    then it will be chained (its value or error will be passed to the
+    next callback). Note that once the returned ``Deferred`` is
+    chained, it can no longer accept new callbacks.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Deferred.prototype.addErrback(func)`:
+
+    Add a single errback to the end of the callback sequence.
+
+    If additional arguments are given, then ``func`` will be replaced
+    with :mochiref:`MochiKit.Base.partial.apply(null,
+    arguments)`. This differs from `Twisted`_, because the result of
+    the errback will be the *last* argument passed to ``func``.
+
+    If ``func`` returns a :mochiref:`Deferred`, then it will be
+    chained (its value or error will be passed to the next
+    callback). Note that once the returned ``Deferred`` is chained, it
+    can no longer accept new callbacks.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Deferred.prototype.callback([result])`:
+
+    Begin the callback sequence with a non-``Error`` result. Result
+    may be any value except for a :mochiref:`Deferred`.
+
+    Either ``.callback`` or ``.errback`` should be called exactly once
+    on a :mochiref:`Deferred`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Deferred.prototype.cancel()`:
+
+    Cancels a :mochiref:`Deferred` that has not yet received a value,
+    or is waiting on another :mochiref:`Deferred` as its value.
+
+    If a canceller is defined, the canceller is called.  If the
+    canceller did not return an ``Error``, or there was no canceller,
+    then the errback chain is started with :mochiref:`CancelledError`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Deferred.prototype.errback([result])`:
+
+    Begin the callback sequence with an error result.  Result may be
+    any value except for a :mochiref:`Deferred`, but if ``!(result
+    instanceof Error)``, it will be wrapped with
+    :mochiref:`GenericError`.
+
+    Either ``.callback`` or ``.errback`` should be called exactly once
+    on a :mochidef:`Deferred`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`DeferredLock()`:
+
+    A lock for asynchronous systems.
+
+    The ``locked`` property of a :mochiref:`DeferredLock` will be
+    ``true`` if it locked, ``false`` otherwise. Do not change this
+    property.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`DeferredLock.prototype.acquire()`:
+
+    Attempt to acquire the lock. Returns a :mochiref:`Deferred` that
+    fires on lock acquisition with the :mochiref:`DeferredLock` as the
+    value.  If the lock is locked, then the :mochiref:`Deferred` goes
+    into a waiting list.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`DeferredLock.prototype.release()`:
+
+    Release the lock. If there is a waiting list, then the first
+    :mochiref:`Deferred` in that waiting list will be called back.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])`:
+
+    Combine a list of :mochiref:`Deferred` into one. Track the
+    callbacks and return a list of (success, result) tuples, 'success'
+    being a boolean indicating whether result is a normal result or an
+    error.
+
+    Once created, you have access to all :mochiref:`Deferred` methods,
+    like addCallback, addErrback, addBoth. The behaviour can be
+    changed by the following options:
+
+    ``fireOnOneCallback``:
+        Flag for launching the callback once the first Deferred of the
+        list has returned.
+
+    ``fireOnOneErrback``:
+        Flag for calling the errback at the first error of a Deferred.
+
+    ``consumeErrors``:
+        Flag indicating that any errors raised in the Deferreds should
+        be consumed by the DeferredList.
+
+    Example::
+
+        // We need to fetch data from 2 different urls
+        var d1 = loadJSONDoc(url1);
+        var d2 = loadJSONDoc(url2);
+        var l1 = new DeferredList([d1, d2], false, false, true);
+        l1.addCallback(function (resultList) {
+            MochiKit.Base.map(function (result) {
+                if (result[0]) {
+                    alert("Data is here: " + result[1]);
+                } else {
+                    alert("Got an error: " + result[1]);
+                }
+            }, resultList);
+        });
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Functions
+---------
+
+:mochidef:`callLater(seconds, func[, args...])`:
+
+    Call ``func(args...)`` after at least ``seconds`` seconds have
+    elapsed.  This is a convenience method for::
+
+        func = partial.apply(extend(null, arguments, 1));
+        return wait(seconds).addCallback(function (res) { return func() });
+
+    Returns a cancellable :mochiref:`Deferred`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`doXHR(url[, {option: value, ...}])`:
+
+    Perform a customized ``XMLHttpRequest`` and wrap it with a
+    :mochiref:`Deferred` that may be cancelled.
+
+    Note that only ``200`` (OK), ``201`` (CREATED),
+    ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered
+    success codes. All other status codes will
+    result in an errback with an ``XMLHttpRequestError``.
+
+    ``url``:
+        The URL for this request.
+
+    The following options are currently accepted:
+
+    ``method``:
+        The HTTP method. Default is ``'GET'``.
+
+    ``sendContent``:
+        The content to send (e.g. with POST). Default is no content.
+
+    ``queryString``:
+        If present it will be used to build a query string to append to
+        the url using :mochiref:`MochiKit.Base.queryString`. Default is
+        no query string.
+
+    ``username``:
+        The username for the request. Default is no username.
+
+    ``password``:
+        The password for the request. Default is no password.
+
+    ``headers``:
+        Additional headers to set in the request, either as an object
+        such as ``{'Accept': 'text/xml'}`` or as an Array of 2-Arrays
+        ``[['Accept', 'text/xml']]``. Default is no additional headers.
+
+    ``mimeType``:
+        An override mime type. The typical use of this is to pass
+        'text/xml' to force XMLHttpRequest to attempt to parse responseXML.
+        Default is no override.
+
+    *returns*:
+        :mochiref:`Deferred` that will callback with the
+        ``XMLHttpRequest`` instance on success
+
+    *Availability*:
+        Available in MochiKit 1.4+.
+
+
+:mochidef:`doSimpleXMLHttpRequest(url[, queryArguments...])`:
+
+    Perform a simple ``XMLHttpRequest`` and wrap it with a
+    :mochiref:`Deferred` that may be cancelled.
+
+    Note that only ``200`` (OK), ``201`` (CREATED),
+    ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered
+    success codes. All other status codes will
+    result in an errback with an ``XMLHttpRequestError``.
+
+    ``url``:
+        The URL to GET
+
+    ``queryArguments``:
+        If this function is called with more than one argument, a
+        ``"?"`` and the result of
+        :mochiref:`MochiKit.Base.queryString` with the rest of the
+        arguments are appended to the URL.
+
+        For example, this will do a GET request to the URL
+        ``http://example.com?bar=baz``::
+
+            doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
+
+    *returns*:
+        :mochiref:`Deferred` that will callback with the
+        ``XMLHttpRequest`` instance on success
+
+    *Availability*:
+        Available in MochiKit 1.3.1+. Support for 201 and 204 were added in
+        MochiKit 1.4.
+
+
+:mochidef:`evalJSONRequest(req)`:
+
+    Evaluate a JSON [4]_ ``XMLHttpRequest``
+
+    ``req``:
+        The request whose ``.responseText`` property is to be
+        evaluated
+
+    *returns*:
+        A JavaScript object
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`fail([result])`:
+
+    Return a :mochiref:`Deferred` that has already had
+    ``.errback(result)`` called.
+
+    See ``succeed`` documentation for rationale.
+
+    ``result``:
+        The result to give to
+        :mochiref:`Deferred.prototype.errback(result)`.
+
+    *returns*:
+        A ``new`` :mochiref:`Deferred()`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`gatherResults(deferreds)`:
+
+    A convenience function that returns a :mochiref:`DeferredList`
+    from the given ``Array`` of :mochiref:`Deferred` instances that
+    will callback with an ``Array`` of just results when they're
+    available, or errback on the first array.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`getXMLHttpRequest()`:
+
+    Return an ``XMLHttpRequest`` compliant object for the current
+    platform.
+
+    In order of preference:
+
+    - ``new XMLHttpRequest()``
+    - ``new ActiveXObject('Msxml2.XMLHTTP')``
+    - ``new ActiveXObject('Microsoft.XMLHTTP')``
+    - ``new ActiveXObject('Msxml2.XMLHTTP.4.0')``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`maybeDeferred(func[, argument...])`:
+
+    Call a ``func`` with the given arguments and ensure the result is
+    a :mochiref:`Deferred`.
+
+    ``func``:
+        The function to call.
+
+    *returns*:
+        A new :mochiref:`Deferred` based on the call to ``func``. If
+        ``func`` does not naturally return a :mochiref:`Deferred`, its
+        result or error value will be wrapped by one.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`loadJSONDoc(url[, queryArguments...])`:
+
+    Do a simple ``XMLHttpRequest`` to a URL and get the response as a
+    JSON [4]_ document.
+
+    ``url``:
+        The URL to GET
+
+    ``queryArguments``:
+        If this function is called with more than one argument, a
+        ``"?"`` and the result of
+        :mochiref:`MochiKit.Base.queryString` with the rest of the
+        arguments are appended to the URL.
+
+        For example, this will do a GET request to the URL
+        ``http://example.com?bar=baz``::
+
+            loadJSONDoc("http://example.com", {bar: "baz"});
+
+    *returns*:
+        :mochiref:`Deferred` that will callback with the evaluated
+        JSON [4]_ response upon successful ``XMLHttpRequest``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`sendXMLHttpRequest(req[, sendContent])`:
+
+    Set an ``onreadystatechange`` handler on an ``XMLHttpRequest``
+    object and send it off. Will return a cancellable
+    :mochiref:`Deferred` that will callback on success.
+
+    Note that only ``200`` (OK), ``201`` (CREATED),
+    ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered
+    success codes. All other status codes will
+    result in an errback with an ``XMLHttpRequestError``.
+
+    ``req``:
+        An preconfigured ``XMLHttpRequest`` object (open has been
+        called).
+
+    ``sendContent``:
+        Optional string or DOM content to send over the
+        ``XMLHttpRequest``.
+
+    *returns*:
+        :mochiref:`Deferred` that will callback with the
+        ``XMLHttpRequest`` instance on success.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+. Support for 201 and 204 were added in
+        MochiKit 1.4.
+
+
+:mochidef:`succeed([result])`:
+
+    Return a :mochiref:`Deferred` that has already had
+    ``.callback(result)`` called.
+
+    This is useful when you're writing synchronous code to an
+    asynchronous interface: i.e., some code is calling you expecting a
+    :mochiref:`Deferred` result, but you don't actually need to do
+    anything asynchronous. Just return ``succeed(theResult)``.
+
+    See ``fail`` for a version of this function that uses a failing
+    :mochiref:`Deferred` rather than a successful one.
+
+    ``result``:
+        The result to give to
+        :mochiref:`Deferred.prototype.callback(result)`
+
+    *returns*:
+        a ``new`` :mochiref:`Deferred`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`wait(seconds[, res])`:
+
+    Return a new cancellable :mochiref:`Deferred` that will
+    ``.callback(res)`` after at least ``seconds`` seconds have
+    elapsed.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+See Also
+========
+
+.. [1] AJAX, Asynchronous JavaScript and XML: http://en.wikipedia.org/wiki/AJAX
+.. [2] Twisted, an event-driven networking framework written in Python: http://twistedmatrix.com/
+.. [3] Twisted Deferred Reference: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
+.. [4] JSON, JavaScript Object Notation: http://json.org/
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/Base.rst b/mochikit_v14/doc/rst/MochiKit/Base.rst
new file mode 100755 (executable)
index 0000000..4740ffd
--- /dev/null
@@ -0,0 +1,1416 @@
+.. title:: MochiKit.Base - functional programming and useful comparisons
+
+Name
+====
+
+MochiKit.Base - functional programming and useful comparisons
+
+
+Synopsis
+========
+
+::
+
+    myObjectRepr = function () {
+        // gives a nice, stable string representation for objects,
+        // ignoring any methods
+        var keyValuePairs = [];
+        for (var k in this) {
+            var v = this[k];
+            if (typeof(v) != 'function') {
+                keyValuePairs.push([k, v]);
+            }
+        };
+        keyValuePairs.sort(compare);
+        return "{" + map(
+            function (pair) {
+                return map(repr, pair).join(":");
+            },
+            keyValuePairs
+        ).join(", ") + "}";
+    };
+
+    // repr() will look for objects that have a repr method
+    myObjectArray = [
+        {"a": 3, "b": 2, "repr": myObjectRepr},
+        {"a": 1, "b": 2, "repr": myObjectRepr}
+    ];
+
+    // sort it by the "a" property, check to see if it matches
+    myObjectArray.sort(keyComparator("a"));
+    expectedRepr = '[{"a": 1, "b": 2}, {"a": 3, "b": 2}]';
+    assert( repr(myObjectArray) == expectedRepr );
+
+    // get just the "a" values out into an array
+    sortedAValues = map(itemgetter("a"), myObjectArray);
+    assert( compare(sortedAValues, [1, 3]) == 0 );
+
+    // serialize an array as JSON, unserialize it, expect something equivalent
+    myArray = [1, 2, "3", null, undefined];
+    assert( objEqual(evalJSON(serializeJSON(myArray)), myArray) );
+
+
+Description
+===========
+
+:mochiref:`MochiKit.Base` is the foundation for the MochiKit suite.
+It provides:
+
+-   An extensible comparison facility
+    (:mochiref:`compare`, :mochiref:`registerComparator`)
+-   An extensible programmer representation facility
+    (:mochiref:`repr`, :mochiref:`registerRepr`)
+-   An extensible JSON [1]_ serialization and evaluation facility
+    (:mochiref:`serializeJSON`, :mochiref:`evalJSON`,
+    :mochiref:`registerJSON`)
+-   A simple adaptation facility (:mochiref:`AdapterRegistry`)
+-   Convenience functions for manipulating objects and Arrays
+    (:mochiref:`update`, :mochiref:`setdefault`, :mochiref:`extend`, etc.)
+-   Array-based functional programming
+    (:mochiref:`map`, :mochiref:`filter`, etc.)
+-   Bound and partially applied functions
+    (:mochiref:`bind`, :mochiref:`method`, :mochiref:`partial`)
+
+Python users will feel at home with :mochiref:`MochiKit.Base`, as the
+facilities are quite similar to those available as part of Python and
+the Python standard library.
+
+
+Dependencies
+============
+
+None.
+
+
+Overview
+========
+
+Comparison
+----------
+
+The comparators (operators for comparison) in JavaScript are deeply
+broken, and it is not possible to teach them new tricks.
+
+MochiKit exposes an extensible comparison facility as a simple
+:mochiref:`compare(a, b)` function, which should be used in lieu of
+JavaScript's operators whenever comparing objects other than numbers
+or strings (though you can certainly use :mochiref:`compare` for
+those, too!).
+
+The :mochiref:`compare` function has the same signature and return
+value as a sort function for ``Array.prototype.sort``, and is often
+used in that context.
+
+Defining new comparators for the :mochiref:`compare` function to use
+is done by adding an entry to its :mochiref:`AdapterRegistry` with the
+:mochiref:`registerComparator` function.
+
+
+Programmer Representation
+-------------------------
+
+JavaScript's default representation mechanism, ``toString``, is
+notorious for having terrible default behavior. It's also very unwise
+to change that default, as other JavaScript code you may be using may
+depend on it.
+
+It's also useful to separate the concept of a "string representation"
+and a "string representation for programmers", much like Python does
+with its str and repr protocols.
+
+:mochiref:`repr` provides this programmer representation for
+JavaScript, in a way that doesn't require object prototype hacking:
+using an :mochiref:`AdapterRegistry`.
+
+Objects that implement the repr protocol can either implement a
+``.repr()`` or ``.__repr__()`` method, or they can simply have an
+adapter setup to generate programmer representations. By default, the
+registry provides nice representations for ``null``, ``undefined``,
+``Array``, and objects or functions with a ``NAME`` attribute that use
+the default ``toString``. For objects that ``repr`` doesn't already
+understand, it simply defaults to ``toString``, so it will integrate
+seamlessly with code that implements the idiomatic JavaScript
+``toString`` method!
+
+To define a programmer representation for your own objects, simply add
+a ``.repr()`` or ``.__repr__()`` method that returns a string. For
+objects that you didn't create (e.g., from a script you didn't write,
+or a built-in object), it is instead recommended that you create an
+adapter with :mochiref:`registerRepr`.
+
+
+JSON Serialization
+------------------
+
+JSON [1]_, JavaScript Object Notation, is a widely used serialization
+format in the context of web development. It's extremely simple,
+lightweight, and fast. In its essence, JSON is a restricted subset of
+JavaScript syntax suitable for sending over the wire that can be
+unserialized with a simple eval. It's often used as an alternative to
+XML in "AJAX" contexts because it is compact, fast, and much simpler
+to use for most purposes.
+
+To create a JSON serialization of any object, simply call
+:mochiref:`serializeJSON()` with that object. To unserialize a JSON
+string, simply call :mochiref:`evalJSON()` with the serialization.
+
+In order of precedence, :mochiref:`serializeJSON` coerces the given
+argument into a JSON serialization:
+
+1.  Primitive types are returned as their JSON representation:
+    ``string``, ``number``, ``boolean``, ``null``.
+2.  If the object has a ``__json__`` or ``json`` method, then it is
+    called with no arguments. If the result of this method is not the
+    object itself, then the new object goes through rule processing
+    again (e.g. it may return a string, which is then serialized in
+    JSON format).
+3.  If the object is ``Array``-like (has a ``length`` property that is
+    a number, and is not a function), then it is serialized as a JSON
+    array.  Each element will be processed according to these rules in
+    order.  Elements that can not be serialized (e.g. functions) will
+    be replaced with ``undefined``.
+4.  The ``jsonRegistry`` :mochiref:`AdapterRegistry` is consulted for
+    an adapter for this object. JSON adapters take one argument (the
+    object), and are expected to behave like a ``__json__`` or
+    ``json`` method (return another object to be serialized, or
+    itself).
+5.  If the object is ``undefined``, a ``TypeError`` is thrown. If you
+    wish to serialize ``undefined`` as ``null`` or some other value, you
+    should create an adapter to do so.
+6.  If no adapter is available, the object is enumerated and
+    serialized as a JSON object (name:value pairs). All names are
+    expected to be strings.  Each value is serialized according to
+    these rules, and if it can not be serialized (e.g. methods), then
+    that name:value pair will be skipped.
+
+
+Adapter Registries
+------------------
+
+MochiKit makes extensive use of adapter registries, which enable you
+to implement object-specific behaviors for objects that you do not
+necessarily want to modify, such as built-in objects. This is
+especially useful because JavaScript does not provide a method for
+hiding user-defined properties from ``for propName in obj``
+enumeration.
+
+:mochiref:`AdapterRegistry` is simply an encapsulation for an ordered
+list of "check" and "wrap" function pairs. Each
+:mochiref:`AdapterRegistry` instance should perform one function, but
+may have multiple ways to achieve that function based upon the
+arguments. One way to think of it is as a poor man's generic function,
+or multiple dispatch (on arbitrary functions, not just type!).
+
+Check functions take one or more arguments, and return ``true`` if the
+argument list is suitable for the wrap function. Check functions
+should perform "cheap" checks of an object's type or contents, before
+the "expensive" wrap function is called.
+
+Wrap functions take the same arguments as check functions and do some
+operation, such as creating a programmer representation or comparing
+both arguments.
+
+
+Convenience Functions
+---------------------
+
+Much of :mochiref:`MochiKit.Base` is there to simply remove the grunt
+work of doing generic JavaScript programming.
+
+Need to take every property from one object and set them on another?
+No problem, just call :mochiref:`update(dest, src)`! What if you just
+wanted to update keys that weren't already set? Look no further than
+:mochiref:`setdefault(dest, src[, ...])`.
+
+Want to return a mutable object, but don't want to suffer the
+consequences if the user mutates it? Just :mochiref:`clone(it)` and
+you'll get a copy-on-write clone. Cheaper than a copy!
+
+Need to extend an ``Array`` with another array? Or even an
+``Array``-like object such as a ``NodeList`` or the special
+``arguments`` object? Even if you need to skip the first few elements
+of the source ``Array``-like object, it's no problem with
+:mochiref:`extend(dstArray, srcArrayLike[, skip])`!
+
+Wouldn't it be convenient to have all of the JavaScript operators were
+available as functions somewhere? That's what the
+:mochiref:`operators` table is for, and it even comes with additional
+operators based on the :mochiref:`compare` function.
+
+Need to walk some tree of objects and manipulate or find something in
+it?  A DOM element tree perhaps? Use :mochiref:`nodeWalk(node,
+visitor)`!
+
+There's plenty more, so check out the `API Reference`_ below.
+
+
+Functional Programming
+----------------------
+
+Functional programming constructs such as :mochiref:`map` and
+:mochiref:`filter` can save you a lot of time, because JavaScript
+iteration is error-prone and arduous. Writing less code is the best
+way to prevent bugs, and functional programming can help you do that.
+
+:mochiref:`MochiKit.Base` ships with a few simple Array-based
+functional programming constructs, namely :mochiref:`map` and
+:mochiref:`filter`, and their "extended" brethren, :mochiref:`xmap`
+and :mochiref:`xfilter`.
+
+:mochiref:`map(func, arrayLike[, ...])` takes a function and an
+``Array``-like object, and creates a new ``Array``. The new ``Array``
+is the result of ``func(element)`` for every element of ``arrayLike``,
+much like the ``Array.prototype.map`` extension in Mozilla. However,
+:mochiref:`MochiKit.Base` takes that a step further and gives you the
+full blown Python version of :mochiref:`map`, which will take several
+``Array``-like objects, and calls the function with one argument per
+given ``Array``-like, e.g.::
+
+   var arrayOne = [1, 2, 3, 4, 5];
+   var arrayTwo = [1, 5, 2, 4, 3];
+   var arrayThree = [5, 2, 1, 3, 4];
+   var biggestElements = map(objMax, arrayOne, arrayTwo, arrayThree);
+   assert( objEqual(biggestElements, [5, 5, 3, 4, 5]) );
+
+:mochiref:`filter(func, arrayLike[, self])` takes a function and an
+``Array``-like object, and returns a new ``Array``.  This is basically
+identical to the ``Array.prototype.filter`` extension in
+Mozilla. self, if given, will be used as ``this`` in the context of
+func when called.
+
+:mochiref:`xmap` and :mochiref:`xfilter` are just special forms of
+:mochiref:`map` and :mochiref:`filter` that accept a function as the
+first argument, and use the extra arguments as the ``Array``-like. Not
+terribly interesting, but a definite time-saver in some cases.
+
+If you appreciate the functional programming facilities here, you
+should definitely check out :mochiref:`MochiKit.Iter`, which provides
+full blown iterators, :mochiref:`MochiKit.Iter.range`,
+:mochiref:`MochiKit.Iter.reduce`, and a near-complete port of Python's
+itertools [2]_ module, with some extra stuff thrown in for good
+measure!
+
+
+Bound and Partial Functions
+---------------------------
+
+JavaScript's method-calling special form and lack of bound functions
+(functions that know what ``this`` should be) are one of the first
+stumbling blocks that programmers new to JavaScript face. The
+:mochiref:`bind(func, self)` method fixes that right up by returning a
+new function that calls func with the right ``this``.
+
+In order to take real advantage of all this fancy functional
+programming stuff, you're probably going to want partial
+application. This allows you to create a new function from an existing
+function that remembers some of the arguments.  For example, if you
+wanted to compare a given object to a slew of other objects, you could
+do something like this::
+
+    compareWithOne = partial(compare, 1);
+    results = map(compareWithOne, [0, 1, 2, 3]);
+    assert( objEqual(results, [-1, 0, 1, 1]) );
+
+One of the better uses of partial functions is in
+:mochiref:`MochiKit.DOM`, which is certainly a must-see for those of
+you creating lots of DOM elements with JavaScript!
+
+
+API Reference
+=============
+
+Errors
+------
+
+:mochidef:`NotFound`:
+
+    A singleton error raised when no suitable adapter is found
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Constructors
+------------
+
+:mochidef:`AdapterRegistry`:
+
+    A registry to facilitate adaptation.
+
+    All ``check``/``wrap`` function pairs in a given registry should
+    take the same number of arguments.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`AdapterRegistry.prototype.register(name, check, wrap[, override])`:
+
+    ``name``:
+        a unique identifier used to identify this adapter so that it
+        may be unregistered.
+
+    ``check``:
+        function that should return ``true`` if the given arguments
+        are appropriate for the ``wrap`` function.
+
+    ``wrap``:
+        function that takes the same parameters as ``check`` and does
+        the adaptation.  Every ``wrap``/``check`` function pair in the
+        registry should have the same number of arguments.
+
+    ``override``:
+        if ``true``, the ``check`` function will be
+        given highest priority. Otherwise, the lowest.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`AdapterRegistry.prototype.match(obj[, ...])`:
+
+    Find an adapter for the given arguments by calling every ``check``
+    function until one returns ``true``.
+
+    If no suitable adapter is found, throws :mochiref:`NotFound`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`AdapterRegistry.prototype.unregister(name)`:
+
+    Remove a named adapter from the registry
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`NamedError`:
+
+    Convenience constructor for creating new errors
+    (e.g. :mochiref:`NotFound`)
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Functions
+---------
+
+:mochidef:`arrayEqual(self, arr)`:
+
+    Compare the arrays ``self`` and ``arr`` for equality using
+    ``compare`` on each element. Uses a fast-path for length
+    differences.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`average(lst[, ...])`:
+
+    This function is an alias of :mochiref:`mean()`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`bind(func, self[, arg, ...])`:
+
+    Return a copy of ``func`` bound to ``self``. This means whenever
+    and however the returned function is called, ``this`` will always
+    reference the given ``self``. ``func`` may be either a function
+    object, or a string. If it is a string, then ``self[func]`` will
+    be used, making these two statements equivalent::
+
+        bind("method", self);
+        bind(self.method, self);
+
+    Calling :mochiref:`bind(func, self)` on an already bound function
+    will return a new function that is bound to the new ``self``! If
+    ``self`` is ``undefined``, then the previous ``self`` is used.  If
+    ``self`` is ``null``, then the ``this`` object is used (which may
+    or may not be the global object). To force binding to the global
+    object, you should pass it explicitly.
+
+    Additional arguments, if given, will be partially applied to the
+    function. These three expressions are equivalent and return
+    equally efficient functions (:mochiref:`bind` and
+    :mochiref:`partial` share the same code path):
+
+    - :mochiref:`bind(oldfunc, self, arg1, arg2)`
+    - :mochiref:`bind(partial(oldfunc, arg1, arg2), self)`
+    - :mochiref:`partial(bind(oldfunc, self), arg1, arg2)`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`bindMethods(self)`:
+
+    Replace all functions ``meth`` on ``self`` with
+    :mochiref:`bind(meth, self)`.  This emulates Python's bound
+    instance methods, where there is no need to worry about preserving
+    ``this`` when the method is used as a callback.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`camelize(str)`:
+
+    Converts hyphenated strings to camelCase::
+
+        assert( camelize("border-left") == "borderLeft" );
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`clone(obj)`:
+
+    Return a new object using ``obj`` as its prototype. Use this if
+    you want to return a mutable object (e.g. instance state), but
+    don't want the user to mutate it. If they do, it won't have any
+    effect on the original ``obj``.
+
+    Note that this is a shallow clone, so mutable properties will have
+    to be cloned separately if you want to "protect" them.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`compare(a, b)`:
+
+    Compare two objects in a sensible manner. Currently this is:
+
+    1.  ``undefined`` and ``null`` compare equal to each other
+    2.  ``undefined`` and ``null`` are less than anything else
+    3.  If JavaScript says ``a == b``, then we trust it
+    4.  comparators registered with registerComparator are used to
+        find a good comparator. Built-in comparators are currently
+        available for ``Array``-like and ``Date``-like objects.
+    5.  Otherwise hope that the built-in comparison operators do
+        something useful, which should work for numbers and strings.
+    6.  If neither ``a < b`` or ``a > b``, then throw a ``TypeError``
+
+    Returns what one would expect from a comparison function:
+
+    +-----------+---------------+
+    | Value     | Condition     |
+    +-----------+---------------+
+    | ``0``     | ``a == b``    |
+    +-----------+---------------+
+    | ``1``     | ``a > b``     |
+    +-----------+---------------+
+    | ``-1``    | ``a < b``     |
+    +-----------+---------------+
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`compose(f1, f2, ..., fN)`:
+
+    Return a new function as the combination of the given function
+    arguments, equivalent to ``f1(f2(arguments))``.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`concat(lst[, ...])`:
+
+    Concatenates all given ``Array``-like arguments and returns
+    a new ``Array``::
+
+        var lst = concat(["1","3","5"], ["2","4","6"]);
+        assert( lst.toString() == "1,3,5,2,4,6" );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`counter(n=1)`:
+
+    Returns a function that will return a number one greater than
+    the previous returned value, starting at ``n``. For example::
+
+        nextId = counter()
+        assert( nextId() == 1 )
+        assert( nextId() == 2 )
+
+    For an iterator with this behavior, see
+    :mochiref:`MochiKit.Iter.count`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`extend(self, obj, skip=0)`:
+
+    Mutate the array ``self`` by extending it with an ``Array``-like
+    ``obj``, starting from index ``skip``. If ``null`` is given as the
+    initial array, a new one will be created.
+
+    This mutates *and returns* ``self``, be warned.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`evalJSON(aJSONString)`:
+
+    Unserialize a JSON [1]_ represenation of an object.
+
+    Note that this uses the ``eval`` function of the interpreter, and
+    therefore trusts the contents of ``aJSONString`` to be safe.  This
+    is acceptable when the JSON and JavaScript application originate
+    from the same server, but in other scenarios it may not be the
+    appropriate security model. Currently, a validating JSON parser is
+    beyond the scope of MochiKit, but there is one available from
+    json.org [1]_.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`filter(fn, lst)`:
+
+    Returns a new ``Array`` composed of all elements from ``lst``
+    where ``fn(lst[i])`` returns a true value.
+
+    If ``fn`` is ``null``, ``operator.truth`` will be used.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`findValue(lst, value, start=0, end=lst.length)`:
+
+    Finds the index of ``value`` in the ``Array``-like object ``lst``
+    using :mochiref:`compare`. The search starts at the index
+    ``start``, and ends at the index ``end - 1``. If ``value`` is not
+    found in ``lst``, it will return ``-1``.
+
+    For example::
+
+        assert( findValue([1, 2, 3, 2, 1], 2) == 1 )
+        assert( findValue([1, 2, 3, 2, 1], 2, 2) == 3 )
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`findIdentical(lst, value, start=0, end=lst.length)`:
+
+    Finds the index of ``value`` in the ``Array``-like object ``lst``
+    using the ``===`` operator. The search starts at the index
+    ``start``, and ends at the index ``end - 1``. If ``value`` is not
+    found in ``lst``, it will return ``-1``.
+
+    You should use this function instead of :mochiref:`findValue` if
+    ``lst`` may be comprised of objects for which no comparator is
+    defined and all you care about is finding an identical object
+    (e.g. the same instance), or if ``lst`` is comprised of just
+    numbers or strings and performance is important.
+
+    For example::
+
+        assert( findIdentical([1, 2, 3, 2, 1], 2) == 1 )
+        assert( findIdentical([1, 2, 3, 2, 1], 2, 2) == 3 )
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`flattenArguments(arg[, ...])`:
+
+    Given a bunch of arguments, return a single ``Array`` containing
+    all of those arguments. Any ``Array``-like argument will be extended
+    in-place, e.g.::
+
+        compare(flattenArguments(1, [2, 3, [4, 5]]), [1, 2, 3, 4, 5]) == 0
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`flattenArray(lst)`:
+
+    Return a new ``Array`` consisting of every item in lst with ``Array``
+    items expanded in-place recursively. This differs from 
+    :mochiref:`flattenArguments` in that it only takes one argument and
+    it only flattens items that are ``instanceof Array``.
+
+        compare(flattenArray([1, [2, 3, [4, 5]]]), [1, 2, 3, 4, 5]) == 0
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`forwardCall(name)`:
+
+    Returns a function that forwards a method call to
+    ``this.name(...)``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isArrayLike(obj[, ...])`:
+
+    Returns ``true`` if all given arguments are ``Array``-like (have a
+    ``.length`` property and ``typeof(obj) == 'object'``)
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isDateLike(obj[, ...])`:
+
+    Returns ``true`` if all given arguments are ``Date``-like (have a
+    ``.getTime()`` method)
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isEmpty(obj[, ...])`:
+
+    Returns ``true`` if all the given ``Array``-like or string
+    arguments are empty ``(obj.length == 0)``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isNotEmpty(obj[, ...])`:
+
+    Returns ``true`` if all the given ``Array``-like or string
+    arguments are not empty ``(obj.length > 0)``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isNull(obj[, ...])`:
+
+    Returns ``true`` if all arguments are ``null``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isUndefinedOrNull(obj[, ...])`:
+
+    Returns ``true`` if all arguments are undefined or ``null``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`itemgetter(name)`:
+
+    Returns a ``function(obj)`` that returns ``obj[name]``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`items(obj)`:
+
+    Return an ``Array`` of ``[propertyName, propertyValue]`` pairs for
+    the given ``obj`` (in the order determined by ``for propName in
+    obj``).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`keyComparator(key[, ...])`:
+
+    A comparator factory that compares ``a[key]`` with ``b[key]``.
+    e.g.::
+
+        var lst = ["a", "bbb", "cc"];
+        lst.sort(keyComparator("length"));
+        assert( lst.toString() == "a,cc,bbb" );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`keys(obj)`:
+
+    Return an ``Array`` of the property names of an object (in the
+    order determined by ``for propName in obj``).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`listMax(lst)`:
+
+    Return the largest element of an ``Array``-like object, as
+    determined by :mochiref:`compare`. This is a special form of
+    :mochiref:`listMinMax`, specifically
+    :mochiref:`partial(listMinMax, 1)`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`listMin(lst)`:
+
+    Return the smallest element of an ``Array``-like object, as
+    determined by :mochiref:`compare`. This is a special form of
+    :mochiref:`listMinMax`, specifically
+    :mochiref:`partial(listMinMax, -1)`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`listMinMax(which, lst)`:
+
+    If ``which == -1`` then it will return the smallest element of the
+    ``Array``-like ``lst``. This is also available as
+    :mochiref:`listMin(lst)`.
+
+    If ``which == 1`` then it will return the largest element of the
+    ``Array``-like ``lst``. This is also available as
+    :mochiref:`listMax(list)`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`map(fn, lst[, ...])`:
+
+    Return a new array composed of the results of ``fn(x)`` for every
+    ``x`` in ``lst``.
+
+    If ``fn`` is ``null``, and only one sequence argument is given the
+    identity function is used.
+
+        :mochiref:`map(null, lst)` -> ``lst.slice()``;
+
+    If ``fn`` is not ``null`` and more than one sequence argument is
+    given, then one element from each sequence is used to build the
+    argument list for ``fn``.
+
+        :mochiref:`map(fn, p, q, ...)`
+            ->  ``[fn(p[0], q[0], ..), fn(p[1], q[1], ...), ...]``
+    
+    If ``fn`` is ``null``, and more than one sequence is given as
+    arguments, then the ``Array`` function is used, making it
+    equivalent to :mochiref:`MochiKit.Iter.zip`.
+
+        :mochiref:`map(null, p, q, ...)`
+            -> :mochiref:`MochiKit.Iter.zip(p, q, ...)`
+            -> ``[[p0, q0, ...], [p1, q1, ...], ...];``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`mean(lst[, ...])`:
+
+    Returns the arithmetic mean (average) of the argument list, or an array.
+    This function applies :mochiref:`flattenArguments()` to the argument list.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`median(lst[, ...])`:
+
+    Returns the median of the argument list, or an array. This function
+    applies :mochiref:`flattenArguments()` to the argument list.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`merge(obj[, ...])`:
+
+    Create a new instance of ``Object`` that contains every property
+    from all given objects. If a property is defined on more than one
+    of the objects, the last property is used.
+
+    This is a special form of :mochiref:`update(self, obj[, ...])`,
+    specifically, it is defined as :mochiref:`partial(update, null)`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`method(self, func, ...)`:
+
+    Alternate form of :mochiref:`bind` that takes the object before
+    the function. These two calls are equivalent::
+
+        bind("method", myobject)
+        method(myobject, "method")
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`methodcaller(name[, args...])`:
+
+    Return a new function that calls a method on its argument,
+    for example::
+
+        lst = map(methodcaller("toLowerCase"), ["THIS", "is", "LoWeRCaSe"]);
+        assert( lst.join(" ") == "this is lowercase" );
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`nameFunctions(namespace)`:
+
+    Given a ``namespace`` (object or function) with a ``NAME``
+    property, find all methods in it and give them nice ``NAME``
+    properties too (for use with :mochiref:`repr`). e.g.::
+
+        namespace = {
+            NAME: "Awesome",
+            Dude: function () {}
+        }
+        nameFunctions(namespace);
+        assert( namespace.Dude.NAME == 'Awesome.Dude' );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`noop()`:
+
+    A function that performs no operation. Use this where you would
+    otherwise use ``(function () {})`` in order to avoid Internet
+    Explorer cyclic garbage leakage.
+
+    *Availability*:
+        Available in MochiKit 1.4
+
+
+:mochidef:`objEqual(a, b)`:
+
+    Return ``true`` if ``compare(a, b) == 0``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`nodeWalk(node, visitor)`:
+
+    Non-recursive generic node walking function (e.g. for a DOM).
+
+    The walk order for nodeWalk is breadth first, meaning that all
+    siblings will be visited before any children.
+
+    ``node``:
+        The initial node to be searched.
+
+    ``visitor``:
+        The visitor function, will be called as ``visitor(node)``, and
+        should return an ``Array``-like of nodes to be searched next
+        (e.g. ``node.childNodes``).  Leaf nodes may return ``null`` or
+        ``undefined``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`objMax(obj[, ...])`:
+
+    Return the maximum object according to :mochiref:`compare` out of
+    the given arguments. This is similar to :mochiref:`listMax`,
+    except is uses the arguments instead of a given ``Array``-like.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`objMin(obj[, ...])`:
+
+    Return the minimum object according to :mochiref:`compare` out of
+    the given arguments. This is similar to :mochiref:`listMin`,
+    except it uses the arguments instead of a given ``Array``-like.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`operator`:
+
+    A table of JavaScript's operators for usage with :mochiref:`map`,
+    :mochiref:`filter`, etc.
+
+
+    Unary Logic Operators:
+
+        +--------------------+--------------------------+-------------------+
+        | Operator           | Implementation           | Description       |
+        +====================+==========================+===================+
+        | ``truth(a)``       | ``!!a``                  | Logical truth     |
+        +--------------------+--------------------------+-------------------+
+        | ``lognot(a)``      | ``!a``                   | Logical not       |
+        +--------------------+--------------------------+-------------------+
+        | ``identity(a)``    | ``a``                    | Logical identity  |
+        +--------------------+--------------------------+-------------------+
+
+
+
+    Unary Math Operators:
+
+        +--------------------+--------------------------+---------------+
+        | Operator           | Implementation           | Description   |
+        +====================+==========================+===============+
+        | ``not(a)``         | ``~a``                   | Bitwise not   |
+        +--------------------+--------------------------+---------------+
+        | ``neg(a)``         | ``-a``                   | Negation      |
+        +--------------------+--------------------------+---------------+
+
+
+
+    Binary Operators:
+
+        +-------------------+-------------------+-------------------------------+
+        | Operator          | Implementation    | Description                   |
+        +===================+===================+===============================+
+        | ``add(a, b)``     | ``a + b``         | Addition                      |
+        +-------------------+-------------------+-------------------------------+
+        | ``sub(a, b)``     | ``a - b``         | Subtraction                   |
+        +-------------------+-------------------+-------------------------------+
+        | ``div(a, b)``     | ``a / b``         | Division                      |
+        +-------------------+-------------------+-------------------------------+
+        | ``mod(a, b)``     | ``a % b``         | Modulus                       |
+        +-------------------+-------------------+-------------------------------+
+        | ``mul(a, b)``     | ``a * b``         | Multiplication                |
+        +-------------------+-------------------+-------------------------------+
+        | ``and(a, b)``     | ``a & b``         | Bitwise and                   |
+        +-------------------+-------------------+-------------------------------+
+        | ``or(a, b)``      | ``a | b``         | Bitwise or                    |
+        +-------------------+-------------------+-------------------------------+
+        | ``xor(a, b)``     | ``a ^ b``         | Bitwise exclusive or          |
+        +-------------------+-------------------+-------------------------------+
+        | ``lshift(a, b)``  | ``a << b``        | Bitwise left shift            |
+        +-------------------+-------------------+-------------------------------+
+        | ``rshift(a, b)``  | ``a >> b``        | Bitwise signed right shift    |
+        +-------------------+-------------------+-------------------------------+
+        | ``zrshift(a, b)`` | ``a >>> b``       | Bitwise unsigned right shift  |
+        +-------------------+-------------------+-------------------------------+
+
+
+
+    Built-in Comparators:
+
+        +---------------+-------------------+---------------------------+
+        | Operator      | Implementation    | Description               |
+        +===============+===================+===========================+
+        | ``eq(a, b)``  | ``a == b``        | Equals                    |
+        +---------------+-------------------+---------------------------+
+        | ``ne(a, b)``  | ``a != b``        | Not equals                |
+        +---------------+-------------------+---------------------------+
+        | ``gt(a, b)``  | ``a > b``         | Greater than              |
+        +---------------+-------------------+---------------------------+
+        | ``ge(a, b)``  | ``a >= b``        | Greater than or equal to  |
+        +---------------+-------------------+---------------------------+
+        | ``lt(a, b)``  | ``a < b``         | Less than                 |
+        +---------------+-------------------+---------------------------+
+        | ``le(a, b)``  | ``a <= b``        | Less than or equal to     |
+        +---------------+-------------------+---------------------------+
+
+
+
+    Strict Built-in Comparators:
+
+        +---------------+-------------------+---------------------------+
+        | Operator      | Implementation    | Description               |
+        +===============+===================+===========================+
+        | ``seq(a, b)`` | ``a === b``       | Strict equals             |
+        +---------------+-------------------+---------------------------+
+        | ``sne(a, b)`` | ``a !== b``       | Strict not equals         |
+        +---------------+-------------------+---------------------------+
+
+
+
+    Extended Comparators (uses :mochiref:`compare`):
+
+        +---------------+---------------------------+---------------------------+
+        | Operator      | Implementation            | Description               |
+        +===============+===========================+===========================+
+        | ``ceq(a, b)`` | ``compare(a, b) == 0``    | Equals                    |
+        +---------------+---------------------------+---------------------------+
+        | ``cne(a, b)`` | ``compare(a, b) != 0``    | Not equals                |
+        +---------------+---------------------------+---------------------------+
+        | ``cgt(a, b)`` | ``compare(a, b) == 1``    | Greater than              |
+        +---------------+---------------------------+---------------------------+
+        | ``cge(a, b)`` | ``compare(a, b) != -1``   | Greater than or equal to  |
+        +---------------+---------------------------+---------------------------+
+        | ``clt(a, b)`` | ``compare(a, b) == -1``   | Less than                 |
+        +---------------+---------------------------+---------------------------+
+        | ``cle(a, b)`` | ``compare(a, b) != 1``    | Less than or equal to     |
+        +---------------+---------------------------+---------------------------+
+
+
+
+    Binary Logical Operators:
+
+        +-----------------------+-------------------+---------------------------+
+        | Operator              | Implementation    | Description               |
+        +=======================+===================+===========================+
+        | ``logand(a, b)``      | ``a && b``        | Logical and               |
+        +-----------------------+-------------------+---------------------------+
+        | ``logor(a, b)``       | ``a || b``        | Logical or                |
+        +-----------------------+-------------------+---------------------------+
+        | ``contains(a, b)``    | ``b in a``        | Has property (note order) |
+        +-----------------------+-------------------+---------------------------+
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`parseQueryString(encodedString[, useArrays=false])`:
+
+    Parse a name=value pair URL query string into an object with a
+    property for each pair. e.g.::
+
+        var args = parseQueryString("foo=value%20one&bar=two");
+        assert( args.foo == "value one" && args.bar == "two" );
+
+    If you expect that the query string will reuse the same name, then
+    give ``true`` as a second argument, which will use arrays to store
+    the values. e.g.::
+
+        var args = parseQueryString("foo=one&foo=two", true);
+        assert( args.foo[0] == "one" && args.foo[1] == "two" );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`partial(func, arg[, ...])`:
+
+    Return a partially applied function, e.g.::
+
+        addNumbers = function (a, b) {
+            return a + b;
+        }
+
+        addOne = partial(addNumbers, 1);
+
+        assert(addOne(2) == 3);
+
+    :mochiref:`partial` is a special form of :mochiref:`bind` that
+    does not alter the bound ``self`` (if any). It is equivalent to
+    calling::
+
+        bind(func, undefined, arg[, ...]);
+
+    See the documentation for :mochiref:`bind` for more details about
+    this facility.
+
+    This could be used to implement, but is NOT currying.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`queryString(names, values)`:
+
+    Creates a URL query string from a pair of ``Array``-like objects
+    representing ``names`` and ``values``. Each name=value pair will
+    be URL encoded by :mochiref:`urlEncode`. name=value pairs with a
+    value of ``undefined`` or ``null`` will be skipped. e.g.::
+
+        var keys = ["foo", "bar"];
+        var values = ["value one", "two"];
+        assert( queryString(keys, values) == "foo=value%20one&bar=two" );
+
+    Alternate form 1:
+        :mochiref:`queryString(domElement)`
+
+    If :mochiref:`MochiKit.DOM` is loaded, one argument is given, and
+    that argument is either a string or has a ``nodeType`` property
+    greater than zero, then ``names`` and ``values`` will be the
+    result of :mochiref:`MochiKit.DOM.formContents(domElement)`.
+
+    Alternate form 2:
+        :mochiref:`queryString({name: value, ...})`
+
+    Note that when using the alternate form, the order of the
+    name=value pairs in the resultant query string is dependent on how
+    the particular JavaScript implementation handles ``for (..in..)``
+    property enumeration.
+
+    When using the second alternate form, name=value pairs with
+    ``typeof(value) == "function"`` are ignored. This is a workaround
+    for the case where a poorly designed library has modified
+    ``Object.prototype`` and inserted "convenience functions".
+
+    Values that are Array-like will be expanded as if they were multiply
+    defined HTML elements. For example::
+
+        assert( queryString({a: [1,2]}) === "a=1&a=2" );
+    
+    Alternate form 2 (MochiKit 1.4+):
+        :mochiref:`queryString([names, values])`
+
+    This form behaves identically to :mochiref:`queryString(names, values)`,
+    except it takes both arguments as a single Array. This mirrors the
+    return value of :mochiref:`MochiKit.DOM.formContents`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`registerComparator(name, check, comparator[, override])`:
+
+    Register a comparator for use with :mochiref:`compare`.
+
+    ``name``:
+        unique identifier describing the comparator.
+
+    ``check``:
+        ``function(a, b)`` that returns ``true`` if ``a`` and ``b``
+        can be compared with ``comparator``.
+
+    ``comparator``:
+        ``function(a, b)`` that returns:
+
+        +-------+-----------+
+        | Value | Condition |
+        +-------+-----------+
+        | 0     | a == b    |
+        +-------+-----------+
+        | 1     | a > b     |
+        +-------+-----------+
+        | -1    | a < b     |
+        +-------+-----------+
+
+        ``comparator`` is guaranteed to only be called if ``check(a,
+        b)`` returns a ``true`` value.
+
+    ``override``:
+        if ``true``, then this will be made the highest precedence
+        comparator.  Otherwise, the lowest.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`registerJSON(name, check, simplifier[, override])`:
+
+    Register a simplifier function for use with
+    :mochiref:`serializeJSON`.
+
+    ``name``:
+        unique identifier describing the serialization.
+
+    ``check``:
+        ``function(obj)`` that returns ``true`` if ``obj`` can
+        can be simplified for serialization by ``simplifier``.
+
+    ``simplifier``:
+        ``function(obj)`` that returns a simpler object that can be
+        further serialized by :mochiref:`serializeJSON`. For example,
+        you could simplify ``Date``-like objects to ISO 8601 timestamp
+        strings with the following simplifier::
+
+            var simplifyDateAsISO = function (obj) {
+                return toISOTimestamp(obj, true);
+            };
+            registerJSON("DateLike", isDateLike, simplifyDateAsISO);
+
+        ``simplifier`` is guaranteed to only be called if
+        ``check(obj)`` returns a ``true`` value.
+
+    ``override``:
+        if ``true``, then this will be made the highest precedence
+        serialization. Otherwise, the lowest.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`registerRepr(name, check, wrap[, override])`:
+
+    Register a programmer representation function.  :mochiref:`repr`
+    functions should take one argument and return a string
+    representation of it suitable for developers, primarily used when
+    debugging.
+
+    If ``override`` is given, it is used as the highest priority repr,
+    otherwise it will be used as the lowest.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`repr(obj)`:
+
+    Return a programmer representation for ``obj``. See the
+    `Programmer Representation`_ overview for more information about
+    this function.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`reverseKeyComparator(key)`:
+
+    A comparator factory that compares ``a[key]`` with ``b[key]`` in
+    reverse.  e.g.::
+
+        var lst = ["a", "bbb", "cc"];
+        lst.sort(reverseKeyComparator("length"));
+        assert(lst.toString() == "bbb,cc,a");
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`serializeJSON(anObject)`:
+
+    Serialize ``anObject`` in the JSON [1]_ format, see `JSON
+    Serialization`_ for the coercion rules. For unserializable objects
+    (functions that do not have an adapter, ``__json__`` method, or
+    ``json`` method), this will return ``undefined``.
+
+    For those familiar with Python, JSON is similar in scope to
+    pickle, but it can not handle recursive object graphs.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`setdefault(self, obj[, ...])`:
+
+    Mutate ``self`` by adding all properties from other object(s) that
+    it does not already have set.
+
+    If ``self`` is ``null``, a new ``Object`` instance will be created
+    and returned.
+
+    This mutates *and returns* ``self``, be warned.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`typeMatcher(typ[, ...])`:
+
+    Given a set of types (as string arguments), returns a
+    ``function(obj[, ...])`` that will return ``true`` if the types of
+    the given arguments are all members of that set.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`update(self, obj[, ...])`:
+
+    Mutate ``self`` by replacing its key:value pairs with those from
+    other object(s). Key:value pairs from later objects will overwrite
+    those from earlier objects.
+
+    If ``self`` is ``null``, a new ``Object`` instance will be created
+    and returned.
+
+    This mutates *and returns* ``self``, be warned.
+
+    A version of this function that creates a new object is available
+    as :mochiref:`merge(a, b[, ...])`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`updatetree(self, obj[, ...])`:
+
+    Mutate ``self`` by replacing its key:value pairs with those from
+    other object(s). If a given key has an object value in both
+    ``self`` and ``obj``, then this function will be called
+    recursively, updating instead of replacing that object.
+
+    If ``self`` is ``null``, a new ``Object`` instance will be created
+    and returned.
+
+    This mutates *and returns* ``self``, be warned.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`urlEncode(unencoded)`:
+
+    Converts ``unencoded`` into a URL-encoded string. In this
+    implementation, spaces are converted to %20 instead of "+". e.g.::
+
+        assert( URLencode("1+2=2") == "1%2B2%3D2");
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`values(obj)`:
+
+    Return an ``Array`` of the property values of an object (in the
+    order determined by ``for propName in obj``).
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`xfilter(fn, obj[, ...])`:
+
+    Returns a new ``Array`` composed of the arguments where
+    ``fn(obj)`` returns a true value.
+
+    If ``fn`` is ``null``, ``operator.truth`` will be used.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`xmap(fn, obj[, ...)`:
+
+    Return a new ``Array`` composed of ``fn(obj)`` for every ``obj``
+    given as an argument.
+
+    If ``fn`` is ``null``, ``operator.identity`` is used.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+See Also
+========
+
+.. [1] JSON, JavaScript Object Notation: http://json.org/
+.. [2] Python's itertools
+       module: http://docs.python.org/lib/module-itertools.html
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/Color.rst b/mochikit_v14/doc/rst/MochiKit/Color.rst
new file mode 100755 (executable)
index 0000000..d21ae06
--- /dev/null
@@ -0,0 +1,651 @@
+.. title:: MochiKit.Color - color abstraction with CSS3 support
+
+Name
+====
+
+MochiKit.Color - color abstraction with CSS3 support
+
+
+Synopsis
+========
+
+::
+
+    // RGB color expressions are supported
+    assert(
+        objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)"))
+    );
+
+    // So is instantiating directly from HSL or RGB values.
+    // Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
+    assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
+
+    // Or even SVG color keyword names, as per CSS3!
+    assert( Color.fromString("aquamarine"), "#7fffd4" );
+
+    // NSColor-like colors built in
+    assert( Color.whiteColor().toHexString() == "#ffffff" );
+
+
+Description
+===========
+
+MochiKit.Color is an abstraction for handling colors and strings that
+represent colors.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.DOM`
+- :mochiref:`MochiKit.Style`
+
+
+Overview
+========
+
+MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with
+alpha.  It supports parsing and generating of CSS3 colors, and has a
+full CSS3 (SVG) color table.
+
+All of the functionality in this module is exposed through a Color
+constructor and its prototype, but a few of its internals are
+available for direct use at module level.
+
+
+API Reference
+=============
+
+Constructors
+------------
+
+:mochidef:`Color()`:
+
+    Represents a color. Component values should be integers between
+    ``0.0`` and ``1.0``. You should use one of the :mochiref:`Color`
+    factory functions such as :mochiref:`Color.fromRGB`,
+    :mochiref:`Color.fromHSL`, etc. instead of constructing
+    :mochiref:`Color` objects directly.
+
+    :mochiref:`Color` instances can be compared with
+    :mochiref:`MochiKit.Base.compare` (though ordering is on RGB, so
+    is not particularly meaningful except for equality), and the
+    default ``toString`` implementation returns
+    :mochiref:`Color.prototype.toHexString()`.
+
+    :mochiref:`Color` instances are immutable, and much of the
+    architecture is inspired by AppKit's NSColor [1]_
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromBackground(elem)`:
+
+    Returns a :mochiref:`Color` object based on the background of the
+    provided element. Equivalent to::
+
+        c = Color.fromComputedStyle(
+            elem, "backgroundColor", "background-color") || Color.whiteColor();
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromComputedStyle(elem, style)`:
+
+    Returns a :mochiref:`Color` object based on the result of
+    :mochiref:`MochiKit.Style.getStyle(elem, style)` or ``null`` if not 
+    found.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromHexString(hexString)`:
+
+    Returns a :mochiref:`Color` object from the given hexadecimal
+    color string.  For example, ``"#FFFFFF"`` would return a
+    :mochiref:`Color` with RGB values ``[255/255, 255/255, 255/255]``
+    (white).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromHSL(hue, saturation, lightness, alpha=1.0)`:
+
+    Return a :mochiref:`Color` object from the given ``hue``,
+    ``saturation``, ``lightness`` values. Values should be numbers
+    between ``0.0`` and ``1.0``.
+
+    If ``alpha`` is not given, then ``1.0`` (completely opaque) will
+    be used.
+
+    Alternate form:
+        :mochiref:`Color.fromHSL({h: hue, s: saturation, l: lightness,
+        a: alpha})`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromHSLString(hslString)`:
+
+    Returns a :mochiref:`Color` object from the given decimal hsl
+    color string.  For example, ``"hsl(0,0%,100%)"`` would return a
+    :mochiref:`Color` with HSL values ``[0/360, 0/360, 360/360]``
+    (white).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromHSV(hue, saturation, value, alpha=1.0)`:
+
+    Return a :mochiref:`Color` object from the given ``hue``,
+    ``saturation``, ``value`` values. Values should be numbers between
+    ``0.0`` and ``1.0``.
+
+    If ``alpha`` is not given, then ``1.0`` (completely opaque) will
+    be used.
+
+    Alternate form:
+        :mochiref:`Color.fromHSV({h: hue, s: saturation, v: value, a:
+        alpha})`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromName(colorName)`:
+
+    Returns a :mochiref:`Color` object corresponding to the given SVG
+    1.0 color keyword name [2]_ as per the W3C CSS3 Color Module
+    [3]_. ``"transparent"`` is also accepted as a color name, and will
+    return :mochiref:`Color.transparentColor()`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromRGB(red, green, blue, alpha=1.0)`:
+
+    Return a :mochiref:`Color` object from the given ``red``,
+    ``green``, ``blue``, and ``alpha`` values. Values should be
+    numbers between ``0`` and ``1.0``.
+
+    If ``alpha`` is not given, then ``1.0`` (completely opaque) will
+    be used.
+
+    Alternate form:
+        :mochiref:`Color.fromRGB({r: red, g: green, b: blue, a:
+        alpha})`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromRGBString(rgbString)`:
+
+    Returns a :mochiref:`Color` object from the given decimal rgb
+    color string.  For example, ``"rgb(255,255,255)"`` would return a
+    :mochiref:`Color` with RGB values ``[255/255, 255/255, 255/255]``
+    (white).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromText(elem)`:
+
+    Returns a :mochiref:`Color` object based on the text color of the
+    provided element. Equivalent to::
+
+        c = Color.fromComputedStyle(elem, "color") || Color.whiteColor();
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.fromString(rgbOrHexString)`:
+
+    Returns a :mochiref:`Color` object from the given RGB, HSL, hex,
+    or name.  Will return ``null`` if the string can not be parsed by
+    any of these methods.
+
+    See :mochiref:`Color.fromHexString`,
+    :mochiref:`Color.fromRGBString`, :mochiref:`Color.fromHSLString`
+    and :mochiref:`Color.fromName` more information.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.namedColors()`:
+
+    Returns an object with properties for each SVG 1.0 color keyword
+    name [2]_ supported by CSS3 [3]_. Property names are the color
+    keyword name in lowercase, and the value is a string suitable for
+    :mochiref:`Color.fromString()`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.colorWithAlpha(alpha)`:
+
+    Return a new :mochiref:`Color` based on this color, but with the
+    provided ``alpha`` value.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.colorWithHue(hue)`:
+
+    Return a new :mochiref:`Color` based on this color, but with the
+    provided ``hue`` value.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.colorWithSaturation(saturation)`:
+
+    Return a new :mochiref:`Color` based on this color, but with the
+    provided ``saturation`` value (using the HSL color model).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.colorWithLightness(lightness)`:
+
+    Return a new :mochiref:`Color` based on this color, but with the
+    provided ``lightness`` value.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.darkerColorWithLevel(level)`:
+
+    Return a new :mochiref:`Color` based on this color, but darker by
+    the given ``level`` (between ``0`` and ``1.0``).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.lighterColorWithLevel(level)`:
+
+    Return a new :mochiref:`Color` based on this color, but lighter by
+    the given ``level`` (between ``0`` and ``1.0``).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.blendedColor(other, fraction=0.5)`:
+
+    Return a new :mochiref:`Color` whose RGBA component values are a
+    weighted sum of this color and ``other``. Each component of the
+    returned color is the ``fraction`` of other's value plus ``1 -
+    fraction`` of this color's.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.isLight()`:
+
+    Return ``true`` if the lightness value of this color is greater
+    than ``0.5``.
+
+    Note that ``alpha`` is ignored for this calculation (color
+    components are not premultiplied).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.isDark()`:
+
+    Return ``true`` if the lightness value of this color is less than
+    or equal to ``0.5``.
+
+    Note that ``alpha`` is ignored for this calculation (color
+    components are not premultiplied).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.toRGBString()`:
+
+    Return the decimal ``"rgb(red, green, blue)"`` string
+    representation of this color.
+
+    If the alpha component is not ``1.0`` (fully opaque), the
+    ``"rgba(red, green, blue, alpha)"`` string representation will be
+    used.
+
+    For example::
+
+        assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.toHSLString()`:
+
+    Return the decimal ``"hsl(hue, saturation, lightness)"`` string
+    representation of this color.
+
+    If the alpha component is not ``1.0`` (fully opaque), the
+    ``"hsla(hue, saturation, lightness, alpha)"`` string
+    representation will be used.
+
+    For example::
+
+        assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.toHexString()`:
+
+    Return the hexadecimal ``"#RRGGBB"`` string representation of this
+    color.
+
+    Note that the alpha component is completely ignored for
+    hexadecimal string representations!
+
+    For example::
+
+        assert( Color.whiteColor().toHexString() == "#FFFFFF" );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.asRGB()`:
+
+    Return the RGB (red, green, blue, alpha) components of this color
+    as an object with ``r``, ``g``, ``b``, and ``a`` properties that
+    have values between ``0.0`` and ``1.0``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.asHSL()`:
+
+    Return the HSL (hue, saturation, lightness, alpha) components of
+    this color as an object with ``h``, ``s``, ``l`` and ``a``
+    properties that have values between ``0.0`` and ``1.0``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.prototype.asHSV()`:
+
+    Return the HSV (hue, saturation, value, alpha) components of this
+    color as an object with ``h``, ``s``, ``v`` and ``a`` properties
+    that have values between ``0.0`` and ``1.0``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.blackColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 0, 0, 0
+    (#000000).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.blueColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 0, 0, 1
+    (#0000ff).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.brownColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 0.6, 0.4,
+    0.2 (#996633).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.cyanColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 0, 1, 1
+    (#00ffff).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.darkGrayColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 1/3, 1/3,
+    1/3 (#555555).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.grayColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 0.5, 0.5,
+    0.5 (#808080).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.greenColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 0, 1, 0.
+    (#00ff00).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.lightGrayColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 2/3, 2/3,
+    2/3 (#aaaaaa).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.magentaColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 1, 0, 1
+    (#ff00ff).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.orangeColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 1, 0.5, 0
+    (#ff8000).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.purpleColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 0.5, 0, 0.5
+    (#800080).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.redColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 1, 0, 0
+    (#ff0000).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.whiteColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 1, 1, 1
+    (#ffffff).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.yellowColor()`:
+
+    Return a :mochiref:`Color` object whose RGB values are 1, 1, 0
+    (#ffff00).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Color.transparentColor()`:
+
+    Return a :mochiref:`Color` object that is completely transparent
+    (has alpha component of 0).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Functions
+---------
+
+:mochidef:`clampColorComponent(num, scale)`:
+
+    Returns ``num * scale`` clamped between ``0`` and ``scale``.
+
+    :mochiref:`clampColorComponent` is not exported by default when
+    using JSAN.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`hslToRGB(hue, saturation, lightness, alpha)`:
+
+    Computes RGB values from the provided HSL values. The return value
+    is a mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
+
+    Alternate form:
+        :mochiref:`hslToRGB({h: hue, s: saturation, l: lightness, a:
+        alpha})`.
+
+    :mochiref:`hslToRGB` is not exported by default when using JSAN.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`hsvToRGB(hue, saturation, value, alpha)`:
+
+    Computes RGB values from the provided HSV values. The return value
+    is a mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
+
+    Alternate form:
+        :mochiref:`hsvToRGB({h: hue, s: saturation, v: value, a:
+        alpha})`.
+
+    :mochiref:`hsvToRGB` is not exported by default when using JSAN.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toColorPart(num)`:
+
+    Convert num to a zero padded hexadecimal digit for use in a
+    hexadecimal color string. Num should be an integer between ``0``
+    and ``255``.
+
+    :mochiref:`toColorPart` is not exported by default when using
+    JSAN.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`rgbToHSL(red, green, blue, alpha)`:
+
+    Computes HSL values based on the provided RGB values. The return
+    value is a mapping with ``"h"``, ``"s"``, ``"l"`` and ``"a"``
+    keys.
+
+    Alternate form:
+        :mochiref:`rgbToHSL({r: red, g: green, b: blue, a: alpha})`.
+
+    :mochiref:`rgbToHSL` is not exported by default when using JSAN.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`rgbToHSV(red, green, blue, alpha)`:
+
+    Computes HSV values based on the provided RGB values. The return
+    value is a mapping with ``"h"``, ``"s"``, ``"v"`` and ``"a"``
+    keys.
+
+    Alternate form:
+        :mochiref:`rgbToHSV({r: red, g: green, b: blue, a: alpha})`.
+
+    :mochiref:`rgbToHSV` is not exported by default when using JSAN.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+See Also
+========
+
+.. [1] Application Kit Reference - NSColor: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html
+.. [2] SVG 1.0 color keywords: http://www.w3.org/TR/SVG/types.html#ColorKeywords
+.. [3] W3C CSS3 Color Module: http://www.w3.org/TR/css3-color/#svg-color
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/DOM.rst b/mochikit_v14/doc/rst/MochiKit/DOM.rst
new file mode 100755 (executable)
index 0000000..bad57f9
--- /dev/null
@@ -0,0 +1,1130 @@
+.. title:: MochiKit.DOM - painless DOM manipulation API
+
+Name
+====
+
+MochiKit.DOM - painless DOM manipulation API
+
+
+Synopsis
+========
+
+::
+
+    var rows = [
+        ["dataA1", "dataA2", "dataA3"],
+        ["dataB1", "dataB2", "dataB3"]
+    ];
+    row_display = function (row) {
+        return TR(null, map(partial(TD, null), row));
+    }
+    var newTable = TABLE({'class': 'prettytable'},
+        THEAD(null,
+            row_display(["head1", "head2", "head3"])),
+        TFOOT(null,
+            row_display(["foot1", "foot2", "foot3"])),
+        TBODY(null,
+            map(row_display, rows)));
+    // put that in your document.createElement and smoke it!
+    swapDOM(oldTable, newTable);
+
+
+Description
+===========
+
+As you probably know, the DOM APIs are some of the most painful
+Java-inspired APIs you'll run across from a highly dynamic
+language. Don't worry about that though, because they provide a
+reasonable basis to build something that sucks a lot less.
+
+MochiKit.DOM takes much of its inspiration from Nevow's [1]_ stan
+[2]_.  This means you choose a tag, give it some attributes, then
+stuff it full of *whatever objects you want*. MochiKit.DOM isn't
+stupid, it knows that a string should be a text node, and that you
+want functions to be called, and that ``Array``-like objects should be
+expanded, and stupid ``null`` values should be skipped.
+
+Hell, it will let you return strings from functions, and use iterators
+from :mochiref:`MochiKit.Iter`. If that's not enough, just teach it
+new tricks with :mochiref:`registerDOMConverter`. If you have never
+used an API like this for creating DOM elements, you've been wasting
+your damn time. Get with it!
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.Style` (optional since MochiKit 1.4 for
+  backwards-compatibility)
+- :mochiref:`MochiKit.Iter` (optional since MochiKit 1.4)
+
+
+Overview
+========
+
+DOM Coercion Rules
+------------------
+
+In order of precedence, :mochiref:`createDOM` coerces given arguments
+to DOM nodes using the following rules:
+
+1.  Functions are called with a ``this`` and first argument of the
+    parent node and their return value is subject to the following
+    rules (even this one).
+2.  ``undefined`` and ``null`` are ignored.
+3.  If :mochiref:`MochiKit.Iter` is loaded, iterables are flattened
+    (as if they were passed in-line as nodes) and each return value is
+    subject to these rules.
+4.  Values that look like DOM nodes (objects with a ``.nodeType > 0``)
+    are ``.appendChild``'ed to the created DOM fragment.
+5.  Strings are wrapped up with ``document.createTextNode``
+6.  Objects that have a ``.dom(node)`` or ``.__dom__(node)`` method
+    are called with the parent node and their result is coerced using
+    these rules.  (MochiKit 1.4+).
+7.  Objects that are not strings are run through the ``domConverters``
+    :mochiref:`MochiKit.Base.AdapterRegistry` (see
+    :mochiref:`registerDOMConverter`).  The adapted value is subject
+    to these same rules (e.g.  if the adapter returns a string, it
+    will be coerced to a text node).
+8.  If no adapter is available, ``.toString()`` is used to create a
+    text node.
+
+
+Creating DOM Element Trees
+--------------------------
+
+:mochiref:`createDOM` provides you with an excellent facility for
+creating DOM trees that is easy on the wrists. One of the best ways to
+understand how to use it is to take a look at an example::
+
+    var rows = [
+        ["dataA1", "dataA2", "dataA3"],
+        ["dataB1", "dataB2", "dataB3"]
+    ];
+    row_display = function (row) {
+        return TR(null, map(partial(TD, null), row));
+    }
+    var newTable = TABLE({'class': 'prettytable'},
+        THEAD(null,
+            row_display(["head1", "head2", "head3"])),
+        TFOOT(null,
+            row_display(["foot1", "foot2", "foot3"])),
+        TBODY(null,
+            map(row_display, rows)));
+
+
+This will create a table with the following visual layout (if it were
+inserted into the document DOM):
+
+    +--------+--------+--------+
+    | head1  | head2  | head3  |
+    +========+========+========+
+    | dataA1 | dataA2 | dataA3 |
+    +--------+--------+--------+
+    | dataB1 | dataB2 | dataB3 |
+    +--------+--------+--------+
+    | foot1  | foot2  | foot3  |
+    +--------+--------+--------+
+
+Corresponding to the following HTML::
+
+    <table class="prettytable">
+        <thead>
+            <tr>
+                <td>head1</td>
+                <td>head2</td>
+                <td>head3</td>
+            </tr>
+        </thead>
+        <tfoot>
+            <tr>
+                <td>foot1</td>
+                <td>foot2</td>
+                <td>foot3</td>
+            </tr>
+        </tfoot>
+        <tbody>
+            <tr>
+                <td>dataA1</td>
+                <td>dataA2</td>
+                <td>dataA3</td>
+            </tr>
+            <tr>
+                <td>dataB1</td>
+                <td>dataB2</td>
+                <td>dataB3</td>
+            </tr>
+        </tbody>
+    </table>
+
+
+DOM Context
+-----------
+
+In order to prevent having to pass a ``window`` and/or ``document``
+variable to every MochiKit.DOM function (e.g. when working with a
+child window), MochiKit.DOM maintains a context variable for each of
+them. They are managed with the :mochiref:`withWindow` and
+:mochiref:`withDocument` functions, and can be acquired with
+:mochiref:`currentWindow()` and :mochiref:`currentDocument()`
+
+For example, if you are creating DOM nodes in a child window, you
+could do something like this::
+
+    withWindow(child, function () {
+        var doc = currentDocument();
+        appendChildNodes(doc.body, H1(null, "This is in the child!"));
+    });
+
+Note that :mochiref:`withWindow(win, ...)` also implies
+:mochiref:`withDocument(win.document, ...)`.
+
+
+DOM Gotchas
+-----------
+
+Performance Tradeoff:
+    DOM is much easier to get correct and more flexible than working
+    directly with markup as strings. Modifying ``innerHTML`` is still
+    the fastest way to make document changes.
+
+Internet Explorer:
+    Internet Explorer's DOM implementation is quite poor in comparison
+    to the other popular implementations. In order to avoid memory
+    leaks due to circular references, you should use
+    :mochiref:`MochiKit.Signal.connect` for all of your event handling
+    needs. Additionally, when creating tables with DOM, it is required
+    to use a ``TBODY`` tag (see `Creating DOM Element Trees`_ for an
+    example of this).
+
+
+API Reference
+=============
+
+Functions
+---------
+
+:mochidef:`$(id[, ...])`:
+
+    An alias for :mochiref:`getElement(id[, ...])`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`addElementClass(element, className)`:
+
+    Ensure that the given ``element`` has ``className`` set as part of
+    its class attribute. This will not disturb other class names.
+    ``element`` is looked up with :mochiref:`getElement`, so string
+    identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`addLoadEvent(func)`:
+
+    Note that :mochiref:`addLoadEvent` can not be used in combination
+    with :mochiref:`MochiKit.Signal` if the ``onload`` event is
+    connected.  Once an event is connected with
+    :mochiref:`MochiKit.Signal`, no other APIs may be used for that
+    same event.
+
+    This will stack ``window.onload`` functions on top of each other.
+    Each function added will be called after ``onload`` in the order
+    that they were added.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`addToCallStack(target, path, func[, once])`:
+
+    Note that :mochiref:`addToCallStack` is not compatible with
+    :mochiref:`MochiKit.Signal`. Once an event is connected with
+    :mochiref:`MochiKit.Signal`, no other APIs may be used for that
+    same event.
+
+    Set the property ``path`` of ``target`` to a function that calls
+    the existing function at that property (if any), then calls
+    ``func``.
+
+    If ``target[path]()`` returns exactly ``false``, then ``func``
+    will not be called.
+
+    If ``once`` is ``true``, then ``target[path]`` is set to ``null``
+    after the function call stack has completed.
+
+    If called several times for the same ``target[path]``, it will
+    create a stack of functions (instead of just a pair).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`appendChildNodes(node[, childNode[, ...]])`:
+
+    Append children to a DOM element using the `DOM Coercion Rules`_.
+
+    ``node``:
+        A reference to the DOM element to add children to (if a string
+        is given, :mochiref:`getElement(node)` will be used to locate
+        the node)
+
+    ``childNode``...:
+        All additional arguments, if any, will be coerced into DOM
+        nodes that are appended as children using the `DOM Coercion
+        Rules`_.
+
+    *returns*:
+        The given DOM element
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+:mochidef:`insertSiblingNodesBefore(node[, siblingNode[, ...]])`:
+
+    Insert children into the DOM structure using the `DOM Coercion
+    Rules`_.
+
+    ``node``:
+        A reference to the DOM element you want to insert children
+        before (if a string is given, :mochiref:`getElement(node)`
+        will be used to locate the node)
+
+    ``siblingNode``...:
+        All additional arguments, if any, will be coerced into DOM
+        nodes that are inserted as siblings using the `DOM Coercion
+        Rules`_.
+
+    *returns*:
+        The parent of the given DOM element
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`insertSiblingNodesAfter(node[, siblingNode[, ...]])`:
+
+    Insert children into the DOM structure using the `DOM Coercion
+    Rules`_.
+
+    ``node``:
+        A reference to the DOM element you want to insert children
+        after (if a string is given, :mochiref:`getElement(node)`
+        will be used to locate the node)
+
+    ``siblingNode``...:
+        All additional arguments, if any, will be coerced into DOM
+        nodes that are inserted as siblings using the `DOM Coercion
+        Rules`_.
+
+    *returns*:
+        The parent of the given DOM element
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`createDOM(name[, attrs[, node[, ...]]])`:
+
+    Create a DOM fragment in a really convenient manner, much like
+    Nevow`s [1]_ stan [2]_.
+
+    Partially applied versions of this function for common tags are
+    available as aliases:
+
+    - ``A``
+    - ``BUTTON``
+    - ``BR``
+    - ``CANVAS``
+    - ``DIV``
+    - ``FIELDSET``
+    - ``FORM``
+    - ``H1``
+    - ``H2``
+    - ``H3``
+    - ``HR``
+    - ``IMG``
+    - ``INPUT``
+    - ``LABEL``
+    - ``LEGEND``
+    - ``LI``
+    - ``OL``
+    - ``OPTGROUP``
+    - ``OPTION``
+    - ``P``
+    - ``PRE``
+    - ``SELECT``
+    - ``SPAN``
+    - ``STRONG``
+    - ``TABLE``
+    - ``TBODY``
+    - ``TD``
+    - ``TEXTAREA``
+    - ``TFOOT``
+    - ``TH``
+    - ``THEAD``
+    - ``TR``
+    - ``TT``
+    - ``UL``
+
+    See `Creating DOM Element Trees`_ for a comprehensive example.
+
+    ``name``:
+        The kind of fragment to create (e.g. 'span'), such as you
+        would pass to ``document.createElement``.
+
+    ``attrs``:
+        An object whose properties will be used as the attributes
+        (e.g. ``{'style': 'display:block'}``), or ``null`` if no
+        attributes need to be set.
+
+        See :mochiref:`updateNodeAttributes` for more information.
+
+        For convenience, if ``attrs`` is a string, ``null`` is used
+        and the string will be considered the first ``node``.
+
+    ``node``...:
+        All additional arguments, if any, will be coerced into DOM
+        nodes that are appended as children using the `DOM Coercion
+        Rules`_.
+
+    *returns*:
+        A DOM element
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`createDOMFunc(tag[, attrs[, node[, ...]]])`:
+
+    Convenience function to create a partially applied createDOM
+    function. You'd want to use this if you add additional convenience
+    functions for creating tags, or if you find yourself creating a
+    lot of tags with a bunch of the same attributes or contents.
+
+    See :mochiref:`createDOM` for more detailed descriptions of the
+    arguments.
+
+    ``tag``:
+        The name of the tag
+
+    ``attrs``:
+        Optionally specify the attributes to apply
+
+    ``node``...:
+        Optionally specify any children nodes it should have
+
+    *returns*:
+        function that takes additional arguments and calls
+        :mochiref:`createDOM`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`currentDocument()`:
+
+    Return the current ``document`` `DOM Context`_. This will always
+    be the same as the global ``document`` unless
+    :mochiref:`withDocument` or :mochiref:`withWindow` is currently
+    executing.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`currentWindow()`:
+
+    Return the current ``window`` `DOM Context`_. This will always be
+    the same as the global ``window`` unless :mochiref:`withWindow` is
+    currently executing.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`emitHTML(dom[, lst])`:
+
+    Convert a DOM tree to an ``Array`` of HTML string fragments. This should
+    be used for debugging/testing purposes only.
+
+    The DOM property ``innerHTML`` or ``cloneNode(true)`` method should
+    be used for most purposes.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`escapeHTML(s)`:
+
+    Make a string safe for HTML, converting the usual suspects (lt,
+    gt, quot, amp)
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`focusOnLoad(element)`:
+
+    Note that :mochiref:`focusOnLoad` can not be used in combination
+    with :mochiref:`MochiKit.Signal` if the ``onload`` event is
+    connected.  Once an event is connected with
+    :mochiref:`MochiKit.Signal`, no other APIs may be used for that
+    same event.
+
+    This adds an onload event to focus the given element.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`formContents(elem=document.body)`:
+
+    Search the DOM tree, starting at ``elem``, for any elements with a
+    ``name`` and ``value`` attribute. Return a 2-element ``Array`` of
+    ``names`` and ``values`` suitable for use with
+    :mochiref:`MochiKit.Base.queryString`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`getElement(id[, ...])`:
+
+    A small quick little function to encapsulate the
+    ``getElementById`` method. It includes a check to ensure we can
+    use that method.
+
+    If the id isn't a string, it will be returned as-is.
+
+    Also available as :mochiref:`$(...)` for convenience and
+    compatibility with other JavaScript frameworks.
+
+    If multiple arguments are given, an ``Array`` will be returned.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`getElementsByTagAndClassName(tagName, className, parent=document)`:
+
+    Returns an array of elements in ``parent`` that match the tag name
+    and class name provided. If ``parent`` is a string, it will be
+    looked up with :mochiref:`getElement`.
+
+    If ``tagName`` is ``null`` or ``"*"``, all elements will be
+    searched for the matching class.
+
+    If ``className`` is ``null``, all elements matching the provided
+    tag are returned.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`getFirstElementByTagAndClassName(tagName, className, parent=document)`:
+
+    Return the first element in ``parent`` that matches the tag name
+    and class name provided. If ``parent`` is a string, it will be 
+    looked up with :mochiref:`getElement`.
+
+    If ``tagName`` is ``null`` or ``"*"``, all elements will be searched
+    for the matching class.
+
+    If ``className`` is ``null``, the first element matching the provided
+    tag will be returned.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`getFirstParentByTagAndClassName(elem, tagName='*', className=null)`:
+
+    Returns the first parent of ``elem`` matches the tag name and class name
+    provided. If parent is a string, it will be looked up using
+    :mochiref:`getElement`.
+
+    If ``tagName`` is ``null`` or ``"*"``, all elements will be searched
+    for the matching class.
+
+    If ``className`` is ``null``, the first element matching the provided
+    tag will be returned.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`getNodeAttribute(node, attr)`:
+
+    Get the value of the given attribute for a DOM element without
+    ever raising an exception (will return ``null`` on exception).
+
+    ``node``:
+        A reference to the DOM element to update (if a string is
+        given, :mochiref:`getElement(node)` will be used to locate the
+        node)
+
+    ``attr``:
+        The name of the attribute
+
+        Note that it will do the right thing for IE, so don't do
+        the ``class`` -> ``className`` hack yourself.
+
+    *returns*:
+        The attribute's value, or ``null``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`hasElementClass(element, className[, ...])`:
+
+    Return ``true`` if ``className`` is found on the ``element``.
+    ``element`` is looked up with :mochiref:`getElement`, so string
+    identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isChildNode(node, maybeParent)`:
+
+    Determine whether ``node`` is a child node of ``maybeParent``.
+    Returns ``true`` if so, and ``false`` if not. A node is considered
+    a child node of itself for the purposes of this function.
+
+    If either ``node`` or ``maybeParent`` are strings, the related
+    nodes will be looked up with :mochiref:`getElement`.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`isParent(child, element)`:
+
+    Returns ``true`` if ``element`` contains ``child``. Returns ``false``
+    if ``element == child`` or ``child`` is not contained in ``element``.
+    If ``child`` or ``element`` are strings, they will be looked up with
+    :mochiref:`getElement`.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`makeClipping(element)`:
+
+    Ensure that ``element.style.overflow = 'hidden'``. If ``element`` is a
+    string, then it will be looked up with :mochiref:`getElement`.
+
+    Returns the original value of ``element.style.overflow``, so that it
+    may be restored with :mochiref:`undoClipping(element, overflow)`.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`makePositioned(element)`:
+
+    Ensure that ``element.style.position`` is set to ``"relative"`` if it
+    is not set or is ``"static"``. If ``element`` is a
+    string, then it will be looked up with :mochiref:`getElement`.
+
+    Returns the original value of ``element.style.position``, so that it
+    may be restored with :mochiref:`undoPositioned(element, position)`.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`registerDOMConverter(name, check, wrap[, override])`:
+
+    Register an adapter to convert objects that match ``check(obj,
+    ctx)`` to a DOM element, or something that can be converted to a
+    DOM element (i.e. number, bool, string, function, iterable).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`removeElement(node)`:
+
+    Remove and return ``node`` from a DOM tree.
+
+    ``node``:
+        the DOM element (or string id of one) to be removed
+
+    *returns*
+        The removed element
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`removeElementClass(element, className)`:
+
+    Ensure that the given ``element`` does not have ``className`` set
+    as part of its class attribute. This will not disturb other class
+    names.  ``element`` is looked up with :mochiref:`getElement`, so
+    string identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`removeEmptyTextNodes(node)`:
+
+    Remove all text node children that contain only whitespace from
+    ``node``. Useful in situations where such empty text nodes can
+    interfere with DOM traversal.
+    
+    ``node``:
+        the DOM element (or string id of one) to remove whitespace child
+        nodes from.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`replaceChildNodes(node[, childNode[, ...]])`:
+
+    Remove all children from the given DOM element, then append any
+    given childNodes to it (by calling :mochiref:`appendChildNodes`).
+
+    ``node``:
+        A reference to the DOM element to add children to (if a string
+        is given, :mochiref:`getElement(node)` will be used to locate
+        the node)
+
+    ``childNode``...:
+        All additional arguments, if any, will be coerced into DOM
+        nodes that are appended as children using the `DOM Coercion
+        Rules`_.
+
+    *returns*:
+        The given DOM element
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`scrapeText(node[, asArray=false])`:
+
+    Walk a DOM tree in-order and scrape all of the text out of it as a
+    ``string``.
+
+    If ``asArray`` is ``true``, then an ``Array`` will be returned
+    with each individual text node. These two are equivalent::
+
+        assert( scrapeText(node) == scrapeText(node, true).join("") );
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`setElementClass(element, className)`:
+
+    Set the entire class attribute of ``element`` to ``className``.
+    ``element`` is looked up with :mochiref:`getElement`, so string
+    identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`setNodeAttribute(node, attr, value)`:
+
+    Set the value of the given attribute for a DOM element without
+    ever raising an exception (will return null on exception). If
+    setting more than one attribute, you should use
+    :mochiref:`updateNodeAttributes`.
+
+    ``node``:
+        A reference to the DOM element to update (if a string is
+        given, :mochiref:`getElement(node)` will be used to locate the
+        node)
+
+    ``attr``:
+        The name of the attribute
+
+        Note that it will do the right thing for IE, so don't do the
+        ``class`` -> ``className`` hack yourself.
+
+    ``value``:
+        The value of the attribute, may be an object to be merged
+        (e.g. for setting style).
+
+    *returns*:
+        The given DOM element or ``null`` on failure
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`swapDOM(dest, src)`:
+
+    Replace ``dest`` in a DOM tree with ``src``, returning ``src``.
+
+    ``dest``:
+        a DOM element (or string id of one) to be replaced
+
+    ``src``:
+        the DOM element (or string id of one) to replace it with, or
+        ``null`` if ``dest`` is to be removed (replaced with nothing).
+
+    *returns*:
+        a DOM element (``src``)
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`swapElementClass(element, fromClass, toClass)`:
+
+    If ``fromClass`` is set on ``element``, replace it with
+    ``toClass``.  This will not disturb other classes on that element.
+    ``element`` is looked up with :mochiref:`getElement`, so string
+    identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toggleElementClass(className[, element[, ...]])`:
+
+    Toggle the presence of a given ``className`` in the class
+    attribute of all given elements. All elements will be looked up
+    with :mochiref:`getElement`, so string identifiers are acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toHTML(dom)`:
+
+    Convert a DOM tree to a HTML string using :mochiref:`emitHTML`.
+    This should be used for debugging/testing purposes only.
+
+    The DOM property ``innerHTML`` or ``cloneNode(true)`` method should
+    be used for most purposes.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`undoClipping(element, overflow)`:
+
+    Restore the setting of ``element.style.overflow`` set by
+    :mochiref:`makeClipping(element)`. If ``element`` is a string, then
+    it will be looked up with :mochiref:`getElement`.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`undoPositioned(element, overflow)`:
+
+    Restore the setting of ``element.style.position`` set by
+    :mochiref:`makePositioned(element)`. If ``element`` is a string, then
+    it will be looked up with :mochiref:`getElement`.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`updateNodeAttributes(node, attrs)`:
+
+    Update the attributes of a DOM element from a given object.
+
+    ``node``:
+        A reference to the DOM element to update (if a string is
+        given, :mochiref:`getElement(node)` will be used to locate the
+        node)
+
+    ``attrs``:
+        An object whose properties will be used to set the attributes
+        (e.g. ``{'class': 'invisible'}``), or ``null`` if no
+        attributes need to be set. If an object is given for the
+        attribute value (e.g. ``{'style': {'display': 'block'}}``)
+        then :mochiref:`MochiKit.Base.updatetree` will be used to set
+        that attribute.
+
+        Note that it will do the right thing for IE, so don't do the
+        ``class`` -> ``className`` hack yourself, and it deals with
+        setting "on..." event handlers correctly.
+
+    *returns*:
+        The given DOM element
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`withWindow(win, func)`:
+
+    Call ``func`` with the ``window`` `DOM Context`_ set to ``win``
+    and the ``document`` `DOM Context`_ set to ``win.document``. When
+    ``func()`` returns or throws an error, the `DOM Context`_ will be
+    restored to its previous state.
+
+    The return value of ``func()`` is returned by this function.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`withDocument(doc, func)`:
+
+    Call ``func`` with the ``doc`` `DOM Context`_ set to ``doc``.
+    When ``func()`` returns or throws an error, the `DOM Context`_
+    will be restored to its previous state.
+
+    The return value of ``func()`` is returned by this function.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Style Functions
+---------------
+
+These functions are available in MochiKit 1.3.1, but have been moved to 
+:mochiref:`MochiKit.Style` in 1.4+.
+
+
+:mochidef:`computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)`:
+
+    Looks up a CSS property for the given element. The element can be
+    specified as either a string with the element's ID or the element
+    object itself.
+    
+    ``cssProperty``:
+        MochiKit 1.3.1 expects camel case, e.g. ``backgroundColor``.
+        MochiKit 1.4+ expects CSS selector case, e.g. ``background-color``,
+        but will accept camel case for backwards-compatibility.
+        
+    ``mozillaEquivalentCSS``:
+        MochiKit 1.3.1 expects selector case.
+        MochiKit 1.4+ ignores this argument.
+
+    *Availability*:
+        Available in MochiKit 1.3.1, deprecated in favor of
+        :mochiref:`MochiKit.Style.getStyle` in 1.4+
+
+
+:mochidef:`elementDimensions(element)`:
+
+    Return the absolute pixel width and height (including padding and border,
+    but not margins) of ``element`` as an object with ``w`` and ``h``
+    properties, or ``undefined`` if ``element`` is not in the document.
+    ``element`` may be specified as a string to be looked up with
+    :mochiref:`getElement`, a DOM element, or trivially as an object with
+    ``w`` and/or ``h`` properties.
+
+    *Availability*:
+        Available in MochiKit 1.3.1, deprecated in favor of
+        :mochiref:`MochiKit.Style.getElementDimensions` in 1.4+
+
+
+:mochidef:`elementPosition(element[, relativeTo={x: 0, y: 0}])`:
+
+    Return the absolute pixel position of ``element`` in the document
+    as an object with ``x`` and ``y`` properties, or ``undefined`` if
+    ``element`` is not in the document. ``element`` may be specified
+    as a string to be looked up with :mochiref:`getElement`, a DOM
+    element, or trivially as an object with ``x`` and/or ``y``
+    properties.
+
+    If ``relativeTo`` is given, then its coordinates are subtracted from
+    the absolute position of ``element``, e.g.::
+
+        var elemPos = elementPosition(elem);
+        var anotherElemPos = elementPosition(anotherElem);
+        var relPos = elementPosition(elem, anotherElem);
+        assert( relPos.x == (elemPos.x - anotherElemPos.x) );
+        assert( relPos.y == (elemPos.y - anotherElemPos.y) );
+
+    ``relativeTo`` may be specified as a string to be looked up with
+    :mochiref:`getElement`, a DOM element, or trivially as an object
+    with ``x`` and/or ``y`` properties.
+
+    *Availability*:
+        Available in MochiKit 1.3.1, deprecated in favor of
+        :mochiref:`MochiKit.Style.getElementPosition` in 1.4+
+
+
+:mochidef:`getViewportDimensions()`:
+
+    Return the pixel width and height of the viewport as an object
+    with ``w`` and ``h`` properties. ``element`` is looked up with
+    :mochiref:`getElement`, so string identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1, moved to
+        :mochiref:`MochiKit.Style.getViewportDimensions` in 1.4+
+
+
+:mochidef:`hideElement(element, ...)`:
+
+    Partial form of :mochiref:`setDisplayForElement`, specifically::
+
+        partial(setDisplayForElement, "none")
+
+    For information about the caveats of using a ``style.display``
+    based show/hide mechanism, and a CSS based alternative, see
+    `Element Visibility`_.
+
+.. _`Element Visibility`: Style.html#element-visibility
+
+    *Availability*:
+        Available in MochiKit 1.3.1, moved to 
+        :mochiref:`MochiKit.Style.hideElement` in 1.4+
+
+
+:mochidef:`setElementDimensions(element, dimensions[, units='px'])`:
+
+    Sets the dimensions of ``element`` in the document from an object
+    with ``w`` and ``h`` properties.
+
+    ``node``:
+        A reference to the DOM element to update (if a string is
+        given, :mochiref:`getElement(node)` will be used to locate the
+        node)
+
+    ``dimensions``:
+        An object with ``w`` and ``h`` properties
+
+    ``units``:
+        Optionally set the units to use, default is ``px``
+
+    *Availability*:
+        Available in MochiKit 1.3.1, moved to 
+        :mochiref:`MochiKit.Style.setElementDimensions` in 1.4+
+
+
+:mochidef:`setElementPosition(element, position[, units='px'])`:
+
+    Sets the absolute position of ``element`` in the document from an
+    object with ``x`` and ``y`` properties.
+
+    ``node``:
+        A reference to the DOM element to update (if a string is
+        given, :mochiref:`getElement(node)` will be used to locate the
+        node)
+
+    ``position``:
+        An object with ``x`` and ``y`` properties
+
+    ``units``:
+        Optionally set the units to use, default is ``px``
+
+    *Availability*:
+        Available in MochiKit 1.3.1, moved to 
+        :mochiref:`MochiKit.Style.setElementPosition` in 1.4+
+
+
+:mochidef:`setDisplayForElement(display, element[, ...])`:
+
+    Change the ``style.display`` for the given element(s). Usually
+    used as the partial forms:
+
+    - :mochiref:`showElement(element, ...)`
+    - :mochiref:`hideElement(element, ...)`
+
+    Elements are looked up with :mochiref:`getElement`, so string
+    identifiers are acceptable.
+
+    For information about the caveats of using a ``style.display``
+    based show/hide mechanism, and a CSS based alternative, see
+    `Element Visibility`_.
+
+    *Availability*:
+        Available in MochiKit 1.3.1, moved to 
+        :mochiref:`MochiKit.Style.setDisplayForElement` in 1.4+
+
+
+:mochidef:`setOpacity(element, opacity)`:
+
+    Sets ``opacity`` for ``element``. Valid ``opacity`` values range
+    from 0 (invisible) to 1 (opaque). ``element`` is looked up with
+    :mochiref:`getElement`, so string identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1, moved to 
+        :mochiref:`MochiKit.Style.setOpacity` in 1.4+
+
+
+:mochidef:`showElement(element, ...)`:
+
+    Partial form of :mochiref:`setDisplayForElement`, specifically::
+
+        partial(setDisplayForElement, "block")
+
+    For information about the caveats of using a ``style.display``
+    based show/hide mechanism, and a CSS based alternative, see
+    `Element Visibility`_.
+
+    *Availability*:
+        Available in MochiKit 1.3.1, moved to 
+        :mochiref:`MochiKit.Style.showElement` in 1.4+
+
+
+Style Objects
+-------------
+
+These objects are available in MochiKit 1.3.1, but have been moved to 
+:mochiref:`MochiKit.Style` in 1.4+.
+
+:mochidef:`Coordinates(x, y)`:
+
+    Constructs an object with ``x`` and ``y`` properties. ``obj.toString()`` 
+    returns something like ``{x: 0, y: 42}`` for debugging.
+
+    *Availability*:
+    Available in MochiKit 1.3.1, moved to 
+    :mochiref:`MochiKit.Style.Coordinates` in 1.4+
+
+:mochidef:`Dimensions(w, h)`:
+
+    Constructs an object with ``w`` and ``h`` properties. ``obj.toString()`` 
+    returns something like ``{w: 0, h: 42}`` for debugging.
+
+    *Availability*:
+    Available in MochiKit 1.3.1, moved to 
+    :mochiref:`MochiKit.Style.Dimensions` in 1.4+
+
+
+
+See Also
+========
+
+.. [1] Nevow, a web application construction kit for Python:
+       http://divmod.org/trac/wiki/DivmodNevow
+.. [2] nevow.stan is a domain specific language for Python (read as
+       "crazy getitem/call overloading abuse") that Donovan and I
+       schemed up at PyCon 2003 at this super ninja Python/C++
+       programmer's (David Abrahams) hotel room. Donovan later
+       inflicted this upon the masses in Nevow. Check out the Nevow
+       Guide for some examples:
+       http://divmod.org/trac/wiki/DivmodNevow
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/DateTime.rst b/mochikit_v14/doc/rst/MochiKit/DateTime.rst
new file mode 100755 (executable)
index 0000000..48f36e3
--- /dev/null
@@ -0,0 +1,145 @@
+.. title:: MochiKit.DateTime - "what time is it anyway?"
+
+Name
+====
+
+MochiKit.DateTime - "what time is it anyway?"
+
+
+Synopsis
+========
+
+::
+
+   stringDate = toISOTimestamp(new Date());
+   dateObject = isoTimestamp(stringDate);
+
+
+Description
+===========
+
+Remote servers don't give you JavaScript Date objects, and they
+certainly don't want them from you, so you need to deal with string
+representations of dates and timestamps. MochiKit.Date does that.
+
+
+Dependencies
+============
+
+None.
+
+
+API Reference
+=============
+
+Functions
+---------
+
+:mochidef:`isoDate(str)`:
+
+    Convert an ISO 8601 date (YYYY-MM-DD) to a ``Date`` object.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`isoTimestamp(str)`:
+
+    Convert any ISO 8601 [1]_ timestamp (or something reasonably close
+    to it) to a ``Date`` object. Will accept the "de facto" form:
+
+        YYYY-MM-DD hh:mm:ss
+
+    or (the proper form):
+
+        YYYY-MM-DDThh:mm:ssZ
+
+    If a time zone designator ("Z" or "[+-]HH:MM") is not present,
+    then the local timezone is used.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toISOTime(date)`:
+
+    Convert a ``Date`` object to a string in the form of hh:mm:ss
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toISOTimestamp(date, realISO=false)`:
+
+    Convert a ``Date`` object to something that's ALMOST but not quite
+    an ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it
+    would be:
+
+        YYYY-MM-DDThh:mm:ssZ
+
+    However, we see junk in SQL and other places that looks like this:
+
+        YYYY-MM-DD hh:mm:ss
+
+    So, this function returns the latter form, despite its name,
+    unless you pass ``true`` for ``realISO``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toISODate(date)`:
+
+    Convert a ``Date`` object to an ISO 8601 [1]_ date string
+    (YYYY-MM-DD)
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`americanDate(str)`:
+
+    Converts a MM/DD/YYYY date to a ``Date`` object
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toPaddedAmericanDate(date)`:
+
+    Converts a ``Date`` object to an MM/DD/YYYY date, e.g. 01/01/2001
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toAmericanDate(date)`:
+
+    Converts a ``Date`` object to an M/D/YYYY date, e.g. 1/1/2001
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+See Also
+========
+
+.. [1] W3C profile of ISO 8601: http://www.w3.org/TR/NOTE-datetime
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/DragAndDrop.rst b/mochikit_v14/doc/rst/MochiKit/DragAndDrop.rst
new file mode 100755 (executable)
index 0000000..b42caf4
--- /dev/null
@@ -0,0 +1,197 @@
+.. title:: MochiKit.DragAndDrop - drag and drop elements with MochiKit
+
+Name
+====
+
+MochiKit.DragAndDrop - drag and drop elements with MochiKit
+
+Synopsis
+========
+
+::
+
+    // Create a draggable
+    new Draggable('mydrag');
+
+    // Create a corresponding droppable
+    new Droppable('mydrop', {
+        accept: ['drag-class'],
+        ondrop: function (element) {
+            alert('"' + element.id + '" was dropped on me');
+        }
+    });
+
+Description
+===========
+
+MochiKit.DragAndDrop enables you the power of dragging elements
+through your pages, for richer interfaces.
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.Iter`
+- :mochiref:`MochiKit.DOM`
+- :mochiref:`MochiKit.Color`
+- :mochiref:`MochiKit.Visual`
+- :mochiref:`MochiKit.Signal`
+
+Overview
+========
+
+The implementation was adapted from Scriptaculous_.
+
+.. _Scriptaculous: http://script.aculo.us
+
+API Reference
+=============
+
+Constructors
+------------
+
+:mochidef:`Draggable(element[, options])`:
+
+    A object that can be drag with the mouse.
+
+    You have the following options, with corresponding default values:
+
+    ``handle (false)``:
+        Option for giving the element where starting the drag. By
+        default it's the element itself, but you can either put a
+        class of a subelement or the id of another element as handle.
+
+    ``starteffect (MochiKit.Visual.Opacity)``:
+        Function called once the drag has begun, taking the dragged
+        element as argument. It's an effect by default but you can
+        define any callback.
+
+    ``reverteffect (MochiKit.Visual.Move)``:
+        Effect applied when drag is cancelled. You have to define the
+        ``revert`` option to enable the call. By default it brings the
+        element back to its initial position, so you should know what
+        you want when you modify this. The function should return an
+        effect that can be cancelled.
+
+    ``endeffect (MochiKit.Visual.Opacity)``:
+        Pending part of starteffect. If you have modified your element
+        during start, you'd usually want to revert it in the function.
+
+    ``zindex (1000)``:
+        Zindex of the drag element. By default it brings it to front.
+
+    ``revert (false)``:
+        Indicate if the reverteffect function should be called. If you
+        define a function here, this function will be called before
+        reverteffect, with the element as first argument.
+
+    ``snap (false)``:
+        Define the behaviour of the drag element when moving. It can
+        either be a function, a value or an array of two values. If
+        it's a function, it should take the (x, y) position of the
+        element as arguments, and return the position draw in the
+        browser. If its a value, it's used as a modulo for each
+        coordinates. If it's an array, each value is applied for the
+        corresponding coordinate.
+
+    ``selectclass (null)``:
+        If defined, name of CSS class applied during the drag.
+
+    ``ghosting (null)``:
+        Make a ghost from the draggable: clone it at start, then
+        remove the clone at end.
+
+    ``onchange  (MochiKit.Base.noop)``:
+        Function called when updates are made on the draggable object.
+
+    ``scroll (false)``:
+        Element to scroll around, if precised. For example, 'window'
+        will allow the draggable to scroll in the page.
+
+    ``scrollSensitivity (20)``:
+        Scroll sensitivity, used when scroll is used.
+
+    ``scrollSpeed (15)``:
+        Scroll speed, used when scroll is used.
+
+    A draggable generates some signals during its lifetime: start, drag and
+    end. They are available through the Draggables handler, and are called
+    with a draggable as argument. You can register a callback for these events
+    like this::
+        
+        onStart = function (draggable) {
+            // Do some stuff
+        };
+
+        connect(Draggables, 'start', onStart);
+
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Droppable(element[, options])`:
+
+    A object where you can drop a draggable.
+
+    You have the following options, with corresponding default values:
+
+    ``greedy (true)``:
+        Stop on this droppable when a draggable drops over it.
+
+    ``hoverclass (null)``:
+        If defined, name of CSS class applied when a draggable is
+        hover the droppable element (hover state).
+
+    ``hoverfunc (MochiKit.Base.noop)``:
+        Function called on hover state.
+
+    ``accept (null)``:
+        Array of CSS classes allowed to drop on this.
+
+    ``activeclass (null)``:
+        If defined, name of CSS class applied if a possible draggable
+        begins its start (active state).
+
+    ``onactive (MochiKit.Base.noop)``:
+        Function called on active state.
+
+    ``containment ([])``:
+        Specify a list of elements to check for active state: only the
+        children of the specified elements can be dropped. Mainly
+        useful for Sortable.
+
+    ``onhover (MochiKit.Base.noop)``:
+        Specific hover function, mainly used for Sortable.
+
+    ``ondrop (MochiKit.Base.noop)``:
+        Function called when a draggable is dropped. The function
+        takes three arguments: the draggable element, the droppable
+        element, and the event that raised the drop.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Authors
+=======
+
+- Thomas Herve <therve@gmail.com>
+- Bob Ippolito <bob@redivi.com>
+- Originally adapted from Script.aculo.us <http://script.aculo.us/>
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>.  This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
+
+Portions adapted from `Scriptaculous`_ are available under the terms
+of the `MIT License`_.
+
+
diff --git a/mochikit_v14/doc/rst/MochiKit/Format.rst b/mochikit_v14/doc/rst/MochiKit/Format.rst
new file mode 100755 (executable)
index 0000000..f1e29ac
--- /dev/null
@@ -0,0 +1,249 @@
+.. title:: MochiKit.Format - string formatting goes here
+
+Name
+====
+
+MochiKit.Format - string formatting goes here
+
+
+Synopsis
+========
+
+::
+
+   assert( truncToFixed(0.12345, 4) == "0.1234" );
+   assert( roundToFixed(0.12345, 4) == "0.1235" );
+   assert( twoDigitAverage(1, 0) == "0" );
+   assert( twoDigitFloat(1.2345) == "1.23" );
+   assert( twoDigitFloat(1) == "1" );
+   assert( percentFormat(1.234567) == "123.46%" );
+   assert( numberFormatter("###,###%")(125) == "12,500%" );
+   assert( numberFormatter("##.000")(1.25) == "1.250" );
+
+
+Description
+===========
+
+Formatting strings and stringifying numbers is boring, so a couple
+useful functions in that domain live here.
+
+
+Dependencies
+============
+
+None.
+
+
+Overview
+========
+
+Formatting Numbers
+------------------
+
+MochiKit provides an extensible number formatting facility, modeled
+loosely after the Number Format Pattern Syntax [1]_ from Java.
+:mochiref:`numberFormatter(pattern[, placeholder=""[,
+locale="default"])` returns a function that converts Number to string
+using the given information.  ``pattern`` is a string consisting of
+the following symbols:
+
++-----------+---------------------------------------------------------------+
+| Symbol    |   Meaning                                                     |
++===========+===============================================================+
+| ``-``     |   If given, used as the position of the minus sign            |
+|           |   for negative numbers. If not given, the position            |
+|           |   to the left of the first number placeholder is used.        |
++-----------+---------------------------------------------------------------+
+| ``#``     |   The placeholder for a number that does not imply zero       |
+|           |   padding.                                                    |
++-----------+---------------------------------------------------------------+
+| ``0``     |   The placeholder for a number that implies zero padding.     |
+|           |   If it is used to the right of a decimal separator, it       |
+|           |   implies trailing zeros, otherwise leading zeros.            |
++-----------+---------------------------------------------------------------+
+| ``,``     |   The placeholder for a "thousands separator". May be used    |
+|           |   at most once, and it must be to the left of a decimal       |
+|           |   separator. Will be replaced by ``locale.separator`` in the  |
+|           |   result (the default is also ``,``).                         |
++-----------+---------------------------------------------------------------+
+| ``.``     |   The decimal separator. The quantity of ``#`` or ``0``       |
+|           |   after the decimal separator will determine the precision of |
+|           |   the result. If no decimal separator is present, the         |
+|           |   fractional precision is ``0`` -- meaning that it will be    |
+|           |   rounded to the nearest integer.                             |
++-----------+---------------------------------------------------------------+
+| ``%``     |   If present, the number will be multiplied by ``100`` and    |
+|           |   the ``%`` will be replaced by ``locale.percent``.           |
++-----------+---------------------------------------------------------------+
+
+
+API Reference
+=============
+
+Functions
+---------
+
+:mochidef:`formatLocale(locale="default")`:
+
+    Return a locale object for the given locale. ``locale`` may be
+    either a string, which is looked up in the
+    ``MochiKit.Format.LOCALE`` object, or a locale object. If no
+    locale is given, ``LOCALE.default`` is used (equivalent to
+    ``LOCALE.en_US``).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`lstrip(str, chars="\\s")`:
+
+    Returns a string based on ``str`` with leading whitespace
+    stripped.
+
+    If ``chars`` is given, then that expression will be used instead
+    of whitespace. ``chars`` should be a string suitable for use in a
+    ``RegExp`` ``[character set]``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`numberFormatter(pattern, placeholder="", locale="default")`:
+
+    Return a function ``formatNumber(aNumber)`` that formats numbers
+    as a string according to the given pattern, placeholder and
+    locale.
+
+    ``pattern`` is a string that describes how the numbers should be
+    formatted, for more information see `Formatting Numbers`_.
+
+    ``locale`` is a string of a known locale (en_US, de_DE, fr_FR,
+    default) or an object with the following fields:
+
+    +-----------+-----------------------------------------------------------+
+    | separator | The "thousands" separator for this locale (en_US is ",")  |
+    +-----------+-----------------------------------------------------------+
+    | decimal   | The decimal separator for this locale (en_US is ".")      |
+    +-----------+-----------------------------------------------------------+
+    | percent   | The percent symbol for this locale (en_US is "%")         |
+    +-----------+-----------------------------------------------------------+
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`percentFormat(someFloat)`:
+
+    Roughly equivalent to: ``sprintf("%.2f%%", someFloat * 100)``
+
+    In new code, you probably want to use:
+    :mochiref:`numberFormatter("#.##%")(someFloat)` instead.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`roundToFixed(aNumber, precision)`:
+
+    Return a string representation of ``aNumber``, rounded to
+    ``precision`` digits with trailing zeros. This is similar to
+    ``Number.toFixed(aNumber, precision)``, but this has
+    implementation consistent rounding behavior (some versions of
+    Safari round 0.5 down!)  and also includes preceding ``0`` for
+    numbers less than ``1`` (Safari, again).
+
+    For example, :mochiref:`roundToFixed(0.1357, 2)` returns ``0.14``
+    on every supported platform, where some return ``.13`` for
+    ``(0.1357).toFixed(2)``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`rstrip(str, chars="\\s")`:
+
+    Returns a string based on ``str`` with trailing whitespace stripped.
+
+    If ``chars`` is given, then that expression will be used instead
+    of whitespace. ``chars`` should be a string suitable for use in a
+    ``RegExp`` ``[character set]``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`strip(str, chars="\\s")`:
+
+    Returns a string based on ``str`` with leading and trailing
+    whitespace stripped (equivalent to :mochiref:`lstrip(rstrip(str,
+    chars), chars)`).
+
+    If ``chars`` is given, then that expression will be used instead
+    of whitespace. ``chars`` should be a string suitable for use in a
+    ``RegExp`` ``[character set]``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`truncToFixed(aNumber, precision)`:
+
+    Return a string representation of ``aNumber``, truncated to
+    ``precision`` digits with trailing zeros. This is similar to
+    ``aNumber.toFixed(precision)``, but this truncates rather than
+    rounds and has implementation consistent behavior for numbers less
+    than 1.  Specifically, :mochiref:`truncToFixed(aNumber,
+    precision)` will always have a preceding ``0`` for numbers less
+    than ``1``.
+
+    For example, :mochiref:`truncToFixed(0.1357, 2)` returns ``0.13``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`twoDigitAverage(numerator, denominator)`:
+
+    Calculate an average from a numerator and a denominator and return
+    it as a string with two digits of precision (e.g. "1.23").
+
+    If the denominator is 0, "0" will be returned instead of ``NaN``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`twoDigitFloat(someFloat)`:
+
+    Roughly equivalent to: ``sprintf("%.2f", someFloat)``
+
+    In new code, you probably want to use
+    :mochiref:`numberFormatter("#.##")(someFloat)` instead.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+See Also
+========
+
+.. [1] Java Number Format Pattern Syntax:
+       http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/Iter.rst b/mochikit_v14/doc/rst/MochiKit/Iter.rst
new file mode 100755 (executable)
index 0000000..689eec9
--- /dev/null
@@ -0,0 +1,454 @@
+.. title:: MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy
+
+Name
+====
+
+MochiKit.Iter - itertools for JavaScript; iteration made HARD, and
+then easy
+
+
+Synopsis
+========
+
+::
+
+
+    theSum = sum(takewhile(
+            partial(operator.gt, 10),
+            imap(
+                partial(operator.mul, 2),
+                count()
+            )
+        )
+    ));
+
+    assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) );
+
+
+Description
+===========
+
+All of the functional programming missing from
+:mochiref:`MochiKit.Base` lives here. The functionality in this module
+is largely inspired by Python's iteration protocol [1]_, and the
+itertools module [2]_.
+
+MochiKit.Iter defines a standard way to iterate over anything, that
+you can extend with :mochiref:`registerIterator`, or by implementing
+the ``.iter()`` or ``.__iterator__()`` (in MochiKit 1.4+) protocol.
+Iterators are lazy, so it can potentially be
+cheaper to build a filter chain of iterators than to build lots of
+intermediate arrays.  Especially when the data set is very large, but
+the result is not.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+
+
+Overview
+========
+
+Iteration for JavaScript
+------------------------
+
+The best overview right now is in my Iteration for JavaScript [3]_
+blog entry.  This information will migrate here eventually.
+
+API Reference
+=============
+
+Errors
+------
+
+:mochidef:`StopIteration`:
+
+    The singleton :mochiref:`MochiKit.Base.NamedError` that signifies
+    the end of an iterator
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Functions
+---------
+
+:mochidef:`applymap(fun, seq[, self])`:
+
+    ``applymap(fun, seq)`` -->
+    fun.apply(self, seq0), fun.apply(self, seq1), ...
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`chain(p, q[, ...])`:
+
+    ``chain(p, q, ...)`` --> p0, p1, ... plast, q0, q1, ...
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`count(n=0)`:
+
+    ``count(n=0)`` --> n, n + 1, n + 2, ...
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`cycle(p)`:
+
+    ``cycle(p)`` --> p0, p1, ... plast, p0, p1, ...
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`dropwhile(pred, seq)`:
+
+    ``dropwhile(pred, seq)`` --> seq[n], seq[n + 1], starting when
+    pred(seq[n]) fails
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`every(iterable, func)`:
+
+    Return ``true`` if ``func(item)`` is ``true`` for every item in
+    ``iterable``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`exhaust(iterable)`:
+
+    Exhausts an iterable without saving the results anywhere, like
+    :mochiref:`list(iterable)` when you don't care what the output is.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`forEach(iterable, func[, self])`:
+
+    Call ``func`` for each item in ``iterable``, and don't save the
+    results.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`groupby(iterable[, keyfunc])`:
+
+    Make an iterator that returns consecutive keys and groups from the
+    iterable. The key is a function computing a key value for each
+    element.  If not specified or is None, key defaults to an identity
+    function and returns the element unchanged. Generally, the
+    iterable needs to already be sorted on the same key function.
+
+    The returned group is itself an iterator that shares the
+    underlying iterable with :mochiref:`groupby()`. Because the source
+    is shared, when the groupby object is advanced, the previous group
+    is no longer visible.  So, if that data is needed later, it should
+    be stored as an array::
+
+        var groups = [];
+        var uniquekeys = [];
+        forEach(groupby(data, keyfunc), function (key_group) {
+            groups.push(list(key_group[1]));
+            uniquekeys.push(key_group[0]);
+        });
+
+    As a convenience, :mochiref:`groupby_as_array()` is provided to
+    suit the above use case.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`groupby_as_array(iterable[, keyfunc])`:
+
+    Perform the same task as :mochiref:`groupby()`, except return an
+    array of arrays instead of an iterator of iterators.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`iextend(lst, iterable)`:
+
+    Just like :mochiref:`list(iterable)`, except it pushes results on
+    ``lst`` rather than creating a new one.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`ifilter(pred, seq)`:
+
+    ``ifilter(pred, seq)`` --> elements of seq where ``pred(elem)`` is
+    ``true``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`ifilterfalse(pred, seq)`:
+
+    ``ifilterfalse(pred, seq)`` --> elements of seq where
+    ``pred(elem)`` is ``false``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`imap(fun, p, q[, ...])`:
+
+    ``imap(fun, p, q, ...)`` --> fun(p0, q0, ...), fun(p1, q1, ...),
+    ...
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`islice(seq, [start,] stop[, step])`:
+
+    ``islice(seq, [start,] stop[, step])`` --> elements from
+    seq[start:stop:step] (in Python slice syntax)
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`iter(iterable[, sentinel])`:
+
+    Convert the given argument to an iterator (object implementing
+    ``.next()``).
+
+    1. If ``iterable`` is an iterator (implements ``.next()``), then
+       it will be returned as-is.
+    2. If ``iterable`` is an iterator factory (implements
+       ``.iter()``), then the result of ``iterable.iter()`` will be
+       returned.
+    3. If ``iterable`` is a JavaScript 1.7 iterator factory (implements
+       ``.__iterable__()``), then the result of ``iterable.__iterable__()``
+       will be returned (MochiKit 1.4+). 
+    4. Otherwise, the iterator factory
+       :mochiref:`MochiKit.Base.AdapterRegistry` is used to find a
+       match.
+    5. If no factory is found, it will throw ``TypeError``
+
+    Built-in iterator factories are present for Array-like objects,
+    and objects that implement the ``iterateNext`` protocol (e.g. the
+    result of Mozilla's ``document.evaluate``).
+
+    When used directly, using an iterator should look like this::
+
+        var it = iter(iterable);
+        try {
+            while (var o = it.next()) {
+                // use o
+            }
+        } catch (e) {
+            if (e != StopIteration) {
+                throw e;
+            }
+            // pass
+        }
+
+    This is ugly, so you should use the higher order functions to work
+    with iterators whenever possible.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`izip(p, q[, ...])`:
+
+    ``izip(p, q, ...)`` --> [p0, q0, ...], [p1, q1, ...], ...
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`list(iterable)`:
+
+    Convert ``iterable`` to a new ``Array``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`next(iterator)`:
+
+    Return ``iterator.next()``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`range([start,] stop[, step])`:
+
+    Return an iterator containing an arithmetic progression of integers.
+
+    ``range(i, j)`` returns :mochiref:`iter([i, i + 1, i + 2, ..., j -
+    1])`
+
+    ``start`` (!) defaults to ``0``. When ``step`` is given, it
+    specifies the increment (or decrement). The end point is omitted!
+
+    For example, ``range(4)`` returns :mochiref:`iter([0, 1, 2, 3])`.
+    This iterates over exactly the valid indexes for an array of 4
+    elements.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`reduce(fn, iterable[, initial])`:
+
+    Apply ``fn(a, b)`` cumulatively to the items of an iterable from
+    left to right, so as to reduce the iterable to a single value.
+
+    For example::
+
+        reduce(function (a, b) { return x + y; }, [1, 2, 3, 4, 5])
+
+    calculates::
+
+        ((((1 + 2) + 3) + 4) + 5).
+
+    If initial is given, it is placed before the items of the sequence
+    in the calculation, and serves as a default when the sequence is
+    empty.
+
+    Note that the above example could be written more clearly as::
+
+        reduce(operator.add, [1, 2, 3, 4, 5])
+
+    Or even simpler::
+
+        sum([1, 2, 3, 4, 5])
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`registerIteratorFactory(name, check, iterfactory[, override])`:
+
+    Register an iterator factory for use with the iter function.
+
+    ``check`` is a ``function(a)`` that returns ``true`` if ``a`` can
+    be converted into an iterator with ``iterfactory``.
+
+    ``iterfactory`` is a ``function(a)`` that returns an object with a
+    ``.next()`` method that returns the next value in the sequence.
+
+    ``iterfactory`` is guaranteed to only be called if ``check(a)``
+    returns a true value.
+
+    If ``override`` is ``true``, then it will be made the
+    highest precedence iterator factory. Otherwise, the lowest.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`repeat(elem[, n])`:
+
+    ``repeat(elem, [,n])`` --> elem, elem, elem, ... endlessly or up
+    to n times
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`reversed(iterable)`:
+
+    Return a reversed array from iterable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`some(iterable, func)`:
+
+    Return ``true`` if ``func(item)`` is ``true`` for at least one
+    item in ``iterable``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`sorted(iterable[, cmp])`:
+
+    Return a sorted array from iterable.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`sum(iterable, start=0)`:
+
+    Returns the sum of a sequence of numbers plus the value of
+    parameter ``start`` (with a default of 0). When the sequence is
+    empty, returns start.
+
+    Equivalent to::
+
+        reduce(operator.add, iterable, start);
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`takewhile(pred, seq)`:
+
+    ``takewhile(pred, seq)`` --> seq[0], seq[1], ... until
+    pred(seq[n]) fails
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`tee(iterable, n=2)`:
+
+    ``tee(it, n=2)`` --> [it1, it2, it3, ... itn] splits one iterator
+    into n
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+See Also
+========
+
+.. [1] The iteration protocol is described in
+       PEP 234 - Iterators: http://www.python.org/peps/pep-0234.html
+.. [2] Python's itertools
+       module: http://docs.python.org/lib/module-itertools.html
+.. [3] Iteration in JavaScript: http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/Logging.rst b/mochikit_v14/doc/rst/MochiKit/Logging.rst
new file mode 100755 (executable)
index 0000000..9ea8b21
--- /dev/null
@@ -0,0 +1,345 @@
+.. title:: MochiKit.Logging - we're all tired of alert()
+
+Name
+====
+
+MochiKit.Logging - we're all tired of alert()
+
+
+Synopsis
+========
+
+::
+
+    log("INFO messages are so boring");
+    logDebug("DEBUG messages are even worse");
+    log("good thing I can pass", objects, "conveniently");
+
+
+Description
+===========
+
+MochiKit.Logging steals some ideas from Python's logging module [1]_,
+but completely forgot about the Java [2]_ inspiration. This is a KISS
+module for logging that provides enough flexibility to do just about
+anything via listeners, but without all the cruft.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+
+
+Overview
+========
+
+Native Console Logging
+----------------------
+
+As of MochiKit 1.3, the default logger will log all messages to your
+browser's native console. This is currently supported in Safari, Opera
+9, and Firefox when the `FireBug`_ extension is installed. MochiKit
+1.4 adds support for the relevant APIs for Internet Explorer (the
+Debugger and the Atlas framework, see `here`__).
+
+.. __: http://www.nikhilk.net/Entry.aspx?id=93
+.. _`FireBug`: http://www.joehewitt.com/software/firebug/
+
+To disable this behavior::
+
+    MochiKit.Logging.logger.useNativeConsole = false;
+
+
+Bookmarklet Based Debugging
+---------------------------
+
+JavaScript is at a serious disadvantage without a standard console for
+"print" statements. Everything else has one. The closest thing that
+you get in a browser environment is the ``alert`` function, which is
+absolutely evil.
+
+This leaves you with one reasonable solution: do your logging in the
+page somehow. The problem here is that you don't want to clutter the
+page with debugging tools. The solution to that problem is what we
+call BBD, or Bookmarklet Based Debugging [3]_.
+
+Simply create a bookmarklet for
+`javascript:MochiKit.Logging.logger.debuggingBookmarklet()`__, and
+whack it whenever you want to see what's in the logger. Of course,
+this means you must drink the MochiKit.Logging kool-aid. It's tangy
+and sweet, don't worry.
+
+.. __: javascript:MochiKit.Logging.logger.debuggingBookmarklet()
+
+Currently this is an ugly ``alert``, but we'll have something spiffy
+Real Soon Now, and when we do, you only have to upgrade
+MochiKit.Logging, not your bookmarklet!
+
+
+API Reference
+=============
+
+Constructors
+------------
+
+:mochidef:`LogMessage(num, level, info)`:
+
+    Properties:
+
+        ``num``:
+            Identifier for the log message
+
+        ``level``:
+            Level of the log message (``"INFO"``, ``"WARN"``,
+            ``"DEBUG"``, etc.)
+
+        ``info``:
+            All other arguments passed to log function as an ``Array``
+
+        ``timestamp``:
+            ``Date`` object timestamping the log message
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger([maxSize])`:
+
+    A basic logger object that has a buffer of recent messages plus a
+    listener dispatch mechanism for "real-time" logging of important
+    messages.
+
+    ``maxSize`` is the maximum number of entries in the log.  If
+    ``maxSize >= 0``, then the log will not buffer more than that many
+    messages. So if you don't like logging at all, be sure to pass
+    ``0``.
+
+    There is a default logger available named "logger", and several of
+    its methods are also global functions:
+
+        ``logger.log``      -> ``log``
+        ``logger.debug``    -> ``logDebug``
+        ``logger.warning``  -> ``logWarning``
+        ``logger.error``    -> ``logError``
+        ``logger.fatal``    -> ``logFatal``
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.addListener(ident, filter, listener)`:
+
+    Add a listener for log messages.
+
+    ``ident`` is a unique identifier that may be used to remove the
+    listener later on.
+
+    ``filter`` can be one of the following:
+
+        ``null``:
+            ``listener(msg)`` will be called for every log message
+            received.
+
+        ``string``:
+            :mochiref:`logLevelAtLeast(filter)` will be used as the
+            function (see below).
+
+        ``function``:
+            ``filter(msg)`` will be called for every msg, if it
+            returns true then ``listener(msg)`` will be called.
+
+    ``listener`` is a function that takes one argument, a log
+    message. A log message is an object (:mochiref:`LogMessage`
+    instance) that has at least these properties:
+
+        ``num``:
+            A counter that uniquely identifies a log message
+            (per-logger)
+
+        ``level``:
+            A string or number representing the log level. If string,
+            you may want to use ``LogLevel[level]`` for comparison.
+
+        ``info``:
+            An Array of objects passed as additional arguments to the
+            ``log`` function.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.baseLog(level, message[, ...])`:
+
+    The base functionality behind all of the log functions.  The first
+    argument is the log level as a string or number, and all other
+    arguments are used as the info list.
+
+    This function is available partially applied as:
+
+        ==============  =========
+        Logger.debug    'DEBUG'
+        Logger.log      'INFO'
+        Logger.error    'ERROR'
+        Logger.fatal    'FATAL'
+        Logger.warning  'WARNING'
+        ==============  =========
+
+    For the default logger, these are also available as global
+    functions, see the :mochiref:`Logger` constructor documentation
+    for more info.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.clear()`:
+
+    Clear all messages from the message buffer.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.debuggingBookmarklet()`:
+
+    Display the contents of the logger in a useful way for browsers.
+
+    Currently, if :mochiref:`MochiKit.LoggingPane` is loaded, then a
+    pop-up :mochiref:`MochiKit.LoggingPane.LoggingPane` will be
+    used. Otherwise, it will be an alert with
+    :mochiref:`Logger.prototype.getMessageText()`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.dispatchListeners(msg)`:
+
+    Dispatch a log message to all listeners.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.getMessages(howMany)`:
+
+    Return a list of up to ``howMany`` messages from the message
+    buffer.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.getMessageText(howMany)`:
+
+    Get a string representing up to the last ``howMany`` messages in
+    the message buffer. The default is ``30``.
+
+    The message looks like this::
+
+        LAST {messages.length} MESSAGES:
+          [{msg.num}] {msg.level}: {m.info.join(' ')}
+          [{msg.num}] {msg.level}: {m.info.join(' ')}
+          ...
+
+    If you want some other format, use
+    :mochiref:`Logger.prototype.getMessages` and do it yourself.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`Logger.prototype.removeListener(ident)`:
+
+    Remove a listener using the ident given to
+    :mochiref:`Logger.prototype.addListener`
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Functions
+---------
+
+:mochidef:`alertListener(msg)`:
+
+    Ultra-obnoxious ``alert(...)`` listener
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`log(message[, info[, ...]])`:
+
+    Log an INFO message to the default logger
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`logDebug(message[, info[, ...]])`:
+
+    Log a DEBUG message to the default logger
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`logError(message[, info[, ...]])`:
+
+    Log an ERROR message to the default logger
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`logFatal(message[, info[, ...]])`:
+
+    Log a FATAL message to the default logger
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`logLevelAtLeast(minLevel)`:
+
+    Return a function that will match log messages whose level is at
+    least minLevel
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`logWarning(message[, info[, ...]])`:
+
+    Log a WARNING message to the default logger
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+See Also
+========
+
+.. [1] Python's logging module: http://docs.python.org/lib/module-logging.html
+.. [2] PEP 282, where they admit all of the Java influence: http://www.python.org/peps/pep-0282.html
+.. [3] Original Bookmarklet Based Debugging blather: http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/LoggingPane.rst b/mochikit_v14/doc/rst/MochiKit/LoggingPane.rst
new file mode 100755 (executable)
index 0000000..7a7575e
--- /dev/null
@@ -0,0 +1,128 @@
+.. title:: MochiKit.LoggingPane - Interactive MochiKit.Logging pane
+
+Name
+====
+
+MochiKit.LoggingPane - Interactive MochiKit.Logging pane
+
+
+Synopsis
+========
+
+::
+
+    // open a pop-up window
+    createLoggingPane()
+    // use a div at the bottom of the document
+    createLoggingPane(true);
+
+
+Description
+===========
+
+MochiKit.Logging does not have any browser dependencies and is
+completely unobtrusive. MochiKit.LoggingPane is a browser-based
+colored viewing pane for your :mochiref:`MochiKit.Logging` output that
+can be used as a pop-up or inline.
+
+It also allows for regex and level filtering!  MochiKit.LoggingPane is
+used as the default
+:mochiref:`MochiKit.Logging.debuggingBookmarklet()` if it is loaded.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.Logging`
+
+
+API Reference
+=============
+
+Constructors
+------------
+
+:mochidef:`LoggingPane(inline=false, logger=MochiKit.Logging.logger)`:
+
+    A listener for a :mochiref:`MochiKit.Logging` logger with an
+    interactive DOM representation.
+
+    If ``inline`` is ``true``, then the ``LoggingPane`` will be a
+    ``DIV`` at the bottom of the document. Otherwise, it will be in a
+    pop-up window with a name based on the calling page's URL. If
+    there is an element in the document with an id of
+    ``_MochiKit_LoggingPane``, it will be used instead of appending a
+    new ``DIV`` to the body.
+
+    ``logger`` is the reference to the
+    :mochiref:`MochiKit.Logging.Logger` to listen to. If not
+    specified, the global default logger is used.
+
+    Properties:
+
+        ``win``:
+            Reference to the pop-up window (``undefined`` if
+            ``inline``)
+
+        ``inline``:
+            ``true`` if the ``LoggingPane`` is inline
+
+        ``colorTable``:
+            An object with property->value mappings for each log level
+            and its color. May also be mutated on
+            ``LoggingPane.prototype`` to affect all instances. For
+            example::
+
+                MochiKit.LoggingPane.LoggingPane.prototype.colorTable = {
+                    DEBUG: "green",
+                    INFO: "black",
+                    WARNING: "blue",
+                    ERROR: "red",
+                    FATAL: "darkred"
+                };
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`LoggingPane.prototype.closePane()`:
+
+    Close the :mochiref:`LoggingPane` (close the child window, or
+    remove the ``_MochiKit_LoggingPane`` ``DIV`` from the document).
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Functions
+---------
+
+
+:mochidef:`createLoggingPane(inline=false)`:
+
+    Create or return an existing :mochiref:`LoggingPane` for this
+    document with the given inline setting. This is preferred over
+    using :mochiref:`LoggingPane` directly, as only one
+    :mochiref:`LoggingPane` should be present in a given document.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/Position.rst b/mochikit_v14/doc/rst/MochiKit/Position.rst
new file mode 100644 (file)
index 0000000..1d459cf
--- /dev/null
@@ -0,0 +1,26 @@
+.. title:: MochiKit.Position - DOM Position manipulation API
+
+Name
+====
+
+MochiKit.Position - DOM Position manipulation API
+
+
+Synopsis
+========
+
+This module is experimental and is present in MochiKit 1.4+ only. No
+functions are currently exported from this module. Documentation is
+forthcoming.
+
+
+Copyright
+=========
+
+Copyright 2005-2006 Bob Ippolito <bob@redivi.com>, and others. 
+This program is dual-licensed free
+software; you can redistribute it and/or modify it under the terms of
+the `MIT License`_ or the `Academic Free License v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/Selector.rst b/mochikit_v14/doc/rst/MochiKit/Selector.rst
new file mode 100644 (file)
index 0000000..5c1c6ab
--- /dev/null
@@ -0,0 +1,182 @@
+.. title:: MochiKit.Selector - Selecting elements by CSS selector syntax
+
+Name
+====
+
+MochiKit.Selector - Selecting elements by CSS selector syntax
+
+
+Synopsis
+========
+
+::
+
+    MochiKit.Base.map(MochiKit.Visual.fade, $$('p.fademe'));
+
+
+Description
+===========
+
+MochiKit.Selector provides utilities to select elements by CSS
+selector syntax. In particular it provides the :mochiref:`$$`
+function.
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.DOM`
+- :mochiref:`MochiKit.Iter`
+
+
+Overview
+========
+
+This module provides facilities to select childs of a DOM node by
+using CSS selector syntax. In particular, it provides the 
+:mochiref:`$$` function, which performs such a selection on the
+current document.
+
+Many of CSS3 [1]_ selectors are supported:
+
+- Select by tag name (``A``)
+- Select by class (``.theclass``)
+- Select by id (``#someid``)
+- Combinators
+      - Descendant: ``E F``
+      - Child: ``E > F``
+      - Immediate following sibling: ``E + F``
+      - Following sibling: ``E ~ F`` 
+- Attribute selectors
+      - simple "has attribute" (without operator)
+      - ``=`` equal
+      - ``!=`` not equal (not in CSS std.)
+      - ``~=`` word containment
+      - ``^=`` starts-with
+      - ``$=`` ends-with
+      - ``*=`` substring containment
+      - ``|=`` first part of hyphen deleimited (eg. lang|="en" matches lang="en-US") 
+- Pseudo-classes
+      - ``:root``, ``:nth-child``, ``:nth-last-child``, ``:nth-of-type``, ``:nth-last-of-type``, ``:first-child``, ``:last-child``, ``:first-of-type``, ``:last-of-type``, ``:only-child``, ``:only-of-type``, ``:empty``, ``:enabled``, ``:disabled``, ``:checked``, ``:not(<any other selector>)`` 
+
+Multiple selectors can be concatenated, like this: ``P.quote[author~='Torvalds']``,
+in which case elements matching *all* the selectors are returned. Furthermore, such
+concatenations can be *combined* by joining them with spaces and combinators.
+This invokes the regular CSS behaviour of matching parts of the combination in
+sequence, starting off each part from the elements returned by the preceeding part.
+
+For the ``:nth-*`` pseudoclasses, the ``an+b`` syntax is partially
+supported, specifically a and b must be non-negative and only a is 
+optional (this differs from the CSS std.) Also, ``odd`` and ``even`` 
+are supported, e.g. ``table tr:nth-child(odd)`` gives you every 
+other row of table starting with the first one.
+
+For further documentation of CSS selectors, refer to the W3C CSS standard. [1]_
+
+The original version of this module was ported from Prototype.
+
+**Note:** Due to how Internet Explorer handles node attributes, some attribute
+selectors may not work as expected. In particular ``a[title]`` will not work
+as all ``A`` elements in the Internet Explorer DOM model have a title attribute
+regardless of whether it's specified in the markup or not.
+
+
+API Reference
+=============
+
+Functions
+---------
+
+:mochidef:`$$(expression[, ...])`:
+    
+    Performs a selection on the active document. Equivalent
+    to ``findChildElements(MochiKit.DOM.currentDocument(), [expression, ...])``
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`findChildElements(element, expressions)`:
+
+    Traverses the child nodes of ``element`` and returns the subset
+    of those that match any of the selector expressions in ``expressions``.
+
+    Each expression can be a combination of simple expressions, by concatenating
+    them with spaces or combinators. In that case, normal CSS rules apply, each
+    simple expression is evaluated in turn and the results of that one is used
+    as the scope for the succeeding expression (see :mochiref:`Selector.findElements`).
+    Finally, the results of the last simple expression is returned as the search result.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Constructors
+-------------
+
+:mochidef:`Selector(simpleExpression)`:
+
+    An object storing the parsed version of a simple CSS selector expression
+    and providing functions for executing searches.
+
+    *Simple* means that the expression is not a combination of expressions,
+    i.e. it does not contain any spaces.
+    
+    Usually the user would not instantiate or use this object directly, but 
+    heres how::
+
+        var selector = MochiKit.Selector.Selector('#someelementid');
+        var searchResults = selector.findElements(rootElement);
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+:mochidef:`Selector.findElements(scope[, axis=""])`:
+
+    Performs a search on ``scope``. The value of axis controls what relatives
+    of ``scope`` are considered.
+
+    ``scope``:
+        A DOM node that acts as a starting point for the search.
+
+    ``axis``:
+        One of ``">"``, ``"+"``, ``"~"`` or the empty string (default).
+        If the empty string, all descendant nodes of ``scope`` are tested against
+        the expression. If ``>`` only direct child nodes of ``scope`` are tested,
+        if ``+`` only the next sibling (if any) of ``scope`` is tested and if
+        ``~`` all succeeding siblings of ``scope`` are tested.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+See Also
+========
+
+.. [1] CSS Selectors Level 3 (Last Call, oct. 2006):
+       http://www.w3.org/TR/2005/WD-css3-selectors-20051215/ 
+
+
+Authors
+=======
+
+- Arnar Birgisson <arnarbi@gmail.com>
+- Thomas Herve <therve@gmail.com>
+- Originally ported from Prototype <http://prototype.conio.net/>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
+
+Based on Prototype, (c) 2005 Sam Stephenson, available under the `Prototype
+license`_
+
+.. _`Prototype license`: http://dev.rubyonrails.org/browser/spinoffs/prototype/LICENSE?rev=3362
diff --git a/mochikit_v14/doc/rst/MochiKit/Signal.rst b/mochikit_v14/doc/rst/MochiKit/Signal.rst
new file mode 100755 (executable)
index 0000000..4c097a8
--- /dev/null
@@ -0,0 +1,468 @@
+.. title:: MochiKit.Signal - Simple universal event handling
+.. |---| unicode:: U+2014  .. em dash, trimming surrounding whitespace
+   :trim:
+
+Name
+====
+
+MochiKit.Signal - Simple universal event handling
+
+
+Synopsis
+========
+
+Signal for DOM events::
+
+    // DOM events are also signals. Connect freely! The functions will be
+    // called with the custom event as a parameter.
+
+    // calls myClicked.apply(getElement('myID'), [event])
+    connect('myID', 'onclick', myClicked);
+
+    // calls wasClicked.apply(myObject, [event])
+    connect('myID', 'onclick', myObject, wasClicked);
+
+    // calls myObject.wasClicked(event)
+    connect('myID', 'onclick', myObject, 'wasClicked');
+
+    // the event is normalized, no more e = e || window.event!
+    myObject.wasClicked = function(e) {
+        var crossBrowserCoordinates = e.mouse().page;
+        // e.mouse().page is a MochiKit.Style.Coordinates object
+    }
+
+
+Signal for non-DOM events::
+
+    // otherObject.gotFlash() will be called when 'flash' signalled.
+    connect(myObject, 'flash', otherObject, 'gotFlash');
+
+    // gotBang.apply(otherObject, [...]) will be called when 'bang' signalled.
+    // You can access otherObject from within gotBang as 'this'.
+    connect(myObject, 'bang', otherObject, gotBang);
+
+    // myFunc.apply(myObject, [...]) will be called when 'flash' signalled.
+    // You can access myObject from within myFunc as 'this'.
+    var ident = connect(myObject, 'flash', myFunc);
+
+    // You may disconnect with the return value from connect
+    disconnect(ident);
+
+    // Signal can take parameters. These will be passed along to the
+    // connected functions.
+    signal(myObject, 'flash');
+    signal(myObject, 'bang', 'BANG!');
+
+
+Description
+===========
+
+Event handling was never so easy!
+
+This module takes care of all the hard work |---| figuring out which
+event model to use, trying to retrieve the event object, and handling
+your own internal events, as well as cleanup when the page is unloaded
+to clean up IE's nasty memory leakage.
+
+This event system is largely based on Qt's signal/slot system. Read
+more on how that is handled and also how it is used in model/view
+programming at: http://doc.trolltech.com/
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.DOM`
+
+
+Overview
+========
+
+Using Signal for DOM Events
+---------------------------
+
+When using MochiKit.Signal, do not use the browser's native event
+API. That means, no ``onclick="blah"``, no
+``elem.addEventListener(...)``, and certainly no
+``elem.attachEvent(...)``. This also means that
+:mochiref:`MochiKit.DOM.addToCallStack` and
+:mochiref:`MochiKit.DOM.addLoadEvent` should not be used in
+combination with this module.
+
+Signals for DOM objects are named with the ``'on'`` prefix, e.g.:
+``'onclick'``, ``'onkeyup'``, etc.
+
+When the signal fires, your slot will be called with one parameter,
+the custom event object.
+
+
+Custom Event Objects for DOM events
+-----------------------------------
+
+Signals triggered by DOM events are called with a custom event object
+as a parameter. The custom event object presents a consistent view of
+the event across all supported platforms and browsers, and provides
+many conveniences not available even in a correct W3C implementation.
+
+See the `DOM Custom Event Object Reference`_ for a detailed API
+description of this object.
+
+If you find that you're accessing the native event for any reason,
+create a `new ticket`_ and we'll look into normalizing the behavior
+you're looking for.
+
+.. _`new ticket`: http://trac.mochikit.com/newticket
+.. _`Safari bug 6595`: http://bugs.webkit.org/show_bug.cgi?id=6595
+.. _`Safari bug 7790`: http://bugs.webkit.org/show_bug.cgi?id=7790
+.. _`Safari bug 8707`: http://bugs.webkit.org/show_bug.cgi?id=8707
+.. _`stopPropagation()`: http://developer.mozilla.org/en/docs/DOM:event.stopPropagation
+.. _`preventDefault()`: http://developer.mozilla.org/en/docs/DOM:event.preventDefault
+
+
+Memory Usage
+------------
+
+Any object that has connected slots (via :mochiref:`connect()`) is
+referenced by the Signal mechanism until it is disconnected via
+:mochiref:`disconnect()` or :mochiref:`disconnectAll()`.
+
+Signal does not leak. It registers an ``'onunload'`` event that
+disconnects all objects on the page when the browser leaves the
+page. However, memory usage will grow during the page view for every
+connection made until it is disconnected. Even if the DOM object is
+removed from the document, it will still be referenced by Signal until
+it is explicitly disconnected.
+
+In order to conserve memory during the page view,
+:mochiref:`disconnectAll()` any DOM elements that are about to be
+removed from the document.
+
+
+Synthesized Events
+------------------
+
+Certain events supported by MochiKit are not generated natively by all
+browsers. MochiKit can synthesize these events even for non-supporting
+browsers, however, by watching for related events and triggering the
+appropriate signals at the right times.
+
+These events include:
+
+``onmouseenter``
+
+    Similar to ``'onmouseover'``, but does not "bubble" up to parent
+    nodes. Such bubbling is often a cause of confusion. On an
+    ``'onmouseenter'`` event, you can be certain that the mouse has
+    left the node attached to the event.
+
+    *Availability:*
+        Available in MochiKit 1.4+
+
+``onmouseleave``
+
+    Similar to ``'onmouseout'``, but does not "bubble" up to parent
+    nodes. This is the analog to ``'onmouseenter'``.
+
+    *Availability:*
+        Available in MochiKit 1.4+
+
+
+Using Signal for non-DOM objects
+--------------------------------
+
+Signals are triggered with the :mochiref:`signal(src, 'signal', ...)`
+function. Additional parameters passed to this are passed onto the
+connected slots. Explicit signals are not required for DOM events.
+
+Slots that are connected to a signal are called in the following
+manner when that signal is signalled:
+
+-   If the slot was a single function, then it is called with ``this``
+    set to the object originating the signal with whatever parameters
+    it was signalled with.
+
+-   If the slot was an object and a function, then it is called with
+    ``this`` set to the object, and with whatever parameters it was
+    signalled with.
+
+-   If the slot was an object and a string, then ``object[string]`` is
+    called with the parameters to the signal.
+
+
+API Reference
+=============
+
+
+Signal API Reference
+--------------------
+
+:mochidef:`connect(src, signal, dest[, func])`:
+
+    Connects a signal to a slot, and return a unique identifier that
+    can be used to disconnect that signal.
+
+    ``src`` is the object that has the signal. You may pass in a
+    string, in which case, it is interpreted as an id for an HTML
+    element.
+
+    ``signal`` is a string that represents a signal name. If 'src' is
+    an HTML Element, ``window``, or the ``document``, then it can be
+    one of the 'on-XYZ' events. You must include the 'on' prefix, and
+    it must be all lower-case.
+
+    ``dest`` and ``func`` describe the slot, or the action to take
+    when the signal is triggered.
+
+        -   If ``dest`` is an object and ``func`` is a string, then
+            ``dest[func].apply(dest, [...])`` will be called when the
+            signal is signalled.
+
+        -   If ``dest`` is an object and ``func`` is a function, then
+            ``func.apply(dest, [...])`` will be called when the signal
+            is signalled.
+
+        -   If ``func`` is undefined and ``dest`` is a function, then
+            ``dest.apply(src, [...])`` will be called when the signal is
+            signalled.
+
+    No other combinations are allowed and will raise an exception.
+
+    The return value can be passed to :mochiref:`disconnect` to
+    disconnect the signal.
+
+    In MochiKit 1.4+, if ``src`` is an object that has a ``__connect__``
+    method, then ``src.__connect__(ident, signal, objOrFunc, funcOrStr)``
+    will be called. This method may be used to disconnect the signal.
+    DOM objects can not implement this feature.
+    
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`disconnect(ident)`:
+
+    To disconnect a signal, pass its ident returned by
+    :mochiref:`connect()`.  This is similar to how the browser's
+    ``setTimeout`` and ``clearTimeout`` works.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`disconnectAll(src[, signal, ...])`:
+
+    ``disconnectAll(src)`` removes all signals from src.
+
+    ``disconnectAll(src, 'onmousedown', 'mySignal')`` will remove all
+    ``'onmousedown'`` and ``'mySignal'`` signals from src.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`disconnectAllTo(dest[, func])`:
+
+    ``disconnectAllTo(dest)`` removes all signals connected to dest.
+
+    ``disconnectAllTo(dest, func)`` will remove all
+    signals connected to dest using func. 
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`signal(src, signal, ...)`:
+
+    This will signal a signal, passing whatever additional parameters
+    on to the connected slots. ``src`` and ``signal`` are the same as
+    for :mochiref:`connect()`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+DOM Custom Event Object Reference
+---------------------------------
+
+:mochidef:`event()`:
+
+    The native event produced by the browser. You should not need to
+    use this.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`src()`:
+
+    The element that this signal is connected to.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`type()`:
+
+    The event type (``'click'``, ``'mouseover'``, ``'keypress'``,
+    etc.) as a string. Does not include the ``'on'`` prefix.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`target()`:
+
+    The element that triggered the event. This may be a child of
+    :mochiref:`src()`.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`modifier()`:
+
+    Returns ``{shift, ctrl, meta, alt, any}``, where each property is
+    ``true`` if its respective modifier key was pressed, ``false``
+    otherwise. ``any`` is ``true`` if any modifier is pressed,
+    ``false`` otherwise.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`stopPropagation()`:
+
+    Works like W3C's `stopPropagation()`_.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`preventDefault()`:
+
+    Works like W3C's `preventDefault()`_.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`stop()`:
+
+    Shortcut that calls ``stopPropagation()`` and
+    ``preventDefault()``.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`key()`:
+
+    Returns ``{code, string}``.
+
+    Use ``'onkeydown'`` and ``'onkeyup'`` handlers to detect control
+    characters such as ``'KEY_F1'``. Use the ``'onkeypress'``
+    handler to detect "printable" characters, such as ``'é'``.
+
+    When a user presses F1, in ``'onkeydown'`` and ``'onkeyup'`` this
+    method returns ``{code: 122, string: 'KEY_F1'}``. In
+    ``'onkeypress'``, it returns ``{code: 0, string: ''}``.
+
+    If a user presses Shift+2 on a US keyboard, this method returns
+    ``{code: 50, string: 'KEY_2'}`` in ``'onkeydown'`` and
+    ``'onkeyup'``.  In ``'onkeypress'``, it returns ``{code: 64,
+    string: '@'}``.
+
+    See ``_specialKeys`` in the source code for a comprehensive list
+    of control characters.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`mouse()`:
+
+    Properties for ``'onmouse*'``, ``'onclick'``, ``'ondblclick'``,
+    and ``'oncontextmenu'``:
+
+        -   ``page`` is a :mochiref:`MochiKit.Style.Coordinates` object
+            that represents the cursor position relative to the HTML
+            document.  Equivalent to ``pageX`` and ``pageY`` in
+            Safari, Mozilla, and Opera.
+
+        -   ``client`` is a :mochiref:`MochiKit.Style.Coordinates`
+            object that represents the cursor position relative to the
+            visible portion of the HTML document. Equivalent to
+            ``clientX`` and ``clientY`` on all browsers. Current versions of
+            Safari incorrectly return clientX as relative to the canvas
+            instead of relative to the viewport (`Safari Bug 8707`_).
+
+    Properties for ``'onmouseup'``, ``'onmousedown'``, ``'onclick'``,
+    and ``'ondblclick'``:
+
+        -   ``mouse().button`` returns ``{left, right, middle}`` where
+            each property is ``true`` if the mouse button was pressed,
+            ``false`` otherwise.
+
+    Known browser bugs:
+
+        -   Current versions of Safari won't signal ``'ondblclick'``
+            when attached via ``connect()`` (`Safari Bug 7790`_).
+            
+        -   In Safari < 2.0.4, calling ``preventDefault()`` or ``stop()`` 
+            in ``'onclick'`` events signalled from ``<a>`` tags does not 
+            prevent the browser from following those links.
+
+        -   Mac browsers don't report right-click consistently. Firefox
+            signals the slot and sets ``modifier().ctrl`` to true,
+            Opera signals the slot and sets ``modifier().meta`` to
+            ``true``, and Safari doesn't signal the slot at all
+            (`Safari Bug 6595`_).
+
+            To find a right-click in Safari, Firefox, and IE, you can
+            connect an element to ``'oncontextmenu'``. This doesn't
+            work in Opera.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`relatedTarget()`:
+
+    Returns the document element that the mouse has moved to. This is
+    generated for ``'onmouseover'`` and ``'onmouseout'`` events.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`confirmUnload(msg)`:
+
+    In browsers that support the ``'onbeforeunload'`` event (IE and
+    Firefox), calling this in the event handler will show a dialog box
+    that allows the user to confirm or cancel the navigation away from
+    the page.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Authors
+=======
+
+-   Jonathan Gardner <jgardner@jonathangardner.net>
+-   Beau Hartshorne <beau@hartshornesoftware.com>
+-   Bob Ippolito <bob@redivi.com>
+
+
+Copyright
+=========
+
+Copyright 2006 Jonathan Gardner <jgardner@jonathangardner.net>, Beau
+Hartshorne <beau@hartshornesoftware.com>, and Bob Ippolito
+<bob@redivi.com>.  This program is dual-licensed free software; you
+can redistribute it and/or modify it under the terms of the `MIT
+License`_ or the `Academic Free License v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/Sortable.rst b/mochikit_v14/doc/rst/MochiKit/Sortable.rst
new file mode 100755 (executable)
index 0000000..7d03b06
--- /dev/null
@@ -0,0 +1,181 @@
+.. title:: MochiKit.Sortable - sortable with drag and drop lists
+
+Name
+====
+
+MochiKit.Sortable - sortable with drag and drop lists
+
+
+Synopsis
+========
+
+::
+
+    <ul id="dnd_sortable">
+        <li>mochibot.com</li>
+        <li>pythonmac.org</li>
+        <li>undefined.org</li>
+        <li>python.org</li>
+    </ul>
+    <script type="text/javascript">
+      MochiKit.Sortable.Sortable.create('dnd_sortable');
+    </script>
+
+
+Description
+===========
+
+MochiKit.Sortable add a new Sortable object to manipulate easily
+drag&drop in lists.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.Iter`
+- :mochiref:`MochiKit.DOM`
+- :mochiref:`MochiKit.Color`
+- :mochiref:`MochiKit.Visual`
+- :mochiref:`MochiKit.Signal`
+- :mochiref:`MochiKit.DragAndDrop`
+
+Overview
+========
+
+MochiKit.Sortable mainly contains the Sortable object offering
+facilities to manipulate a list and drag its items to reorder it. It
+can also be serialized for being send to server. It is ported from
+Scriptaculous_.
+
+.. _Scriptaculous: http://script.aculo.us
+
+
+API Reference
+=============
+
+Objects defined
+---------------
+
+:mochidef:`SortableObserver`:
+
+    Observer for DragAndDrop object. You normally don't have to access
+    this, only for customization purpose.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Sortable.create(element [, options])`:
+
+    Create a new Sortable. Usually you'll call it with a UL element,
+    but it can be customized with options to use something else.
+
+    You have the following options:
+
+    ================= ==================
+    element           element
+    tag               'li'
+    dropOnEmpty       false
+    overlap           'vertical'
+    constraint        'vertical'
+    containment       element
+    handle            false
+    only              false
+    hoverclass        null
+    ghosting          false
+    scroll            false
+    scrollSensitivity 20
+    scrollSpeed       15
+    format            /^[^_]*_(.*)$/
+    onChange          MochiKit.Base.noop
+    onUpdate          MochiKit.Base.noop
+    tree              false
+    treeTag           'ul'
+    ================= ==================
+
+    ``tag``:
+        Name of the tag used to make the draggable elements. It matches all
+        the childNodes of the Sortable element with this tag.
+
+    ``only``:
+        Class or array of classes used to filter the children, combined with
+        the tag criteria.
+
+    ``format``:
+        Regular expression which serves as a match filter for serialization,
+        on children' ids. For example, with the default value, you'll get
+        ['1', '2', '3', '4'] with ids ['sort_1', 'sort_2', 'sort_3', 'sort_4'].
+
+    ``onChange``:
+        Callback called when an element moves between others in the Sortable.
+        It's called for *each* movements, even if you don't release the mouse.
+
+    ``onUpdate``:
+        Callback called when the order changes in the Sortable. It's called
+        only if the Sortable is modified, after you dropped an element.
+
+    ``tree``:
+        Option for creating a Sortable tree. It's an experimental
+        setting, that can be very slow even with a few elements. You
+        can customize its behaviour with the ``treeTag`` option, that
+        defines the node used to make branches in your tree (that
+        contains leaves).
+
+    Other options are passed to the Draggables and Droppables objects created.
+    Refer to :mochiref:`MochiKit.DragAndDrop` for more information.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Sortable.destroy(element)`:
+
+    Destroy a previously created sortable. It prevents further use of
+    the Sortable functionnality on the element, unless recreated.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Sortable.serialize(element [, options])`:
+
+    Serialize the content of a Sortable. Useful to send this content
+    through a XMLHTTPRequest. The options overrides the ones of the Sortable
+    only for the serialization.
+
+    ====== ==========================================
+    tag    tag from the Sortable
+    only   only from the Sortable
+    name   id of the element
+    format format of the Sortable or /^[^_]*_(.*)$
+    ====== ==========================================
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Authors
+=======
+
+- Thomas Herve <therve@gmail.com>
+- Bob Ippolito <bob@redivi.com>
+- Originally adapted from Script.aculo.us <http://script.aculo.us/>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>.  This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
+
+Portions adapted from `Scriptaculous`_ are available under the terms
+of the `MIT License`_.
+
+.. _`Apache License, Version 2.0`: http://www.apache.org/licenses/LICENSE-2.0.html
+
diff --git a/mochikit_v14/doc/rst/MochiKit/Style.rst b/mochikit_v14/doc/rst/MochiKit/Style.rst
new file mode 100755 (executable)
index 0000000..3b5c563
--- /dev/null
@@ -0,0 +1,309 @@
+.. title:: MochiKit.Style - painless Style manipulation API
+
+Name
+====
+
+MochiKit.Style - painless Style manipulation API
+
+
+Synopsis
+========
+
+::
+
+    var messagePos = getElementPosition('message');
+    var messageSize = getElementDimensions('message');
+
+    var notifyPos = new MochiKit.Style.Coordinates(
+         messagePos.x + messageSize.w + 10,
+         messagePos.y);
+
+    setElementPosition('notify', notifyPos);
+
+
+Description
+===========
+
+Refactored from :mochiref:`MochiKit.DOM`.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.DOM`
+
+
+Overview
+========
+
+Refactored from :mochiref:`MochiKit.DOM`.
+
+
+Element Visibility
+------------------
+
+The :mochiref:`hideElement` and :mochiref:`showElement` functions are
+provided as a convenience, but only work for elements that are
+``display: block``. For a general solution to showing, hiding, and
+checking the explicit visibility of elements, we recommend using a
+solution that involves a little CSS. Here's an example::
+
+    <style type="text/css">
+        .invisible { display: none; }
+    </style>
+
+    <script type="text/javascript">
+        function toggleVisible(elem) {
+            toggleElementClass("invisible", elem);
+        }
+
+        function makeVisible(elem) {
+            removeElementClass(elem, "invisible");
+        }
+
+        function makeInvisible(elem) {
+            addElementClass(elem, "invisible");
+        }
+
+        function isVisible(elem) {
+            // you may also want to check for
+            // getElement(elem).style.display == "none"
+            return !hasElementClass(elem, "invisible");
+        };
+    </script>
+
+MochiKit doesn't ship with such a solution, because there is no
+reliable and portable method for adding CSS rules on the fly with
+JavaScript.
+
+
+API Reference
+=============
+
+Functions
+---------
+
+:mochidef:`getStyle(element, cssSelector)`:
+
+    Looks up a CSS property for the given element. The element can be
+    specified as either a string with the element's ID or the element
+    object itself.
+    
+    ``cssSelector``:
+        The CSS selector, e.g. ``background-color``.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`setStyle(element, styles)`:
+
+    Set CSS properties on a the given element. The element can be
+    specified as either a string with the element's ID or the element
+    object itself.
+    
+    ``styles``:
+        Dictionnary holding CSS properties to set, e.g.
+        ``{'background-color': 'red', 'opacity': 0.5}``.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`setOpacity(element, opacity)`:
+
+    Sets ``opacity`` for ``element``. Valid ``opacity`` values range
+    from 0 (invisible) to 1 (opaque). ``element`` is looked up with
+    :mochiref:`getElement`, so string identifiers are also acceptable.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`getElementDimensions(element)`:
+
+    Return the absolute pixel width and height (including padding and border,
+    but not margins) of ``element`` as an object with ``w`` and ``h``
+    properties, or ``undefined`` if ``element`` is not in the document.
+    ``element`` may be specified as a string to be looked up with
+    :mochiref:`getElement`, a DOM element, or trivially as an object with
+    ``w`` and/or ``h`` properties.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`setElementDimensions(element, dimensions[, units='px'])`:
+
+    Sets the dimensions of ``element`` in the document from an object
+    with ``w`` and ``h`` properties.
+
+    Warning: IE in quirks-mode seems to behave strange when you set
+    the height off an element containing text to 0. You can workaround this
+    by setting the value of visibly/display.
+
+    ``element``:
+        A reference to the DOM element to update (if a string is
+        given, :mochiref:`getElement(node)` will be used to locate the
+        node)
+
+    ``dimensions``:
+        An object with ``w`` and ``h`` properties. You can also specify only
+        one property.
+
+    ``units``:
+        Optionally set the units to use, default is ``px``
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`getElementPosition(element[, relativeTo={x: 0, y: 0}])`:
+
+    Return the absolute pixel position of ``element`` in the document
+    as an object with ``x`` and ``y`` properties, or ``undefined`` if
+    ``element`` is not in the document. ``element`` may be specified
+    as a string to be looked up with :mochiref:`getElement`, a DOM
+    element, or trivially as an object with ``x`` and/or ``y``
+    properties.
+
+    If ``relativeTo`` is given, then its coordinates are subtracted
+    from the absolute position of ``element``, e.g.::
+
+        var elemPos = getElementPosition(elem);
+        var anotherElemPos = getElementPosition(anotherElem);
+        var relPos = getElementPosition(elem, anotherElem);
+        assert( relPos.x == (elemPos.x - anotherElemPos.x) );
+        assert( relPos.y == (elemPos.y - anotherElemPos.y) );
+
+    ``relativeTo`` may be specified as a string to be looked up with
+    :mochiref:`getElement`, a DOM element, or trivially as an object
+    with ``x`` and/or ``y`` properties.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`setElementPosition(element, position[, units='px'])`:
+
+    Sets the absolute position of ``element`` in the document from an
+    object with ``x`` and ``y`` properties.
+
+    ``element``:
+        A reference to the DOM element to update (if a string is
+        given, :mochiref:`getElement(node)` will be used to locate the
+        node)
+
+    ``position``:
+        An object with ``x`` and ``y`` properties. You can also specify only
+        one property.
+
+    ``units``:
+        Optionally set the units to use, default is ``px``
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`setDisplayForElement(display, element[, ...])`:
+
+    Change the ``style.display`` for the given element(s). Usually
+    used as the partial forms:
+
+    - :mochiref:`showElement(element, ...)`
+    - :mochiref:`hideElement(element, ...)`
+
+    Elements are looked up with :mochiref:`getElement`, so string
+    identifiers are acceptable.
+
+    For information about the caveats of using a ``style.display``
+    based show/hide mechanism, and a CSS based alternative, see
+    `Element Visibility`_.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`showElement(element, ...)`:
+
+    Partial form of :mochiref:`setDisplayForElement`, specifically::
+
+        partial(setDisplayForElement, "block")
+
+    For information about the caveats of using a ``style.display``
+    based show/hide mechanism, and a CSS based alternative, see
+    `Element Visibility`_.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`hideElement(element, ...)`:
+
+    Partial form of :mochiref:`setDisplayForElement`, specifically::
+
+        partial(setDisplayForElement, "none")
+
+    For information about the caveats of using a ``style.display``
+    based show/hide mechanism, and a CSS based alternative, see
+    `Element Visibility`_.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`getViewportDimensions()`:
+
+    Return the pixel width and height of the viewport as an object
+    with ``w`` and ``h`` properties.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+:mochidef:`getViewportPosition()`:
+
+    Return the pixel position of the viewport inside the window, as a
+    :mochiref:`Coordinates` object.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Objects
+-------
+
+:mochidef:`Coordinates(x, y)`:
+
+    Constructs an object with ``x`` and ``y`` properties. ``obj.toString()`` 
+    returns something like ``{x: 0, y: 42}`` for debugging.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+        
+:mochidef:`Dimensions(w, h)`:
+
+    Constructs an object with ``w`` and ``h`` properties. ``obj.toString()`` 
+    returns something like ``{w: 0, h: 42}`` for debugging.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Authors
+=======
+
+- Bob Ippolito <bob@redivi.com>
+- Beau Hartshorne <beau@hartshornesoftware.com>
+
+
+Copyright
+=========
+
+Copyright 2005-2006 Bob Ippolito <bob@redivi.com>, and Beau Hartshorne
+<beau@hartshornesoftware.com>. This program is dual-licensed free
+software; you can redistribute it and/or modify it under the terms of
+the `MIT License`_ or the `Academic Free License v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/doc/rst/MochiKit/VersionHistory.rst b/mochikit_v14/doc/rst/MochiKit/VersionHistory.rst
new file mode 100755 (executable)
index 0000000..e026e0e
--- /dev/null
@@ -0,0 +1,311 @@
+2006-XX-XX      v1.4
+
+- MochiKit.Color's HSV to RGB conversion code fixed to return the correct
+  value (hsv.v for RGB values) in cases where saturation === 0.
+- doXHR workaround for a Mozilla bug when calling XMLHttpRequest in certain
+  situations. Always wraps call in a callLater(0, doXHR, url, opts).
+- parseQueryString will now parse values with embedded "="
+- Workaround for a Safari DOM crash when using MochiKit.Iter.list.
+  http://bugs.webkit.org/show_bug.cgi?id=12191
+- New removeNodeAttribute function in MochiKit.DOM.
+- MochiKit.Async.doXHR and dependent functions now accept 201 CREATED and
+  204 NO CONTENT as valid.
+- MochiKit.DOM.formContents now treats option tags the same way that
+  form posts do in the case of missing and empty string value attributes,
+  even in IE.
+- MochiKit.Base.queryString now accepts third queryString([names, values])
+  form.
+- MochiKit.DOM.formContents now defaults to document.body if no element is
+  given.
+- New MochiKit.Selector module
+- MochiKit.LoggingPane fixes for Internet Explorer
+- MochiKit.DOM now creates XHTML nodes in XUL documents.
+- MochiKit.LoggingPane now works on pages with '#' in the URL on IE
+- New MochiKit.Async.doXHR as a convenient method for doing custom
+  XMLHttpRequests (e.g. extra headers, overrideMimeType, etc.)
+- New __connect__ protocol for MochiKit.Signal.connect source notifications
+- Added colSpan, bgColor to the list of DOM renames for Internet Explorer
+- New MochiKit.Signal.disconnectAllTo function
+- MochiKit.Base.parseQueryString now accepts leading question mark
+- New MochiKit.Base.values function
+- Fixed MochiKit.Signal.disconnect when called from a signal handler invoked
+  by MochiKit.Signal.signal
+- parseQueryString now splits on HTML entities equivalent to ampersand as well
+- Better XHTML compatibility (removed obvious cases where uppercase tagName or
+  nodeName was assumed)
+- MochiKit.Base.queryString now handles array values in the same way HTML
+  forms handle multiple elements of the same name.
+- MochiKit.Base.parseQueryString now returns {} for empty query string instead
+  of {"": "undefined"}
+- MochiKit.DOM.formContents now handles option value="" correctly.
+- MochiKit.DOM now checks for undefined className.
+- MochiKit.Iter.groupby() now uses compare() to group rather than == and !=
+- serializeJSON no longer serializes undefined, as per the JSON spec
+- Fixed an infinite recursion bug in serializeJSON if an adapter
+  returns the object itself.
+- New MochiKit.Base.operator.seq and sne to support strict comparison
+- MochiKit.Base.isArrayLike no longer returns true for DOM text nodes
+- Added readonly-readOnly to the list of DOM renames for Internet Explorer
+- New MochiKit.Signal event method: confirmUnload (sets returnValue for 
+  onbeforeunload)
+- Fix interpreter help() function for Firefox and IE
+- API version compatibility notes added
+- New MochiKit.Base functions methodcaller and compose
+- Support IE-based native console logging (Debugger, Atlas)
+- Refactored style functions from MochiKit.DOM to MochiKit.Style
+- MochiKit.Async.DeferredList is now a proper Deferred
+- MochiKit.DOM.formContents now supports SELECT multiple tags
+- Re-use StopIteration Error if the browser already has it
+- Workaround IE type="" bug for INPUT elements
+- Allow LoggingPane to work in IE with hyphen-containing URLs
+- Replace percents for Safari native logging to avoid crashing
+- New MochiKit.DOM.coerceToDOM .dom(node) / .__dom__(node) protocol
+- MochiKit.DOM's MochiKit.Iter dependency is now optional
+- Added expand all link to the documentation index
+- Added MochiKit.DOM.isChildNode
+- Added synthesizing for onmouseenter/onmouseleave
+
+2006-04-29      v1.3.1 (bug fix release)
+
+- Fix sendXMLHttpRequest sendContent regression
+- Internet Explorer fix in MochiKit.Logging (printfire exception)
+- Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async
+
+2006-04-26      v1.3 "warp zone"
+
+- IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)
+- IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)
+- New MochiKit.Base.method as a convenience form of bind that takes the
+  object before the method
+- New MochiKit.Base.flattenArguments for flattening a list of arguments to
+  a single Array
+- Refactored MochiRegExp example to use MochiKit.Signal
+- New key_events example demonstrating use of MochiKit.Signal's key handling
+  capabilities.
+- MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
+  null is used and the string will be considered the first node. This
+  allows for the more natural P("foo") rather than P(null, "foo").
+- MochiKit Interpreter example refactored to use MochiKit.Signal and now
+  provides multi-line input and a help() function to get MochiKit function
+  signature from the documentation.
+- Native Console Logging for the default MochiKit.Logging logger
+- New MochiKit.Async.DeferredList, gatherResults, maybeDeferred
+- New MochiKit.Signal example: draggable
+- Added sanity checking to Deferred to ensure that errors happen when chaining
+  is used incorrectly
+- Opera sendXMLHttpRequest fix (sends empty string instead of null by default)
+- Fix a bug in MochiKit.Color that incorrectly generated hex colors for
+  component values smaller than 16/255.
+- Fix a bug in MochiKit.Logging that prevented logs from being capped at a
+  maximum size
+- MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
+  Error, so that the errback chain is used instead of the callback chain.
+- MochiKit.DOM.appendChildNodes and associated functions now append iterables
+  in the correct order.
+- New MochiKit-based SimpleTest test runner as a replacement for Test.Simple
+- MochiKit.Base.isNull no longer matches undefined
+- example doctypes changed to HTML4
+- isDateLike no longer throws error on null
+- New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt
+- updated elementDimensions to calculate width from offsetWidth instead
+  of clientWidth 
+- formContents now works with FORM tags that have a name attribute
+- Documentation now uses MochiKit to generate a function index
+
+2006-01-26      v1.2 "the ocho"
+
+- Fixed MochiKit.Color.Color.lighterColorWithLevel
+- Added new MochiKit.Base.findIdentical function to find the index of an
+  element in an Array-like object. Uses === for identity comparison.
+- Added new MochiKit.Base.find function to find the index of an element in
+  an Array-like object. Uses compare for rich comparison.
+- MochiKit.Base.bind will accept a string for func, which will be immediately
+  looked up as self[func].
+- MochiKit.DOM.formContents no longer skips empty form elements for Zope
+  compatibility
+- MochiKit.Iter.forEach will now catch StopIteration to break
+- New MochiKit.DOM.elementDimensions(element) for determining the width and
+  height of an element in the document
+- MochiKit.DOM's initialization is now compatible with
+  HTMLUnit + JWebUnit + Rhino
+- MochiKit.LoggingPane will now re-use a ``_MochiKit_LoggingPane`` DIV element
+  currently in the document instead of always creating one.
+- MochiKit.Base now has operator.mul
+- MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
+  a custom value attribute
+- Added new MochiKit.Color constructors fromComputedStyle and fromText
+- MochiKit.DOM.setNodeAttribute should work now
+- MochiKit.DOM now has a workaround for an IE bug when setting the style
+  property to a string
+- MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
+  name and for properties
+- MochiKit.DOM.scrapeText now walks the DOM tree in-order
+- MochiKit.LoggingPane now sanitizes the window name to work around IE bug
+- MochiKit.DOM now translates usemap to useMap to work around IE bug
+- MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks
+- Added new MochiKit.DOM documentation on element visibility
+- New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
+  for determining the position of an element in the document
+- Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG
+
+2005-11-14      v1.1
+
+- Fixed a bug in numberFormatter with large numbers
+- Massively overhauled documentation
+- Fast-path for primitives in MochiKit.Base.compare
+- New groupby and groupby_as_array in MochiKit.Iter
+- Added iterator factory adapter for objects that implement iterateNext()
+- Fixed isoTimestamp to handle timestamps with time zone correctly
+- Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP, 
+  LEGEND, FIELDSET
+- New MochiKit.DOM formContents and enhancement to queryString to support it
+- Updated view_source example to use dp.SyntaxHighlighter 1.3.0
+- MochiKit.LoggingPane now uses named windows based on the URL so that
+  a given URL will get the same LoggingPane window after a reload
+  (at the same position, etc.)
+- MochiKit.DOM now has currentWindow() and currentDocument() context
+  variables that are set with withWindow() and withDocument(). These
+  context variables affect all MochiKit.DOM functionality (getElement,
+  createDOM, etc.)
+- MochiKit.Base.items will now catch and ignore exceptions for properties
+  that are enumerable but not accessible (e.g. permission denied)
+- MochiKit.Async.Deferred's addCallback/addErrback/addBoth
+  now accept additional arguments that are used to create a partially
+  applied function. This differs from Twisted in that the callback/errback
+  result becomes the *last* argument, not the first when this feature
+  is used.
+- MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
+  arguments which are used to create a GET query string
+- Did some refactoring to reduce the footprint of MochiKit by a few
+  kilobytes
+- escapeHTML to longer escapes ' (apos) and now uses
+  String.replace instead of iterating over every char.
+- Added DeferredLock to Async
+- Renamed getElementsComputedStyle to computedStyle and moved
+  it from MochiKit.Visual to MochiKit.DOM
+- Moved all color support out of MochiKit.Visual and into MochiKit.Color
+- Fixed range() to accept a negative step
+- New alias to MochiKit.swapDOM called removeElement
+- New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
+  an attribute on a node without raising, roughly equivalent to:
+  updateNodeAttributes(node, {attr: value})
+- New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
+  a node's attribute or returns null without raising
+- Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
+  directly (addLoadEvent did not leak, since it clears the handler)
+
+2005-10-24      v1.0
+
+- New interpreter example that shows usage of MochiKit.DOM  to make
+  an interactive JavaScript interpreter
+- New MochiKit.LoggingPane for use with the MochiKit.Logging
+  debuggingBookmarklet, with logging_pane example to show its usage
+- New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
+  in order to provide a live regular expression matching tool
+- Added advanced number formatting capabilities to MochiKit.Format:
+  numberFormatter(pattern, placeholder="", locale="default") and
+  formatLocale(locale="default")
+- Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
+  MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.
+- Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE
+- Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
+  to MochiKit.Format
+- MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
+  isoTimestamp(isoString) will convert them to Date objects, and
+  toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC
+- Fixed missing errback for sendXMLHttpRequest when the server does not
+  respond
+- Fixed infinite recusion bug when using roundClass("DIV", ...)
+- Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
+  from being cancelled properly
+- Workaround in MochiKit.Base bind (and partial) for functions that don't
+  have an apply method, such as alert
+- Reliably return null from the string parsing/manipulation functions if
+  the input can't be coerced to a string (s + "") or the input makes no sense;
+  e.g. isoTimestamp(null) and isoTimestamp("") return null
+
+2005-10-08      v0.90
+
+- Fixed ISO compliance with toISODate
+- Added missing operator.sub
+- Placated Mozilla's strict warnings a bit
+- Added JSON serialization and unserialization support to MochiKit.Base:
+  serializeJSON, evalJSON, registerJSON. This is very similar to the repr
+  API.
+- Fixed a bug in the script loader that failed in some scenarios when a script
+  tag did not have a "src" attribute (thanks Ian!)
+- Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
+  P, FORM
+- Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
+  and parseQueryString, when available.
+
+2005-08-12      v0.80
+
+- Source highlighting in all examples, moved to a view-source example
+- Added some experimental syntax highlighting for the Rounded Corners example,
+  via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib
+- Use an indirect binding for the logger conveniences, so that the global
+  logger could be replaced by setting MochiKit.Logger.logger to something else
+  (though an observer is probably a better choice).
+- Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
+  which will be looked up with getElement
+- Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
+  node.parentNode)
+- Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success
+- Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues
+- Possible workaround for Safari issue with swapDOM, where it would get
+  confused because two elements were in the DOM at the same time with the
+  same id
+- Added missing THEAD convenience function to MochiKit.DOM
+- Added lstrip, rstrip, strip to MochiKit.Format
+- Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
+  MochiKit.DOM
+- MochiKit.Iter.iextend now has a fast-path for array-like objects
+- Added HSV color space support to MochiKit.Visual
+- Fixed a bug in the sortable_tables example, it now converts types
+  correctly
+- Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
+  scope
+
+2005-08-04      v0.70
+
+- New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
+  a little TAL-ish DOM templating attribute language.
+- sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
+  ignore requests with status == 0, which seems to happen for cached or local
+  requests
+- Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.
+- Changed scrapeText API to return a string by default. This is API-breaking!
+  It was dumb to have the default return value be the form you almost never
+  want. Sorry.
+- Added special form to swapDOM(dest, src). If src is null, dest is removed
+  (where previously you'd likely get a DOM exception).
+- Added three new functions to MochiKit.Base for dealing with URL query
+  strings: urlEncode, queryString, parseQueryString
+- MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
+  starts with "on" (e.g. "onclick"). If v is a string, it will set it to
+  new Function(v).
+- Another workaround for Internet "worst browser ever" Explorer's setAttribute
+  usage in MochiKit.DOM.createDOM (checked -> defaultChecked).
+- Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM
+- Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
+  now!
+
+2005-07-29      v0.60
+
+- Beefed up the MochiKit.DOM test suite
+- Fixed return value for MochiKit.DOM.swapElementClass, could return
+  false unexpectedly before
+- Added an optional "parent" argument to
+  MochiKit.DOM.getElementsByTagAndClassName
+- Added a "packed" version in packed/MochiKit/MochiKit.js
+- Changed build script to rewrite the URLs in tests to account for the
+  JSAN-required reorganization
+- MochiKit.Compat to potentially work around IE 5.5 issues
+  (5.0 still not supported). Test.Simple doesn't seem to work there,
+  though.
+- Several minor documentation corrections
+
+2005-07-27      v0.50
+
+- Initial Release
diff --git a/mochikit_v14/doc/rst/MochiKit/Visual.rst b/mochikit_v14/doc/rst/MochiKit/Visual.rst
new file mode 100755 (executable)
index 0000000..00a6b99
--- /dev/null
@@ -0,0 +1,531 @@
+.. title:: MochiKit.Visual - visual effects
+
+Name
+====
+
+MochiKit.Visual - visual effects
+
+
+Synopsis
+========
+
+::
+
+    // round the corners of all h1 elements
+    roundClass("h1", null);
+
+    // round the top left corner of the element with the id "title"
+    roundElement("title", {corners: "tl"});
+
+    // Add an fade effect to an element
+    fade('myelement');
+
+
+Description
+===========
+
+MochiKit.Visual provides visual effects and support functions for
+visuals.
+
+
+Dependencies
+============
+
+- :mochiref:`MochiKit.Base`
+- :mochiref:`MochiKit.Iter`
+- :mochiref:`MochiKit.DOM`
+- :mochiref:`MochiKit.Color`
+- :mochiref:`MochiKit.Position`
+
+Overview
+========
+
+MochiKit.Visual provides different visual effect: rounded corners and
+animations for your HTML elements. Rounded corners are created
+completely through CSS manipulations and require no external images or
+style sheets.  This implementation was adapted from Rico_. Dynamic
+effects are ported from Scriptaculous_.
+
+.. _Rico: http://www.openrico.org
+
+.. _Scriptaculous: http://script.aculo.us
+
+
+API Reference
+=============
+
+Functions
+---------
+
+:mochidef:`roundClass(tagName[, className[, options]])`:
+
+    Rounds all of the elements that match the ``tagName`` and
+    ``className`` specifiers, using the options provided.  ``tagName``
+    or ``className`` can be ``null`` to match all tags or classes.
+    For more information about the options, see the
+    :mochiref:`roundElement` function.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`roundElement(element[, options])`:
+
+    Immediately round the corners of the specified element.  The
+    element can be given as either a string with the element ID, or as
+    an element object.
+
+    The options mapping has the following defaults:
+
+    ========= =================
+    corners   ``"all"``
+    color     ``"fromElement"``
+    bgColor   ``"fromParent"``
+    blend     ``true``
+    border    ``false``
+    compact   ``false``
+    ========= =================
+
+    corners:
+
+        specifies which corners of the element should be rounded.
+        Choices are:
+
+        - all
+        - top
+        - bottom
+        - tl (top left)
+        - bl (bottom left)
+        - tr (top right)
+        - br (bottom right)
+
+        Example:
+            ``"tl br"``: top-left and bottom-right corners are rounded
+
+    blend:
+        specifies whether the color and background color should be
+        blended together to produce the border color.
+
+    *Availability*:
+        Available in MochiKit 1.3.1+
+
+
+:mochidef:`toggle(element[, effect[, options]])`:
+
+    Toggle an element between visible and invisible state using an effect.
+
+    effect:
+        One of the visual pairs to use, between 'slide', 'blind',
+        'appear', and 'size'.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`tagifyText(element[, tagifyStyle])`:
+
+    Transform a node text into nodes containing one letter by tag.
+
+    tagifyStyle:
+        style to apply to character nodes, default to 'position:
+        relative'.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`multiple(elements, effect[, options])`:
+
+    Launch the same effect on a list of elements.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Basic Effects classes
+---------------------
+
+:mochidef:`DefaultOptions`:
+
+    Default options for all Effect creation.
+
+    =========== ========================================
+    transition  ``MochiKit.Visual.Transitions.sinoidal``
+    duration    ``1.0``
+    fps         ``25.0``
+    sync        ``false``
+    from        ``0.0``
+    to          ``1.0``
+    delay       ``0.0``
+    queue       ``'parallel'``
+    =========== ========================================
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Base()`:
+
+    Base class to all effects. Define a basic looping service, use it
+    for creating new effects.
+
+    You can override the methods ``setup``, ``update`` and ``finish```.
+
+    The class defines a number of events that will be called during effect
+    life. The events are:
+
+    - beforeStart
+    - beforeSetup
+    - beforeUpdate
+    - afterUpdate
+    - beforeFinish
+    - afterFinish
+
+    If you want to define your own callbacks, define it in the options
+    parameter of the effect. Example::
+
+        // I slide it up and then down again
+        slideUp('myelement', {afterFinish: function () {
+            slideDown('myelement');
+        });
+    Specific ``internal`` events are also available: for each one abone the
+    same exists with 'Internal' (example: 'beforeStartInternal'). Their purpose
+    is mainly for creating your own effect and keep the user access to event
+    callbacks (not overriding the library ones).
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Parallel(effects [, options])`:
+
+    Launch effects in parallel.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Opacity(element [, options])`:
+
+    Change the opacity of an element progressively.
+
+    options:
+
+    ====== ========
+    from   ``0.0``
+    to     ``1.0``
+    ====== ========
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Move(element [, options])`:
+
+    Change the position of an element in small steps, creating a
+    moving effect.
+
+    options:
+
+    ========= ================
+    x         ``0``
+    y         ``0``
+    position  ``'relative'``
+    ========= ================
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Scale(element, percent [, options])`:
+
+    Change the size of an element.
+
+    percent:
+        Final wanted size in percent of current size. The size will be
+        reduced if the value is between 0 and 100, and raised if the
+        value is above 100.
+
+    options:
+
+    ================ ============
+    scaleX           ``true``
+    scaleY           ``true``
+    scaleContent     ``true``
+    scaleFromCenter  ``false``
+    scaleMode        ``'box'``
+    scaleFrom        ``100.0``
+    scaleTo          ``percent``
+    ================ ============
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Highlight(element [, options])`:
+
+    Highlight an element, flashing with one color.
+
+    options:
+
+    =========== ==============
+    startcolor  ``'#ffff99'``
+    =========== ==============
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`ScrollTo(element [, options])`:
+
+    Scroll the window to the position of the given element.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`Morph(element [, options])`:
+
+    Make a transformation to the given element. It's called with the option
+    ``style`` with an array holding the styles to change. It works with
+    properties for size (``font-size``, ``border-width``, ...) and properties
+    for color (``color``, ``background-color``, ...). 
+
+    For size, it's better to have defined the original style. You *must*
+    use the same unit in the call to Morph (no translation exists between two
+    different units).
+    
+    Parsed length are postfixed with: em, ex, px, in, cm, mm, pt, pc.
+    
+    Example::
+        
+        <div id="foo" style="font-size: 1em">MyDiv</div>
+        ...
+        Morph("foo", {"style": {"font-size": "2em"}});
+
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+Combination Effects
+-------------------
+
+:mochidef:`fade(element [, options])`:
+
+    Change the opacity of an element until making it disappear.
+
+    options:
+
+    ====== =============================================
+    from   ``element.opacity || 1.0``
+    to     ``0.0``
+    ====== =============================================
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`appear(element [, options])`:
+
+    Slowly show an invisible element.
+
+    options:
+
+    ===== =========
+    from  ``0.0``
+    to    ``1.0``
+    ===== =========
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`puff(element [, options])`:
+
+    Make an element double size, and then make it disappear.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`blindUp(element [, options])`:
+
+    Blind an element up, changing its vertical size to 0.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`blindDown(element [, options])`:
+
+    Blind an element down, restoring its vertical size.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`switchOff(element [, options])`:
+
+    A switch-off like effect, making the element disappear.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`dropOut(element [, options])`:
+
+    Make the element fall and fade.
+
+    options:
+
+    ======== =======
+    distance ``100``
+    ======== =======
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`shake(element [, options])`:
+
+    Shake an element from left to right.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`slideDown(element [, options])`:
+
+    Slide an element down.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`slideUp(element [, options])`:
+
+    Slide an element up.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`squish(element [, options])`:
+
+    Reduce the horizontal and vertical sizes at the same time, using
+    the top left corner.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`grow(element [, options])`:
+
+    Restore the size of an element.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`shrink(element [, options])`:
+
+    Shrink an element to its center.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`pulsate(element [, options])`:
+
+    Switch an element between appear and fade.
+
+    options:
+
+    ====== ========
+    pulses ``null``
+    ====== ========
+
+    pulses controls the number of pulses made during the effect.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+:mochidef:`fold(element [, options])`:
+
+    Reduce first the vertical size, and then the horizontal size.
+
+    *Availability*:
+        Available in MochiKit 1.4+
+
+
+The Effects Queue
+-----------------
+
+When you create effects based on user input (mouse clicks for example), it can
+create conflicts between the effects if multiple effects are running at the
+same time. To manage this problem, the Queue mechanism has been introduced:
+it's responsible for running the effects as you desired.
+
+By default, you have one Queue called 'global', and the effects run in 'parallel'
+(see default options). Every effects have a queue option to customize this.
+It can be a string, the scope is then global:
+    
+- `start`: the effect will be run before any other;
+- `end`: the effect will be run after any other;
+- `break`: every other effects break when the the effect start;
+- `parallel`: the effect run normally with others.
+
+
+But you have even more control if you use an array with the following keys:
+
+- `position` takes a value listed above;
+- `scope` manages how the information has to be taken. If it's `global` 
+  then it's the same information for every effects. Otherwise you can define
+  your own scode. For example, if you add an effect on a specified element,
+  you may use the element id as scode;
+- `limit` defines how many effects can run in the current scode. If an
+  effect is added whereas the limit is reached, it will never be run (it's
+  lost).
+
+
+See Also
+========
+
+.. [1] Application Kit Reference - NSColor: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html
+.. [2] SVG 1.0 color keywords: http://www.w3.org/TR/SVG/types.html#ColorKeywords
+.. [3] W3C CSS3 Color Module: http://www.w3.org/TR/css3-color/#svg-color
+
+
+Authors
+=======
+
+- Kevin Dangoor <dangoor@gmail.com>
+- Bob Ippolito <bob@redivi.com>
+- Thomas Herve <therve@gmail.com>
+- Round corners originally adapted from Rico <http://openrico.org/>
+  (though little remains)
+- Effects originally adapted from Script.aculo.us
+  <http://script.aculo.us/>
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>.  This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
+
+Portions adapted from `Rico`_ are available under the terms of the
+`Apache License, Version 2.0`_.
+
+Portions adapted from `Scriptaculous`_ are available under the terms
+of the `MIT License`_.
+
+.. _`Apache License, Version 2.0`: http://www.apache.org/licenses/LICENSE-2.0.html
diff --git a/mochikit_v14/doc/rst/MochiKit/index.rst b/mochikit_v14/doc/rst/MochiKit/index.rst
new file mode 100755 (executable)
index 0000000..59ff018
--- /dev/null
@@ -0,0 +1,81 @@
+.. title:: MochiKit Documentation Index
+
+Distribution
+============
+
+MochiKit - makes JavaScript suck a bit less
+
+- :mochiref:`MochiKit.Async` - manage asynchronous tasks
+- :mochiref:`MochiKit.Base` - functional programming and useful comparisons
+- :mochiref:`MochiKit.DOM` - painless DOM manipulation API
+- :mochiref:`MochiKit.DragAndDrop` - drag and drop
+- :mochiref:`MochiKit.Color` - color abstraction with CSS3 support
+- :mochiref:`MochiKit.DateTime` - "what time is it anyway?"
+- :mochiref:`MochiKit.Format` - string formatting goes here
+- :mochiref:`MochiKit.Iter` - itertools for JavaScript; iteration made HARD,
+  and then easy
+- :mochiref:`MochiKit.Logging` - we're all tired of ``alert()``
+- :mochiref:`MochiKit.LoggingPane` - interactive :mochiref:`MochiKit.Logging`
+  pane
+- :mochiref:`MochiKit.Selector` - selecting elements by CSS selector syntax
+- :mochiref:`MochiKit.Signal` - simple universal event handling
+- :mochiref:`MochiKit.Style` - painless CSS manipulation API
+- :mochiref:`MochiKit.Sortable` - sortable
+- :mochiref:`MochiKit.Visual` - visual effects
+
+
+Notes
+=====
+
+To turn off MochiKit's export feature (which may be necessary for
+compatibility with some existing code), do this before loading
+MochiKit::
+
+    <script type="text/javascript">MochiKit = {__export__: false};</script>
+
+When export mode is off, you must use fully qualified names for
+all MochiKit functions (e.g. ``MochiKit.Base.map(...)``).
+
+
+Screencasts
+===========
+
+- `MochiKit 1.1 Intro`__
+
+.. __: http://mochikit.com/screencasts/MochiKit_Intro-1
+
+See Also
+========
+
+.. _`mochikit.com`: http://mochikit.com/
+.. _`from __future__ import *`: http://bob.pythonmac.org/
+.. _`MochiKit on JSAN`: http://openjsan.org/doc/b/bo/bob/MochiKit/
+.. _`MochiKit tag on del.icio.us`: http://del.icio.us/tag/mochikit
+.. _`MochiKit tag on Technorati`: http://technorati.com/tag/mochikit
+.. _`Google Groups: MochiKit`: http://groups.google.com/group/mochikit
+
+- `Google Groups: MochiKit`_: The official mailing list for discussions
+  related to development of and with MochiKit
+- `mochikit.com`_: MochiKit's home on the web
+- `from __future__ import *`_: Bob Ippolito's blog
+- `MochiKit on JSAN`_: the JSAN distribution page for MochiKit
+- `MochiKit tag on del.icio.us`_: Recent bookmarks related to MochiKit
+- `MochiKit tag on Technorati`_: Recent blog entries related to MochiKit
+
+
+Version History
+===============
+
+.. include:: VersionHistory.rst
+
+
+Copyright
+=========
+
+Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
+dual-licensed free software; you can redistribute it and/or modify it
+under the terms of the `MIT License`_ or the `Academic Free License
+v2.1`_.
+
+.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
+.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
diff --git a/mochikit_v14/examples/ajax_tables/ajax_tables.css b/mochikit_v14/examples/ajax_tables/ajax_tables.css
new file mode 100755 (executable)
index 0000000..d214965
--- /dev/null
@@ -0,0 +1,69 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
+
+table.datagrid {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+table.datagrid thead th { 
+    text-align: left;
+    background-color: #4B4545;
+    background-repeat: no-repeat;
+    background-position: right center;
+    color: white;
+    font-weight: bold;
+    padding: .3em .7em;
+    font-size: .9em;
+    padding-right: 5px;
+    background-repeat: no-repeat;
+    background-position: 95% right;
+}
+
+table.datagrid thead th a {
+    color: white;
+    text-decoration: none;
+    font-size: 1.0em;
+    background-repeat: no-repeat;
+    background-position: center right;
+    padding-right: 15px;
+}
+
+table.datagrid thead th.over {
+    background-color: #746B6B;
+    cursor: pointer;
+}
+
+table.datagrid tbody th {
+    font-weight: bold;
+}
+
+table.datagrid tbody td, table.datagrid tbody th {
+    text-align: left;
+    padding: .3em .7em;
+    border-bottom: 1px solid #eee;
+}
+
+table.datagrid tbody tr.alternate td, table.datagrid tbody tr.alternate th {
+    background-color: #f1f1f1;
+}
+
+table.datagrid tfoot td, table.datagrid tfoot th { 
+    background-color: #FFFEE3;
+    color: #4B4545;
+    padding: .5em;
+    font-weight: bold;
+    border-top: 2px solid #4B4545;
+}
+
+table.datagrid tfoot th { text-align: left; }
+
+table.datagrid tfoot td {  }
+
+.invisible { display: none; }
+
+.mochi-template { display: none; }
+.mochi-example { display: none; }
diff --git a/mochikit_v14/examples/ajax_tables/ajax_tables.js b/mochikit_v14/examples/ajax_tables/ajax_tables.js
new file mode 100644 (file)
index 0000000..5390dd7
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+
+On page load, the SortableManager:
+
+- Rips out all of the elements with the mochi-example class.
+- Finds the elements with the mochi-template class and saves them for
+  later parsing with "MochiTAL".
+- Finds the anchor tags with the mochi:dataformat attribute and gives them
+  onclick behvaiors to load new data, using their href as the data source.
+  This makes your XML or JSON look like a normal link to a search engine
+  (or javascript-disabled browser).
+- Clones the thead element from the table because it will be replaced on each
+  sort.
+- Sets up a default sort key of "domain_name" and queues a load of the json
+  document.
+
+
+On data load, the SortableManager:
+
+- Parses the table data from the document (columns list, rows list-of-lists)
+  and turns them into a list of [{column:value, ...}] objects for easy sorting
+  and column order stability.
+- Chooses the default (or previous) sort state and triggers a sort request
+
+
+On sort request:
+
+- Replaces the cloned thead element with a copy of it that has the sort
+  indicator (&uarr; or &darr;) for the most recently sorted column (matched up
+  to the first field in the th's mochi:sortcolumn attribute), and attaches
+  onclick, onmousedown, onmouseover, onmouseout behaviors to them. The second
+  field of mochi:sortcolumn attribute is used to perform a non-string sort.
+- Performs the sort on the domains list.  If the second field of
+  mochi:sortcolumn was not "str", then a custom function is used and the
+  results are stored away in a __sort__ key, which is then used to perform the
+  sort (read: shwartzian transform).
+- Calls processMochiTAL on the page, which finds the mochi-template sections 
+  and then looks for mochi:repeat and mochi:content attributes on them, using
+  the data object.
+
+*/
+
+processMochiTAL = function (dom, data) {
+    /***
+
+        A TAL-esque template attribute language processor,
+        including content replacement and repeat
+
+    ***/
+
+    // nodeType == 1 is an element, we're leaving
+    // text nodes alone.
+    if (dom.nodeType != 1) {
+        return;
+    }
+    var attr;
+    // duplicate this element for each item in the
+    // given list, and then process the duplicated
+    // element again (sans mochi:repeat tag)
+    attr = getAttribute(dom, "mochi:repeat");
+    if (attr) {
+        dom.removeAttribute("mochi:repeat");
+        var parent = dom.parentNode;
+        attr = attr.split(" ");
+        var name = attr[0];
+        var lst = valueForKeyPath(data, attr[1]);
+        if (!lst) {
+            return;
+        }
+        for (var i = 0; i < lst.length; i++) {
+            data[name] = lst[i];
+            var newDOM = dom.cloneNode(true);
+            processMochiTAL(newDOM, data);
+            parent.insertBefore(newDOM, dom);
+        }
+        parent.removeChild(dom);
+        return;
+    }
+    // do content replacement if there's a mochi:content attribute
+    // on the element
+    attr = getAttribute(dom, "mochi:content");
+    if (attr) {
+        dom.removeAttribute("mochi:content");
+        replaceChildNodes(dom, valueForKeyPath(data, attr));
+        return;
+    }
+    // we make a shallow copy of the current list of child nodes
+    // because it *will* change if there's a mochi:repeat in there!
+    var nodes = list(dom.childNodes);
+    for (var i = 0; i < nodes.length; i++) {
+        processMochiTAL(nodes[i], data);
+    }
+};
+
+mouseOverFunc = function () {
+    addElementClass(this, "over");
+};
+
+mouseOutFunc = function () {
+    removeElementClass(this, "over");
+};
+
+ignoreEvent = function (ev) {
+    if (ev && ev.preventDefault) {
+        ev.preventDefault();
+        ev.stopPropagation();
+    } else if (typeof(event) != 'undefined') {
+        event.cancelBubble = false;
+        event.returnValue = false;
+    }
+};
+
+SortTransforms = {
+    "str": operator.identity,
+    "istr": function (s) { return s.toLowerCase(); },
+    "isoDate": isoDate
+};
+
+getAttribute = function (dom, key) {
+    try {
+        return dom.getAttribute(key);
+    } catch (e) {
+        return null;
+    }
+};
+
+datatableFromXMLRequest = function (req) {
+    /***
+
+        This effectively converts domains.xml to the
+        same form as domains.json
+
+    ***/
+    var xml = req.responseXML;
+    var nodes = xml.getElementsByTagName("column");
+    var rval = {"columns": map(scrapeText, nodes)};
+    var rows = [];
+    nodes = xml.getElementsByTagName("row") 
+    for (var i = 0; i < nodes.length; i++) {
+        var cells = nodes[i].getElementsByTagName("cell");
+        rows.push(map(scrapeText, cells));
+    }
+    rval.rows = rows;
+    return rval;
+};
+
+loadFromDataAnchor = function (ev) {
+    ignoreEvent(ev);
+    var format = this.getAttribute("mochi:dataformat");
+    var href = this.href;
+    sortableManager.loadFromURL(format, href);
+};
+
+valueForKeyPath = function (data, keyPath) {
+    var chunks = keyPath.split(".");
+    while (chunks.length && data) {
+        data = data[chunks.shift()];
+    }
+    return data;
+};
+
+
+SortableManager = function () {
+    this.thead = null;
+    this.thead_proto = null;
+    this.tbody = null;
+    this.deferred = null;
+    this.columns = [];
+    this.rows = [];
+    this.templates = [];
+    this.sortState = {};
+    bindMethods(this);
+};
+
+SortableManager.prototype = {
+
+    "initialize": function () {
+        // just rip all mochi-examples out of the DOM
+        var examples = getElementsByTagAndClassName(null, "mochi-example");
+        while (examples.length) {
+            swapDOM(examples.pop(), null);
+        }
+        // make a template list
+        var templates = getElementsByTagAndClassName(null, "mochi-template");
+        for (var i = 0; i < templates.length; i++) {
+            var template = templates[i];
+            var proto = template.cloneNode(true);
+            removeElementClass(proto, "mochi-template");
+            this.templates.push({
+                "template": proto,
+                "node": template
+            });
+        }
+        // set up the data anchors to do loads
+        var anchors = getElementsByTagAndClassName("a", null);
+        for (var i = 0; i < anchors.length; i++) {
+            var node = anchors[i];
+            var format = getAttribute(node, "mochi:dataformat");
+            if (format) {
+                node.onclick = loadFromDataAnchor;
+            }
+        }
+
+        // to find sort columns
+        this.thead = getElementsByTagAndClassName("thead", null)[0];
+        this.thead_proto = this.thead.cloneNode(true);
+
+        this.sortkey = "domain_name";
+        this.loadFromURL("json", "domains.json");
+    },
+
+    "loadFromURL": function (format, url) {
+        log('loadFromURL', format, url);
+        var d;
+        if (this.deferred) {
+            this.deferred.cancel();
+        }
+        if (format == "xml") {
+            var d = doXHR(url, {
+                mimeType: 'text/xml',
+                headers: {Accept: 'text/xml'}
+            });
+            d.addCallback(datatableFromXMLRequest);
+        } else if (format == "json") {
+            d = loadJSONDoc(url);
+        } else {
+            throw new TypeError("format " + repr(format) + " not supported");
+        }
+        // keep track of the current deferred, so that we can cancel it
+        this.deferred = d;
+        var self = this;
+        // on success or error, remove the current deferred because it has
+        // completed, and pass through the result or error
+        d.addBoth(function (res) {
+            self.deferred = null; 
+            log('loadFromURL success');
+            return res;
+        });
+        // on success, tag the result with the format used so we can display
+        // it
+        d.addCallback(function (res) {
+            res.format = format;
+            return res;
+        });
+        // call this.initWithData(data) once it's ready
+        d.addCallback(this.initWithData);
+        // if anything goes wrong, except for a simple cancellation,
+        // then log the error and show the logger
+        d.addErrback(function (err) {
+            if (err instanceof CancelledError) {
+                return;
+            }
+            logError(err);
+            logger.debuggingBookmarklet();
+        });
+        return d;
+    },
+
+    "initWithData": function (data) {
+        /***
+
+            Initialize the SortableManager with a table object
+        
+        ***/
+
+        // reformat to [{column:value, ...}, ...] style as the domains key
+        var domains = [];
+        var rows = data.rows;
+        var cols = data.columns;
+        for (var i = 0; i < rows.length; i++) {
+            var row = rows[i];
+            var domain = {};
+            for (var j = 0; j < cols.length; j++) {
+                domain[cols[j]] = row[j];
+            }
+            domains.push(domain);
+        }
+        data.domains = domains;
+        this.data = data;
+        // perform a sort and display based upon the previous sort state,
+        // defaulting to an ascending sort if this is the first sort
+        var order = this.sortState[this.sortkey];
+        if (typeof(order) == 'undefined') {
+            order = true;
+        }
+        this.drawSortedRows(this.sortkey, order, false);
+
+    },
+
+    "onSortClick": function (name) {
+        /***
+
+            Return a sort function for click events
+
+        ***/
+        // save ourselves from doing a bind
+        var self = this;
+        // on click, flip the last sort order of that column and sort
+        return function () {
+            log('onSortClick', name);
+            var order = self.sortState[name];
+            if (typeof(order) == 'undefined') {
+                // if it's never been sorted by this column, sort ascending
+                order = true;
+            } else if (self.sortkey == name) {
+                // if this column was sorted most recently, flip the sort order
+                order = !((typeof(order) == 'undefined') ? false : order);
+            }
+            self.drawSortedRows(name, order, true);
+        };
+    },
+
+    "drawSortedRows": function (key, forward, clicked) {
+        /***
+
+            Draw the new sorted table body, and modify the column headers
+            if appropriate
+
+        ***/
+        log('drawSortedRows', key, forward);
+
+        // save it so we can flip next time
+        this.sortState[key] = forward;
+        this.sortkey = key;
+        var sortstyle;
+
+        // setup the sort columns   
+        var thead = this.thead_proto.cloneNode(true);
+        var cols = thead.getElementsByTagName("th");
+        for (var i = 0; i < cols.length; i++) {
+            var col = cols[i];
+            var sortinfo = getAttribute(col, "mochi:sortcolumn").split(" ");
+            var sortkey = sortinfo[0];
+            col.onclick = this.onSortClick(sortkey);
+            col.onmousedown = ignoreEvent;
+            col.onmouseover = mouseOverFunc;
+            col.onmouseout = mouseOutFunc;
+            // if this is the sorted column
+            if (sortkey == key) {
+                sortstyle = sortinfo[1];
+                // \u2193 is down arrow, \u2191 is up arrow
+                // forward sorts mean the rows get bigger going down
+                var arrow = (forward ? "\u2193" : "\u2191");
+                // add the character to the column header
+                col.appendChild(SPAN(null, arrow));
+                if (clicked) {
+                    col.onmouseover();
+                }
+            }
+        }
+        this.thead = swapDOM(this.thead, thead);
+
+        // apply a sort transform to a temporary column named __sort__,
+        // and do the sort based on that column
+        if (!sortstyle) {
+            sortstyle = "str";
+        }
+        var sortfunc = SortTransforms[sortstyle];
+        if (!sortfunc) {
+            throw new TypeError("unsupported sort style " + repr(sortstyle));
+        }
+        var domains = this.data.domains;
+        for (var i = 0; i < domains.length; i++) {
+            var domain = domains[i];
+            domain.__sort__ = sortfunc(domain[key]);
+        }
+
+        // perform the sort based on the state given (forward or reverse)
+        var cmp = (forward ? keyComparator : reverseKeyComparator);
+        domains.sort(cmp("__sort__"));
+
+        // process every template with the given data
+        // and put the processed templates in the DOM
+        for (var i = 0; i < this.templates.length; i++) {
+            log('template', i, template);
+            var template = this.templates[i];
+            var dom = template.template.cloneNode(true);
+            processMochiTAL(dom, this.data);
+            template.node = swapDOM(template.node, dom);
+        }
+
+    }
+
+};
+
+// create the global SortableManager and initialize it on page load
+sortableManager = new SortableManager();
+addLoadEvent(sortableManager.initialize);
+
+// rewrite the view-source links
+addLoadEvent(function () {
+    var elems = getElementsByTagAndClassName("A", "view-source");
+    var page = "ajax_tables/";
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        var href = elem.href.split(/\//).pop();
+        elem.target = "_blank";
+        elem.href = "../view-source/view-source.html#" + page + href;
+    }
+});
diff --git a/mochikit_v14/examples/ajax_tables/domains.json b/mochikit_v14/examples/ajax_tables/domains.json
new file mode 100755 (executable)
index 0000000..61624d8
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "columns": [ "domain_name", "create_date", "expiry_date", "organization_name"],
+    "rows": [
+        ["json.org", "2000-05-08", "2006-05-08", "Douglas Crockford"],
+        ["mochibot.com", "2005-02-10", "2007-02-10", "Jameson Hsu"],
+        ["pythonmac.org", "2003-09-24", "2006-09-24", "Bob Ippolito"],
+        ["undefined.org", "2000-01-10", "2006-01-10", "Robert J Ippolito"],
+        ["python.org", "1995-03-27", "2007-03-28", "Python Software Foundation"]
+    ]
+}
diff --git a/mochikit_v14/examples/ajax_tables/domains.xml b/mochikit_v14/examples/ajax_tables/domains.xml
new file mode 100755 (executable)
index 0000000..ba9f24b
--- /dev/null
@@ -0,0 +1,40 @@
+<datatable>
+    <columns>
+        <column>domain_name</column>
+        <column>create_date</column>
+        <column>expiry_date</column>
+        <column>organization_name</column>
+    </columns>
+    <rows>
+        <row>
+            <cell>xml.com</cell>
+            <cell>1996-09-30</cell>
+            <cell>2012-09-29</cell>
+            <cell>Tim Bray</cell>
+        </row>
+        <row>
+            <cell>mochibot.com</cell>
+            <cell>2005-02-10</cell>
+            <cell>2007-02-10</cell>
+            <cell>Jameson Hsu</cell>
+        </row>
+        <row>
+            <cell>pythonmac.org</cell>
+            <cell>2003-09-24</cell>
+            <cell>2006-09-24</cell>
+            <cell>Bob Ippolito</cell>
+        </row>
+        <row>
+            <cell>undefined.org</cell>
+            <cell>2000-01-10</cell>
+            <cell>2006-01-10</cell>
+            <cell>Robert J Ippolito</cell>
+        </row>
+        <row>
+            <cell>python.org</cell>
+            <cell>1995-03-27</cell>
+            <cell>2007-03-28</cell>
+            <cell>Python Software Foundation</cell>
+        </row>
+    </rows>
+</datatable>
diff --git a/mochikit_v14/examples/ajax_tables/index.html b/mochikit_v14/examples/ajax_tables/index.html
new file mode 100644 (file)
index 0000000..e90aa84
--- /dev/null
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+
+Using a made-up xmlns..
+
+-->
+<html xmlns:mochi="http://mochikit.com/examples/ajax_tables">
+    <head>
+        <title>Sortable Tables from Scratch with MochiKit</title>
+        <link href="ajax_tables.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="ajax_tables.js"></script>
+    </head>
+    <body>
+        <h1>
+            Sortable Ajax Tables in JSON and XML with MochiKit
+        </h1>
+        <div>
+            <div>
+                <p>
+                    This is an example of how one might use <a href="http://mochikit.com/">MochiKit</a> to do
+                    sortable tables from data given by the server in either JSON
+                    or XML format.  It uses
+                    <a href="../../doc/html/MochiKit/Async.html">MochiKit.Async</a>
+                    to fetch the data, and 
+                    <a href="../../doc/html/MochiKit/DOM.html">MochiKit.DOM</a>
+                    to display it.
+                </p>
+                <p>
+                    Includes a micro implementation of something
+                    <a href="http://www.zope.org/Wikis/DevSite/Projects/ZPT/FrontPage">TAL</a>-esque
+                    (called "MochiTAL" in the source, using a mochi: namespace).
+                    For a more detailed description of what happens under the
+                    covers, view the <a href="ajax_tables.js" class="view-source">ajax_tables.js</a>
+                    source and look at the comments.
+                </p>
+            </div>
+        </div>
+        <div>
+            View Source: [
+            <a href="index.html" class="view-source">index.html</a> |
+            <a href="ajax_tables.js" class="view-source">ajax_tables.js</a> |
+            <a href="domains.json" class="view-source">domains.json</a> |
+            <a href="domains.xml" class="view-source">domains.xml</a> 
+            ]
+        </div>
+        <div>
+            Load data: [
+            <a href="domains.json" mochi:dataformat="json">domains.json</a>
+            | <a href="domains.xml" mochi:dataformat="xml">domains.xml</a>
+            ]
+            (current format: <span class="mochi-template" mochi:content="format">loading</span>)
+        </div>
+        <table id="sortable_table" class="datagrid">
+            <thead>
+                <tr>
+                    <th mochi:sortcolumn="domain_name str">Domain Name</th>
+                    <th mochi:sortcolumn="create_date isoDate">Creation Date</th>
+                    <th mochi:sortcolumn="expiry_date isoDate">Expiry Date</th>
+                    <th mochi:sortcolumn="organization_name istr">Organization Name</th>
+                </tr>
+            </thead>
+            <tfoot class="invisible">
+                <tr>
+                    <td colspan="0"></td>
+                </tr>
+            </tfoot>
+            <tbody class="mochi-template">
+                <tr mochi:repeat="item domains">
+                    <td mochi:content="item.domain_name">mochibot.com</td>
+                    <td mochi:content="item.create_date">2005-02-10</td>
+                    <td mochi:content="item.expiry_date">2007-02-10</td>
+                    <td mochi:content="item.organization_name">Jameson Hsu</td>
+                </tr>
+                <tr class="mochi-example">
+                    <td>pythonmac.org</td>
+                    <td>2003-09-24</td>
+                    <td>2006-09-24</td>
+                    <td>Bob Ippolito</td>
+                </tr>
+                <tr class="mochi-example">
+                    <td>undefined.org</td>
+                    <td>2000-01-10</td>
+                    <td>2006-01-10</td>
+                    <td>Robert J Ippolito</td>
+                </tr>
+                <tr class="mochi-example">
+                    <td>python.org</td>
+                    <td>1995-03-27</td>
+                    <td>2007-03-28</td>
+                    <td>Python Software Foundation</td>
+                </tr>
+            </tbody>
+        </table>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/color_wheel/color_wheel.css b/mochikit_v14/examples/color_wheel/color_wheel.css
new file mode 100755 (executable)
index 0000000..21b4ace
--- /dev/null
@@ -0,0 +1,4 @@
+h1 { text-align: center; }
+#docs { text-align: center; }
+#source { text-align: center; }
+#color_wheel_container { position:absolute; left: 50%; top: 50% }
diff --git a/mochikit_v14/examples/color_wheel/color_wheel.js b/mochikit_v14/examples/color_wheel/color_wheel.js
new file mode 100644 (file)
index 0000000..4d844b0
--- /dev/null
@@ -0,0 +1,95 @@
+var radius = 225;
+var twoPI = Math.PI * 2;
+var amplification = 10;
+
+var calcAlpha = function (target, lightness) {
+    return Math.max(1.0 - (Math.abs(lightness - target) * amplification), 0);
+};
+
+var makeColorDiv = function (name) {
+    var c = Color.fromName(name);
+    var hsl = c.asHSL();
+    var r = hsl.s * radius;
+    var e = DIV({"style": {
+            "color": Color.fromHSL(hsl).toString(),
+            "width": "100px",
+            "height": "30px",
+            "position": "absolute",
+            "verticalAlign": "middle",
+            "textAlign": "center",
+            "left": Math.floor((Math.cos(hsl.h * twoPI) * r) - 50) + "px",
+            "top": Math.floor((Math.sin(hsl.h * twoPI) * r)) + "px"
+        }},
+        name 
+    );
+    // hsl.a = 0;
+    return [c, e];
+};
+
+var colorWheelOnLoad = function () {
+    var seenColors = {};
+    var colors = Color.namedColors();
+    var colorDivs = [];
+    for (var k in colors) {
+        var val = colors[k];
+        if (val in seenColors) {
+            continue;
+        }
+        colorDivs.push(makeColorDiv(k));
+    }
+    swapDOM(
+        "color_wheel",
+        DIV(null, map(itemgetter(1), colorDivs))
+    );
+    var colorCanary = DIV({"style":{"color": "blue"}}, "");
+    try {
+        colorCanary.style.color = "rgba(100,100,100,0.5)";
+    } catch (e) {
+        // IE passtastic
+    }
+    var colorFunc;
+    // Check for CSS3 HSL support
+    if (colorCanary.style.color == "blue") { 
+        var bgColor = Color.fromBackground();
+        colorFunc  = function (color, alpha) {
+            return bgColor.blendedColor(color, alpha).toHexString();
+        };
+    } else {
+        colorFunc = function (color, alpha) {
+            return color.colorWithAlpha(alpha).toRGBString();
+        }
+    }
+    // Per-frame animation
+    var intervalFunc = function (cycle, timeout) {
+        var target = 0.5 + (0.5 * Math.sin(Math.PI * (cycle / 180)));
+        for (var i = 0; i < colorDivs.length; i++) {
+            var cd = colorDivs[i];
+            var color = cd[0];
+            var alpha = calcAlpha(target, color.asHSL().l);
+            var style = cd[1].style;
+            if (alpha == 0) {
+                style.display = "none";
+            } else {
+                style.display ="";
+                style.color = colorFunc(color, alpha);
+            }
+        }
+        callLater(timeout, arguments.callee, cycle + 2, timeout);
+    };
+    // < 5 fps
+    intervalFunc(0, 1/5);
+};
+
+addLoadEvent(colorWheelOnLoad);
+
+// rewrite the view-source links
+addLoadEvent(function () {
+    var elems = getElementsByTagAndClassName("A", "view-source");
+    var page = "color_wheel/";
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        var href = elem.href.split(/\//).pop();
+        elem.target = "_blank";
+        elem.href = "../view-source/view-source.html#" + page + href;
+    }
+});
diff --git a/mochikit_v14/examples/color_wheel/index.html b/mochikit_v14/examples/color_wheel/index.html
new file mode 100644 (file)
index 0000000..2464e15
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>Demo of MochiKit.Color</title>
+        <link href="color_wheel.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="color_wheel.js"></script>
+    </head>
+    <body>
+        <h1>Color Wheel</h1>
+        <div id="docs">
+            Animated visualization of all the CSS3 colors by:
+            hue (angle), saturation (distance), luminance (time/alpha).
+            <br />
+            Uses <a href="http://mochikit.com/">MochiKit</a>'s 
+            <a href="../../doc/html/MochiKit/Color.html">MochiKit.Color</a>,
+            <a href="../../doc/html/MochiKit/DOM.html">MochiKit.DOM</a>,
+            and <a href="../../doc/html/MochiKit/Async.html">MochiKit.Async</a>.
+        </div>
+        <div id="source">
+            View Source: [
+                <a href="index.html" class="view-source">index.html</a> |
+                <a href="color_wheel.js" class="view-source">color_wheel.js</a>
+            ]
+        </div>
+
+        <div id="color_wheel_container">
+            <div id="color_wheel" /> 
+        </div>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/dnd_sortable/dnd_sortable.css b/mochikit_v14/examples/dnd_sortable/dnd_sortable.css
new file mode 100755 (executable)
index 0000000..080d6b9
--- /dev/null
@@ -0,0 +1,23 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
+
+#dnd_sortable {
+  margin: 0;
+  margin-top: 10px;
+  padding: 0;
+  list-style-type: none;
+  width: 250px;
+}
+
+#dnd_sortable li {
+    margin: 0;
+    margin-bottom: 4px;
+    padding: 5px;
+    border: 1px solid #888;
+    cursor: move;
+    text-align: center;
+}
+
diff --git a/mochikit_v14/examples/dnd_sortable/dropmarker.png b/mochikit_v14/examples/dnd_sortable/dropmarker.png
new file mode 100755 (executable)
index 0000000..77d7387
Binary files /dev/null and b/mochikit_v14/examples/dnd_sortable/dropmarker.png differ
diff --git a/mochikit_v14/examples/dnd_sortable/icon.png b/mochikit_v14/examples/dnd_sortable/icon.png
new file mode 100755 (executable)
index 0000000..f752986
Binary files /dev/null and b/mochikit_v14/examples/dnd_sortable/icon.png differ
diff --git a/mochikit_v14/examples/dnd_sortable/index.html b/mochikit_v14/examples/dnd_sortable/index.html
new file mode 100644 (file)
index 0000000..718de3f
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+    <head>
+        <title>Drag and Drop Sortable Tables with MochiKit</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+        <link href="dnd_sortable.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+        <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+    </head>
+    <body>
+        <h1>
+            Drag and Drop Sortable Tables with MochiKit
+        </h1>
+        <p>
+            View Source: [
+                <a href="index.html" class="view-source">index.html</a> 
+            ]
+        </p>
+        <ul id="dnd_sortable">
+            <li>mochibot.com</li>
+            <li>pythonmac.org</li>
+            <li>undefined.org</li>
+            <li>python.org</li>
+        </ul>
+        <p>
+            <a onclick="validate()">Validate order choice</a>
+        </p>
+<script type="text/javascript">
+MochiKit.Sortable.Sortable.create('dnd_sortable');
+
+validate = function () {
+    var children = MochiKit.DOM.getElement("dnd_sortable").childNodes;
+    var res = '';
+    for (var i = 0; i < children.length; i++) {
+        res += children[i].firstChild.nodeValue + ' ';
+    }
+    alert(res);
+}
+</script>
+<p>
+    <ul>
+        <li><a href="sortable_test.html">Test 1</a></li>
+        <li><a href="sortable2_test.html">Test 2</a></li>
+        <li><a href="sortable3_test.html">Test 3</a></li>
+        <li><a href="sortable4_test.html">Test 4</a></li>
+        <li><a href="sortable5_test.html">Test 5</a></li>
+        <li><a href="sortable_tree_test.html">Test tree</a></li>
+    </ul>
+</p>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/dnd_sortable/sortable2_test.html b/mochikit_v14/examples/dnd_sortable/sortable2_test.html
new file mode 100644 (file)
index 0000000..f969e83
--- /dev/null
@@ -0,0 +1,150 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Sortable ghosting functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Signal.js"></script>
+        <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+  <style>
+    ul.testlist { 
+      list-style-type:none;
+      margin:0;
+      padding:0;
+    }
+    ul.testlist li {
+      width:200px;
+      font:12px Verdana;
+      padding:4px;
+      cursor:move;
+    }
+    ul.testlist li.over {
+      background-color:#fcb;
+    }
+    ul.testlist li img {
+      float:left;
+      margin-right:8px;
+    }
+    div.dropmarker {
+      height:6px;
+      width:200px;
+      background: url(dropmarker.png) left top;
+      margin-top:-3px;
+      margin-left:-5px;
+      z-index:1000;
+      overflow: hidden;
+    }
+    #testlist4 li {
+      float:left;
+    }
+  </style>
+</head>
+<body>
+<h1>script.aculo.us Sortable ghosting functional test file</h1>
+
+<h2>Ghosting</h2>
+
+<ul id="testlist" class="testlist">
+<li id="item_1"><img src="icon.png" alt=""/> Lorem ipsum dolor</li>
+<li id="item_2"><img src="icon.png" alt=""/> sit amet</li>
+<li id="item_3"><img src="icon.png" alt=""/> consectetur adipisicing</li>
+<li id="item_4"><img src="icon.png" alt=""/> elit</li>
+<li id="item_5"><img src="icon.png" alt=""/> sed do eiusmod</li>
+<li id="item_6"><img src="icon.png" alt=""/> tempor incididunt</li>
+<li id="item_7"><img src="icon.png" alt=""/> ut labore et dolore</li>
+<li id="item_8"><img src="icon.png" alt=""/> magna aliqua</li>
+</ul>
+
+<p id="testlist_serialize">(waiting for onChange)</p>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  MochiKit.Sortable.Sortable.create('testlist',{ghosting:true,constraint:false,hoverclass:'over',
+    onUpdate:function(sortable){alert(MochiKit.Sortable.Sortable.serialize(sortable))},
+    onChange:function(element){$('testlist_serialize').innerHTML = MochiKit.Sortable.Sortable.serialize(element.parentNode)}
+  });
+// ]]>
+</script>
+
+<h2>No ghosting</h2>
+
+<ul id="testlist2" class="testlist">
+<li id="item_9"><img src="icon.png" alt=""/> Lorem ipsum dolor</li>
+<li id="item_10"><img src="icon.png" alt=""/> sit amet</li>
+<li id="item_11"><img src="icon.png" alt=""/> consectetur adipisicing</li>
+<li id="item_12"><img src="icon.png" alt=""/> elit</li>
+<li id="item_13"><img src="icon.png" alt=""/> sed do eiusmod</li>
+<li id="item_14"><img src="icon.png" alt=""/> tempor incididunt</li>
+<li id="item_15"><img src="icon.png" alt=""/> ut labore et dolore</li>
+<li id="item_16"><img src="icon.png" alt=""/> magna aliqua</li>
+</ul>
+
+<p id="testlist2_serialize">(waiting for onChange)</p>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  MochiKit.Sortable.Sortable.create('testlist2',{ghosting:false,constraint:false,hoverclass:'over',
+    onUpdate:function(sortable){alert(MochiKit.Sortable.Sortable.serialize(sortable))},
+    onChange:function(element){$('testlist2_serialize').innerHTML = MochiKit.Sortable.Sortable.serialize(element.parentNode)}
+  });
+// ]]>
+</script>
+
+<h2>Ghosting (inside position:relative container)</h2>
+<div style="position:relative;left:100px;top:-5px;">
+<ul id="testlist3" class="testlist">
+<li id="item_17"><img src="icon.png" alt=""/> Lorem ipsum dolor</li>
+<li id="item_18"><img src="icon.png" alt=""/> sit amet</li>
+<li id="item_19"><img src="icon.png" alt=""/> consectetur adipisicing</li>
+<li id="item_20"><img src="icon.png" alt=""/> elit</li>
+<li id="item_21"><img src="icon.png" alt=""/> sed do eiusmod</li>
+<li id="item_22"><img src="icon.png" alt=""/> tempor incididunt</li>
+<li id="item_23"><img src="icon.png" alt=""/> ut labore et dolore</li>
+<li id="item_24"><img src="icon.png" alt=""/> magna aliqua</li>
+</ul>
+</div>
+<p id="testlist3_serialize">(waiting for onChange)</p>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  MochiKit.Sortable.Sortable.create('testlist3',{ghosting:true,constraint:false,
+    onUpdate:function(sortable){alert(MochiKit.Sortable.Sortable.serialize(sortable))},
+    onChange:function(element){$('testlist3_serialize').innerHTML = MochiKit.Sortable.Sortable.serialize(element.parentNode)}
+  });
+// ]]>
+</script>
+
+
+<h2>Ghosting (inside position:relative container)</h2>
+<div style="position:relative;left:100px;top:-5px;">
+<ul id="testlist4" class="testlist">
+<li id="item_417"><img src="icon.png" alt=""/> Lorem ipsum dolor</li>
+<li id="item_418"><img src="icon.png" alt=""/> sit amet</li>
+<li id="item_419"><img src="icon.png" alt=""/> consectetur adipisicing</li>
+<li id="item_420"><img src="icon.png" alt=""/> elit</li>
+<li id="item_421"><img src="icon.png" alt=""/> sed do eiusmod</li>
+<li id="item_422"><img src="icon.png" alt=""/> tempor incididunt</li>
+<li id="item_423"><img src="icon.png" alt=""/> ut labore et dolore</li>
+<li id="item_424"><img src="icon.png" alt=""/> magna aliqua</li>
+</ul>
+</div>
+<p id="testlist4_serialize">(waiting for onChange)</p>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  MochiKit.Sortable.Sortable.create('testlist4',{overlap:'horizontal',ghosting:true,constraint:false,
+    onUpdate:function(sortable){alert(MochiKit.Sortable.Sortable.serialize(sortable))},
+    onChange:function(element){$('testlist4_serialize').innerHTML = MochiKit.Sortable.Sortable.serialize(element.parentNode)}
+  });
+// ]]>
+</script>
+
+
+<div id="debug"></div>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/dnd_sortable/sortable3_test.html b/mochikit_v14/examples/dnd_sortable/sortable3_test.html
new file mode 100644 (file)
index 0000000..bfcf0d2
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us sortable functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Signal.js"></script>
+        <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+  <style type="text/css" media="screen">
+    ul { height: 100px; border:1px dotted #888; }
+  </style>
+</head>
+<body>
+<h1>script.aculo.us Sortable two-lists w/ dropOnEmpty functional test file</h1>
+
+<ul id="thelist1">
+<li id="thelist1_1">Hey there! I'm item#1/1</li>
+<li id="thelist1_2">Hey there! I'm item#1/2</li>
+<li id="thelist1_3">Hey there! I'm item#1/3</li>
+</ul>
+
+<ul id="thelist2">
+</ul>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  MochiKit.Sortable.Sortable.create('thelist1',{containment:['thelist1','thelist2'], dropOnEmpty:true});
+  MochiKit.Sortable.Sortable.create('thelist2',{containment:['thelist1','thelist2'], dropOnEmpty:true});
+// ]]>
+</script>
+
+<a href="#" onclick="alert(MochiKit.Sortable.Sortable.serialize('thelist1'));return false;">Serialize sortable1</a>
+<a href="#" onclick="alert(MochiKit.Sortable.Sortable.serialize('thelist2'));return false;">Serialize sortable2</a>
+
+<div id="debug"></div>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/dnd_sortable/sortable4_test.html b/mochikit_v14/examples/dnd_sortable/sortable4_test.html
new file mode 100644 (file)
index 0000000..657f157
--- /dev/null
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us sortable functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Signal.js"></script>
+        <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+  <style type="text/css" media="screen">
+  ul.sortablelist {
+    list-style-image:none;
+    list-style-type:none;
+    margin-top:5px;
+    margin:0px;
+    padding:0px;
+  }
+
+  ul.sortabledemo li {
+    padding:0px;
+    margin:0px;
+  }
+
+  span.handle {
+    background-color: #E8A400;
+    color:white;
+    cursor: move;
+  }
+
+  li.green {
+    background-color: #ECF3E1;
+    border:1px solid #C5DEA1;
+    cursor: move;
+  }
+
+  li.orange {
+    border:1px solid #E8A400;
+    background-color: #FFF4D8;
+  }
+  </style>
+</head>
+<body>
+<h1>script.aculo.us: Two floating sortables with containment and dropOnEmpty</h1>
+
+<div style="height:200px;">
+<div style="float:left;">
+<h3>This is the first list</h3>
+ <ul class="sortabledemo" id="firstlist" style="height:150px;width:200px;">
+   <li class="green" id="firstlist_firstlist1">Item 1 from first list.</li>
+   <li class="green" id="firstlist_firstlist2">Item 2 from first list.</li>
+   <li class="green" id="firstlist_firstlist3">Item 3 from first list.</li>
+ </ul>
+</div>
+ <div style="float:left;">
+ <h3>And now the second list</h3>
+ <ul class="sortabledemo" id="secondlist" style="height:150px;width:200px;">
+   <li class="orange" id="secondlist_secondlist1">
+     <span class="handle">DRAG HERE</span> Item 1 from second list.
+   </li>
+   <li class="orange" id="secondlist_secondlist2">
+     <span class="handle">DRAG HERE</span> Item 2 from second list.
+   </li>
+   <li class="orange" id="secondlist_secondlist3">
+     <span class="handle">DRAG HERE</span> Item 3 from second list.
+   </li>
+ </ul>
+</div>
+</div>
+
+<hr style="clear:both" />
+
+<pre id="firstlist_debug"></pre>
+<pre id="secondlist_debug"></pre>
+
+ <script type="text/javascript">
+ // <![CDATA[
+   MochiKit.Sortable.Sortable.create("firstlist",
+     {dropOnEmpty:true,containment:["firstlist","secondlist"],constraint:false,
+      onChange:function(){$('firstlist_debug').innerHTML = MochiKit.Sortable.Sortable.serialize('firstlist') }});
+   MochiKit.Sortable.Sortable.create("secondlist",
+     {dropOnEmpty:true,handle:'handle',containment:["firstlist","secondlist"],constraint:false,
+     onChange:function(){$('secondlist_debug').innerHTML = MochiKit.Sortable.Sortable.serialize('secondlist') }});
+ // ]]>
+ </script>
+ </body>
+ </html>
diff --git a/mochikit_v14/examples/dnd_sortable/sortable5_test.html b/mochikit_v14/examples/dnd_sortable/sortable5_test.html
new file mode 100644 (file)
index 0000000..3a3bbe1
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us sortable functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Signal.js"></script>
+        <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+</head>
+<body>
+  
+  <div id="container_div">
+    
+  </div>
+  
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  var new_ul_id = 'new_id_123';
+  var ul = document.createElement("ul");
+  var ul_id = document.createAttribute("id");
+  ul_id.nodeValue = new_ul_id;
+  ul.setAttributeNode(ul_id);
+  
+  var li = document.createElement("li");
+  li.setAttribute("id", "test_1");
+  li.appendChild(document.createTextNode("blah1"));
+  ul.appendChild(li);
+  
+  var li2 = document.createElement("li");
+  li2.setAttribute("id", "test_2");
+  li2.appendChild(document.createTextNode("blah2"));
+  ul.appendChild(li2);
+  
+  $('container_div').appendChild(ul);
+  
+  MochiKit.Sortable.Sortable.create(new_ul_id, { onUpdate: function() { alert(MochiKit.Sortable.Sortable.serialize('new_id_123')); } });
+// ]]>
+</script>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/dnd_sortable/sortable_test.html b/mochikit_v14/examples/dnd_sortable/sortable_test.html
new file mode 100644 (file)
index 0000000..9272fa1
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us sortable functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Signal.js"></script>
+        <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+  <style type="text/css" media="screen">
+    #thelist li { background: green; margin:5px; padding: 30px; }
+    div.dropmarker {
+     height:6px;
+     width:200px;
+     background: url(dropmarker.png) left top;
+     margin-top:-3px;
+     margin-left:-5px;
+     z-index:1000;
+     overflow: hidden;
+    }
+  </style>
+</head>
+<body>
+<ul id="thelist">
+<li id="thelist_1">Hey there! I'm item#1</li>
+<li id="thelist_2">Hey there! I'm item#2</li>
+<li id="thelist_3">Hey there! I'm item#3</li>
+</ul>
+
+<a href="#" onclick="MochiKit.Sortable.Sortable.create('thelist');return false;">Create sortable</a> | 
+<a href="#" onclick="MochiKit.Sortable.Sortable.destroy('thelist');return false;">Destroy sortable</a> |
+<a href="#" onclick="alert(MochiKit.Sortable.Sortable.serialize('thelist'));return false;">Serialize sortable</a>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/dnd_sortable/sortable_tree_test.html b/mochikit_v14/examples/dnd_sortable/sortable_tree_test.html
new file mode 100644 (file)
index 0000000..6a11671
--- /dev/null
@@ -0,0 +1,189 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+    <title>Sortable tree test</title>
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Signal.js"></script>
+        <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+        <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+    <style type="text/css">
+      ul  {padding-top:4px; padding-bottom: 2px; border: 1px solid #ccf;}
+      li  {border: 1px solid #fcc;}
+    </style>
+  </head>
+
+  <body>
+    <a href="#" onclick="alert(MochiKit.Sortable.Sortable.serialize('menu'));return false">serialize 1</a>
+    
+    <ul id="menu" style="padding-top: 6px; padding-bottom: 6px;">
+        <li class="edit_link level0" id="t1_7">
+          System
+          <ul class="edit_list">
+          <li class="edit_link level1" id="t1_8">
+            Page Not Found
+            <ul class="edit_list"></ul>
+          </li>
+          <li class="edit_link level1" id="t1_9">
+            Translation Not Available
+            <ul class="edit_list"></ul>
+          </li>
+        </ul>
+      </li>
+        <li class="edit_link level0" id="t1_10">
+        Main Menu
+          <ul class="edit_list">
+          <li class="edit_link level1" id="t1_1">
+            Welcome
+               <ul class="edit_list"></ul>
+          </li>
+          <li class="edit_link level1" id="t1_2">
+            Software
+            <ul class="edit_list">
+              <li class="edit_link level2" id="t1_4">
+                Serial Console
+                <ul class="edit_list">
+                  <li class="edit_link level3" id="t1_6">
+                    Features
+                    <ul class="edit_list"></ul>
+                  </li>
+                </ul>
+              </li>
+              <li class="edit_link level2" id="t1_5">
+                Property Manager
+                <ul class="edit_list"></ul>
+              </li>
+              <li class="edit_link level2" id="t1_11">
+                Geomap
+                <ul class="edit_list"></ul>
+              </li>
+            </ul>
+          </li>
+          <li class="edit_link level1" id="t1_12">
+            Services
+            <ul class="edit_list"></ul>
+          </li>
+          <li class="edit_link level1" id="t1_13">
+            Software
+            <ul class="edit_list">
+              <li class="edit_link level2" id="t1_14">
+                Serial Console
+                <ul class="edit_list">
+                  <li class="edit_link level3" id="t1_15">
+                    Features
+                    <ul class="edit_list"></ul>
+                  </li>
+                </ul>
+              </li>
+              <li class="edit_link level2" id="t1_16">
+                Property Manager
+                <ul class="edit_list"></ul>
+              </li>
+              <li class="edit_link level2" id="t1_17">
+                Geomap
+                <ul class="edit_list"></ul>
+              </li>
+            </ul>
+          </li>
+          <li class="edit_link level1" id="t1_18">
+            Services
+            <ul class="edit_list"></ul>
+          </li>
+        </ul>
+      </li>
+    </ul>
+
+    <script type="text/javascript">
+    //<![CDATA[
+    MochiKit.Sortable.Sortable.create('menu', {tree:true,scroll:window});
+    //]]>
+    </script>
+    
+    <ul id="menu2" style="padding-top: 6px; padding-bottom: 6px;">
+        <li class="edit_link level0" id="t2_7">
+          System
+          <ul class="edit_list">
+          <li class="edit_link level1" id="t2_8">
+            Page Not Found
+            <ul class="edit_list"></ul>
+          </li>
+          <li class="edit_link level1" id="t2_9">
+            Translation Not Available
+            <ul class="edit_list"></ul>
+          </li>
+        </ul>
+      </li>
+        <li class="edit_link level0" id="t2_10">
+        Main Menu
+          <ul class="edit_list">
+          <li class="edit_link level1" id="t2_1">
+            Welcome
+               <ul class="edit_list"></ul>
+          </li>
+          <li class="edit_link level1" id="t2_2">
+            Software
+            <ul class="edit_list">
+              <li class="edit_link level2" id="t2_4">
+                Serial Console
+                <ul class="edit_list">
+                  <li class="edit_link level3" id="t2_6">
+                    Features
+                    <ul class="edit_list"></ul>
+                  </li>
+                </ul>
+              </li>
+              <li class="edit_link level2" id="t2_5">
+                Property Manager
+                <ul class="edit_list"></ul>
+              </li>
+              <li class="edit_link level2" id="t2_11">
+                Geomap
+                <ul class="edit_list"></ul>
+              </li>
+            </ul>
+          </li>
+          <li class="edit_link level1" id="t2_12">
+            Services
+            <ul class="edit_list"></ul>
+          </li>
+          <li class="edit_link level1" id="t2_13">
+            Software
+            <ul class="edit_list">
+              <li class="edit_link level2" id="t2_14">
+                Serial Console
+                <ul class="edit_list">
+                  <li class="edit_link level3" id="t2_15">
+                    Features
+                    <ul class="edit_list"></ul>
+                  </li>
+                </ul>
+              </li>
+              <li class="edit_link level2" id="t2_16">
+                Property Manager
+                <ul class="edit_list"></ul>
+              </li>
+              <li class="edit_link level2" id="t2_17">
+                Geomap
+                <ul class="edit_list"></ul>
+              </li>
+            </ul>
+          </li>
+          <li class="edit_link level1" id="t2_18">
+            Services
+            <ul class="edit_list"></ul>
+          </li>
+        </ul>
+      </li>
+    </ul>
+    
+    <script type="text/javascript">
+    //<![CDATA[
+    MochiKit.Sortable.Sortable.create('menu2', {tree:true,scroll:window});
+    //]]>
+    </script>
+
+  </body>
+</html>
diff --git a/mochikit_v14/examples/draggable/draggable.css b/mochikit_v14/examples/draggable/draggable.css
new file mode 100755 (executable)
index 0000000..b9b3ba0
--- /dev/null
@@ -0,0 +1,28 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
+
+.draggable
+{
+    color: white;
+    cursor: move;
+    font-size: 25px;
+    height: 100px;
+    line-height: 100px;
+    position: absolute;
+    text-align: center;
+    top: 200px;
+    width: 100px;
+}
+
+.blue { background: blue; }
+.green { background: green; }
+.red { background: red; }
+.white
+{
+    background: white;
+    border: 1px solid black;
+    color: black;
+}
diff --git a/mochikit_v14/examples/draggable/draggable.js b/mochikit_v14/examples/draggable/draggable.js
new file mode 100644 (file)
index 0000000..6f56d76
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+
+    Drag: A Really Simple Drag Handler
+    
+*/
+Drag = {
+    _move: null,
+    _down: null,
+    
+    start: function(e) {
+        e.stop();
+        
+        // We need to remember what we're dragging.
+        Drag._target = e.target();
+        
+        /*
+            There's no cross-browser way to get offsetX and offsetY, so we
+            have to do it ourselves. For performance, we do this once and
+            cache it.
+        */
+        Drag._offset = Drag._diff(
+            e.mouse().page,
+            getElementPosition(Drag._target));
+        
+        Drag._move = connect(document, 'onmousemove', Drag._drag);
+        Drag._down = connect(document, 'onmouseup', Drag._stop);
+    },
+
+    _offset: null,
+    _target: null,
+    
+    _diff: function(lhs, rhs) {
+        return new MochiKit.Style.Coordinates(lhs.x - rhs.x, lhs.y - rhs.y);
+    },
+        
+    _drag: function(e) {
+        e.stop();
+        setElementPosition(
+            Drag._target,
+            Drag._diff(e.mouse().page, Drag._offset));
+    },
+    
+    _stop: function(e) {
+        disconnect(Drag._move);
+        disconnect(Drag._down);
+    }
+};
+
+connect(window, 'onload',   
+    function() {
+        /*
+            Find all DIVs tagged with the draggable class, and connect them to
+            the Drag handler.
+        */
+        var d = getElementsByTagAndClassName('DIV', 'draggable');
+        forEach(d,
+            function(elem) {
+                connect(elem, 'onmousedown', Drag.start);
+            });
+                        
+    });
+    
+connect(window, 'onload',
+    function() {
+        var elems = getElementsByTagAndClassName("A", "view-source");
+        var page = "draggable/";
+        for (var i = 0; i < elems.length; i++) {
+            var elem = elems[i];
+            var href = elem.href.split(/\//).pop();
+            elem.target = "_blank";
+            elem.href = "../view-source/view-source.html#" + page + href;
+        } 
+    });
diff --git a/mochikit_v14/examples/draggable/index.html b/mochikit_v14/examples/draggable/index.html
new file mode 100644 (file)
index 0000000..21a134f
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>Signal Example</title>
+    <link href="draggable.css" rel="stylesheet" type="text/css" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="draggable.js"></script>
+</head>
+<body>
+
+    <h1>
+        Dragging with MochiKit
+    </h1>
+    <p>
+        This is an example of one might implement a drag handler with
+        MochiKit&#8217;s Signal.
+    </p>
+    <p>
+        For a detailed description of what happens under the hood, check out
+        <a href="draggable.js" class="view-source">draggable.js</a>.
+    </p>
+    <p>
+        View Source: [
+            <a href="index.html" class="view-source">index.html</a> | 
+            <a href="draggable.js" class="view-source">draggable.js</a> |
+            <a href="draggable.css" class="view-source">draggable.css</a>
+        ]
+    </p>
+
+
+    <div class="draggable red" style="left: 10px;">R</div>
+    <div class="draggable green" style="left: 120px;">G</div>
+    <div class="draggable blue" style="left: 230px;">B</div>
+    <div class="draggable white" style="left: 340px;">W</div>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_bigslide.html b/mochikit_v14/examples/effects/effects_bigslide.html
new file mode 100644 (file)
index 0000000..37cf9e1
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+</head>
+<body>
+<h1>script.aculo.us Effects functional test file</h1>
+
+<h2>Effect.SlideDown/Effect.SlideUp</h2>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  var effect_1 = null;
+// ]]>
+</script>
+
+<a onclick="effect_1 = MochiKit.Visual.slideDown('d1', {duration: 1.0}); return false;">Start slide down</a> | 
+<a onclick="effect_1 = MochiKit.Visual.slideUp('d1', {duration: 1.0}); return false;">Start slide up</a> | 
+<a onclick="effect_1.cancel(); return false;">cancel()</a> |
+<a onclick="alert($('d1').firstChild.style); return false;">inspect()</a> |
+<a onclick="$('d1').firstChild.innerHTML += $('d1').firstChild.innerHTML; return false;">add content</a>
+
+<div id="d1" style="display:none;"><div style="background-color:#ff8080;width:300px;border:2px solid red;padding:10px;">
+<p>
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas enim. Nulla facilisi. Vestibulum accumsan augue vulputate justo. Fusce faucibus. Sed blandit, neque sed lacinia nonummy, diam quam imperdiet justo, at dictum augue nunc a neque. Sed urna lacus, tincidunt at, aliquam id, fringilla id, felis. Vivamus feugiat molestie quam. Sed id dolor. Sed ac purus id sapien sollicitudin ultricies. Aliquam hendrerit orci et odio. Suspendisse volutpat wisi at sem. Integer eget nulla. Duis eu diam a nunc condimentum tempus. Praesent gravida metus vitae massa. Aliquam neque magna, fringilla eu, porta id, interdum sit amet, dui. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin lorem est, ultrices sit amet, condimentum vitae, vehicula a, massa.
+</p>
+</div></div>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_blind.html b/mochikit_v14/examples/effects/effects_blind.html
new file mode 100644 (file)
index 0000000..a7b6bb1
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+  <style type="text/css" media="screen">
+  /* <![CDATA[ */
+    #d1 { background-color: #fcb; width: 200px; }
+  /* ]]> */
+  </style>
+  
+</head>
+<body>
+<h1>script.aculo.us Effects functional test file</h1>
+
+<h2>Effect.BlindUp/Effect.BlindDown</h2>
+
+<div id="d1">
+  Lorem ipsum dolor sit amet
+  <ul>
+    <li>test!</li>
+    <li>test!</li>
+  </ul>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  <img src="icon.png" alt="test!"/>
+  Lorem ipsum dolor sit amet
+  <ul>
+    <li>test!</li>
+    <li>test!</li>
+  </ul>
+  Lorem ipsum dolor sit amet
+  <ul>
+    <li>test!</li>
+    <li>test!</li>
+  </ul>
+  Lorem ipsum dolor sit amet
+  <ul>
+    <li>test!</li>
+    <li>test!</li>
+  </ul>
+</div>
+
+<p>
+  <a onclick="MochiKit.Visual.blindDown('d1');; return false;">BlindDown()</a>
+</p>
+
+<p>
+  <a onclick="MochiKit.Visual.blindUp('d1');; return false;">BlindUp()</a>
+</p>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_blindslide.html b/mochikit_v14/examples/effects/effects_blindslide.html
new file mode 100644 (file)
index 0000000..b7c258a
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+  <style type="text/css" media="screen">
+  /* <![CDATA[ */
+    #d1 { background-color: #888; }
+  /* ]]> */
+  </style>
+  
+</head>
+<body>
+<h1>script.aculo.us Effects functional test file</h1>
+
+<a onclick="new MochiKit.Visual.Highlight('d1',{duration:1.5}); return false;">Highlight</a> |
+<a onclick="MochiKit.Visual.blindUp('d1',{duration:1.5}); return false;">BlindUp</a> |
+<a onclick="MochiKit.Visual.blindDown('d1',{duration:1.5}); return false;">BlindDown</a> |
+<a onclick="MochiKit.Visual.slideUp('d1',{duration:1.5}); return false;">SlideUp</a> |
+<a onclick="MochiKit.Visual.slideDown('d1',{duration:1.5}); return false;">SlideDown</a>
+
+<div id="d1"><div style="overflow:hidden">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas enim. Nulla facilisi. Vestibulum accumsan augue vulputate justo. Fusce faucibus. Sed blandit, neque sed lacinia nonummy, diam quam imperdiet justo, at dictum augue nunc a neque. Sed urna lacus, tincidunt at, aliquam id, fringilla id, felis. Vivamus feugiat molestie quam. Sed id dolor. Sed ac purus id sapien sollicitudin ultricies. Aliquam hendrerit orci et odio. Suspendisse volutpat wisi at sem. Integer eget nulla. Duis eu diam a nunc condimentum tempus. Praesent gravida metus vitae massa. Aliquam neque magna, fringilla eu, porta id, interdum sit amet, dui. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin lorem est, ultrices sit amet, condimentum vitae, vehicula a, massa.
+</div></div>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_combi.css b/mochikit_v14/examples/effects/effects_combi.css
new file mode 100755 (executable)
index 0000000..4658886
--- /dev/null
@@ -0,0 +1,34 @@
+h3 {
+    clear: both;
+}
+.example {
+    font-size: 1.0em;
+    float: left;
+    margin-right: 10px;
+    margin-bottom: 10px;
+    width: 120px;
+    height: 120px;
+    background-color: #AAAAAA;
+    text-align: center;
+    padding: 1em 0.2em 0.2em 0.2em;
+}
+.demo {
+    clear: both;
+}
+#reset {
+    position: absolute;
+    top: 600px;
+    left: 600px;
+}
+#demo-all {
+    position: absolute;
+    top: 600px;
+    left: 400px;
+    font-size: 1.0em;
+    width: 120px;
+    height: 120px;
+    background-color: #AAAAAA;
+    text-align: center;
+    padding: 1em 0.2em 0.2em 0.2em;
+}
+
diff --git a/mochikit_v14/examples/effects/effects_fadeappear.html b/mochikit_v14/examples/effects/effects_fadeappear.html
new file mode 100644 (file)
index 0000000..46d7aec
--- /dev/null
@@ -0,0 +1,61 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+</head>
+<body>
+<h1>script.aculo.us fade/appear effect functional test</h1>
+<p>Note: these tests use the browser default CSS style rules.</p>
+
+<h2>DIV</h2>
+<div id="test_div">TEST</div>
+<a href="#" onclick="MochiKit.Visual.fade('test_div'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_div'); return false;">MochiKit.Visual.appear</a>
+
+<h2>SPAN</h2>
+<span id="test_span">TEST</span><br/>
+<a href="#" onclick="MochiKit.Visual.fade('test_span'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_span'); return false;">MochiKit.Visual.appear</a>
+
+<h2>P</h2>
+<p id="test_p">TEST</p><br/>
+<a href="#" onclick="MochiKit.Visual.fade('test_p'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_p'); return false;">MochiKit.Visual.appear</a>
+
+<h2>IMG</h2>
+<img id="test_img" src="icon.png" alt="test image" /><br/>
+<a href="#" onclick="MochiKit.Visual.fade('test_img'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_img'); return false;">MochiKit.Visual.appear</a>
+
+
+<hr/>
+
+<p style="color:red;">The following elements are not supported with fade/appear on all browsers!</p>
+
+<h2>TABLE</h2>
+<table id="test_table"><tbody><tr><td>TEST</td></tr></tbody></table>
+<a href="#" onclick="MochiKit.Visual.fade('test_table'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_table'); return false;">MochiKit.Visual.appear</a>
+
+<h2>TBODY</h2>
+<table><tbody id="test_tbody"><tr><td>TEST</td></tr></tbody></table>
+<a href="#" onclick="MochiKit.Visual.fade('test_tbody'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_tbody'); return false;">MochiKit.Visual.appear</a>
+
+<h2>TR</h2>
+<table><tbody><tr id="test_tr"><td>TEST</td></tr></tbody></table>
+<a href="#" onclick="MochiKit.Visual.fade('test_tr'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_tr'); return false;">MochiKit.Visual.appear</a>
+
+<h2>TD</h2>
+<table><tbody><tr><td id="test_td">TEST</td></tr></tbody></table>
+<a href="#" onclick="MochiKit.Visual.fade('test_td'); return false;">MochiKit.Visual.fade</a> | 
+<a href="#" onclick="MochiKit.Visual.appear('test_td'); return false;">MochiKit.Visual.appear</a>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_grow_shrink.html b/mochikit_v14/examples/effects/effects_grow_shrink.html
new file mode 100644 (file)
index 0000000..2fd3d23
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+  <style type="text/css" media="screen">
+  /* <![CDATA[ */
+    #d1 { background-color: #fcb; width: 200px; height: 200px; }
+  /* ]]> */
+  </style>
+  
+</head>
+<body>
+<h1>script.aculo.us Effects functional test file</h1>
+
+<h2>Effect.Grow/Effect.Shrink</h2>
+
+<div id="d1" style="font-size: 2em;">
+  <p style="font-size:1em;">Lorem ipsum dolor sit amet</p>
+</div>
+
+<p>
+  Grow:
+  <a onclick="MochiKit.Visual.grow('d1');; return false;">Grow()</a>
+</p>
+
+<p>
+  Shrink:
+  <a onclick="MochiKit.Visual.shrink('d1');; return false;">Shrink()</a>
+</p>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_onload.html b/mochikit_v14/examples/effects/effects_onload.html
new file mode 100644 (file)
index 0000000..312e70a
--- /dev/null
@@ -0,0 +1,66 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+<body>
+<h1>script.aculo.us Effects functional test file</h1>
+
+<h2>Effect.Highlight</h2>
+
+<div id="debug"> </div>
+
+<a href="#" onclick="MochiKit.Visual.slideDown('d1'); return false;">asdasd</a>
+
+<div id="d1" onclick="MochiKit.Visual.slideUp('d1');" style="overflow:hidden;"><div  style="background-color:#ff8080;">
+
+  (highlight to red)
+
+</div></div>
+
+<div id="d2" style="width:100px;height:100px;background-color:#80ff80;">
+  (highlight to greenish)
+</div>
+
+<div id="d3" style="width:100px;height:100px;background-color:#dde;">
+  (bottom-right-grow)
+</div>
+
+<div id="d4" style="width:100px;height:100px;background-color:#dde;" onclick="MochiKit.Visual.shake(this)">
+  click to test shake
+</div>
+
+<div id="d5" style="width:100px;height:100px;background-color:#dde;" onclick="MochiKit.Visual.puff(this)">
+  click to test puff
+</div>
+<a href="#" onclick="MochiKit.DOM.showElement('d5'); return false;">show puff div again</a>
+
+<a href="#" onclick="MochiKit.Visual.appear('d6')">test appear</a>
+<div id="d6" style="width:100px;height:100px;background-color:#dde;display:none">
+  appear
+</div>
+
+<a href="#" onclick="MochiKit.Visual.grow('d7')">test grow</a>
+<div id="d7" style="width:100px;height:100px;background-color:#dde;display:none">
+  grow
+</div>
+
+<a href="#" onclick="MochiKit.Visual.pulsate('d8')">test pulsate</a>
+<div id="d8" style="width:100px;height:100px;background-color:#dde;">
+  pulsate
+</div>
+      
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  new MochiKit.Visual.Highlight("d2",{startcolor:"#000000"});
+  MochiKit.Visual.grow("d3",{duration:5.0,direction: 'bottom-right',opacityTransition:MochiKit.Visual.Transitions.linear});
+  MochiKit.Visual.blindDown("d1");
+// ]]>
+</script>    
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_queue.html b/mochikit_v14/examples/effects/effects_queue.html
new file mode 100644 (file)
index 0000000..f5a307b
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+  <style type="text/css" media="screen">
+  /* <![CDATA[ */
+    #d1 { background-color: #fcb; width: 200px; height: 200px; float:left; }
+    #d2 { background-color: #cfb; font-size: 2em; width: 200px; height: 200px; float:left; }
+    #d3 { background-color: #bcf; font-size: 2em; width: 200px; height: 200px; float:left; }
+  /* ]]> */
+  </style>
+  
+</head>
+<body>
+<h1>script.aculo.us Effects functional test file</h1>
+
+<h2>Effect.Queue</h2>
+
+<div id="d1" style="font-size: 2em;">
+  <p style="font-size:1em;">Lorem ipsum dolor sit amet</p>
+</div>
+
+<div id="d2">
+  <p>Lorem ipsum dolor sit amet</p>
+</div>
+
+<div id="d3">
+  <p>Lorem ipsum dolor sit amet</p>
+</div>
+
+<div style="clear: both">
+  <a href="#" onclick="startTimeline(); return false;">Start queued effects</a> (in 'global' queue)
+</div>
+
+<div id="sliding"><div style="background-color:#ccc;font-size:20px;height:300px;width:150px;">
+  <a href="#" onclick="MochiKit.Visual.slideUp('sliding',{queue:{scope:'myscope', position:'end'}}); MochiKit.Visual.slideDown('sliding',{queue:{scope:'myscope', position:'end'}}); return false;">
+    Do a bit sliding in parallel, with a scoped queue
+  </a>
+</div></div>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  function startTimeline() {
+    // 3x highlight in front
+    for(var i=0; i<3; i++)
+      new MochiKit.Visual.Highlight('d3', { duration: 1.0, queue: 'front' });
+    
+    // insert scale at very beginning
+    new MochiKit.Visual.Scale('d1', 75, { scaleContent: true, duration: 1.0, queue: 'front' });
+    
+    // parallel implied, delay 0.5 sec
+    new MochiKit.Visual.Highlight('d1', { delay: 0.5 }); 
+    
+    // puff at end
+    MochiKit.Visual.puff('d2', { duration: 4.0, queue: 'end' });
+  }
+// ]]>
+</script>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_queue_limit.html b/mochikit_v14/examples/effects/effects_queue_limit.html
new file mode 100644 (file)
index 0000000..c885833
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+  <style type="text/css" media="screen">
+  /* <![CDATA[ */
+    #d1 { background-color: #fcb; width: 200px; height: 200px; float:left; }
+    #d2 { background-color: #cfb; font-size: 2em; width: 200px; height: 200px; float:left; }
+    #d3 { background-color: #bcf; font-size: 2em; width: 200px; height: 200px; float:left; }
+  /* ]]> */
+  </style>
+</head>
+<body>
+<h1>script.aculo.us Effects functional test file</h1>
+
+<h2>Effect.Queue limit</h2>
+
+<a href="#" onclick="MochiKit.Visual.slideUp('slidingtwice',{queue:{scope:'myscope', position:'end', limit: 1}});">up</a>
+<a href="#" onclick="MochiKit.Visual.slideDown('slidingtwice',{queue:{scope:'myscope', position:'end', limit: 1}});">down</a>
+<div id="slidingtwice"><div style="background-color:#000;color:white;font-size:20px;height:300px;width:150px;">
+    Do a bit sliding in parallel, with a scoped queue, but I am limited to one : ) so don't try over and over again...
+</div></div>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_scroll.html b/mochikit_v14/examples/effects/effects_scroll.html
new file mode 100644 (file)
index 0000000..1738c8c
--- /dev/null
@@ -0,0 +1,483 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Effects functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+</head>
+<body>
+<h1>script.aculo.us ScrollTo effect functional test</h1>
+
+<a onclick="new MochiKit.Visual.ScrollTo('down-below',{duration:5.0}); return false;">scroll (slow-mo) down-below...</a>,
+<a onclick="new MochiKit.Visual.ScrollTo('last-heading'); return false;">scroll last-heading</a>
+
+<h2 id="first-heading"><b>first-heading</b>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2 id="down-below"><b>DOWN BELOW</b>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<a onclick="new MochiKit.Visual.ScrollTo('first-heading'); return false;">scroll...</a>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2>Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+<h2 id="last-heading">Heading 2</h2>
+<ul>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+  <li>item</li>
+</ul>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/effects_slide.html b/mochikit_v14/examples/effects/effects_slide.html
new file mode 100644 (file)
index 0000000..346f284
--- /dev/null
@@ -0,0 +1,63 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Untitled Document</title>
+<style type="text/css">
+#menu {
+  width: 300px;
+  border: 1px #000 solid;
+}
+.menu_header {
+  background-color: #00CC99;
+  color: #FFFFFF;
+}
+.menu_block {
+  background-color: #006699;
+  color: #FFFFFF;
+  overflow:hidden;
+}
+.menu_block div {
+}
+.close_block {
+  position: relative;
+  width: 100%;
+  bottom: 0px;
+  height: 15px;
+  text-align: center;
+  display: block;
+}
+</style>
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="menu">
+  <div class="menu_header" id="menu_header1"><a onClick="MochiKit.Visual.slideDown('menu_block1'); return false;">HEADER 1</a></div>
+  <div class="menu_block_container" id="menu_block_container1">
+    <div class="menu_block" id="menu_block1"><div>
+           text<br>
+        text<br>
+        text<br>
+        text<br>
+        text<br>
+        text<br>
+        text<br>
+        <a class="close_block" onClick="MochiKit.Visual.slideUp('menu_block1'); return false;">close</a></div></div>
+  </div>
+  <div class="menu_header" id="menu_header2"><a onClick="MochiKit.Visual.slideDown('menu_block2'); return false;">HEADER 2</a></div>
+  <div class="menu_block_container" id="menu_block_container2">
+    <div class="menu_block" id="menu_block2"><div>
+           text<br>
+        text<br>
+        text<br>
+        text<br>
+        text<br>
+        text<br>
+        text<br>
+        <a class="close_block" onClick="MochiKit.Visual.slideUp('menu_block2'); return false;">close</a></div></div>
+  </div>
+</div>
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/full.html b/mochikit_v14/examples/effects/full.html
new file mode 100644 (file)
index 0000000..c980d2a
--- /dev/null
@@ -0,0 +1,71 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>Full Effects Test Suite</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <link rel="stylesheet" href="../../include/css/documentation.css" type="text/css" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <style type="text/css">
+#demo {
+}
+
+#demo li {
+    color: #8ba726;
+    font-size: 1.2em;
+}
+
+#democontainer {
+    margin: 30px 5px 0px 5px;
+}
+
+#demoall {
+    position: absolute;
+    top: 250px;
+    left: 400px;
+    font-size: 20px;
+    background: #f3f3f3;
+    color: #1C1D1F; 
+    text-align: center;
+    border: 1px solid #ccc;
+    width: 150px;
+    height: 150px;
+}
+    </style>
+</head>
+
+<body>
+<div class="document">
+<div class="section">
+<h1>Full Effects Test Suite</h1>
+<ul id="demo">
+    <li onclick="setStyle('demoall', {'display': 'block'});fade('demoall')">fade</li>
+    <li onclick="setStyle('demoall', {'display': 'none'});appear('demoall')">appear</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});puff('demoall')">puff</li>
+    <li onclick="blindDown('demoall')">blindDown</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});blindUp('demoall')">blindUp</li>
+    <li onclick="switchOff('demoall')">switchOff</li>
+    <li onclick="slideDown('demoall')">slideDown</li>
+    <li onclick="slideUp('demoall')">slideUp</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});dropOut('demoall', {'distance': 500})">dropOut</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});shake('demoall')">shake</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});pulsate('demoall')">pulsate</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});squish('demoall')">squish</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});fold('demoall')">fold</li>
+    <li onclick="grow('demoall')">grow</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});shrink('demoall')">shrink</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});Highlight('demoall', {startcolor: '#ffff33'})">Highlight</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});Morph('demoall', {'style': {'font-size': '3px'}, 'queue': 'start'});Morph('demoall', {'style': {'font-size': '20px'}, 'queue': 'end'});">Morph font</li>
+    <li onclick="setStyle('demoall', {'display': 'block'});Morph('demoall', {'style': {'background-color': 'red'}, 'queue': 'start'});Morph('demoall', {'style': {'background-color': '#f3f3f3'}, 'queue': 'end'});">Morph color</li>
+    <li onclick="toggle('demoall', 'blind')">toggle (blind)</li>
+    <li onclick="toggle('demoall', 'slide')">toggle (slide)</li>
+    <li onclick="toggle('demoall', 'appear')">toggle (appear)</li>
+    <li onclick="toggle('demoall', 'size')">toggle (size)</li>
+</ul>
+<div id="demoall">
+    <div id="democontainer">Click on one of the left to see the effect</div>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/mochikit_v14/examples/effects/icon.png b/mochikit_v14/examples/effects/icon.png
new file mode 100755 (executable)
index 0000000..f752986
Binary files /dev/null and b/mochikit_v14/examples/effects/icon.png differ
diff --git a/mochikit_v14/examples/effects/index.html b/mochikit_v14/examples/effects/index.html
new file mode 100644 (file)
index 0000000..05f9569
--- /dev/null
@@ -0,0 +1,113 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>Test Effects</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <link href="effects_combi.css" rel="stylesheet" type="text/css" />
+    <script src="../../MochiKit/MochiKit.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Position.js" type="text/javascript"></script>
+    <script src="../../MochiKit/Visual.js" type="text/javascript"></script>
+</head>
+
+<body>
+       <h3>Here are demos of all combination effects:</h3>
+ <div class="demo">
+      <div class="example" id="demo-effect-appear" onclick="MochiKit.Visual.appear('demo-effect-fade')">
+        <span>Click for Visual.appear demo</span>
+      </div>
+      <div class="example" id="demo-effect-fade" onclick="MochiKit.Visual.fade(this)">
+        <span>Click for Visual.fade demo</span>
+      </div>
+      <div class="example" id="demo-effect-puff" onclick="MochiKit.Visual.puff(this)">
+        <span>Click for Visual.puff demo</span>
+      </div>
+      <div class="example" id="demo-effect-blinddown" onclick="MochiKit.Visual.blindDown(this)">
+        <div style="height:120px;">
+
+          <span>Click for Visual.blindDown demo</span>
+        </div>
+      </div>
+      <div class="example" id="demo-effect-blindup" onclick="MochiKit.Visual.blindUp(this)">
+        <span>Click for Visual.blindUp demo</span>
+      </div>
+      <div class="example" id="demo-effect-switchoff" onclick="MochiKit.Visual.switchOff(this)">
+        <span>Click for Visual.switchOff demo</span>
+      </div>
+      <div class="example" id="demo-effect-slidedown" onclick="MochiKit.Visual.slideDown(this)"><div style="height:120px;">
+        <span>Click for Visual.slideDown demo</span>
+      </div></div>
+      <div class="example" id="demo-effect-slideup" onclick="MochiKit.Visual.slideUp(this)"><div style="height:120px;">
+        <span>Click for Visual.slideUp demo</span>
+      </div></div>
+      <div class="example" id="demo-effect-dropout" onclick="MochiKit.Visual.dropOut(this)">
+        <span>Click for Visual.dropOut demo</span>
+      </div>
+      <div class="example" id="demo-effect-shake" onclick="MochiKit.Visual.shake(this)">
+        <span>Click for Visual.shake demo</span>
+      </div>
+      <div class="example" id="demo-effect-pulsate" onclick="MochiKit.Visual.pulsate(this)">
+        <span>Click for Visual.pulsate demo</span>
+      </div>
+      <div class="example" id="demo-effect-squish" onclick="MochiKit.Visual.squish(this)">
+        <span>Click for Visual.squish demo</span>
+      </div>
+      <div class="example" id="demo-effect-fold" onclick="MochiKit.Visual.fold(this)">
+        <span>Click for Visual.fold demo</span>
+      </div>
+       <div class="example" id="demo-effect-grow" onclick="MochiKit.Visual.grow(this)">
+        <span>Click for Visual.grow demo</span>
+      </div>
+      <div class="example" id="demo-effect-shrink" onclick="MochiKit.Visual.shrink(this)">
+        <span>Click for Visual.shrink demo</span>
+      </div>
+      <div class="example" id="demo-effect-highlight" onclick="new MochiKit.Visual.Highlight(this)">
+        <span>Click for Visual.Highlight demo</span>
+      </div>
+</div>
+
+       <h3>Here are all demos on one single element:</h3>
+ <ul class="demo">
+    <li onclick="MochiKit.Visual.appear('demo-all')">Click for Visual.appear demo</li>
+    <li onclick="MochiKit.Visual.fade('demo-all')">Click for Visual.fade demo</li>
+    <li onclick="MochiKit.Visual.puff('demo-all')">Click for Visual.puff demo</li>
+    <li onclick="MochiKit.Visual.blindDown('demo-all')">Click for Visual.blindDown demo</li>
+    <li onclick="MochiKit.Visual.blindUp('demo-all')">Click for Visual.blindUp demo</li>
+    <li onclick="MochiKit.Visual.switchOff('demo-all')">Click for Visual.switchOff demo</li>
+    <li onclick="MochiKit.Visual.slideDown('demo-all')">Click for Visual.slideDown demo</li>
+    <li onclick="MochiKit.Visual.slideUp('demo-all')">Click for Visual.slideUp demo</li>
+    <li onclick="MochiKit.Visual.dropOut('demo-all')">Click for Visual.dropOut demo</li>
+    <li onclick="MochiKit.Visual.shake('demo-all')">Click for Visual.shake demo</li>
+    <li onclick="MochiKit.Visual.pulsate('demo-all')">Click for Visual.pulsate demo</li>
+    <li onclick="MochiKit.Visual.squish('demo-all')">Click for Visual.squish demo</li>
+    <li onclick="MochiKit.Visual.fold('demo-all')">Click for Visual.fold demo</li>
+    <li onclick="MochiKit.Visual.grow('demo-all')">Click for Visual.grow demo</li>
+    <li onclick="MochiKit.Visual.shrink('demo-all')">Click for Visual.shrink demo</li>
+    <li onclick="new MochiKit.Visual.Highlight('demo-all')">Click for Visual.Highlight demo</li>
+    <li onclick="MochiKit.Visual.toggle('demo-all', 'blind')">Click for Visual.toggle demo (blind)</li>
+    <li onclick="MochiKit.Visual.toggle('demo-all', 'slide')">Click for Visual.toggle demo (slide)</li>
+    <li onclick="MochiKit.Visual.toggle('demo-all', 'appear')">Click for Visual.toggle demo (appear)</li>
+    <li onclick="MochiKit.Visual.toggle('demo-all', 'size')">Click for Visual.toggle demo (size)</li>
+</ul>
+      <div id="demo-all">
+        <span>Click on one of the left to see the effect</span>
+      </div>
+<span id="reset" onclick="new MochiKit.Visual.appear('demo-all')">Click here to reset box</span>
+
+    <div>
+    Links to other samples:
+    <ul>
+    <li><a href="effects_bigslide.html">Big slide effects</a></li>
+    <li><a href="effects_slide.html">Slide effects</a></li>
+    <li><a href="effects_blind.html">Blind effects</a></li>
+    <li><a href="effects_blindslide.html">Blind/Slide effects</a></li>
+    <li><a href="effects_fadeappear.html">Fade/Appear effects</a></li>
+    <li><a href="effects_onload.html">Onload effects</a></li>
+    <li><a href="effects_scroll.html">Scroll effects</a></li>
+    <li><a href="effects_grow_shrink.html">Grow/Shrink effects</a></li>
+    <li><a href="effects_queue.html">Queue effects</a></li>
+    <li><a href="effects_queue_limit.html">Queue limit effects</a></li>
+    </ul>
+    </div>
+</body>
+</html>
diff --git a/mochikit_v14/examples/interpreter/index.html b/mochikit_v14/examples/interpreter/index.html
new file mode 100644 (file)
index 0000000..d9c8a3e
--- /dev/null
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>Interpreter - JavaScript Interactive Interpreter</title>
+        <link href="interpreter.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="interpreter.js"></script>
+    </head>
+    <body>
+        <h1>
+            Interpreter - JavaScript Interactive Interpreter
+        </h1>
+        <div>
+            <p>
+                This demo is a JavaScript interpreter.  Type some code into
+                the text input and press enter to see the results.  It uses
+                <a href="http://mochikit.com">MochiKit</a>'s
+                <a href="../../doc/html/MochiKit/DOM.html">MochiKit.DOM</a>
+                to manipulate the display.  It also supports waiting for
+                <a href="../../doc/html/MochiKit/Async.html">MochiKit.Async</a>
+                 Deferreds via <tt>blockOn(aDeferred)</tt>.
+            </p>
+        </div>
+
+        <div>
+            View Source: [
+            <a href="index.html" class="view-source">index.html</a> |
+            <a href="interpreter.js" class="view-source">interpreter.js</a>
+            ]
+        </div>
+        <form id="interpreter_form" autocomplete="off">
+            <div id="interpreter_area">
+                <div id="interpreter_output"></div>
+            </div>
+            <div id="oneline">
+                <input id="interpreter_text" name="input_text" type="text" class="textbox" size="100" />
+            </div>
+            <div id="multiline">
+                <textarea id="interpreter_textarea" name="input_textarea" type="text" class="textbox" cols="97" rows="10"></textarea>
+                <br />
+            </div>
+        </form>
+        <div>
+            Notes:
+            <ul>
+                <li>
+                    To show the signature of a MochiKit function and link
+                    to its documentation, type help(fn) on any MochiKit
+                    function.
+                </li>
+                <li>
+                    To write multi-line code snippets, use the lower text area
+                    and press ctrl-enter or cmd-enter to submit.
+                </li>
+                <li>
+                    <tt>function name() {}</tt> syntax might not end up in
+                    window scope, so use <tt>name = function () {}</tt>
+                    syntax instead
+                </li>
+                <li>
+                    If you want to stuff something into the output window
+                    other than the <tt>repr(...)</tt> of the expression
+                    result, use the <tt>writeln(...)</tt> function.
+                    It accepts anything that MochiKit.DOM does, so you can
+                    even put styled stuff in there!
+                </li>
+                <li>
+                    Use <tt>clear()</tt> to clear the interpreter window.
+                </li>
+                <li>
+                    You can use <tt>blockOn(aDeferred)</tt> to wait on a
+                    Deferred.  This expression must be used by itself, so
+                    the value must be obtained from <tt>_</tt> or
+                    <tt>last_exc</tt>.  Typing any expression will
+                    cancel the Deferred.
+                </li>
+                <li>
+                    Up and down arrow keys work as a rudimentary history
+                </li>
+                <li>
+                    <tt>_</tt> is the value of the last expression
+                    that was not <tt>undefined</tt>, <tt>last_exc</tt> is
+                    the value of the last unhandled exception.
+                </li>
+            </ul>
+        </div>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/interpreter/interpreter.css b/mochikit_v14/examples/interpreter/interpreter.css
new file mode 100755 (executable)
index 0000000..56c7320
--- /dev/null
@@ -0,0 +1,54 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
+
+textarea.textbox {
+    font-family: Monaco, "lucida console", Courier;
+    border: 1px solid #CCCCCC;
+    font-size: .60em; 
+    padding: 2px 4px;
+    margin-top: .3em;
+}
+
+input.textbox {
+    font-family: Monaco, "lucida console", Courier;
+    border: 1px solid #CCCCCC;
+    font-size: .60em; 
+    padding: 2px 4px;
+    margin-top: .3em;
+}
+
+#interpreter_area {
+    display: block;
+    border: 1px solid #CCCCCC;
+    padding: 2px 4px;
+    margin-top: .3em;
+    width: 600px;
+    height: 300px;
+    overflow: auto;
+}
+
+#interpreter_output {
+    display: inline;
+    font-family: Monaco, "lucida console", Courier;
+    font-size: .60em;
+}
+
+#interpreter_output span {
+    white-space: -moz-pre-wrap; /* Mozilla */
+    white-space: -o-pre-wrap; /* Opera 7 */
+    white-space: pre-wrap; /* CSS 2.1 */
+    white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
+    word-wrap: break-word; /* IE */
+    wrap-option: emergency; /* CSS 3 */
+}
+
+input.textbox:focus { background-color: #FFFEE3; }
+
+.code { color: blue; }
+.data { color: black; }
+.error { color: red; }
+.banner { color: green; }
+.invisible { display: none; }
diff --git a/mochikit_v14/examples/interpreter/interpreter.js b/mochikit_v14/examples/interpreter/interpreter.js
new file mode 100644 (file)
index 0000000..c79021a
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+
+    Interpreter: JavaScript Interactive Interpreter
+
+*/
+InterpreterManager = function () {
+    bindMethods(this);
+};
+
+InterpreterManager.prototype.initialize = function () {
+    connect("interpreter_text", "onkeyup", this.keyUp);
+    connect("interpreter_textarea", "onkeydown", this.areaKeyDown);
+    connect("interpreter_form", "onsubmit", this.submit);
+    getElement("interpreter_text").focus();
+
+    this.banner();
+    this.lines = [];
+    this.history = [];
+    this.currentHistory = "";
+    this.historyPos = -1;
+    this.blockingOn = null;
+    if (typeof(this.doEval) == "undefined") {
+        // detect broken eval, warn at some point if a namespace ever gets used
+        this.doEval = function () {
+            return eval(arguments[0]);
+        }
+    }
+    window.help = this.help;
+    this.help.NAME = 'type help(func) for help on a MochiKit function';
+};
+
+InterpreterManager.prototype.banner = function () {
+    var _ua = window.navigator.userAgent;
+    var ua = _ua.replace(/^Mozilla\/.*?\(.*?\)\s*/, "");
+    if (ua == "") {
+        // MSIE
+        ua = _ua.replace(/^Mozilla\/4\.0 \(compatible; MS(IE .*?);.*$/, "$1");
+    }
+    appendChildNodes("interpreter_output",
+        SPAN({"class": "banner"},
+            "MochiKit v" + MochiKit.Base.VERSION + " [" + ua + "]",
+            BR(),
+            "Type your expression in the input box below and press return, or see the notes below for more information.",
+            BR()
+        ),
+        BR()
+    );
+};
+
+InterpreterManager.prototype.submit = function (event) {
+    if (this.blockingOn) {
+        try {
+            this.blockingOn.cancel();
+        } catch (e) {
+            this.showError(e);
+        }
+        this.blockingOn = null;
+    }
+    this.doSubmit();
+    this.doScroll();
+    event.stop();
+};
+
+InterpreterManager.prototype.help = function (fn) {
+    if (fn && fn.NAME) {
+        fn = fn.NAME;
+    }
+    if (typeof(fn) != "string" || fn.length == 0) {
+        writeln("help(func) on any MochiKit function for help");
+        return;
+    }
+    var comps = fn.split('.');
+    var base = comps.splice(0, 2);
+    var shortfn = comps.join('.');
+    var url = '../../doc/html/' + base.join('/') + '.html';
+    var d = doXHR(url, {mimeType: 'text/xml'});
+    d.addCallback(function (req) {
+        var els = getElementsByTagAndClassName(
+            'a', 'mochidef', req.responseXML);
+        var match = '#fn-' + shortfn.toLowerCase();
+        for (var i = 0; i < els.length; i++) {
+            var elem = els[i];
+            var href = elem.href;
+            var idx = href.indexOf('#');
+            if (idx != -1 && href.substring(idx) == match) {
+                writeln(A({href: url + match, target: '_blank'},
+                    scrapeText(elem)));
+                return;
+            }
+        }
+        writeln('documentation for ' + fn + ' not found');
+    });
+    blockOn(d);
+};
+
+
+InterpreterManager.prototype.doScroll = function () {
+    var p = getElement("interpreter_output").lastChild;
+    if (typeof(p) == "undefined" || p == null) {
+        return;
+    }
+    var area = getElement("interpreter_area");
+    if (area.offsetHeight > area.scrollHeight) {
+        area.scrollTop = 0;
+    } else {
+        area.scrollTop = area.scrollHeight;
+    }
+};
+
+InterpreterManager.prototype.moveHistory = function (dir) {
+    // totally bogus value
+    if (dir == 0 || this.history.length == 0) {
+        return;
+    }
+    var elem = getElement("interpreter_text");
+    if (this.historyPos == -1) {
+        this.currentHistory = elem.value;
+        if (dir > 0) {
+            return;
+        }
+        this.historyPos = this.history.length - 1;
+        elem.value = this.history[this.historyPos];
+        return;
+    }
+    if (this.historyPos == 0 && dir < 0) {
+        return;
+    }
+    if (this.historyPos == this.history.length - 1 && dir > 0) {
+        this.historyPos = -1;
+        elem.value = this.currentHistory;
+        return;
+    } 
+    this.historyPos += dir;
+    elem.value = this.history[this.historyPos];
+}
+
+InterpreterManager.prototype.runMultipleLines = function (text) {
+    var lines = rstrip(text).replace("\r\n", "\n").split(/\n/);
+    appendChildNodes("interpreter_output",
+        SPAN({"class": "code"}, ">>> ", izip(lines, imap(BR, cycle([null]))))
+    );
+    this.runCode(text);
+}
+
+InterpreterManager.prototype.areaKeyDown = function (e) {
+    var mod = e.modifier();
+    var hasMod = mod.alt || mod.ctrl || mod.meta;
+    if (e.key().string == 'KEY_ENTER' && hasMod) {
+        var elem = getElement("interpreter_textarea");
+        var text = elem.value;
+        elem.value = "";
+        this.runMultipleLines(text);
+        e.stop();
+    }
+};
+
+InterpreterManager.prototype.keyUp = function (e) {
+    var key = e.key();
+    // if any meta key is pressed, don't handle the signal
+    if (e.modifier().any) {
+        return;
+    }
+    switch (key.string) {
+        case 'KEY_ARROW_UP': this.moveHistory(-1); break;
+        case 'KEY_ARROW_DOWN': this.moveHistory(1); break;
+        default: return;
+    }
+    e.stop();
+};
+
+InterpreterManager.prototype.blockOn = function (d) {
+    var node = SPAN({"class": "banner"}, "blocking on " + repr(d) + "...");
+    this.blockingOn = d;
+    appendChildNodes("interpreter_output", node);
+    this.doScroll();
+    d.addBoth(function (res) {
+        swapDOM(node);
+        this.blockingOn = null;
+        if (res instanceof CancelledError) {
+            window.writeln(SPAN({"class": "error"}, repr(d) + " cancelled!"));
+            return undefined;
+        }
+        return res;
+    });
+    d.addCallbacks(this.showResult, this.showError);
+};
+
+InterpreterManager.prototype.showError = function (e) {
+    if (typeof(e) != "object") {
+        e = new Error(e);
+    }
+    appendChildNodes("interpreter_output",
+        SPAN({"class": "error"}, "Error:"),
+        TABLE({"class": "error"},
+            THEAD({"class": "invisible"}, TD({"colspan": 2})),
+            TFOOT({"class": "invisible"}, TD({"colspan": 2})),
+            TBODY(null,
+                map(function (kv) {
+                    var v = kv[1];
+                    if (typeof(v) == "function") {
+                        return;
+                    }
+                    if (typeof(v) == "object") {
+                        v = repr(v);
+                    }
+                    return TR(null,
+                        TD({"class": "error"}, kv[0]),
+                        TD({"class": "data"}, v)
+                    );
+                }, sorted(items(e)))
+            )
+        )
+    );
+    window.last_exc = e;
+    this.doScroll();
+};
+
+EvalFunctions = {
+    evalWith: function () {
+        with (arguments[1] || window) { return eval(arguments[0]); };
+    },
+    evalCall: function () {
+        return eval.call(arguments[1] || window, arguments[0]);
+    },
+    choose: function () {
+        var ns = {__test__: this};
+        var e;
+        try {
+            if (this.evalWith("return __test__", ns) === this) {
+                return this.evalWith;
+            }
+        } catch (e) {
+            // pass
+        }
+        try {
+            if (this.evalCall("return __test__", ns) === this) {
+                return this.evalCall;
+            }
+        } catch (e) {
+            // pass
+        }
+        return undefined;
+    }
+};
+        
+InterpreterManager.prototype.doEval = EvalFunctions.choose();
+
+InterpreterManager.prototype.doSubmit = function () {
+    var elem = getElement("interpreter_text");
+    var code = elem.value;
+    elem.value = "";
+    var isContinuation = false;
+    if (code.length >= 2 && code.lastIndexOf("//") == code.length - 2) {
+        isContinuation = true;
+        code = code.substr(0, code.length - 2);
+    }
+    appendChildNodes("interpreter_output",
+        SPAN({"class": "code"}, ">>> ", code),
+        BR()
+    );
+    this.lines.push(code);
+    this.history.push(code);
+    this.historyPos = -1;
+    this.currentHistory = "";
+    if (isContinuation) {
+        return;
+    }
+    var allCode = this.lines.join("\n");
+    this.lines = [];
+    this.runCode(allCode);
+    return;
+};
+
+InterpreterManager.prototype.runCode = function (allCode) {
+    var res;
+    try {
+        res = this.doEval(allCode);
+    } catch (e) {
+        // mozilla shows some keys more than once!
+        this.showError(e);
+        return;
+    }
+    this.showResult(res);
+};
+
+InterpreterManager.prototype.showResult = function (res) {
+    if (typeof(res) != "undefined") {
+        window._ = res;
+    }
+    if (typeof(res) != "undefined") {
+        appendChildNodes("interpreter_output",
+            SPAN({"class": "data"}, repr(res)),
+            BR()
+        );
+        this.doScroll();
+    }
+};
+
+window.writeln = function () {
+    appendChildNodes("interpreter_output",
+        SPAN({"class": "data"}, arguments),
+        BR()
+    );
+    interpreterManager.doScroll();
+};
+
+window.clear = function () {
+    replaceChildNodes("interpreter_output");
+    getElement("interpreter_area").scrollTop = 0;
+};
+
+window.blockOn = function (d) {
+    if (!(d instanceof Deferred)) {
+        throw new TypeError(repr(d) + " is not a Deferred!");
+    }
+    interpreterManager.blockOn(d);
+};
+
+window.dir = function (o) {
+    // Python muscle memory!
+    return sorted(keys(o));
+};
+
+window.inspect = function (o) {
+    window._ = o;
+    if ((typeof(o) != "function" && typeof(o) != "object") || o == null) {
+        window.writeln(repr(o));
+        return;
+    }
+    var pairs = items(o);
+    if (pairs.length == 0) {
+        window.writeln(repr(o));
+        return;
+    }
+    window.writeln(TABLE({"border": "1"},
+        THEAD({"class": "invisible"}, TR(null, TD(), TD())),
+        TFOOT({"class": "invisible"}, TR(null, TD(), TD())),
+        TBODY(null,
+            map(
+                function (kv) {
+                    var click = function () {
+                        try {
+                            window.inspect(kv[1]);
+                        } catch (e) {
+                            interpreterManager.showError(e);
+                        }
+                        return false;
+                    }
+                    return TR(null,
+                        TD(null, A({href: "#", onclick: click}, kv[0])),
+                        TD(null, repr(kv[1]))
+                    );
+                },
+                pairs
+            )
+        )
+    ));
+};
+    
+interpreterManager = new InterpreterManager();
+addLoadEvent(interpreterManager.initialize);
+
+// rewrite the view-source links
+addLoadEvent(function () {
+    var elems = getElementsByTagAndClassName("A", "view-source");
+    var page = "interpreter/";
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        var href = elem.href.split(/\//).pop();
+        elem.target = "_blank";
+        elem.href = "../view-source/view-source.html#" + page + href;
+    }
+});
diff --git a/mochikit_v14/examples/key_events/index.html b/mochikit_v14/examples/key_events/index.html
new file mode 100644 (file)
index 0000000..e58e5e6
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>Signal Example</title>
+    <link href="key_events.css" rel="stylesheet" type="text/css" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="key_events.js"></script>
+</head>
+<body>
+
+    <h1>
+        Key Events with MochiKit
+    </h1>
+    <p>
+        This is an example of one might implement a key listener with
+        MochiKit&#8217;s Signal.
+    </p>
+    <p>
+        For a detailed description of what happens under the hood, check out
+        <a href="key_events.js" class="view-source">key_events.js</a>.
+    </p>
+
+    <p>
+        View Source: [
+            <a href="index.html" class="view-source">index.html</a> | 
+            <a href="key_events.js" class="view-source">key_events.js</a> |
+            <a href="key_events.css" class="view-source">key_events.css</a>
+        ]
+    </p>
+
+    <p>Check this box to test <a href="http://mochikit.com/doc/html/MochiKit/Signal.html#fn-preventdefault">
+    preventDefault()</a> in your browser:
+    <input type="checkbox" id="stopBox" /></p>
+    
+    <p id="specialMessage">This text is replaced with a message when you press Escape or F1.</p>
+    
+    <table>
+        <tr>
+            <th>Event</th>
+            <th>Key Code</th>
+            <th>Key String</th>
+        </tr>
+        <tr>
+            <td>onkeydown</td>
+            <td id="onkeydown_code">-</td>
+            <td id="onkeydown_string">-</td>
+        </tr>
+        <tr>
+            <td>onkeyup</td>
+            <td id="onkeyup_code">-</td>
+            <td id="onkeyup_string">-</td>
+        </tr>
+        <tr>
+            <td>onkeypress</td>
+            <td id="onkeypress_code">-</td>
+            <td id="onkeypress_string">-</td>
+        </tr>
+    </table>
+    
+    <h3>Modifiers</h3>
+    <table>
+        <tr>
+            <th>Shift</th>
+            <th>Ctrl</th>
+            <th>Alt (Option)</th>
+            <th>Meta (Command)</th>
+        </tr>
+        <tr>
+            <td id="shift">-</td>
+            <td id="ctrl">-</td>
+            <td id="alt">-</td>
+            <td id="meta">-</td>
+        </tr>
+    </table>    
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/key_events/key_events.css b/mochikit_v14/examples/key_events/key_events.css
new file mode 100755 (executable)
index 0000000..1e71029
--- /dev/null
@@ -0,0 +1,5 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
\ No newline at end of file
diff --git a/mochikit_v14/examples/key_events/key_events.js b/mochikit_v14/examples/key_events/key_events.js
new file mode 100644 (file)
index 0000000..9eab2fa
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+
+    Key Events: A Really Simple Key Handler
+    
+*/
+
+KeyEvents = {
+    handled: false,
+    handleF1: function() {
+        replaceChildNodes('specialMessage', 'You invoked the special F1 handler!');
+    },
+    handleEscape: function() {
+        replaceChildNodes('specialMessage', 'You invoked the special Escape handler!');
+    },
+    updateModifiers: function(e) {
+        var modifiers = e.modifier();
+        replaceChildNodes('shift', modifiers.shift);
+        replaceChildNodes('ctrl', modifiers.ctrl);
+        replaceChildNodes('alt', modifiers.alt);
+        replaceChildNodes('meta', modifiers.meta);
+    }
+};
+
+KeyEvents.specialKeyMap = {
+    'KEY_F1': KeyEvents.handleF1,
+    'KEY_ESCAPE': KeyEvents.handleEscape
+};
+
+connect(document, 'onkeydown', 
+    function(e) {
+        if (getElement('stopBox').checked == true) {
+            e.preventDefault();
+        }
+        
+        // We're storing a handled flag to work around a Safari bug: 
+        // http://bugs.webkit.org/show_bug.cgi?id=3387
+        if (!KeyEvents.handled) {
+            var key = e.key();
+            var fn = KeyEvents.specialKeyMap[key.string];
+            if (fn) {
+                fn();
+            }
+            replaceChildNodes('onkeydown_code', key.code);
+            replaceChildNodes('onkeydown_string', key.string);
+            KeyEvents.updateModifiers(e);
+        }
+        KeyEvents.handled = true;
+    });
+    
+connect(document, 'onkeyup', 
+    function(e) {
+        if (getElement('stopBox').checked == true) {
+            e.preventDefault();
+        }
+        
+        KeyEvents.handled = false;
+        var key = e.key();
+        replaceChildNodes('onkeyup_code', key.code);
+        replaceChildNodes('onkeyup_string', key.string);
+        KeyEvents.updateModifiers(e);
+    });
+
+connect(document, 'onkeypress', 
+    function(e) {
+        if (getElement('stopBox').checked == true) {
+            e.preventDefault();
+        }
+        
+        var key = e.key();
+        replaceChildNodes('onkeypress_code', key.code);
+        replaceChildNodes('onkeypress_string', key.string);
+        KeyEvents.updateModifiers(e);
+    });
+
+connect(window, 'onload',
+    function() {        
+        var elems = getElementsByTagAndClassName("A", "view-source");
+        var page = "key_events/";
+        for (var i = 0; i < elems.length; i++) {
+            var elem = elems[i];
+            var href = elem.href.split(/\//).pop();
+            elem.target = "_blank";
+            elem.href = "../view-source/view-source.html#" + page + href;
+        }
+    });
\ No newline at end of file
diff --git a/mochikit_v14/examples/logging_pane/index.html b/mochikit_v14/examples/logging_pane/index.html
new file mode 100644 (file)
index 0000000..d046f19
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>Demo of MochiKit.LoggingPane</title>
+        <link href="logging_pane.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="logging_pane.js"></script>
+    </head>
+    <body>
+        <h1>MochiKit.LoggingPane</h1>
+        <div>
+            <p>
+                Demonstrates <a href="http://mochikit.com/">MochiKit</a>'s
+                <a href="../../doc/html/MochiKit/Logging.html">MochiKit.Logging</a>
+                and <a href="../../doc/html/MochiKit/LoggingPane.html">MochiKit.LoggingPane</a>.
+            </p>
+            <p>
+                Click one of the Logging Panes to pop up a view, and then
+                start clicking on Logging Actions to see it in action!
+            </p>
+        </div>
+        <div>
+            Logging Panes:
+            <ul>
+                <li><a href="javascript:logger.debuggingBookmarklet();">Debugging Bookmarklet</a> - Pop-up with LoggingPane</li>
+                <li><a href="javascript:void(createLoggingPane(true));">Inline LoggingPane</a></li>
+            </ul>
+        </div>
+        <div>
+            Logging Actions:
+            <ul>
+                <li><a href="javascript:logDebug('a DEBUG level message');">logDebug(...)</a></li>
+                <li><a href="javascript:log('an INFO level message');">log(...)</a></li>
+                <li><a href="javascript:logWarning('a WARNING level message');">logWarning(...)</a></li>
+                <li><a href="javascript:logError('an ERROR level message');">logError(...)</a></li>
+                <li><a href="javascript:logFatal('a FATAL level message');">logFatal(...)</a></li>
+            </ul>
+        <div>
+            View Source:
+            <ul>
+                <li><a href="logging_pane.js" class="view-source">logging_pane.js</a></li>
+                <li><a href="index.html" class="view-source">index.html</a></li>
+            </ul>
+        </div>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/logging_pane/logging_pane.css b/mochikit_v14/examples/logging_pane/logging_pane.css
new file mode 100755 (executable)
index 0000000..350065a
--- /dev/null
@@ -0,0 +1,78 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
+
+table.datagrid {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+table.datagrid thead th { 
+    text-align: left;
+    background-color: #4B4545;
+    background-repeat: no-repeat;
+    background-position: right center;
+    color: white;
+    font-weight: bold;
+    padding: .3em .7em;
+    font-size: .9em;
+    padding-right: 5px;
+    background-repeat: no-repeat;
+    background-position: 95% right;
+}
+
+table.datagrid thead th a {
+    color: white;
+    text-decoration: none;
+    font-size: 1.0em;
+    background-repeat: no-repeat;
+    background-position: center right;
+    padding-right: 15px;
+}
+
+table.datagrid thead th.over {
+    background-color: #746B6B;
+    cursor: pointer;
+}
+
+table.datagrid tbody th {
+    font-weight: bold;
+}
+
+table.datagrid tbody td, table.datagrid tbody th {
+    text-align: left;
+    padding: .3em .7em;
+    border-bottom: 1px solid #eee;
+}
+
+table.datagrid tbody tr.alternate td, table.datagrid tbody tr.alternate th {
+    background-color: #f1f1f1;
+}
+
+table.datagrid tfoot td, table.datagrid tfoot th { 
+    background-color: #FFFEE3;
+    color: #4B4545;
+    padding: .5em;
+    font-weight: bold;
+    border-top: 2px solid #4B4545;
+}
+
+table.datagrid tfoot th { text-align: left; }
+
+table.datagrid tfoot td {  }
+
+.invisible { display: none; }
+
+input.textbox, textarea { border: 1px solid #CCCCCC; font-size: .95em; padding: 2px 4px; margin-top: .3em; }
+input.textbox:focus, textarea:focus { background-color: #FFFEE3; }
+
+.highlight { font-weight: bold; };
+form { margin: 0; padding: 0; }
+
+fieldset { border: none; margin: 0; padding: 0; }
+fieldset label { font-weight: bold; color: #4B4545; }
+fieldset .field { margin-bottom: 1em; }
+
+label.error { color: red; }
diff --git a/mochikit_v14/examples/logging_pane/logging_pane.js b/mochikit_v14/examples/logging_pane/logging_pane.js
new file mode 100644 (file)
index 0000000..61bd1ee
--- /dev/null
@@ -0,0 +1,11 @@
+// rewrite the view-source links
+addLoadEvent(function () {
+    var elems = getElementsByTagAndClassName("A", "view-source");
+    var page = "logging_pane/";
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        var href = elem.href.split(/\//).pop();
+        elem.target = "_blank";
+        elem.href = "../view-source/view-source.html#" + page + href;
+    }
+});
diff --git a/mochikit_v14/examples/mochiregexp/index.html b/mochikit_v14/examples/mochiregexp/index.html
new file mode 100644 (file)
index 0000000..bd2ad09
--- /dev/null
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>MochiRegExp - JavaScript Regular Expression (RegExp) Explorer</title>
+        <link href="mochiregexp.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="mochiregexp.js"></script>
+    </head>
+    <body>
+        <h1>
+            MochiRegExp - JavaScript Regular Expression (RegExp) Explorer
+        </h1>
+        <div>
+            <p>
+                This demo does "live" Regular Expression matching to help you
+                toy with JavaScript Regular Expressions.
+                It takes advantage of
+                <a href="http://mochikit.com">MochiKit</a>'s
+                <a href="../../doc/html/MochiKit/DOM.html">MochiKit.DOM</a>
+                to manipulate the display and 
+                <a href="../../doc/html/MochiKit/Async.html">MochiKit.Async</a>
+                to facilitate the "half a second" live updating.
+            </p>
+            <p>
+                The table will update while you're typing if you're idle for
+                half a second or when you tab away from the field, whichever
+                comes first.  If you enter an invalid RegExp, the RegExp label
+                will turn <span class="error">red</span> (the "error" class).
+                For a good JavaScript's RegExp reference, see
+                <a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Regular_Expressions">Regular Expressions</a>
+                over at <a href="http://developer.mozilla.org">DevMo</a>.
+            </p>
+        </div>
+
+        <form id="regexp_form">
+            <table class="form">
+                <col class="column1">
+                <col class="column2">
+                <tbody>
+                    <tr>
+                        <th><label id="lab_text" for="inp_text">Input Text:</label></th>
+                        <td><input id="inp_text" name="text" type="text" class="textbox" size="80" /></td>
+                    </tr>
+                    <tr>
+                        <th><label id="lab_regexp" for="inp_regexp">RegExp:</label></th>
+                        <td><input id="inp_regexp" name="regexp" type="text" class="textbox" size="80" /></td>
+                    </tr>
+                    <tr>
+                        <th></th>
+                        <td><input type="reset" value="Clear" /></td>
+                    </tr>
+                </tbody>
+            </table>
+        </form>
+        
+        <div>
+            View Source: [
+            <a href="index.html" class="view-source">index.html</a> |
+            <a href="mochiregexp.js" class="view-source">mochiregexp.js</a>
+            ]
+        </div>
+        <table class="datagrid">
+            <thead>
+                <tr>
+                    <th>Property</th>
+                    <th>Result</th>
+                    <th>Repr</th>
+                </tr>
+            </thead>
+            <tfoot class="invisible"><tr><td colspan="3"></td></tr></tfoot>
+            <tbody id="result_body"><tr><td colspan="3"></td></tr></tbody>
+        </table>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/mochiregexp/mochiregexp.css b/mochikit_v14/examples/mochiregexp/mochiregexp.css
new file mode 100755 (executable)
index 0000000..be4e78e
--- /dev/null
@@ -0,0 +1,73 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
+
+table.datagrid {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+table.datagrid thead th { 
+    text-align: left;
+    background-color: #4B4545;
+    background-repeat: no-repeat;
+    background-position: right center;
+    color: white;
+    font-weight: bold;
+    padding: .3em .7em;
+    font-size: .9em;
+    padding-right: 5px;
+    background-repeat: no-repeat;
+    background-position: 95% right;
+}
+
+table.datagrid thead th a {
+    color: white;
+    text-decoration: none;
+    font-size: 1.0em;
+    background-repeat: no-repeat;
+    background-position: center right;
+    padding-right: 15px;
+}
+
+table.datagrid tbody th {
+    font-weight: bold;
+}
+
+table.datagrid tbody td, table.datagrid tbody th {
+    text-align: left;
+    padding: .3em .7em;
+    border-bottom: 1px solid #eee;
+}
+
+table.datagrid tbody tr.alternate td, table.datagrid tbody tr.alternate th {
+    background-color: #f1f1f1;
+}
+
+table.datagrid tfoot td, table.datagrid tfoot th { 
+    background-color: #FFFEE3;
+    color: #4B4545;
+    padding: .5em;
+    font-weight: bold;
+    border-top: 2px solid #4B4545;
+}
+
+table.datagrid tfoot th { text-align: left; }
+
+table.datagrid tfoot td {  }
+
+.invisible { display: none; }
+
+input.textbox, textarea { border: 1px solid #CCCCCC; font-size: .95em; padding: 2px 4px; margin-top: .3em; }
+input.textbox:focus, textarea:focus { background-color: #FFFEE3; }
+
+.highlight { font-weight: bold; };
+form { margin: 0; padding: 0; }
+
+fieldset { border: none; margin: 0; padding: 0; }
+fieldset label { font-weight: bold; color: #4B4545; }
+fieldset .field { margin-bottom: 1em; }
+
+.error { color: red; }
diff --git a/mochikit_v14/examples/mochiregexp/mochiregexp.js b/mochikit_v14/examples/mochiregexp/mochiregexp.js
new file mode 100644 (file)
index 0000000..911c6cf
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+
+    MochiRegExp: JavaScript Regular Expression Explorer
+
+*/
+RegExpManager = function () {
+    this.timer = null;
+    bindMethods(this);
+};
+
+RegExpManager.prototype.initialize = function () {
+    /*
+       Fill in the event handlers and sample text, and do the initial update
+       The reason we do the sample text here is so that "clear" really does
+       clear the fields.
+    */
+    setNodeAttribute("inp_text", "value", "matched with your pattern");
+    connect("inp_text", "onkeyup", this, "updateSoon");
+    connect("inp_text", "onchange", this, "update");
+
+    setNodeAttribute("inp_regexp", "value", "/(pattern)/");
+    connect("inp_regexp", "onkeyup", this, "updateSoon");
+    connect("inp_regexp", "onchange", this, "update");
+
+    connect("regexp_form", "onsubmit", this, "submit");
+
+    this.update();
+};
+
+RegExpManager.prototype.updateSoon = function () {
+    /*
+        If the user stops typing for half a second, do one update.
+    */
+    this.cancelTimer();
+    this.timer = callLater(0.5, this.update);
+};
+
+RegExpManager.prototype.cancelTimer = function () {
+    /*
+        Cancel the timer that waits for the user to idle for half a second.
+    */
+    if (this.timer) {
+        this.timer.cancel();
+    }
+    this.timer = null;
+};
+
+RegExpManager.prototype.update = function () {
+    /*
+        Cancel the update timer and actually do an update of the
+        RegExp
+    */
+    this.cancelTimer();
+    var re;
+    try {
+        // Evaluate the regexp
+        re = eval("(" + getElement("inp_regexp").value + ")");
+    } catch (e) {
+        // If invalid, color it red and stop
+        addElementClass("lab_regexp", "error");
+        return;
+    }
+    // Make sure that it's not red
+    removeElementClass("lab_regexp", "error");
+
+    // replace the contents of the tbody
+    var match = getElement("inp_text").value.match(re);
+    replaceChildNodes("result_body", this.getRows(match));
+};
+
+RegExpManager.prototype.getRows = function (match) {
+    /*
+        Return rows for the tbody given a match object
+    */
+    if (!match) {
+        // No match, bail with a no match row
+        return TR(null, TD({"colspan": "3"}, "No match!"));
+    }
+    var isAlternate = true;
+    var res = [];
+    for (var k in match) {
+        isAlternate = !isAlternate;
+        var trAttribs = isAlternate ? {"class": "alternate"} : null;
+        var v = match[k];
+        var result = v;
+        // Highlight the result for the input property as three spans:
+        //    [beforeMatch, duringMatch, afterMatch]
+        if (k == "input") {
+            var end = match.index + match[0].length;
+            result = [
+                SPAN(null, v.substr(0, match.index)),
+                SPAN({"class": "highlight"}, v.substring(match.index, end)),
+                SPAN(null, v.substr(end))
+            ];
+        }
+        res.push(
+            TR((isAlternate ? {"class": "alternate"} : null),
+                TD(null, k),
+                TD(null, result),
+                TD(null, repr(v))
+            )
+        );
+    }
+    return res;
+};
+
+RegExpManager.prototype.submit = function () {
+    this.update();
+    return false;
+};
+
+regExpManager = new RegExpManager();
+addLoadEvent(regExpManager.initialize);
+
+// rewrite the view-source links
+addLoadEvent(function () {
+    var elems = getElementsByTagAndClassName("A", "view-source");
+    var page = "mochiregexp/";
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        var href = elem.href.split(/\//).pop();
+        elem.target = "_blank";
+        elem.href = "../view-source/view-source.html#" + page + href;
+    }
+});
diff --git a/mochikit_v14/examples/rounded_corners/index.html b/mochikit_v14/examples/rounded_corners/index.html
new file mode 100644 (file)
index 0000000..9513631
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>Demo of MochiKit Visual Elements</title>
+        <link href="rounded_corners.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="rounded_corners.js"></script>
+    </head>
+    <body>
+        <h1>MochiKit.Visual <span id="visual_version"></span></h1>
+        <h2>Rounded Corners</h2>
+        <p>
+            This example demonstrates the rounded corners functionality of 
+            <a href="http://mochikit.com">MochiKit</a>'s
+            <a href="../../doc/html/MochiKit/Visual.html">MochiKit.Visual</a>.
+        </p>
+        <p>
+            The heading at the top of this page should have all four corners
+            rounded. The heading for this section should just have the bottom
+            corners rounded.
+        </p>
+        View Source:
+        <ul>
+            <li><a href="rounded_corners.js" class="view-source">rounded_corners.js</a></li>
+            <li><a href="index.html" class="view-source">index.html</a></li>
+        </ul>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/rounded_corners/rounded_corners.css b/mochikit_v14/examples/rounded_corners/rounded_corners.css
new file mode 100755 (executable)
index 0000000..a700b69
--- /dev/null
@@ -0,0 +1,3 @@
+h1 { background: darkgreen; color: yellow; text-align: center; }
+h2 { background: darkgreen; color: yellow; padding-top: 0.25em;}
+.invisible { display: none; }
diff --git a/mochikit_v14/examples/rounded_corners/rounded_corners.js b/mochikit_v14/examples/rounded_corners/rounded_corners.js
new file mode 100644 (file)
index 0000000..d063ae1
--- /dev/null
@@ -0,0 +1,19 @@
+var roundedCornersOnLoad = function () {
+    swapDOM("visual_version", SPAN(null, MochiKit.Visual.VERSION));
+    roundClass("h1", null);
+    roundClass("h2", null, {corners: "bottom"});
+};
+addLoadEvent(roundedCornersOnLoad);
+
+// rewrite the view-source links
+addLoadEvent(function () {
+    var elems = getElementsByTagAndClassName("A", "view-source");
+    var page = "rounded_corners/";
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        var href = elem.href.split(/\//).pop();
+        elem.target = "_blank";
+        elem.href = "../view-source/view-source.html#" + page + href;
+    }
+});
+
diff --git a/mochikit_v14/examples/simple_dnd/dnd_boxes.html b/mochikit_v14/examples/simple_dnd/dnd_boxes.html
new file mode 100644 (file)
index 0000000..81074e4
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Drag and drop functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+  <style type="text/css" media="screen">
+    #thelist li { background: green; margin:5px; padding: 30px; }
+    #thelist2 li { background: #ffb; margin:2px; padding: 2px; }
+  </style>
+</head>
+<body>
+<h1>script.aculo.us Drag and drop functional test file</h1>
+
+<h2>Draggables/Droppables</h2>
+
+<div id="revertbox1" class="box1" style="z-index:1000;width:150px;height:150px;background:#bbf;">
+  <span id="handle1">drag here</span><br/>
+  <input type="checkbox" id="shouldrevert1"/> Revert?
+</div>
+
+<div id="revertbox2" class="box" style="z-index:1000;width:150px;height:150px;background:#bbf;">
+  <span id="handle2">drag here</span><br/>
+  <input type="checkbox" id="shouldrevert2"/> Revert?
+</div>
+
+<div id="droptarget1" style="width:200px;height:200px;background-color:#eee;">accepts first box</div>
+<div id="droptarget2" style="width:200px;height:200px;background-color:#eee;">accepts second box</div>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  new MochiKit.DragAndDrop.Draggable('revertbox1',{handle:'handle1',revert:function(element){return ($('shouldrevert1').checked)}});
+  new MochiKit.DragAndDrop.Draggable('revertbox2',{handle:'handle2',revert:function(element){return ($('shouldrevert2').checked)}});
+  new MochiKit.DragAndDrop.Droppable('droptarget1',{accept:['box1','otherstuff'],ondrop:function(){alert('drop!')}});
+  new MochiKit.DragAndDrop.Droppable('droptarget2',{accept:['box'],ondrop:function(){alert('drop!')}});
+// ]]>
+</script>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/simple_dnd/dnd_full.html b/mochikit_v14/examples/simple_dnd/dnd_full.html
new file mode 100644 (file)
index 0000000..da8e613
--- /dev/null
@@ -0,0 +1,119 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Drag and drop functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+  <style type="text/css" media="screen">
+    #thelist li { background: green; margin:5px; padding: 30px; }
+    #thelist2 li { background: #ffb; margin:2px; padding: 2px; }
+    #revertbox2 { position:absolute;top:40px;left:50px;z-index:1000;width:150px;height:150px;background:#bbf; }
+  </style>
+</head>
+<body>
+<h1>script.aculo.us Drag and drop functional test file</h1>
+
+<h2>Draggables/Droppables</h2>
+
+<div id="revertbox1" class="box1" style="z-index:1000;width:150px;height:150px;background:#bbf;">
+  <span class="handle1">drag here</span><br/>
+  <input type="checkbox" id="shouldrevert1"/> Revert?
+</div>
+
+<div id="revertbox2" class="box">
+  <span id="handle2">drag here</span><br/>
+  <input type="checkbox" id="shouldrevert2"/> Revert?
+</div>
+
+<div id="xxxx">testtest</div>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  new MochiKit.DragAndDrop.Draggable('revertbox1',{zindex:-5,handle:'handle1',revert:function(element){return ($('shouldrevert1').checked)}});
+  new MochiKit.DragAndDrop.Draggable('revertbox2',{handle:'handle2',revert:function(element){return ($('shouldrevert2').checked)}});
+  new MochiKit.DragAndDrop.Droppable('xxxx',{accept:['box1','box2'],onDrop:function(){alert('drop!')}});
+// ]]>
+</script>
+
+
+
+
+<ul id="thelist" style="padding: 10px; position: absolute; top:20px; left:200px;z-index:1000;">
+<li id="thelist_4">Hey there! I'm absolutely positioned</li>
+<li id="thelist_1">one<br/><form id="form1"><input type="checkbox" onclick="this.checked = !this.checked" value="x" name="x" id="xyz"/><input type="text" id="xxx"></input></form></li>
+<li id="thelist_2">two<br/><form id="form2"><input type="text" id="xyx"></input></form></li>
+<li id="thelist_3">three<br/><form id="form3"><input type="text" id="xu3"></input></form></li>
+</ul>
+
+<ul id="thelist2" style="padding: 2px; background:red;">
+<li>Relatively here!</li>
+<li><input onclick="this.checked = !this.checked" name="x" id="x" type="checkbox"/>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+</ul>
+
+
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+//  Sortable.create('thelist', {overlap: 'horizontal', constraint: false});
+MochiKit.Sortable.Sortable.create('thelist');
+MochiKit.Sortable.Sortable.create('thelist2');
+
+// ]]>
+</script>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/simple_dnd/dnd_ghost.html b/mochikit_v14/examples/simple_dnd/dnd_ghost.html
new file mode 100644 (file)
index 0000000..5f6806b
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Drag and drop functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+</head>
+<body style="background-color:#eee;">
+<div style="position:relative;margin-left:100px;top:40px;background-color:white;">
+(inside position:relative container)
+<h1>script.aculo.us Drag and drop functional test file</h1>
+
+<h2>Draggables/Droppables</h2>
+
+<div id="absolute_positioned_element" class="box1" style="width:150px;height:150px;background:#bbf;">
+  <b>Ghosting effect</b>
+  <input type="text" value="blah"/>
+  <div id="hurradiegams">test!</div>
+  <br/>
+</div>
+
+<a href="#" onclick="alert($('hurradiegams').innerHTML); return false;">alert contents of test div</a>
+
+<div id="absolute_positioned_element2" class="box1" style="width:150px;height:150px;background:#bbf;">
+  <span id="handle1">Ghost effect</span><br/>
+</div>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  new MochiKit.DragAndDrop.Draggable('absolute_positioned_element',{ghosting: true});
+  new MochiKit.DragAndDrop.Draggable('absolute_positioned_element2',{ghosting: true, revert:true});
+// ]]>
+</script>
+</div>
+</body>
+</html>
diff --git a/mochikit_v14/examples/simple_dnd/dnd_hoverclass.html b/mochikit_v14/examples/simple_dnd/dnd_hoverclass.html
new file mode 100644 (file)
index 0000000..65e43ca
--- /dev/null
@@ -0,0 +1,43 @@
+<html>
+<head>
+<title>script.aculo.us Drag and drop functional test file</title>
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+</head>
+<style>
+  div.hoverclass123 {
+    border:1px solid red;
+  }
+</style>
+<body>
+
+<h1>script.aculo.us Drag and drop functional test file</h1>
+
+<h2>w/o hoverclass</h2>
+
+<div id="cart" class="cart" style="text-align:center;height:50px;padding:10px;background-color:#fba">
+### DROP HERE ###
+</div>
+
+<script type="text/javascript">new MochiKit.DragAndDrop.Droppable('cart', {ondrop:function(element,dropon){alert('w/o hoverclass, should be \'product_id\':' + encodeURIComponent(element.id) + ', dropon should be \'cart\':' + dropon.id)}})</script>
+
+<br/>
+
+<img alt="Product2" id="product_id" src="icon.png" /> &lt;-- drag this!
+
+<script type="text/javascript">new MochiKit.DragAndDrop.Draggable('product_id', {revert:true})</script>
+
+<h2>w/ hoverclass</h2>
+
+
+<div id="carth" class="cart" style="text-align:center;height:50px;padding:10px;background-color:#fba">
+### DROP HERE ###
+</div>
+
+<script type="text/javascript">new MochiKit.DragAndDrop.Droppable('carth', {hoverclass:'hoverclass123',ondrop:function(element, dropon, event){alert('w/ hoverclass: should be \'product_id\':' + encodeURIComponent(element.id) + ', dropon should be \'carth\':' + dropon.id)}})</script>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/simple_dnd/dnd_scroll.html b/mochikit_v14/examples/simple_dnd/dnd_scroll.html
new file mode 100644 (file)
index 0000000..829425e
--- /dev/null
@@ -0,0 +1,91 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Drag and drop functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Sortable.js"></script>
+  <style type="text/css" media="screen">
+    #thelist li { background: green; margin:5px; padding: 30px; }
+    #thelist2 li { background: #ffb; margin:2px; padding: 2px; }
+  </style>
+</head>
+<body>
+<h1>script.aculo.us Drag and drop functional test file</h1>
+
+<h2>Draggables/Droppables</h2>
+
+<div style="width:400px;height:400px;overflow:scroll;position:relative;" id="scroll-container">
+
+<ul id="thelist2" style="padding: 2px; background:red;">
+<li>Relatively here!</li>
+<li><input onclick="this.checked = !this.checked" name="x" id="x" type="checkbox"/>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+<li>one</li>
+</ul>
+
+</div>
+
+<pre id="debug"></pre>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+//  Sortable.create('thelist', {overlap: 'horizontal', constraint: false});
+MochiKit.Position.includeScrollOffsets = true;
+MochiKit.Sortable.Sortable.create('thelist2', {scroll: 'scroll-container'});
+
+// ]]>
+</script>
+</body>
+</html>
diff --git a/mochikit_v14/examples/simple_dnd/dnd_snap.html b/mochikit_v14/examples/simple_dnd/dnd_snap.html
new file mode 100644 (file)
index 0000000..936557f
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>script.aculo.us Drag and drop functional test file</title>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+  <style type="text/css" media="screen">
+    div.box { background: green; width:100px; height:100px }
+  </style>
+</head>
+<body>
+<h1>script.aculo.us Drag and drop functional test file</h1>
+
+<h2>Draggables/Droppables</h2>
+
+<div id="box-normal" class="box">
+  Normal box
+</div>
+
+<div id="box-grid-numeric" class="box">
+  snap: 25
+</div>
+
+<div id="box-grid-array" class="box">
+  snap: [5,25]
+</div>
+
+<div id="box-grid-procedural" class="box">
+  snap: procedural (e.g. constrain to box)
+</div>
+
+<script type="text/javascript" language="javascript" charset="utf-8">
+// <![CDATA[
+  new MochiKit.DragAndDrop.Draggable('box-normal',{snap:false,revert:true});
+  new MochiKit.DragAndDrop.Draggable('box-grid-numeric',{snap:25,revert:true});
+  new MochiKit.DragAndDrop.Draggable('box-grid-array',{snap:[5,25],revert:true});
+  new MochiKit.DragAndDrop.Draggable('box-grid-procedural',{
+    snap: function(x,y) {
+      return[
+        x<100 ? (x > 0 ? x : 0 ) : 100,
+        y<50 ? (y > 0 ? y : 0) : 50];
+    },
+    revert:true
+  });
+// ]]>
+</script>
+
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/simple_dnd/index.html b/mochikit_v14/examples/simple_dnd/index.html
new file mode 100644 (file)
index 0000000..1401e96
--- /dev/null
@@ -0,0 +1,93 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+  <head>
+    <title>Test Drag and drop with MochiKit</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <link href="simple_dnd.css" rel="stylesheet" type="text/css" />
+    <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="../../MochiKit/DragAndDrop.js"></script>
+  </head>
+  <body>
+    <h3>Drag and Drop examples.</h3>
+    <div>
+        <div id="drag-1" class="drag">test drag 1</div>
+        <div id="drag-2" class="drag">test drag 2 (horizontal)</div>
+        <div id="drag-3" class="drag">test drag 3 (vertical)</div>
+        <div id="drag-4" class="drag">test drag 4 (selectclass)</div>
+        <div id="drag-5" class="drag">test drag 5 (fixed)</div>
+        <div id="drag-6" class="drag">test drag 6 (absolute)</div>
+        <div id="drag-7" class="drag">test drag 7 (relative)</div>
+        <div id="drag-8" class="drag">test drag 8 (handle)</div>
+        <div id="handle" class="drag">handle for drag 8</div>
+    </div>
+    <div id="dropzones">
+        <div id="drop-1" class="drop">test drop 1</div>
+        <div id="drop-2" class="drop">test drop 2 (hoverclass)</div>
+        <div id="drop-3" class="drop">test drop 3 (activeclass)</div>
+        <div id="drop-4" class="drop">test drop 4 (hoverFunc)</div>
+        <div id="drop-5" class="drop">test drop 5 (activeFunc)</div>
+        <div id="drop-6">test drop 6</div>
+        <div id="droptext">No select</div>
+    </div>
+    <script type="text/javascript">
+    <!--
+    var saveTxt = "";
+    onHoverFunc = function (element, onhover) {
+        if (onhover) {
+            saveTxt = element.childNodes[0].nodeValue;
+            element.childNodes[0].nodeValue = "Please drop on me!";
+        } else {
+        element.childNodes[0].nodeValue = saveTxt;
+        }
+    };
+    onActiveFunc = function (element, dragElt) {
+        element.childNodes[0].nodeValue += " and I'm active ! (" + dragElt.id + ")";
+    };
+    onDesactiveFunc = function (element, dragElt) {
+        var ind = element.childNodes[0].nodeValue.lastIndexOf(" and I'm active !");
+        element.childNodes[0].nodeValue = element.childNodes[0].nodeValue.slice(0, ind);
+    };
+    onSelectFunc = function (element) {
+        new MochiKit.Visual.Highlight(element);
+    };
+    onDeselectFunc = function (element) {
+        element.childNodes[0].nodeValue += ".";
+    };
+    ondrop = function (element, dropElt) {
+        MochiKit.Visual.pulsate(dropElt);
+        MochiKit.DOM.getElement('droptext').childNodes[0].nodeValue = "Selected: " + element.id;
+    };
+    
+    new MochiKit.DragAndDrop.Draggable('drag-1', {'revert': true, 'ghosting': true});
+    new MochiKit.DragAndDrop.Draggable('drag-2', {'revert': true, 'constraint': 'horizontal'});
+    new MochiKit.DragAndDrop.Draggable('drag-3', {'revert': true, 'constraint': 'vertical'});
+    new MochiKit.DragAndDrop.Draggable('drag-4', {'revert': true, 'selectclass': 'drag-select'});
+    new MochiKit.DragAndDrop.Draggable('drag-5', {'revert': true, 'starteffect': onSelectFunc, 'endeffect': onDeselectFunc});
+    new MochiKit.DragAndDrop.Draggable('drag-6', {'revert': true});
+    new MochiKit.DragAndDrop.Draggable('drag-7', {'revert': true});
+    new MochiKit.DragAndDrop.Draggable('drag-8', {'revert': true, 'handle': 'handle'});
+
+    new MochiKit.DragAndDrop.Droppable('drop-1', {'ondrop': ondrop});
+    new MochiKit.DragAndDrop.Droppable('drop-2', {'ondrop': ondrop, 'hoverclass': 'drop-hover'});
+    new MochiKit.DragAndDrop.Droppable('drop-3', {'ondrop': ondrop, 'activeclass': 'drop-active'});
+    new MochiKit.DragAndDrop.Droppable('drop-4', {'ondrop': ondrop, 'hoverfunc': onHoverFunc});
+    new MochiKit.DragAndDrop.Droppable('drop-5', {'ondrop': ondrop, 'onactive': onActiveFunc, 'ondesactive': onDesactiveFunc});
+    new MochiKit.DragAndDrop.Droppable('drop-6', {'ondrop': ondrop, 'transparent': true});
+    // -->
+    </script>
+    <div>
+    Links to other samples:
+    <ul>
+    <li><a href="dnd_boxes.html">Boxes DND</a></li>
+    <li><a href="dnd_hoverclass.html">Hoverclass DND</a></li>
+    <li><a href="dnd_snap.html">Snap DND</a></li>
+    <li><a href="dnd_ghost.html">Ghost DND</a></li>
+    <li><a href="dnd_scroll.html">Scroll DND</a></li>
+    <li><a href="dnd_full.html">Full DND</a></li>
+    </ul>
+    </div>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/simple_dnd/simple_dnd.css b/mochikit_v14/examples/simple_dnd/simple_dnd.css
new file mode 100755 (executable)
index 0000000..78554aa
--- /dev/null
@@ -0,0 +1,64 @@
+.drag {
+    background-color: blue;
+    width: 100px;
+    padding: 5px;
+    margin: 10px;
+    border: 1px solid black;
+}
+
+#dropzones {
+    margin-top: 100px;
+    display: inline;
+}
+
+.drop {
+    background-color: red;
+    width: 100px;
+    padding: 5px;
+    margin: 10px;
+    border: 1px solid black;
+    display: inline;
+}
+
+.droptrans {
+    width: 100px;
+    padding: 5px;
+    margin: 10px;
+    border: 1px solid black;
+}
+
+.drop-hover {
+    border: 2px solid green;
+}
+
+.drop-active {
+    background-color: #FF79ED;
+}
+
+.drag-select {
+    background-color: green;
+}
+
+#drag-5 {
+    position: fixed;
+    top: 100px;
+    left: 200px;
+}
+#drag-6 {
+    position: absolute;
+    top: 100px;
+    left: 350px;
+}
+#drag-7 {
+    position: relative;
+    top: -100px;
+    left: 500px;
+}
+#drop-6 {
+    display: inline;
+}
+#droptext {
+    margin-top: 20px;
+    border: 1px dashed black;
+    padding: 10px;
+}
diff --git a/mochikit_v14/examples/sortable_tables/index.html b/mochikit_v14/examples/sortable_tables/index.html
new file mode 100644 (file)
index 0000000..404e2b3
--- /dev/null
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>Sortable Tables from Scratch with MochiKit</title>
+        <link href="sortable_tables.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <script type="text/javascript" src="sortable_tables.js"></script>
+    </head>
+    <body>
+        <h1>
+            Sortable Tables from Scratch with MochiKit
+        </h1>
+        <p>
+            This is an example of how one might do sortable tables in
+            an inobtrusive manner.  The data is supplied by the server
+            and is already in the table.
+        </p>
+        <p>
+            For a detailed description of what happens under the hood,
+            check out
+            <a href="sortable_tables.js" class="view-source">sortable_tables.js</a>.
+        </p>
+        <p>
+            View Source: [
+                <a href="index.html" class="view-source">index.html</a> | 
+                <a href="sortable_tables.js" class="view-source">sortable_tables.js</a>
+            ]
+        </p>
+        <table id="sortable_table" class="datagrid">
+            <thead>
+                <tr>
+                    <th mochi:format="str">Domain Name</th>
+                    <th mochi:format="isodate">Creation Date</th>
+                    <th mochi:format="isodate">Expiry Date</th>
+                    <th mochi:format="istr">Organization Name</th>
+                </tr>
+            </thead>
+            <tfoot class="invisible">
+                <tr>
+                    <td colspan="0"></td>
+                </tr>
+            </tfoot>
+            <tbody>
+                <tr>
+                    <td>mochibot.com</td>
+                    <td>2005-02-10</td>
+                    <td>2007-02-10</td>
+                    <td>Jameson Hsu</td>
+                </tr>
+                <tr>
+                    <td>pythonmac.org</td>
+                    <td>2003-09-24</td>
+                    <td>2006-09-24</td>
+                    <td>Bob Ippolito</td>
+                </tr>
+                <tr>
+                    <td>undefined.org</td>
+                    <td>2000-01-10</td>
+                    <td>2006-01-10</td>
+                    <td>Robert J Ippolito</td>
+                </tr>
+                <tr>
+                    <td>python.org</td>
+                    <td>1995-03-27</td>
+                    <td>2007-03-28</td>
+                    <td>Python Software Foundation</td>
+                </tr>
+            </tbody>
+        </table>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/sortable_tables/sortable_tables.css b/mochikit_v14/examples/sortable_tables/sortable_tables.css
new file mode 100755 (executable)
index 0000000..902bc05
--- /dev/null
@@ -0,0 +1,66 @@
+h1 {
+    font-size: 2em;
+    color: #4B4545;
+    text-align: center;
+}
+
+table.datagrid {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+table.datagrid thead th { 
+    text-align: left;
+    background-color: #4B4545;
+    background-repeat: no-repeat;
+    background-position: right center;
+    color: white;
+    font-weight: bold;
+    padding: .3em .7em;
+    font-size: .9em;
+    padding-right: 5px;
+    background-repeat: no-repeat;
+    background-position: 95% right;
+}
+
+table.datagrid thead th a {
+    color: white;
+    text-decoration: none;
+    font-size: 1.0em;
+    background-repeat: no-repeat;
+    background-position: center right;
+    padding-right: 15px;
+}
+
+table.datagrid thead th.over {
+    background-color: #746B6B;
+    cursor: pointer;
+}
+
+table.datagrid tbody th {
+    font-weight: bold;
+}
+
+table.datagrid tbody td, table.datagrid tbody th {
+    text-align: left;
+    padding: .3em .7em;
+    border-bottom: 1px solid #eee;
+}
+
+table.datagrid tbody tr.alternate td, table.datagrid tbody tr.alternate th {
+    background-color: #f1f1f1;
+}
+
+table.datagrid tfoot td, table.datagrid tfoot th { 
+    background-color: #FFFEE3;
+    color: #4B4545;
+    padding: .5em;
+    font-weight: bold;
+    border-top: 2px solid #4B4545;
+}
+
+table.datagrid tfoot th { text-align: left; }
+
+table.datagrid tfoot td {  }
+
+.invisible { display: none; }
diff --git a/mochikit_v14/examples/sortable_tables/sortable_tables.js b/mochikit_v14/examples/sortable_tables/sortable_tables.js
new file mode 100644 (file)
index 0000000..2466f90
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+
+On page load, the SortableManager:
+
+- Finds the table by its id (sortable_table).
+- Parses its thead for columns with a "mochi:format" attribute.
+- Parses the data out of the tbody based upon information given in the
+  "mochi:format" attribute, and clones the tr elements for later re-use.
+- Clones the column header th elements for use as a template when drawing 
+  sort arrow columns.
+- Stores away a reference to the tbody, as it will be replaced on each sort.
+- Performs the first sort.
+
+
+On sort request:
+
+- Sorts the data based on the given key and direction
+- Creates a new tbody from the rows in the new ordering
+- Replaces the column header th elements with clickable versions, adding an
+   indicator (&uarr; or &darr;) to the most recently sorted column.
+
+*/
+
+SortableManager = function () {
+    this.thead = null;
+    this.tbody = null;
+    this.columns = [];
+    this.rows = [];
+    this.sortState = {};
+    this.sortkey = 0;
+};
+
+mouseOverFunc = function () {
+    addElementClass(this, "over");
+};
+
+mouseOutFunc = function () {
+    removeElementClass(this, "over");
+};
+
+ignoreEvent = function (ev) {
+    if (ev && ev.preventDefault) {
+        ev.preventDefault();
+        ev.stopPropagation();
+    } else if (typeof(event) != 'undefined') {
+        event.cancelBubble = false;
+        event.returnValue = false;
+    }
+};
+
+
+update(SortableManager.prototype, {
+
+    "initWithTable": function (table) {
+        /***
+
+            Initialize the SortableManager with a table object
+        
+        ***/
+        // Ensure that it's a DOM element
+        table = getElement(table);
+        // Find the thead
+        this.thead = table.getElementsByTagName('thead')[0];
+        // get the mochi:format key and contents for each column header
+        var cols = this.thead.getElementsByTagName('th');
+        for (var i = 0; i < cols.length; i++) {
+            var node = cols[i];
+            var attr = null;
+            try {
+                attr = node.getAttribute("mochi:format");
+            } catch (err) {
+                // pass
+            }
+            var o = node.childNodes;
+            this.columns.push({
+                "format": attr,
+                "element": node,
+                "proto": node.cloneNode(true)
+            });
+        }
+        // scrape the tbody for data
+        this.tbody = table.getElementsByTagName('tbody')[0];
+        // every row
+        var rows = this.tbody.getElementsByTagName('tr');
+        for (var i = 0; i < rows.length; i++) {
+            // every cell
+            var row = rows[i];
+            var cols = row.getElementsByTagName('td');
+            var rowData = [];
+            for (var j = 0; j < cols.length; j++) {
+                // scrape the text and build the appropriate object out of it
+                var cell = cols[j];
+                var obj = scrapeText(cell);
+                switch (this.columns[j].format) {
+                    case 'isodate':
+                        obj = isoDate(obj);
+                        break;
+                    case 'str':
+                        break;
+                    case 'istr':
+                        obj = obj.toLowerCase();
+                        break;
+                    // cases for numbers, etc. could be here
+                    default:
+                        break;
+                }
+                rowData.push(obj);
+            }
+            // stow away a reference to the TR and save it
+            rowData.row = row.cloneNode(true);
+            this.rows.push(rowData);
+
+        }
+
+        // do initial sort on first column
+        this.drawSortedRows(this.sortkey, true, false);
+
+    },
+
+    "onSortClick": function (name) {
+        /***
+
+            Return a sort function for click events
+
+        ***/
+        return method(this, function () {
+            log('onSortClick', name);
+            var order = this.sortState[name];
+            if (order == null) {
+                order = true;
+            } else if (name == this.sortkey) {
+                order = !order;
+            }
+            this.drawSortedRows(name, order, true);
+        });
+    },
+
+    "drawSortedRows": function (key, forward, clicked) {
+        /***
+
+            Draw the new sorted table body, and modify the column headers
+            if appropriate
+
+        ***/
+        log('drawSortedRows', key, forward);
+        this.sortkey = key;
+        // sort based on the state given (forward or reverse)
+        var cmp = (forward ? keyComparator : reverseKeyComparator);
+        this.rows.sort(cmp(key));
+        // save it so we can flip next time
+        this.sortState[key] = forward;
+        // get every "row" element from this.rows and make a new tbody
+        var newBody = TBODY(null, map(itemgetter("row"), this.rows));
+        // swap in the new tbody
+        this.tbody = swapDOM(this.tbody, newBody);
+        for (var i = 0; i < this.columns.length; i++) {
+            var col = this.columns[i];
+            var node = col.proto.cloneNode(true);
+            // remove the existing events to minimize IE leaks
+            col.element.onclick = null;
+            col.element.onmousedown = null;
+            col.element.onmouseover = null;
+            col.element.onmouseout = null;
+            // set new events for the new node
+            node.onclick = this.onSortClick(i);
+            node.onmousedown = ignoreEvent;
+            node.onmouseover = mouseOverFunc;
+            node.onmouseout = mouseOutFunc;
+            // if this is the sorted column
+            if (key == i) {
+                // \u2193 is down arrow, \u2191 is up arrow
+                // forward sorts mean the rows get bigger going down
+                var arrow = (forward ? "\u2193" : "\u2191");
+                // add the character to the column header
+                node.appendChild(SPAN(null, arrow));
+                if (clicked) {
+                    node.onmouseover();
+                }
+            }
+            // swap in the new th
+            col.element = swapDOM(col.element, node);
+        }
+    }
+});
+
+sortableManager = new SortableManager();
+
+addLoadEvent(function () {
+    sortableManager.initWithTable('sortable_table');
+});
+
+// rewrite the view-source links
+addLoadEvent(function () {
+    var elems = getElementsByTagAndClassName("A", "view-source");
+    var page = "sortable_tables/";
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        var href = elem.href.split(/\//).pop();
+        elem.target = "_blank";
+        elem.href = "../view-source/view-source.html#" + page + href;
+    }
+});
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css
new file mode 100755 (executable)
index 0000000..9649794
--- /dev/null
@@ -0,0 +1,177 @@
+
+/* Main style for the table */
+
+.dp-highlighter {
+       width: 100%;
+       overflow: auto;
+       line-height: 100% !important;
+       margin: 18px 0px 18px 0px;
+}
+
+.dp-highlighter table {
+       width: 100%;
+       margin: 2px 0px 2px 0px;
+       border-collapse: collapse;
+       border-bottom: 2px solid #eee;
+       background-color: #fff;
+}
+
+.dp-highlighter tbody.hide { display: none; }
+.dp-highlighter tbody.show { display: table-row-group; _display: block; }
+
+.dp-highlighter td 
+{
+       font-family: Courier New;
+       font-size: 11px;
+}
+
+/* Styles for the tools */
+
+.dp-highlighter .tools-corner {
+       background-color: #eee;
+       font-size: 9px;
+}
+
+.dp-highlighter .tools {
+       background-color: #eee;
+       padding: 3px 8px 3px 10px;
+       border-bottom: 1px solid gray;
+       font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;
+       color: silver;
+}
+
+.dp-highlighter .tools-corner {
+       background-color: #eee;
+}
+
+.dp-highlighter .tools a {
+       font-size: 9px;
+       color: gray;
+       text-decoration: none;
+}
+
+.dp-highlighter .tools a:hover {
+       color: red;
+       text-decoration: underline;
+}
+
+/* Gutter with line number */
+
+.dp-highlighter .gutter {
+       padding-right: 5px; 
+       padding-left: 10px; 
+       width: 5px;
+       background-color: #eee; 
+       border-right: 1px solid gray; 
+       color: gray;
+       text-align: right;
+       vertical-align: top;
+}
+
+/* Single line style */
+
+.dp-highlighter .line1, .line2 {
+       padding-left: 10px;
+       border-bottom: 1px solid #F7F7F7;
+       white-space:nowrap;
+}
+
+.dp-highlighter .line2 {
+       background-color: #F7F7F7;
+}
+
+/* About dialog styles */
+
+.dp-about {
+       background-color: #fff;
+       margin: 0px;
+}
+
+.dp-about table {
+       width: 100%;
+       height: 100%;
+       font-size: 11px;
+       font-family: Tahoma, Verdana, Arial, sans-serif !important;
+}
+
+.dp-about td {
+       padding: 10px;
+       vertical-align: top;
+}
+
+.dp-about .copy {
+       border-bottom: 1px solid #ACA899;
+       height: 95%;
+}
+
+.dp-about .title {
+       color: red;
+       font-weight: bold;
+}
+
+.dp-about .para {
+       margin-bottom: 4px;
+}
+
+.dp-about .footer {
+       background-color: #ECEADB;
+       border-top: 1px solid #fff;
+       text-align: right;
+}
+
+.dp-about .close {
+       font-size: 11px;
+       font-family: Tahoma, Verdana, Arial, sans-serif !important;
+       background-color: #ECEADB;
+       width: 60px;
+       height: 22px;
+}
+
+/* Language specific styles */
+
+.dp-c {}
+.dp-c .comment { color: green; }
+.dp-c .string { color: blue; }
+.dp-c .preprocessor { color: gray; }
+.dp-c .keyword { color: blue; }
+.dp-c .vars { color: #d00; }
+
+.dp-vb {}
+.dp-vb .comment { color: green; }
+.dp-vb .string { color: blue; }
+.dp-vb .preprocessor { color: gray; }
+.dp-vb .keyword { color: blue; }
+
+.dp-sql {}
+.dp-sql .comment { color: green; }
+.dp-sql .string { color: red; }
+.dp-sql .keyword { color: blue; }
+.dp-sql .func { color: #ff1493; }
+.dp-sql .op { color: #808080; }
+
+.dp-xml {}
+.dp-xml .cdata { color: #ff1493; }
+.dp-xml .comments { color: green; }
+.dp-xml .tag { color: blue; }
+.dp-xml .tag-name { color: black; font-weight: bold; }
+.dp-xml .attribute { color: red; }
+.dp-xml .attribute-value { color: blue; }
+
+.dp-delphi {}
+.dp-delphi .comment { color: #008200; font-style: italic; }
+.dp-delphi .string { color: blue; }
+.dp-delphi .number { color: blue; }
+.dp-delphi .directive { color: #008284; }
+.dp-delphi .keyword { font-weight: bold; color: navy; }
+.dp-delphi .vars { color: #000; }
+
+.dp-py {}
+.dp-py .comment { color: green; }
+.dp-py .string { color: red; }
+.dp-py .docstring { color: brown; }
+.dp-py .keyword { color: blue; font-weight: bold;}
+.dp-py .builtins { color: #ff1493; }
+.dp-py .magicmethods { color: #808080; }
+.dp-py .exceptions { color: brown; }
+.dp-py .types { color: brown; font-style: italic; }
+.dp-py .commonlibs { color: #8A2BE2; font-style: italic; }
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/Tests.html b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/Tests.html
new file mode 100644 (file)
index 0000000..71eb63f
--- /dev/null
@@ -0,0 +1,339 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <title>dp.SyntaxHighlighter testing</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+
+       <link type="text/css" rel="stylesheet" href="SyntaxHighlighter.css"></link>
+
+       <style>
+       /* @import url(SyntaxHighlighter.css); */
+
+       body {
+               font-family: Arial;
+               font-size: 12px;
+       }
+       </style>
+</head>
+
+<body bgcolor="#cecece">
+  
+<h3>Smart Tabs &amp; First Line</h3>
+  
+<textarea name="code" class="c#:firstline[42]">
+1      2       3       4       5       6       7       8       9
+string         path                    = "";
+string         safeReferrer    = null;
+FileInfo       fileInfo                = new FileInfo(string.Format("{0}/{1}", path, image));
+int                    index                   = 0;
+</textarea>
+  
+<h3>C Sharp</h3>
+  
+<textarea name="code" class="c#:collapse">
+// single line comments
+// second single line
+override protected void OnLoad(EventArgs e)
+{
+       if(Attributes["class"] != null)
+       {
+               //_year.CssClass = _month.CssClass = _day.CssClass = Attributes["class"];
+       }
+//     base.OnLoad(e);
+}
+
+/***********************************
+ ** Multiline block comments
+ **********************************/
+
+/// <summary>
+///            Gets or sets currently selected date of birth or <see cref="DateTime.MinValue"/> if selection is incomplete or invalid.
+/// </summary>
+public DateTime Date
+{
+       String stringWithUrl = "http://blog.dreamprojections.com";
+       
+       get
+       {
+               #region Hello world
+               try
+               {
+                       /*
+                       DateTime result = new DateTime(
+                               int.Parse(_year.SelectedItem.Value),
+                               int.Parse(_month.SelectedItem.Value),
+                               int.Parse(_day.SelectedItem.Value)
+                               );
+                       
+                       i *= 2;
+                       */
+                       return result;
+               }
+               catch
+               {
+                       /* return _minDate; */
+               }
+               #endregion
+       }
+       set
+       {
+               Day             = value.Day;
+               Month   = value.Month;
+               Year    = value.Year;
+       }
+}
+</textarea>
+  
+<h3>JavaScript</h3>
+  
+<textarea name="code" class="javascript">
+/***********************************
+ ** Multiline block comments
+ **********************************/
+
+var stringWithUrl1 = "http://blog.dreamprojections.com";
+var stringWithUrl2 = 'http://www.dreamprojections.com';
+
+// callback for the match sorting
+dpSyntaxHighlighter.prototype.SortCallback = function(m1, m2)
+{
+       // sort matches by index first
+       if(m1.index < m2.index)
+               return -1;
+       else if(m1.index > m2.index)
+               return 1;
+       else
+       {
+               /*
+               // if index is the same, sort by length
+               if(m1.length < m2.length)
+                       return -1;
+               else if(m1.length > m2.length)
+                       return 1;
+               */
+       }
+       
+       alert('hello // world');
+       return 0;
+}
+</textarea>
+  
+<h3>Visual Basic</h3>
+  
+<textarea name="code" class="vb">
+'
+' This is a VB test
+'
+
+Imports System.Collections
+
+Dim stringWithUrl = "http://blog.dreamprojections.com"
+
+Public Class MyVbClass
+    Private m_MyString As String
+
+    Public Sub New()
+        myString = "Hello there"
+    End Sub
+
+    Public Property MyString() As String
+        Get
+            Return m_MyString
+        End Get
+        Set(ByVal Value As String)
+            m_MyString = Value
+        End Set
+    End Property
+
+#Region "This is my region"
+    ' This is a comment
+    Public Function MyFunction( ByVal i as Integer ) As Double
+        MyFunction = 123.456
+    End Function
+#End Region
+End Class
+</textarea>
+  
+<h3>XML / HTML</h3>
+  
+<textarea name="code" class="xml">
+<?xml version="1.0" encoding="utf-8" ?> 
+
+<!-- comments -->
+<rootNode>
+       <childNodes>
+               <childNode attribute = "value" attribute='value' attribute=/>
+               <childNode />
+               <childNode />
+               <childNode />
+               <childNode attribute="value"></childNode>
+               <childNode>
+                       &lt;![CDATA[
+                               this is some CDATA content
+                               <!-- comments inside cdata -->
+                               <b alert='false'>tags inside cdata</b>
+                       ]]>
+               </childNode>
+       </childNodes>
+</rootNode>
+
+<!--
+  -- Multiline comments <b>tag</b>
+  -->
+</textarea>
+  
+<h3>PHP</h3>
+  
+<textarea name="code" class="php">
+/***********************************
+ ** Multiline block comments
+ **********************************/
+
+$stringWithUrl = "http://blog.dreamprojections.com";
+$stringWithUrl = 'http://www.dreamprojections.com';
+
+ob_start("parseOutputBuffer");         // Start Code Buffering
+session_start();
+
+function parseOutputBuffer($buf) {
+       global $portal_small_code, $portal_gzcompress;
+       global $PHP_SELF, $HTTP_ACCEPT_ENCODING;
+
+       // cleaning out the code.
+       if($portal_small_code && !$portal_gzcompress) {
+               $buf = str_replace("    ", "", $buf);
+               $buf = str_replace("\n", "", $buf);
+               $buf = str_replace(chr(13), "", $buf);
+       }
+}
+</textarea>
+  
+<h3>SQL</h3>
+  
+<textarea name="code" class="sql">
+SELECT TOP 10
+       FirstName,
+       LastName,
+       Email,
+       --SUBSTRING(Phone, 2, 3) AS CityCode,
+       SUBSTRING(Phone, 7, 8) AS PhoneNumber,
+       upper(LanguagePref) AS Language,
+       Address1,
+       UpdatedOn AS CreatedOn
+FROM
+       profiles
+WHERE
+       -- Exclude all test emails
+       Email NOT LIKE '%test%'
+       AND Email NOT LIKE '%asdf%'
+ORDER BY
+       UpdatedOn DESC
+</textarea>
+
+<h3>Delphi</h3>
+
+<textarea name="code" id="dd" class="delphi">
+{$IFDEF VER140}
+(***********************************
+ ** Multiline block comments
+ **********************************)
+procedure TForm1.Button1Click(Sender: TObject); var
+  Number, I, X: Integer;
+  Y: Integer;
+begin
+  str := 'http://blog.dreamprojections.com';
+
+  Number := 12356;
+  Caption := 'The Number is ' + IntToStr(Number);
+  for I := 0 to Number do
+  begin
+    Inc(X);
+       {
+    Dec(X);
+    X := X * 1.0;
+       }
+    Y := $F5D3;
+    ListBox1.Items.Add(IntToStr(X));
+       
+       (* 
+       ShowMessage('Hello'); *)
+  end;
+  asm
+    MOV AX,1234H
+//    MOV Number,AX
+  end;
+end;
+</textarea>
+
+<h3>Python</h3>
+
+<textarea name="code" class="python:nogutter:nocontrols">
+cache = {}
+
+string s = "## comments inside a string"
+
+def arrange(plans, lines, totalMinutes):
+    """arrangements of plans taken lines times with an heuristic that the sum
+       of values in one arrangement is less then totalMinutes
+    """
+    #if in cache we are done otherwise start calculating and save them to cache
+    if (plans, lines, totalMinutes) in cache:
+        return cache[(plans, lines, totalMinutes)]
+    if lines==1:
+        r = [[plan] for plan in plans]
+        cache[(plans, lines, totalMinutes)] = r
+        return r
+    solutions = []
+    for plan in plans:
+        for ar in sort(list(arrange(plans, lines-1, totalMinutes))):
+            try:
+                one_solution = tuple(sort([plan] + list(ar)))
+                if sum(one_solution) <= totalMinutes and one_solution not in solutions:
+                    solutions.append(one_solution)
+            except Exception, e:
+                print "Error:", str(e)
+    cache[(plans, lines, totalMinutes)] = solutions
+    return solutions
+
+if __name__ == "__main__":
+    import sys
+    lines, totalMinutes = int(sys.argv[1]), int(sys.argv[2])
+    plans = tuple([int(p) for p in sys.argv[3:]])
+    print "for", lines, totalMinutes, plans
+    for sol in arrange(plans, lines, totalMinutes):
+        print sol
+</textarea>
+  
+<h3>Auto Overflow Test</h3>
+  
+400px
+<div style="width: 400px; border-top: 2px solid black;">
+  
+<textarea id="Textarea1" name="code" class="xml">
+       // this is a long line that will stretch the whole box causing it to scroll horizontally.
+       if($portal_small_code && !$portal_gzcompress) {
+               $buf = str_replace("    ", "", $buf);
+               $buf = str_replace("\n", "", $buf);
+               $buf = str_replace(chr(13), "", $buf);
+       }
+</textarea>
+  
+</div>
+  
+</div>
+<script class="javascript" src="shCore.js"></script>
+<script class="javascript" src="shBrushCSharp.js"></script>
+<script class="javascript" src="shBrushPhp.js"></script>
+<script class="javascript" src="shBrushJScript.js"></script>
+<script class="javascript" src="shBrushVb.js"></script>
+<script class="javascript" src="shBrushSql.js"></script>
+<script class="javascript" src="shBrushXml.js"></script>
+<script class="javascript" src="shBrushDelphi.js"></script>
+<script class="javascript" src="shBrushPython.js"></script>
+<script class="javascript">
+dp.SyntaxHighlighter.HighlightAll('code');
+</script>
+
+</body>
+</html>
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js
new file mode 100644 (file)
index 0000000..5743b93
--- /dev/null
@@ -0,0 +1,30 @@
+dp.sh.Brushes.CSharp = function()
+{
+       var keywords =  'abstract as base bool break byte case catch char checked class const ' +
+                                       'continue decimal default delegate do double else enum event explicit ' +
+                                       'extern false finally fixed float for foreach get goto if implicit in int ' +
+                                       'interface internal is lock long namespace new null object operator out ' +
+                                       'override params private protected public readonly ref return sbyte sealed set ' +
+                                       'short sizeof stackalloc static string struct switch this throw true try ' +
+                                       'typeof uint ulong unchecked unsafe ushort using virtual void while';
+
+       this.regexList = [
+               // There's a slight problem with matching single line comments and figuring out
+               // a difference between // and ///. Using lookahead and lookbehind solves the
+               // problem, unfortunately JavaScript doesn't support lookbehind. So I'm at a 
+               // loss how to translate that regular expression to JavaScript compatible one.
+//             { regex: new RegExp('(?<!/)//(?!/).*$|(?<!/)////(?!/).*$|/\\*[^\\*]*(.)*?\\*/', 'gm'),  css: 'comment' },                       // one line comments starting with anything BUT '///' and multiline comments
+//             { regex: new RegExp('(?<!/)///(?!/).*$', 'gm'),                                                                                 css: 'comments' },              // XML comments starting with ///
+
+               { regex: new RegExp('//.*$', 'gm'),                                                     css: 'comment' },                       // one line comments
+               { regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),                         css: 'comment' },                       // multiline comments
+               { regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'),                         css: 'string' },                        // strings
+               { regex: new RegExp('^\\s*#.*', 'gm'),                                          css: 'preprocessor' },          // preprocessor tags like #region and #endregion
+               { regex: new RegExp(this.GetKeywords(keywords), 'gm'),          css: 'keyword' }                        // c# keyword
+               ];
+
+       this.CssClass = 'dp-c';
+}
+
+dp.sh.Brushes.CSharp.prototype = new dp.sh.Highlighter();
+dp.sh.Brushes.CSharp.Aliases   = ['c#', 'c-sharp', 'csharp'];
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushDelphi.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushDelphi.js
new file mode 100644 (file)
index 0000000..efb0601
--- /dev/null
@@ -0,0 +1,31 @@
+/* Delphi brush is contributed by Eddie Shipman */
+dp.sh.Brushes.Delphi = function()
+{
+       var keywords =  'abs addr and ansichar ansistring array as asm begin boolean byte cardinal ' +
+                                       'case char class comp const constructor currency destructor div do double ' +
+                                       'downto else end except exports extended false file finalization finally ' +
+                                       'for function goto if implementation in inherited int64 initialization ' +
+                                       'integer interface is label library longint longword mod nil not object ' +
+                                       'of on or packed pansichar pansistring pchar pcurrency pdatetime pextended ' + 
+                                       'pint64 pointer private procedure program property pshortstring pstring ' + 
+                                       'pvariant pwidechar pwidestring protected public published raise real real48 ' +
+                                       'record repeat set shl shortint shortstring shr single smallint string then ' +
+                                       'threadvar to true try type unit until uses val var varirnt while widechar ' +
+                                       'widestring with word write writeln xor';
+
+       this.regexList = [
+               { regex: new RegExp('\\(\\*[\\s\\S]*?\\*\\)', 'gm'),            css: 'comment' },                       // multiline comments (* *)
+               { regex: new RegExp('{(?!\\$)[\\s\\S]*?}', 'gm'),                       css: 'comment' },                       // multiline comments { }
+               { regex: new RegExp('//.*$', 'gm'),                                                     css: 'comment' },                       // one line
+               { regex: new RegExp('\'(?:\\.|[^\\\'\'])*\'', 'g'),                     css: 'string' },                        // strings
+               { regex: new RegExp('\\{\\$[a-zA-Z]+ .+\\}', 'g'),                      css: 'directive' },                     // Compiler Directives and Region tags
+               { regex: new RegExp('\\b[\\d\\.]+\\b', 'g'),                            css: 'number' },                        // numbers 12345
+               { regex: new RegExp('\\$[a-zA-Z0-9]+\\b', 'g'),                         css: 'number' },                        // numbers $F5D3
+               { regex: new RegExp(this.GetKeywords(keywords), 'gm'),          css: 'keyword' }                        // keyword
+               ];
+
+       this.CssClass = 'dp-delphi';
+}
+
+dp.sh.Brushes.Delphi.prototype = new dp.sh.Highlighter();
+dp.sh.Brushes.Delphi.Aliases   = ['delphi', 'pascal'];
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushJScript.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushJScript.js
new file mode 100644 (file)
index 0000000..2468f54
--- /dev/null
@@ -0,0 +1,22 @@
+dp.sh.Brushes.JScript = function()
+{
+       var keywords =  'abstract boolean break byte case catch char class const continue debugger ' +
+                                       'default delete do double else enum export extends false final finally float ' +
+                                       'for function goto if implements import in instanceof int interface long native ' +
+                                       'new null package private protected public return short static super switch ' +
+                                       'synchronized this throw throws transient true try typeof var void volatile while with';
+
+       this.regexList = [
+               { regex: new RegExp('//.*$', 'gm'),                                                     css: 'comment' },                       // one line comments
+               { regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),                         css: 'comment' },                       // multiline comments
+               { regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'),                        css: 'string' },                        // double quoted strings
+               { regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'),                        css: 'string' },                        // single quoted strings
+               { regex: new RegExp('^\\s*#.*', 'gm'),                                          css: 'preprocessor' },          // preprocessor tags like #region and #endregion
+               { regex: new RegExp(this.GetKeywords(keywords), 'gm'),          css: 'keyword' }                        // keywords
+               ];
+
+       this.CssClass = 'dp-c';
+}
+
+dp.sh.Brushes.JScript.prototype        = new dp.sh.Highlighter();
+dp.sh.Brushes.JScript.Aliases  = ['js', 'jscript', 'javascript'];
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js
new file mode 100644 (file)
index 0000000..f13df7e
--- /dev/null
@@ -0,0 +1,23 @@
+dp.sh.Brushes.Php = function()
+{
+       var keywords =  'and or xor __FILE__ __LINE__ array as break case ' +
+                                       'cfunction class const continue declare default die do echo else ' +
+                                       'elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exit ' +
+                                       'extends for foreach function global if include include_once isset list ' +
+                                       'new old_function print require require_once return static switch unset use ' +
+                                       'var while __FUNCTION__ __CLASS__';
+
+       this.regexList = [
+               { regex: new RegExp('//.*$', 'gm'),                                                     css: 'comment' },                       // one line comments
+               { regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),                         css: 'comment' },                       // multiline comments
+               { regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'),                        css: 'string' },                        // double quoted strings
+               { regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'),                        css: 'string' },                        // single quoted strings
+               { regex: new RegExp('\\$\\w+', 'g'),                                            css: 'vars' },                          // variables
+               { regex: new RegExp(this.GetKeywords(keywords), 'gm'),          css: 'keyword' }                        // keyword
+               ];
+
+       this.CssClass = 'dp-c';
+}
+
+dp.sh.Brushes.Php.prototype    = new dp.sh.Highlighter();
+dp.sh.Brushes.Php.Aliases      = ['php'];
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushPython.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushPython.js
new file mode 100644 (file)
index 0000000..96d2196
--- /dev/null
@@ -0,0 +1,71 @@
+/* Python 2.3 syntax contributed by Gheorghe Milas */
+dp.sh.Brushes.Python = function()
+{
+       var keywords =          'and assert break class continue def del elif else except exec ' +
+                                               'finally for from global if import in is lambda not or object pass print ' +
+                                               'raise return try yield while';
+       
+       var builtins =          'self __builtin__ __dict__ __future__ __methods__ __members__ __author__ __email__ __version__' +
+                                               '__class__ __bases__ __import__ __main__ __name__ __doc__ __self__ __debug__ __slots__ ' +
+                                               'abs append apply basestring bool buffer callable chr classmethod clear close cmp coerce compile complex ' +
+                                               'conjugate copy count delattr dict dir divmod enumerate Ellipsis eval execfile extend False file fileno filter float flush ' +
+                                               'get getattr globals has_key hasarttr hash hex id index input insert int intern isatty isinstance isubclass ' +
+                                               'items iter keys len list locals long map max min mode oct open ord pop pow property range ' +
+                                               'raw_input read readline readlines reduce reload remove repr reverse round seek setattr slice sum ' +
+                                               'staticmethod str super tell True truncate tuple type unichr unicode update values write writelines xrange zip';
+       
+       var magicmethods =      '__abs__ __add__ __and__ __call__ __cmp__ __coerce__ __complex__ __concat__ __contains__ __del__ __delattr__ __delitem__ ' +
+                                               '__delslice__ __div__ __divmod__ __float__ __getattr__ __getitem__ __getslice__ __hash__ __hex__ __eq__ __le__ __lt__ __gt__ __ge__ ' +
+                                               '__iadd__ __isub__ __imod__ __idiv__ __ipow__ __iand__ __ior__ __ixor__ __ilshift__ __irshift__ ' +
+                                               '__invert__ __init__ __int__ __inv__ __iter__ __len__ __long__ __lshift__ __mod__ __mul__ __new__ __neg__ __nonzero__ __oct__ __or__ ' +
+                                               '__pos__ __pow__ __radd__ __rand__ __rcmp__ __rdiv__ __rdivmod__ __repeat__ __repr__ __rlshift__ __rmod__ __rmul__ ' +
+                                               '__ror__ __rpow__ __rrshift__ __rshift__ __rsub__ __rxor__ __setattr__ __setitem__ __setslice__ __str__ __sub__ __xor__';
+       
+       var exceptions =        'Exception StandardError ArithmeticError LookupError EnvironmentError AssertionError AttributeError EOFError ' +
+                                               'FutureWarning IndentationError OverflowWarning PendingDeprecationWarning ReferenceError RuntimeWarning ' +
+                                               'SyntaxWarning TabError UnicodeDecodeError UnicodeEncodeError UnicodeTranslateError UserWarning Warning ' +
+                                               'IOError ImportError IndexError KeyError KeyboardInterrupt MemoryError NameError NotImplementedError OSError ' +
+                                               'RuntimeError StopIteration SyntaxError SystemError SystemExit TypeError UnboundLocalError UnicodeError ValueError ' +
+                                               'FloatingPointError OverflowError WindowsError ZeroDivisionError';
+       
+       var types =                     'NoneType TypeType IntType LongType FloatType ComplexType StringType UnicodeType BufferType TupleType ListType ' +
+                                               'DictType FunctionType LambdaType CodeType ClassType UnboundMethodType InstanceType MethodType BuiltinFunctionType BuiltinMethodType ' +
+                                               'ModuleType FileType XRangeType TracebackType FrameType SliceType EllipsisType';
+       
+       var commonlibs =        'anydbm array asynchat asyncore AST base64 binascii binhex bisect bsddb buildtools bz2 ' +
+                                               'BaseHTTPServer Bastion calendar cgi cmath cmd codecs codeop commands compiler copy copy_reg ' +
+                                               'cPickle crypt cStringIO csv curses Carbon CGIHTTPServer ConfigParser Cookie datetime dbhash ' +
+                                               'dbm difflib dircache distutils doctest DocXMLRPCServer email encodings errno exceptions fcntl ' +
+                                               'filecmp fileinput ftplib gc gdbm getopt getpass glob gopherlib gzip heapq htmlentitydefs ' +
+                                               'htmllib httplib HTMLParser imageop imaplib imgfile imghdr imp inspect itertools jpeg keyword ' +
+                                               'linecache locale logging mailbox mailcap marshal math md5 mhlib mimetools mimetypes mimify mmap ' +
+                                               'mpz multifile mutex MimeWriter netrc new nis nntplib nsremote operator optparse os parser pickle pipes ' +
+                                               'popen2 poplib posix posixfile pprint preferences profile pstats pwd pydoc pythonprefs quietconsole ' +
+                                               'quopri Queue random re readline resource rexec rfc822 rgbimg sched select sets sgmllib sha shelve shutil ' +
+                                               'signal site smtplib socket stat statcache string struct symbol sys syslog SimpleHTTPServer ' +
+                                               'SimpleXMLRPCServer SocketServer StringIO tabnanny tarfile telnetlib tempfile termios textwrap ' +
+                                               'thread threading time timeit token tokenize traceback tty types Tkinter unicodedata unittest ' +
+                                               'urllib urllib2 urlparse user UserDict UserList UserString warnings weakref webbrowser whichdb ' +
+                                               'xml xmllib xmlrpclib xreadlines zipfile zlib';
+
+       this.regexList = [
+               { regex: new RegExp('#.*$', 'gm'),                                                              css: 'comment' },                       // comments
+               { regex: new RegExp('^\\s*"""(.|\n)*?"""\\s*$', 'gm'),                  css: 'docstring' },                     // documentation string "
+               { regex: new RegExp('^\\s*\'\'\'(.|\n)*?\'\'\'\\s*$', 'gm'),    css: 'docstring' },                     // documentation string '
+               { regex: new RegExp('"""(.|\n)*?"""', 'g'),                                             css: 'string' },                        // multi-line strings "
+               { regex: new RegExp('\'\'\'(.|\n)*?\'\'\'', 'g'),                               css: 'string' },                        // multi-line strings '
+               { regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'),                                 css: 'string' },                        // strings "
+               { regex: new RegExp('\'(?:\\.|[^\\\'\'])*\'', 'g'),                             css: 'string' },                        // strings '
+               { regex: new RegExp(this.GetKeywords(keywords), 'gm'),                  css: 'keyword' },                       // keywords
+               { regex: new RegExp(this.GetKeywords(builtins), 'gm'),                  css: 'builtins' },                      // builtin objects, functions, methods, magic attributes
+               { regex: new RegExp(this.GetKeywords(magicmethods), 'gm'),              css: 'magicmethods' },          // special methods
+               { regex: new RegExp(this.GetKeywords(exceptions), 'gm'),                css: 'exceptions' },            // standard exception classes
+               { regex: new RegExp(this.GetKeywords(types), 'gm'),                             css: 'types' },                         // types from types.py
+               { regex: new RegExp(this.GetKeywords(commonlibs), 'gm'),                css: 'commonlibs' }                     // common standard library modules
+               ];
+
+       this.CssClass = 'dp-py';
+}
+
+dp.sh.Brushes.Python.prototype = new dp.sh.Highlighter();
+dp.sh.Brushes.Python.Aliases   = ['py', 'python'];
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushSql.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushSql.js
new file mode 100644 (file)
index 0000000..b52543e
--- /dev/null
@@ -0,0 +1,40 @@
+dp.sh.Brushes.Sql = function()
+{
+       var funcs       =       'abs avg case cast coalesce convert count current_timestamp ' +
+                                       'current_user day isnull left lower month nullif replace right ' +
+                                       'session_user space substring sum system_user upper user year';
+
+       var keywords =  'absolute action add after alter as asc at authorization begin bigint ' +
+                                       'binary bit by cascade char character check checkpoint close collate ' +
+                                       'column commit committed connect connection constraint contains continue ' +
+                                       'create cube current current_date current_time cursor database date ' +
+                                       'deallocate dec decimal declare default delete desc distinct double drop ' +
+                                       'dynamic else end end-exec escape except exec execute false fetch first ' +
+                                       'float for force foreign forward free from full function global goto grant ' +
+                                       'group grouping having hour ignore index inner insensitive insert instead ' +
+                                       'int integer intersect into is isolation key last level load local max min ' +
+                                       'minute modify move name national nchar next no numeric of off on only ' +
+                                       'open option order out output partial password precision prepare primary ' +
+                                       'prior privileges procedure public read real references relative repeatable ' +
+                                       'restrict return returns revoke rollback rollup rows rule schema scroll ' +
+                                       'second section select sequence serializable set size smallint static ' +
+                                       'statistics table temp temporary then time timestamp to top transaction ' +
+                                       'translation trigger true truncate uncommitted union unique update values ' +
+                                       'varchar varying view when where with work';
+
+       var operators = 'all and any between cross in join like not null or outer some';
+
+       this.regexList = [
+               { regex: new RegExp('--(.*)$', 'gm'),                                           css: 'comment' },                       // one line and multiline comments
+               { regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'),                         css: 'string' },                        // strings
+               { regex: new RegExp('\'(?:\\.|[^\\\'\'])*\'', 'g'),                     css: 'string' },                        // strings
+               { regex: new RegExp(this.GetKeywords(funcs), 'gmi'),            css: 'func' },                          // functions
+               { regex: new RegExp(this.GetKeywords(operators), 'gmi'),        css: 'op' },                            // operators and such
+               { regex: new RegExp(this.GetKeywords(keywords), 'gmi'),         css: 'keyword' }                        // keyword
+               ];
+
+       this.CssClass = 'dp-sql';
+}
+
+dp.sh.Brushes.Sql.prototype    = new dp.sh.Highlighter();
+dp.sh.Brushes.Sql.Aliases      = ['sql'];
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushVb.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushVb.js
new file mode 100644 (file)
index 0000000..197adcc
--- /dev/null
@@ -0,0 +1,29 @@
+dp.sh.Brushes.Vb = function()
+{
+       var keywords =  'AddHandler AddressOf AndAlso Alias And Ansi As Assembly Auto ' +
+                                       'Boolean ByRef Byte ByVal Call Case Catch CBool CByte CChar CDate ' +
+                                       'CDec CDbl Char CInt Class CLng CObj Const CShort CSng CStr CType ' +
+                                       'Date Decimal Declare Default Delegate Dim DirectCast Do Double Each ' +
+                                       'Else ElseIf End Enum Erase Error Event Exit False Finally For Friend ' +
+                                       'Function Get GetType GoSub GoTo Handles If Implements Imports In ' +
+                                       'Inherits Integer Interface Is Let Lib Like Long Loop Me Mod Module ' +
+                                       'MustInherit MustOverride MyBase MyClass Namespace New Next Not Nothing ' +
+                                       'NotInheritable NotOverridable Object On Option Optional Or OrElse ' +
+                                       'Overloads Overridable Overrides ParamArray Preserve Private Property ' +
+                                       'Protected Public RaiseEvent ReadOnly ReDim REM RemoveHandler Resume ' +
+                                       'Return Select Set Shadows Shared Short Single Static Step Stop String ' +
+                                       'Structure Sub SyncLock Then Throw To True Try TypeOf Unicode Until ' +
+                                       'Variant When While With WithEvents WriteOnly Xor';
+
+       this.regexList = [
+               { regex: new RegExp('\'.*$', 'gm'),                                                     css: 'comment' },                       // one line comments
+               { regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'),                         css: 'string' },                        // strings
+               { regex: new RegExp('^\\s*#.*', 'gm'),                                          css: 'preprocessor' },          // preprocessor tags like #region and #endregion
+               { regex: new RegExp(this.GetKeywords(keywords), 'gm'),          css: 'keyword' }                        // c# keyword
+               ];
+
+       this.CssClass = 'dp-vb';
+}
+
+dp.sh.Brushes.Vb.prototype     = new dp.sh.Highlighter();
+dp.sh.Brushes.Vb.Aliases       = ['vb', 'vb.net'];
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushXml.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shBrushXml.js
new file mode 100644 (file)
index 0000000..0286082
--- /dev/null
@@ -0,0 +1,61 @@
+dp.sh.Brushes.Xml = function()
+{
+       this.CssClass = 'dp-xml';
+}
+
+dp.sh.Brushes.Xml.prototype    = new dp.sh.Highlighter();
+dp.sh.Brushes.Xml.Aliases      = ['xml', 'xhtml', 'xslt', 'html', 'xhtml'];
+
+dp.sh.Brushes.Xml.prototype.ProcessRegexList = function()
+{
+       function push(array, value)
+       {
+               array[array.length] = value;
+       }
+       
+       /* If only there was a way to get index of a group within a match, the whole XML
+          could be matched with the expression looking something like that:
+       
+          (<!\[CDATA\[\s*.*\s*\]\]>)
+          | (<!--\s*.*\s*?-->)
+          | (<)*(\w+)*\s*(\w+)\s*=\s*(".*?"|'.*?'|\w+)(/*>)*
+          | (</?)(.*?)(/?>)
+       */
+       var index       = 0;
+       var match       = null;
+       var regex       = null;
+
+       // Match CDATA in the following format <![ ... [ ... ]]>
+       // <\!\[[\w\s]*?\[(.|\s)*?\]\]>
+       this.GetMatches(new RegExp('<\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\]>', 'gm'), 'cdata');
+       
+       // Match comments
+       // <!--\s*.*\s*?-->
+       this.GetMatches(new RegExp('<!--\\s*.*\\s*?-->', 'gm'), 'comments');
+
+       // Match attributes and their values
+       // (\w+)\s*=\s*(".*?"|\'.*?\'|\w+)*
+       regex = new RegExp('([\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\'|\\w+)*', 'gm');
+       while((match = regex.exec(this.code)) != null)
+       {
+               push(this.matches, new dp.sh.Match(match[1], match.index, 'attribute'));
+       
+               // if xml is invalid and attribute has no property value, ignore it     
+               if(match[2] != undefined)
+               {
+                       push(this.matches, new dp.sh.Match(match[2], match.index + match[0].indexOf(match[2]), 'attribute-value'));
+               }
+       }
+
+       // Match opening and closing tag brackets
+       // </*\?*(?!\!)|/*\?*>
+       this.GetMatches(new RegExp('</*\\?*(?!\\!)|/*\\?*>', 'gm'), 'tag');
+
+       // Match tag names
+       // </*\?*\s*(\w+)
+       regex = new RegExp('</*\\?*\\s*([\\w-\.]+)', 'gm');
+       while((match = regex.exec(this.code)) != null)
+       {
+               push(this.matches, new dp.sh.Match(match[1], match.index + match[0].indexOf(match[1]), 'tag-name'));
+       }
+}
diff --git a/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shCore.js b/mochikit_v14/examples/view-source/lib/SyntaxHighlighter/shCore.js
new file mode 100644 (file)
index 0000000..0e39125
--- /dev/null
@@ -0,0 +1,622 @@
+/**
+ * Code Syntax Highlighter.
+ * Version 1.3.0
+ * Copyright (C) 2004 Alex Gorbatchev.
+ * http://www.dreamprojections.com/syntaxhighlighter/
+ * 
+ * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General 
+ * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) 
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to 
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+//
+// create namespaces
+//
+var dp = {
+       sh :                                    // dp.sh
+       {
+               Utils   : {},           // dp.sh.Utils
+               Brushes : {},           // dp.sh.Brushes
+               Strings : {},
+               Version : '1.3.0'
+       }
+};
+
+dp.sh.Strings = {
+       AboutDialog : '<html><head><title>About...</title></head><body class="dp-about"><table cellspacing="0"><tr><td class="copy"><p class="title">dp.SyntaxHighlighter</div><div class="para">Version: {V}</p><p><a href="http://www.dreamprojections.com/syntaxhighlighter/?ref=about" target="_blank">http://www.dreamprojections.com/SyntaxHighlighter</a></p>&copy;2004-2005 Alex Gorbatchev. All right reserved.</td></tr><tr><td class="footer"><input type="button" class="close" value="OK" onClick="window.close()"/></td></tr></table></body></html>',
+       
+       // tools
+       ExpandCode : '+ expand code',
+       ViewPlain : 'view plain',
+       Print : 'print',
+       CopyToClipboard : 'copy to clipboard',
+       About : '?',
+       
+       CopiedToClipboard : 'The code is in your clipboard now.'
+};
+
+dp.SyntaxHighlighter = dp.sh;
+
+//
+// Dialog and toolbar functions
+//
+
+dp.sh.Utils.Expand = function(sender)
+{
+       var table = sender;
+       var span = sender;
+
+       // find the span in which the text label and pipe contained so we can hide it
+       while(span != null && span.tagName.toUpperCase() != 'SPAN')
+               span = span.parentNode;
+
+       // find the table
+       while(table != null && table.tagName.toUpperCase() != 'TABLE')
+               table = table.parentNode;
+       
+       // remove the 'expand code' button
+       span.parentNode.removeChild(span);
+       
+       table.tBodies[0].className = 'show';
+       table.parentNode.style.height = '100%'; // containing div isn't getting updated properly when the TBODY is shown
+}
+
+// opens a new windows and puts the original unformatted source code inside.
+dp.sh.Utils.ViewSource = function(sender)
+{
+       var code = sender.parentNode.originalCode;
+       var wnd = window.open('', '_blank', 'width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=1');
+       
+       code = code.replace(/</g, '&lt;');
+       
+       wnd.document.write('<pre>' + code + '</pre>');
+       wnd.document.close();
+}
+
+// copies the original source code in to the clipboard (IE only)
+dp.sh.Utils.ToClipboard = function(sender)
+{
+       var code = sender.parentNode.originalCode;
+       
+       // This works only for IE. There's a way to make it work with Mozilla as well,
+       // but it requires security settings changed on the client, which isn't by
+       // default, so 99% of users won't have it working anyways.
+       if(window.clipboardData)
+       {
+               window.clipboardData.setData('text', code);
+               
+               alert(dp.sh.Strings.CopiedToClipboard);
+       }
+}
+
+// creates an invisible iframe, puts the original source code inside and prints it
+dp.sh.Utils.PrintSource = function(sender)
+{
+       var td          = sender.parentNode;
+       var code        = td.processedCode;
+       var iframe      = document.createElement('IFRAME');
+       var doc         = null;
+       var wnd         = 
+
+       // this hides the iframe
+       iframe.style.cssText = 'position:absolute; width:0px; height:0px; left:-5px; top:-5px;';
+       
+       td.appendChild(iframe);
+       
+       doc = iframe.contentWindow.document;
+       code = code.replace(/</g, '&lt;');
+       
+       doc.open();
+       doc.write('<pre>' + code + '</pre>');
+       doc.close();
+       
+       iframe.contentWindow.focus();
+       iframe.contentWindow.print();
+       
+       td.removeChild(iframe);
+}
+
+dp.sh.Utils.About = function()
+{
+       var wnd = window.open('', '_blank', 'dialog,width=320,height=150,scrollbars=0');
+       var doc = wnd.document;
+       
+       var styles = document.getElementsByTagName('style');
+       var links = document.getElementsByTagName('link');
+       
+       doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version));
+       
+       // copy over ALL the styles from the parent page
+       for(var i = 0; i < styles.length; i++)
+               doc.write('<style>' + styles[i].innerHTML + '</style>');
+
+       for(var i = 0; i < links.length; i++)
+               if(links[i].rel.toLowerCase() == 'stylesheet')
+                       doc.write('<link type="text/css" rel="stylesheet" href="' + links[i].href + '"></link>');
+       
+       doc.close();
+       wnd.focus();
+}
+
+//
+// Match object
+//
+dp.sh.Match = function(value, index, css)
+{
+       this.value              = value;
+       this.index              = index;
+       this.length             = value.length;
+       this.css                = css;
+}
+
+//
+// Highlighter object
+//
+dp.sh.Highlighter = function()
+{
+       this.addGutter = true;
+       this.addControls = true;
+       this.collapse = false;
+       this.tabsToSpaces = true;
+}
+
+// static callback for the match sorting
+dp.sh.Highlighter.SortCallback = function(m1, m2)
+{
+       // sort matches by index first
+       if(m1.index < m2.index)
+               return -1;
+       else if(m1.index > m2.index)
+               return 1;
+       else
+       {
+               // if index is the same, sort by length
+               if(m1.length < m2.length)
+                       return -1;
+               else if(m1.length > m2.length)
+                       return 1;
+       }
+       return 0;
+}
+
+// gets a list of all matches for a given regular expression
+dp.sh.Highlighter.prototype.GetMatches = function(regex, css)
+{
+       var index = 0;
+       var match = null;
+
+       while((match = regex.exec(this.code)) != null)
+       {
+               this.matches[this.matches.length] = new dp.sh.Match(match[0], match.index, css);
+       }
+}
+
+dp.sh.Highlighter.prototype.AddBit = function(str, css)
+{
+       var span = document.createElement('span');
+       
+       str = str.replace(/&/g, '&amp;');
+       str = str.replace(/ /g, '&nbsp;');
+       str = str.replace(/</g, '&lt;');
+       str = str.replace(/\n/gm, '&nbsp;<br>');
+
+       // when adding a piece of code, check to see if it has line breaks in it 
+       // and if it does, wrap individual line breaks with span tags
+       if(css != null)
+       {
+               var regex = new RegExp('<br>', 'gi');
+               
+               if(regex.test(str))
+               {
+                       var lines = str.split('&nbsp;<br>');
+                       
+                       str = '';
+                       
+                       for(var i = 0; i < lines.length; i++)
+                       {
+                               span                    = document.createElement('SPAN');
+                               span.className  = css;
+                               span.innerHTML  = lines[i];
+                               
+                               this.div.appendChild(span);
+                               
+                               // don't add a <BR> for the last line
+                               if(i + 1 < lines.length)
+                                       this.div.appendChild(document.createElement('BR'));
+                       }
+               }
+               else
+               {
+                       span.className = css;
+                       span.innerHTML = str;
+                       this.div.appendChild(span);
+               }
+       }
+       else
+       {
+               span.innerHTML = str;
+               this.div.appendChild(span);
+       }
+}
+
+// checks if one match is inside any other match
+dp.sh.Highlighter.prototype.IsInside = function(match)
+{
+       if(match == null || match.length == 0)
+               return;
+       
+       for(var i = 0; i < this.matches.length; i++)
+       {
+               var c = this.matches[i];
+               
+               if(c == null)
+                       continue;
+               
+               if((match.index > c.index) && (match.index <= c.index + c.length))
+                       return true;
+       }
+       
+       return false;
+}
+
+dp.sh.Highlighter.prototype.ProcessRegexList = function()
+{
+       for(var i = 0; i < this.regexList.length; i++)
+               this.GetMatches(this.regexList[i].regex, this.regexList[i].css);
+}
+
+dp.sh.Highlighter.prototype.ProcessSmartTabs = function(code)
+{
+       var lines       = code.split('\n');
+       var result      = '';
+       var tabSize     = 4;
+       var tab         = '\t';
+
+       // This function inserts specified amount of spaces in the string
+       // where a tab is while removing that given tab. 
+       function InsertSpaces(line, pos, count)
+       {
+               var left        = line.substr(0, pos);
+               var right       = line.substr(pos + 1, line.length);    // pos + 1 will get rid of the tab
+               var spaces      = '';
+               
+               for(var i = 0; i < count; i++)
+                       spaces += ' ';
+               
+               return left + spaces + right;
+       }
+
+       // This function process one line for 'smart tabs'
+       function ProcessLine(line, tabSize)
+       {
+               if(line.indexOf(tab) == -1)
+                       return line;
+
+               var pos = 0;
+
+               while((pos = line.indexOf(tab)) != -1)
+               {
+                       // This is pretty much all there is to the 'smart tabs' logic.
+                       // Based on the position within the line and size of a tab, 
+                       // calculate the amount of spaces we need to insert.
+                       var spaces = tabSize - pos % tabSize;
+                       
+                       line = InsertSpaces(line, pos, spaces);
+               }
+               
+               return line;
+       }
+
+       // Go through all the lines and do the 'smart tabs' magic.
+       for(var i = 0; i < lines.length; i++)
+               result += ProcessLine(lines[i], tabSize) + '\n';
+       
+       return result;
+}
+
+dp.sh.Highlighter.prototype.SwitchToTable = function()
+{
+       // thanks to Lachlan Donald from SitePoint.com for this <br/> tag fix.
+       var html        = this.div.innerHTML.replace(/<(br)\/?>/gi, '\n');
+       var lines       = html.split('\n');
+       var row         = null;
+       var cell        = null;
+       var tBody       = null;
+       var html        = '';
+       var pipe        = ' | ';
+
+       // creates an anchor to a utility
+       function UtilHref(util, text)
+       {
+               return '<a href="#" onclick="dp.sh.Utils.' + util + '(this); return false;">' + text + '</a>';
+       }
+       
+       tBody = document.createElement('TBODY');        // can be created and all others go to tBodies collection.
+
+       this.table.appendChild(tBody);
+               
+       if(this.addGutter == true)
+       {
+               row = tBody.insertRow(-1);
+               cell = row.insertCell(-1);
+               cell.className = 'tools-corner';
+       }
+
+       if(this.addControls == true)
+       {
+               var tHead = document.createElement('THEAD');    // controls will be placed in here
+               this.table.appendChild(tHead);
+
+               row = tHead.insertRow(-1);
+
+               // add corner if there's a gutter
+               if(this.addGutter == true)
+               {
+                       cell = row.insertCell(-1);
+                       cell.className = 'tools-corner';
+               }
+               
+               cell = row.insertCell(-1);
+               
+               // preserve some variables for the controls
+               cell.originalCode = this.originalCode;
+               cell.processedCode = this.code;
+               cell.className = 'tools';
+               
+               if(this.collapse == true)
+               {
+                       tBody.className = 'hide';
+                       cell.innerHTML += '<span><b>' + UtilHref('Expand', dp.sh.Strings.ExpandCode) + '</b>' + pipe + '</span>';
+               }
+
+               cell.innerHTML += UtilHref('ViewSource', dp.sh.Strings.ViewPlain) + pipe + UtilHref('PrintSource', dp.sh.Strings.Print);
+               
+               // IE has this clipboard object which is easy enough to use
+               if(window.clipboardData)
+                       cell.innerHTML += pipe + UtilHref('ToClipboard', dp.sh.Strings.CopyToClipboard);
+               
+               cell.innerHTML += pipe + UtilHref('About', dp.sh.Strings.About);
+       }
+
+       for(var i = 0, lineIndex = this.firstLine; i < lines.length - 1; i++, lineIndex++)
+       {
+               row = tBody.insertRow(-1);
+               
+               if(this.addGutter == true)
+               {
+                       cell = row.insertCell(-1);
+                       cell.className = 'gutter';
+                       cell.innerHTML = lineIndex;
+               }
+
+               cell = row.insertCell(-1);
+               cell.className = 'line' + (i % 2 + 1);          // uses .line1 and .line2 css styles for alternating lines
+               cell.innerHTML = lines[i];
+       }
+       
+       this.div.innerHTML      = '';
+}
+
+dp.sh.Highlighter.prototype.Highlight = function(code)
+{
+       function Trim(str)
+       {
+               return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1');
+       }
+       
+       function Chop(str)
+       {
+               return str.replace(/\n*$/, '').replace(/^\n*/, '');
+       }
+
+       function Unindent(str)
+       {
+               var lines = str.split('\n');
+               var indents = new Array();
+               var regex = new RegExp('^\\s*', 'g');
+               var min = 1000;
+
+               // go through every line and check for common number of indents
+               for(var i = 0; i < lines.length && min > 0; i++)
+               {
+                       if(Trim(lines[i]).length == 0)
+                               continue;
+                               
+                       var matches = regex.exec(lines[i]);
+
+                       if(matches != null && matches.length > 0)
+                               min = Math.min(matches[0].length, min);
+               }
+
+               // trim minimum common number of white space from the begining of every line
+               if(min > 0)
+                       for(var i = 0; i < lines.length; i++)
+                               lines[i] = lines[i].substr(min);
+
+               return lines.join('\n');
+       }
+       
+       // This function returns a portions of the string from pos1 to pos2 inclusive
+       function Copy(string, pos1, pos2)
+       {
+               return string.substr(pos1, pos2 - pos1);
+       }
+
+       var pos = 0;
+       
+       this.originalCode = code;
+       this.code = Chop(Unindent(code));
+       this.div = document.createElement('DIV');
+       this.table = document.createElement('TABLE');
+       this.matches = new Array();
+
+       if(this.CssClass != null)
+               this.table.className = this.CssClass;
+
+       // replace tabs with spaces
+       if(this.tabsToSpaces == true)
+               this.code = this.ProcessSmartTabs(this.code);
+
+       this.table.border = 0;
+       this.table.cellSpacing = 0;
+       this.table.cellPadding = 0;
+
+       this.ProcessRegexList();        
+
+       // if no matches found, add entire code as plain text
+       if(this.matches.length == 0)
+       {
+               this.AddBit(this.code, null);
+               this.SwitchToTable();
+               return;
+       }
+
+       // sort the matches
+       this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback);
+
+       // The following loop checks to see if any of the matches are inside
+       // of other matches. This process would get rid of highligting strings
+       // inside comments, keywords inside strings and so on.
+       for(var i = 0; i < this.matches.length; i++)
+               if(this.IsInside(this.matches[i]))
+                       this.matches[i] = null;
+
+       // Finally, go through the final list of matches and pull the all
+       // together adding everything in between that isn't a match.
+       for(var i = 0; i < this.matches.length; i++)
+       {
+               var match = this.matches[i];
+
+               if(match == null || match.length == 0)
+                       continue;
+               
+               this.AddBit(Copy(this.code, pos, match.index), null);
+               this.AddBit(match.value, match.css);
+               
+               pos = match.index + match.length;
+       }
+       
+       this.AddBit(this.code.substr(pos), null);
+
+       this.SwitchToTable();
+}
+
+dp.sh.Highlighter.prototype.GetKeywords = function(str) 
+{
+       return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b';
+}
+
+// highlightes all elements identified by name and gets source code from specified property
+dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */)
+{
+       function FindValue()
+       {
+               var a = arguments;
+               
+               for(var i = 0; i < a.length; i++)
+               {
+                       if(a[i] == null)
+                               continue;
+                               
+                       if(typeof(a[i]) == 'string' && a[i] != '')
+                               return a[i] + '';
+               
+                       if(typeof(a[i]) == 'object' && a[i].value != '')
+                               return a[i].value + '';
+               }
+               
+               return null;
+       }
+       
+       function IsOptionSet(value, list)
+       {
+               for(var i = 0; i < list.length; i++)
+                       if(list[i] == value)
+                               return true;
+               
+               return false;
+       }
+       
+       function GetOptionValue(name, list, defaultValue)
+       {
+               var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi');
+               var matches = null;
+
+               for(var i = 0; i < list.length; i++)
+                       if((matches = regex.exec(list[i])) != null)
+                               return matches[1];
+               
+               return defaultValue;
+       }
+
+       var elements = document.getElementsByName(name);
+       var highlighter = null;
+       var registered = new Object();
+       var propertyName = 'value';
+       
+       // if no code blocks found, leave
+       if(elements == null)
+               return;
+
+       // register all brushes
+       for(var brush in dp.sh.Brushes)
+       {
+               var aliases = dp.sh.Brushes[brush].Aliases;
+               
+               if(aliases == null)
+                       continue;
+               
+               for(var i = 0; i < aliases.length; i++)
+                       registered[aliases[i]] = brush;
+       }
+
+       for(var i = 0; i < elements.length; i++)
+       {
+               var element = elements[i];
+               var options = FindValue(
+                               element.attributes['class'], element.className, 
+                               element.attributes['language'], element.language
+                               );
+               var language = '';
+               
+               if(options == null)
+                       continue;
+               
+               options = options.split(':');
+               
+               language = options[0].toLowerCase();
+               
+               if(registered[language] == null)
+                       continue;
+               
+               // instantiate a brush
+               highlighter = new dp.sh.Brushes[registered[language]]();
+               
+               // hide the original element
+               element.style.display = 'none';
+
+               highlighter.addGutter = (showGutter == null) ? !IsOptionSet('nogutter', options) : showGutter;
+               highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls;
+               highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll;
+               
+               // first line idea comes from Andrew Collington, thanks!
+               highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine;
+
+               highlighter.Highlight(element[propertyName]);
+
+               // place the result table inside a div
+               var div = document.createElement('DIV');
+               
+               div.className = 'dp-highlighter';
+               div.appendChild(highlighter.table);
+
+               element.parentNode.insertBefore(div, element);          
+       }       
+}
diff --git a/mochikit_v14/examples/view-source/view-source.css b/mochikit_v14/examples/view-source/view-source.css
new file mode 100755 (executable)
index 0000000..2a8b8cf
--- /dev/null
@@ -0,0 +1 @@
+.invisible {display: none;}
diff --git a/mochikit_v14/examples/view-source/view-source.html b/mochikit_v14/examples/view-source/view-source.html
new file mode 100644 (file)
index 0000000..951e937
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>MochiKit Example Source Viewer</title>
+        <script type="text/javascript" src="../../MochiKit/MochiKit.js"></script>
+        <link href="view-source.css" rel="stylesheet" type="text/css" />
+        <link href="lib/SyntaxHighlighter/SyntaxHighlighter.css" rel="stylesheet" type="text/css" />
+        <script type="text/javascript" src="view-source.js"></script>
+        <script type="text/javascript" src="lib/SyntaxHighlighter/shCore.js"></script>
+        <script type="text/javascript" src="lib/SyntaxHighlighter/shBrushJScript.js"></script>
+        <script type="text/javascript" src="lib/SyntaxHighlighter/shBrushXml.js"></script>
+    </head>
+    <body onload="viewSource();">
+        <h3 id="filename"></h3>
+        <div id="codeview" class="invisible">
+            <textarea name="code" id="code"></textarea>
+        </div>
+    </body>
+</html>
diff --git a/mochikit_v14/examples/view-source/view-source.js b/mochikit_v14/examples/view-source/view-source.js
new file mode 100644 (file)
index 0000000..259eda1
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+
+Do syntax highlighting on every textarea inside of a "codeview" element
+
+The content of textareas are URLs, not code!
+
+*/
+var viewSource = function () {
+    var filename = location.hash;
+    if (!filename) {
+        filename = location.hash = "view-source/view-source.js";
+    }
+    filename = lstrip(filename, "#");
+    var href = "../" + filename;
+    replaceChildNodes("filename", "loading ", A({"href": href}, filename));
+    replaceChildNodes("code", href);
+    ext = filename.split(".").pop();
+    var classes = {
+        "html": "xml",
+        "js": "javascript",
+        "json": "javascript",
+        "xml": "xml"
+    };
+    updateNodeAttributes("code", {"class": classes[ext]});
+    syntaxHighlight(filename);
+};
+
+var syntaxHighlight = function (filename) {
+    var swapContents = function (dest, req) {
+        replaceChildNodes(dest, req.responseText);
+    };
+
+    var showParsing = function () {
+        replaceChildNodes("filename",
+            "parsing ", 
+            A({"href": "../" + filename}, filename)
+        );
+        return wait(0);
+    };
+
+    var finishSyntaxHighlight = function () {
+        dp.sh.HighlightAll("code", true, true, false);
+        replaceChildNodes("filename", A({"href": "../" + filename}, filename));
+        removeElementClass("codeview", "invisible");
+    };
+
+    var elems = getElementsByTagAndClassName("textarea", null, "codeview");
+    var dl = new Deferred();
+    var deferredCount = 0;
+    var checkDeferredList = function () {
+        deferredCount -= 1;
+        if (!deferredCount) {
+            dl.callback();
+        }
+    };
+    for (var i = 0; i < elems.length; i++) {
+        var elem = elems[i];
+        if (elem.name != "code") {
+            continue;
+        }
+        var url = strip(scrapeText(elem))
+        var d = doXHR(url).addCallback(
+            partial(swapContents, elem)
+        );
+        deferredCount += 1;
+        d.addCallback(checkDeferredList);
+    }
+    dl.addCallback(showParsing);
+    dl.addCallback(finishSyntaxHighlight);
+};
diff --git a/mochikit_v14/include/_img/bg_docheader.gif b/mochikit_v14/include/_img/bg_docheader.gif
new file mode 100755 (executable)
index 0000000..7857a47
Binary files /dev/null and b/mochikit_v14/include/_img/bg_docheader.gif differ
diff --git a/mochikit_v14/include/_img/g_bullet.gif b/mochikit_v14/include/_img/g_bullet.gif
new file mode 100755 (executable)
index 0000000..e300cf2
Binary files /dev/null and b/mochikit_v14/include/_img/g_bullet.gif differ
diff --git a/mochikit_v14/include/_img/g_logo_doc.gif b/mochikit_v14/include/_img/g_logo_doc.gif
new file mode 100755 (executable)
index 0000000..b47e6cb
Binary files /dev/null and b/mochikit_v14/include/_img/g_logo_doc.gif differ
diff --git a/mochikit_v14/include/css/documentation.css b/mochikit_v14/include/css/documentation.css
new file mode 100755 (executable)
index 0000000..03ed1b9
--- /dev/null
@@ -0,0 +1,120 @@
+/**************************
+****      GENERAL      ****
+***************************/
+body {
+    font-size: 76%;
+    color: #5C5D5F;
+    margin: 0;
+    font-family:  Verdana, Helvetica, sans-serif;
+    background: url("../_img/bg_docheader.gif") repeat-x;
+}
+
+/* ---- TYPOGRAPHY ----------------------*/
+
+h1, h2, h3, h4, h5, h6 {
+    margin: 0;
+    color: #8ba726;
+    font-family: Trebuchet MS, verdana, sans-serif;
+}
+
+h1 { font-size: 2em; margin-bottom: .5em; border-bottom: 1px dotted #aaaaaa; }
+
+h1 em { color: #8ba726; font-style: normal; background: none; }
+
+h1 a { color: #8ba726; }
+h1 a:hover { background: none; border: none; color: #8ba726; }
+
+
+h2 { font-size: 1.4em; margin-bottom: .3em; font-weight: normal;  }
+h3 { font-size: 1.2em; }
+h4 { font-size: 1.1em; font-family:  Verdana, Helvetica, sans-serif; }
+
+a { color: #8ba726; }
+a:hover {
+    text-decoration: none;
+    background: #faffe9;
+    padding: .1;
+    border-bottom: 1px dotted #8ba726;
+}
+a.email {
+    background: url(../../images/icon_email.gif) no-repeat left center;
+    padding-left: 15px;
+}
+p a {  font-weight: bold; }
+p { line-height: 1.5em; margin: 0em 0em 1em; color: #5C5D5F;  }
+em { font-weight: bold; background-color: transparent; }
+
+ul, ol { line-height: 1.5em; }
+ul { list-style: none; margin: 0em 0em 1em 1.8em; padding: 0; }
+
+
+dl {  }
+dt { font-weight: bold; margin-bottom: .2em; color: #4B4545; }
+dd { margin-left: 2em; margin-bottom: 2em; }
+tt { font-size: 120%; }
+
+strong { color: #4b81bc; font-weight: bold; }
+.weak { font-size: .9em; font-weight: normal; }
+.contextual { font-size: .9em; color: #888; }
+
+div.document {
+    margin: 0em 20px 1em;
+    padding-top: 155px;
+    background: url(../_img/g_logo_doc.gif) no-repeat 0px 34px;
+    padding-left: 10px;
+}
+div.section { margin-bottom: 2em; }
+
+
+a.footnote-reference {
+    vertical-align: super;
+    font-size: 50%;
+    text-decoration: none;
+}
+
+pre.literal-block { 
+    padding: 5px;
+    font-size: 120%;
+    color: #1C1D1F; 
+    background: #f3f3f3;
+    padding: 1em 2em;
+    border-left: 3px solid #ccc;
+}
+
+ul.simple { list-style: none; margin: 0em 0em 1em 1.3em; padding: 0;  }
+ul.simple li {
+    background: url("../_img/g_bullet.gif") no-repeat left .5em;
+    padding-left: 12px;
+}
+
+tt { color: #1C1D1F; }
+table { border: 0px; }
+table th { border: 0px; border-bottom: 1px solid #aaaaaa; }
+table td { border: 0px; }
+table th, table td { padding: 3px; }
+
+.img { 
+    letter-spacing: -1000em;
+    text-indent : -999em;
+    overflow: hidden;
+    display: block;
+    background-repeat: repeat;
+    background-color: transparent;
+    /* IE FLICKER FIX - no background position! */
+}
+/* Just for Opera, but hide from MacIE */
+/*\*/html>body .img { letter-spacing : normal; text-indent : -999em; overflow : hidden;}
+/* End of hack */
+
+
+/* ---- GENERAL ELEMENTS ----------------*/
+
+hr {
+    border: none;
+    border-bottom: 1px solid #aaa;
+    background: none;
+    height: 1px;
+}
+a img { border: none; text-decoration: none; }
+.clear { clear: both; }
+.invisible { display: none; }
diff --git a/mochikit_v14/include/css/general.css b/mochikit_v14/include/css/general.css
new file mode 100755 (executable)
index 0000000..3269f41
--- /dev/null
@@ -0,0 +1,48 @@
+body { font-size: 76%; color: #5C5D5F; margin: 0; font-family:  Verdana, Helvetica, sans-serif; }
+
+/* ---- TYPOGRAPHY ----------------------*/
+
+h1, h2, h3, h4, h5, h6 { margin: 0; color: #4B81BC; font-family: Trebuchet MS, verdana, sans-serif; }
+h1 { font-size: 2em; margin-bottom: .5em; }
+h1 em { color: #00C5E8; font-style: normal; background: none; }
+
+h2 { font-size: 1.4em; margin-bottom: .3em; font-weight: normal; }
+h3 { font-size: 1.2em; }
+h4 { font-size: 1.1em; font-family:  Verdana, Helvetica, sans-serif; }
+
+a { color: #4b81bc; }
+a:hover { color: #abd038; }
+a.email { background: url(../../images/icon_email.gif) no-repeat left center; padding-left: 15px; }
+p a {  font-weight: bold; }
+p { line-height: 1.5em; margin: 0em 0em 1em; color: #5C5D5F;  }
+em { font-style: normal; background-color: #FFFDD4; }
+
+ul, ol { line-height: 1.5em; }
+ul { list-style: none; margin: 0em 0em 1em 1.8em; padding: 0; }
+
+dl {  }
+dt { font-weight: bold; margin-bottom: .2em; color: #4B4545; }
+dd { margin-left: 2em; margin-bottom: 2em; }
+tt { font-size: 120%; }
+
+strong { color: #4b81bc; font-weight: bold; }
+.weak { font-size: .9em; font-weight: normal; }
+.contextual { font-size: .9em; color: #888; }
+
+
+.img { 
+       letter-spacing: -1000em;  text-indent : -999em; overflow: hidden; display: block;
+       background-repeat: repeat; background-color: transparent; /* IE FLICKER FIX - no background position! */
+}
+/* Just for Opera, but hide from MacIE */
+/*\*/html>body .img { letter-spacing : normal; text-indent : -999em; overflow : hidden;}
+/* End of hack */
+
+
+/* ---- GENERAL ELEMENTS ----------------*/
+
+hr { border: none; border-bottom: 1px solid #aaa; background: none; height: 1px; }
+a img { border: none; }
+.clear { clear: both; }
+
+.invisible { display: none; }
diff --git a/mochikit_v14/packed/MochiKit/MochiKit.js b/mochikit_v14/packed/MochiKit/MochiKit.js
new file mode 100644 (file)
index 0000000..960b728
--- /dev/null
@@ -0,0 +1,6905 @@
+/***
+
+    MochiKit.MochiKit 1.4 : 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={};
+}
+if(typeof (MochiKit.__export__)=="undefined"){
+MochiKit.__export__=(MochiKit.__compat__||(typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined"));
+}
+MochiKit.Base.VERSION="1.4";
+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__();
+},camelize:function(_6){
+var _7=_6.split("-");
+var cc=_7[0];
+for(var i=1;i<_7.length;i++){
+cc+=_7[i].charAt(0).toUpperCase()+_7[i].substring(1);
+}
+return cc;
+},counter:function(n){
+if(arguments.length===0){
+n=1;
+}
+return function(){
+return n++;
+};
+},clone:function(_b){
+var me=arguments.callee;
+if(arguments.length==1){
+me.prototype=_b;
+return new me();
+}
+},_flattenArray:function(_d,_e){
+for(var i=0;i<_e.length;i++){
+var o=_e[i];
+if(o instanceof Array){
+arguments.callee(_d,o);
+}else{
+_d.push(o);
+}
+}
+return _d;
+},flattenArray:function(lst){
+return MochiKit.Base._flattenArray([],lst);
+},flattenArguments:function(lst){
+var res=[];
+var m=MochiKit.Base;
+var _15=m.extend(null,arguments);
+while(_15.length){
+var o=_15.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+for(var i=o.length-1;i>=0;i--){
+_15.unshift(o[i]);
+}
+}else{
+res.push(o);
+}
+}
+return res;
+},extend:function(_18,obj,_1a){
+if(!_1a){
+_1a=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(!_18){
+_18=[];
+}
+for(var i=_1a;i<l;i++){
+_18.push(obj[i]);
+}
+}
+return _18;
+},updatetree:function(_1d,obj){
+if(_1d===null){
+_1d={};
+}
+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 (_1d[k])=="object"&&typeof (v)=="object"){
+arguments.callee(_1d[k],v);
+}else{
+_1d[k]=v;
+}
+}
+}
+}
+return _1d;
+},setdefault:function(_23,obj){
+if(_23===null){
+_23={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+for(var k in o){
+if(!(k in _23)){
+_23[k]=o[k];
+}
+}
+}
+return _23;
+},keys:function(obj){
+var _29=[];
+for(var _2a in obj){
+_29.push(_2a);
+}
+return _29;
+},values:function(obj){
+var _2c=[];
+for(var _2d in obj){
+_2c.push(obj[_2d]);
+}
+return _2c;
+},items:function(obj){
+var _2f=[];
+var e;
+for(var _31 in obj){
+var v;
+try{
+v=obj[_31];
+}
+catch(e){
+continue;
+}
+_2f.push([_31,v]);
+}
+return _2f;
+},_newNamedError:function(_33,_34,_35){
+_35.prototype=new MochiKit.Base.NamedError(_33.NAME+"."+_34);
+_33[_34]=_35;
+},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;
+},seq:function(a,b){
+return a===b;
+},sne: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(_73){
+return function(){
+return this[_73].apply(this,arguments);
+};
+},itemgetter:function(_74){
+return function(arg){
+return arg[_74];
+};
+},typeMatcher:function(){
+var _76={};
+for(var i=0;i<arguments.length;i++){
+var typ=arguments[i];
+_76[typ]=typ;
+}
+return function(){
+for(var i=0;i<arguments.length;i++){
+if(!(typeof (arguments[i]) in _76)){
+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"||o.nodeType===3){
+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 _87=[];
+for(var i=1;i<arguments.length;i++){
+_87.push(fn(arguments[i]));
+}
+return _87;
+},map:function(fn,lst){
+var m=MochiKit.Base;
+var itr=MochiKit.Iter;
+var _8d=m.isArrayLike;
+if(arguments.length<=2){
+if(!_8d(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 _8e=[];
+for(var i=0;i<lst.length;i++){
+_8e.push(fn(lst[i]));
+}
+return _8e;
+}else{
+if(fn===null){
+fn=Array;
+}
+var _90=null;
+for(i=1;i<arguments.length;i++){
+if(!_8d(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(_90===null||_90>l){
+_90=l;
+}
+}
+_8e=[];
+for(i=0;i<_90;i++){
+var _92=[];
+for(var j=1;j<arguments.length;j++){
+_92.push(arguments[j][i]);
+}
+_8e.push(fn.apply(this,_92));
+}
+return _8e;
+}
+},xfilter:function(fn){
+var _95=[];
+if(fn===null){
+fn=MochiKit.Base.operator.truth;
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(fn(o)){
+_95.push(o);
+}
+}
+return _95;
+},filter:function(fn,lst,_9a){
+var _9b=[];
+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,_9a);
+}else{
+if(typeof (_9a)=="undefined"||_9a===null){
+for(var i=0;i<lst.length;i++){
+var o=lst[i];
+if(fn(o)){
+_9b.push(o);
+}
+}
+}else{
+for(i=0;i<lst.length;i++){
+o=lst[i];
+if(fn.call(_9a,o)){
+_9b.push(o);
+}
+}
+}
+}
+return _9b;
+},_wrapDumbFunction:function(_9f){
+return function(){
+switch(arguments.length){
+case 0:
+return _9f();
+case 1:
+return _9f(arguments[0]);
+case 2:
+return _9f(arguments[0],arguments[1]);
+case 3:
+return _9f(arguments[0],arguments[1],arguments[2]);
+}
+var _a0=[];
+for(var i=0;i<arguments.length;i++){
+_a0.push("arguments["+i+"]");
+}
+return eval("(func("+_a0.join(",")+"))");
+};
+},methodcaller:function(_a2){
+var _a3=MochiKit.Base.extend(null,arguments,1);
+if(typeof (_a2)=="function"){
+return function(obj){
+return _a2.apply(obj,_a3);
+};
+}else{
+return function(obj){
+return obj[_a2].apply(obj,_a3);
+};
+}
+},method:function(_a6,_a7){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([_a7,_a6],arguments,2));
+},compose:function(f1,f2){
+var _ab=[];
+var m=MochiKit.Base;
+if(arguments.length===0){
+throw new TypeError("compose() requires at least one argument");
+}
+for(var i=0;i<arguments.length;i++){
+var fn=arguments[i];
+if(typeof (fn)!="function"){
+throw new TypeError(m.repr(fn)+" is not a function");
+}
+_ab.push(fn);
+}
+return function(){
+var _af=arguments;
+for(var i=_ab.length-1;i>=0;i--){
+_af=[_ab[i].apply(this,_af)];
+}
+return _af[0];
+};
+},bind:function(_b1,_b2){
+if(typeof (_b1)=="string"){
+_b1=_b2[_b1];
+}
+var _b3=_b1.im_func;
+var _b4=_b1.im_preargs;
+var _b5=_b1.im_self;
+var m=MochiKit.Base;
+if(typeof (_b1)=="function"&&typeof (_b1.apply)=="undefined"){
+_b1=m._wrapDumbFunction(_b1);
+}
+if(typeof (_b3)!="function"){
+_b3=_b1;
+}
+if(typeof (_b2)!="undefined"){
+_b5=_b2;
+}
+if(typeof (_b4)=="undefined"){
+_b4=[];
+}else{
+_b4=_b4.slice();
+}
+m.extend(_b4,arguments,2);
+var _b7=function(){
+var _b8=arguments;
+var me=arguments.callee;
+if(me.im_preargs.length>0){
+_b8=m.concat(me.im_preargs,_b8);
+}
+var _ba=me.im_self;
+if(!_ba){
+_ba=this;
+}
+return me.im_func.apply(_ba,_b8);
+};
+_b7.im_self=_b5;
+_b7.im_func=_b3;
+_b7.im_preargs=_b4;
+return _b7;
+},bindMethods:function(_bb){
+var _bc=MochiKit.Base.bind;
+for(var k in _bb){
+var _be=_bb[k];
+if(typeof (_be)=="function"){
+_bb[k]=_bc(_be,_bb);
+}
+}
+},registerComparator:function(_bf,_c0,_c1,_c2){
+MochiKit.Base.comparatorRegistry.register(_bf,_c0,_c1,_c2);
+},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){
+if(a==b){
+return 0;
+}
+var _c5=(typeof (a)=="undefined"||a===null);
+var _c6=(typeof (b)=="undefined"||b===null);
+if(_c5&&_c6){
+return 0;
+}else{
+if(_c5){
+return -1;
+}else{
+if(_c6){
+return 1;
+}
+}
+}
+var m=MochiKit.Base;
+var _c8=m._primitives;
+if(!(typeof (a) in _c8&&typeof (b) in _c8)){
+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 _c9=m.repr;
+throw new TypeError(_c9(a)+" and "+_c9(b)+" can not be compared");
+},compareDateLike:function(a,b){
+return MochiKit.Base.compare(a.getTime(),b.getTime());
+},compareArrayLike:function(a,b){
+var _ce=MochiKit.Base.compare;
+var _cf=a.length;
+var _d0=0;
+if(_cf>b.length){
+_d0=1;
+_cf=b.length;
+}else{
+if(_cf<b.length){
+_d0=-1;
+}
+}
+for(var i=0;i<_cf;i++){
+var cmp=_ce(a[i],b[i]);
+if(cmp){
+return cmp;
+}
+}
+return _d0;
+},registerRepr:function(_d3,_d4,_d5,_d6){
+MochiKit.Base.reprRegistry.register(_d3,_d4,_d5,_d6);
+},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 _d8=(o+"");
+}
+catch(e){
+return "["+typeof (o)+"]";
+}
+if(typeof (o)=="function"){
+o=_d8.replace(/^\s+/,"");
+var idx=o.indexOf("{");
+if(idx!=-1){
+o=o.substr(0,idx)+"{...}";
+}
+}
+return _d8;
+},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(_de,_df,_e0,_e1){
+MochiKit.Base.jsonRegistry.register(_de,_df,_e0,_e1);
+},evalJSON:function(){
+return eval("("+arguments[0]+")");
+},serializeJSON:function(o){
+var _e3=typeof (o);
+if(_e3=="number"||_e3=="boolean"){
+return o+"";
+}else{
+if(o===null){
+return "null";
+}
+}
+var m=MochiKit.Base;
+var _e5=m.reprString;
+if(_e3=="string"){
+return _e5(o);
+}
+var me=arguments.callee;
+var _e7;
+if(typeof (o.__json__)=="function"){
+_e7=o.__json__();
+if(o!==_e7){
+return me(_e7);
+}
+}
+if(typeof (o.json)=="function"){
+_e7=o.json();
+if(o!==_e7){
+return me(_e7);
+}
+}
+if(_e3!="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{
+_e7=m.jsonRegistry.match(o);
+if(o!==_e7){
+return me(_e7);
+}
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+if(_e3=="undefined"){
+throw new TypeError("undefined can not be serialized as JSON");
+}
+if(_e3=="function"){
+return null;
+}
+res=[];
+for(var k in o){
+var _ec;
+if(typeof (k)=="number"){
+_ec="\""+k+"\"";
+}else{
+if(typeof (k)=="string"){
+_ec=_e5(k);
+}else{
+continue;
+}
+}
+val=me(o[k]);
+if(typeof (val)!="string"){
+continue;
+}
+res.push(_ec+":"+val);
+}
+return "{"+res.join(", ")+"}";
+},objEqual:function(a,b){
+return (MochiKit.Base.compare(a,b)===0);
+},arrayEqual:function(_ef,arr){
+if(_ef.length!=arr.length){
+return false;
+}
+return (MochiKit.Base.compare(_ef,arr)===0);
+},concat:function(){
+var _f1=[];
+var _f2=MochiKit.Base.extend;
+for(var i=0;i<arguments.length;i++){
+_f2(_f1,arguments[i]);
+}
+return _f1;
+},keyComparator:function(key){
+var m=MochiKit.Base;
+var _f6=m.compare;
+if(arguments.length==1){
+return function(a,b){
+return _f6(a[key],b[key]);
+};
+}
+var _f9=m.extend(null,arguments);
+return function(a,b){
+var _fc=0;
+for(var i=0;(_fc===0)&&(i<_f9.length);i++){
+var key=_f9[i];
+_fc=_f6(a[key],b[key]);
+}
+return _fc;
+};
+},reverseKeyComparator:function(key){
+var _100=MochiKit.Base.keyComparator.apply(this,arguments);
+return function(a,b){
+return _100(b,a);
+};
+},partial:function(func){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([func,undefined],arguments,1));
+},listMinMax:function(_105,lst){
+if(lst.length===0){
+return null;
+}
+var cur=lst[0];
+var _108=MochiKit.Base.compare;
+for(var i=1;i<lst.length;i++){
+var o=lst[i];
+if(_108(o,cur)==_105){
+cur=o;
+}
+}
+return cur;
+},objMax:function(){
+return MochiKit.Base.listMinMax(1,arguments);
+},objMin:function(){
+return MochiKit.Base.listMinMax(-1,arguments);
+},findIdentical:function(lst,_10c,_10d,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_10d)=="undefined"||_10d===null){
+_10d=0;
+}
+for(var i=_10d;i<end;i++){
+if(lst[i]===_10c){
+return i;
+}
+}
+return -1;
+},mean:function(){
+var sum=0;
+var m=MochiKit.Base;
+var args=m.extend(null,arguments);
+var _113=args.length;
+while(args.length){
+var o=args.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+_113+=o.length-1;
+for(var i=o.length-1;i>=0;i--){
+sum+=o[i];
+}
+}else{
+sum+=o;
+}
+}
+if(_113<=0){
+throw new TypeError("mean() requires at least one argument");
+}
+return sum/_113;
+},median:function(){
+var data=MochiKit.Base.flattenArguments(arguments);
+if(data.length===0){
+throw new TypeError("median() requires at least one argument");
+}
+data.sort(compare);
+if(data.length%2==0){
+var _117=data.length/2;
+return (data[_117]+data[_117-1])/2;
+}else{
+return data[(data.length-1)/2];
+}
+},findValue:function(lst,_119,_11a,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_11a)=="undefined"||_11a===null){
+_11a=0;
+}
+var cmp=MochiKit.Base.compare;
+for(var i=_11a;i<end;i++){
+if(cmp(lst[i],_119)===0){
+return i;
+}
+}
+return -1;
+},nodeWalk:function(node,_11f){
+var _120=[node];
+var _121=MochiKit.Base.extend;
+while(_120.length){
+var res=_11f(_120.shift());
+if(res){
+_121(_120,res);
+}
+}
+},nameFunctions:function(_123){
+var base=_123.NAME;
+if(typeof (base)=="undefined"){
+base="";
+}else{
+base=base+".";
+}
+for(var name in _123){
+var o=_123[name];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+name;
+}
+catch(e){
+}
+}
+}
+},queryString:function(_127,_128){
+if(typeof (MochiKit.DOM)!="undefined"&&arguments.length==1&&(typeof (_127)=="string"||(typeof (_127.nodeType)!="undefined"&&_127.nodeType>0))){
+var kv=MochiKit.DOM.formContents(_127);
+_127=kv[0];
+_128=kv[1];
+}else{
+if(arguments.length==1){
+if(typeof (_127.length)=="number"&&_127.length==2){
+return arguments.callee(_127[0],_127[1]);
+}
+var o=_127;
+_127=[];
+_128=[];
+for(var k in o){
+var v=o[k];
+if(typeof (v)=="function"){
+continue;
+}else{
+if(typeof (v)!="string"&&typeof (v.length)=="number"){
+for(var i=0;i<v.length;i++){
+_127.push(k);
+_128.push(v[i]);
+}
+}else{
+_127.push(k);
+_128.push(v);
+}
+}
+}
+}
+}
+var rval=[];
+var len=Math.min(_127.length,_128.length);
+var _130=MochiKit.Base.urlEncode;
+for(var i=0;i<len;i++){
+v=_128[i];
+if(typeof (v)!="undefined"&&v!==null){
+rval.push(_130(_127[i])+"="+_130(v));
+}
+}
+return rval.join("&");
+},parseQueryString:function(_131,_132){
+var qstr=(_131.charAt(0)=="?")?_131.substring(1):_131;
+var _134=qstr.replace(/\+/g,"%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
+var o={};
+var _136;
+if(typeof (decodeURIComponent)!="undefined"){
+_136=decodeURIComponent;
+}else{
+_136=unescape;
+}
+if(_132){
+for(var i=0;i<_134.length;i++){
+var pair=_134[i].split("=");
+var name=_136(pair.shift());
+if(!name){
+continue;
+}
+var arr=o[name];
+if(!(arr instanceof Array)){
+arr=[];
+o[name]=arr;
+}
+arr.push(_136(pair.join("=")));
+}
+}else{
+for(i=0;i<_134.length;i++){
+pair=_134[i].split("=");
+var name=pair.shift();
+if(!name){
+continue;
+}
+o[_136(name)]=_136(pair.join("="));
+}
+}
+return o;
+}});
+MochiKit.Base.AdapterRegistry=function(){
+this.pairs=[];
+};
+MochiKit.Base.AdapterRegistry.prototype={register:function(name,_13c,wrap,_13e){
+if(_13e){
+this.pairs.unshift([name,_13c,wrap]);
+}else{
+this.pairs.push([name,_13c,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=["flattenArray","noop","camelize","counter","clone","extend","update","updatetree","setdefault","keys","values","items","NamedError","operator","forwardCall","itemgetter","typeMatcher","isCallable","isUndefined","isUndefinedOrNull","isNull","isEmpty","isNotEmpty","isArrayLike","isDateLike","xmap","map","xfilter","filter","methodcaller","compose","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","average","mean","median"];
+MochiKit.Base.EXPORT_OK=["nameFunctions","comparatorRegistry","reprRegistry","jsonRegistry","compareDateLike","compareArrayLike","reprArrayLike","reprString","reprNumber"];
+MochiKit.Base._exportSymbols=function(_144,_145){
+if(!MochiKit.__export__){
+return;
+}
+var all=_145.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_144[all[i]]=_145[all[i]];
+}
+};
+MochiKit.Base.__new__=function(){
+var m=this;
+m.noop=m.operator.identity;
+m.forward=m.forwardCall;
+m.find=m.findValue;
+if(typeof (encodeURIComponent)!="undefined"){
+m.urlEncode=function(_149){
+return encodeURIComponent(_149).replace(/\'/g,"%27");
+};
+}else{
+m.urlEncode=function(_14a){
+return escape(_14a).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.average=m.mean;
+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.__export__){
+compare=MochiKit.Base.compare;
+compose=MochiKit.Base.compose;
+serializeJSON=MochiKit.Base.serializeJSON;
+}
+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.4";
+MochiKit.Base.update(MochiKit.Iter,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},registerIteratorFactory:function(name,_14e,_14f,_150){
+MochiKit.Iter.iteratorRegistry.register(name,_14e,_14f,_150);
+},iter:function(_151,_152){
+var self=MochiKit.Iter;
+if(arguments.length==2){
+return self.takewhile(function(a){
+return a!=_152;
+},_151);
+}
+if(typeof (_151.next)=="function"){
+return _151;
+}else{
+if(typeof (_151.iter)=="function"){
+return _151.iter();
+}
+}
+try{
+return self.iteratorRegistry.match(_151);
+}
+catch(e){
+var m=MochiKit.Base;
+if(e==m.NotFound){
+e=new TypeError(typeof (_151)+": "+m.repr(_151)+" 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 _15c=self.iter(p);
+return {repr:function(){
+return "cycle(...)";
+},toString:m.forwardCall("repr"),next:function(){
+try{
+var rval=_15c.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(_162){
+return _162.next();
+},izip:function(p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var next=self.next;
+var _168=m.map(self.iter,arguments);
+return {repr:function(){
+return "izip(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return m.map(next,_168);
+}};
+},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 _174=0;
+var stop=0;
+var step=1;
+var i=-1;
+if(arguments.length==2){
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_174=arguments[1];
+stop=arguments[2];
+}else{
+_174=arguments[1];
+stop=arguments[2];
+step=arguments[3];
+}
+}
+return {repr:function(){
+return "islice("+["...",_174,stop,step].join(", ")+")";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+while(i<_174){
+rval=seq.next();
+i++;
+}
+if(_174>=stop){
+throw self.StopIteration;
+}
+_174+=step;
+return rval;
+}};
+},imap:function(fun,p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var _17e=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,_17e));
+}};
+},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 _189=m.map(self.iter,arguments);
+return {repr:function(){
+return "chain(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(_189.length>1){
+try{
+return _189[0].next();
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+_189.shift();
+}
+}
+if(_189.length==1){
+var arg=_189.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(_194,sync,_196){
+sync.pos[_194]=-1;
+var m=MochiKit.Base;
+var _198=m.listMin;
+return {repr:function(){
+return "tee("+_194+", ...)";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+var i=sync.pos[_194];
+if(i==sync.max){
+rval=_196.next();
+sync.deque.push(rval);
+sync.max+=1;
+sync.pos[_194]+=1;
+}else{
+rval=sync.deque[i-sync.min];
+sync.pos[_194]+=1;
+if(i==sync.min&&_198(sync.pos)!=sync.min){
+sync.min+=1;
+sync.deque.shift();
+}
+}
+return rval;
+}};
+},tee:function(_19b,n){
+var rval=[];
+var sync={"pos":[],"deque":[],"max":-1,"min":-1};
+if(arguments.length==1||typeof (n)=="undefined"||n===null){
+n=2;
+}
+var self=MochiKit.Iter;
+_19b=self.iter(_19b);
+var _tee=self._tee;
+for(var i=0;i<n;i++){
+rval.push(_tee(i,sync,_19b));
+}
+return rval;
+},list:function(_1a2){
+var rval;
+if(_1a2 instanceof Array){
+return _1a2.slice();
+}
+if(typeof (_1a2)=="function"&&!(_1a2 instanceof Function)&&typeof (_1a2.length)=="number"){
+rval=[];
+for(var i=0;i<_1a2.length;i++){
+rval.push(_1a2[i]);
+}
+return rval;
+}
+var self=MochiKit.Iter;
+_1a2=self.iter(_1a2);
+var rval=[];
+try{
+while(true){
+rval.push(_1a2.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return rval;
+}
+return undefined;
+},reduce:function(fn,_1a7,_1a8){
+var i=0;
+var x=_1a8;
+var self=MochiKit.Iter;
+_1a7=self.iter(_1a7);
+if(arguments.length<3){
+try{
+x=_1a7.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,_1a7.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},range:function(){
+var _1ac=0;
+var stop=0;
+var step=1;
+if(arguments.length==1){
+stop=arguments[0];
+}else{
+if(arguments.length==2){
+_1ac=arguments[0];
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_1ac=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&&_1ac>=stop)||(step<0&&_1ac<=stop)){
+throw MochiKit.Iter.StopIteration;
+}
+var rval=_1ac;
+_1ac+=step;
+return rval;
+},repr:function(){
+return "range("+[_1ac,stop,step].join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+},sum:function(_1b0,_1b1){
+if(typeof (_1b1)=="undefined"||_1b1===null){
+_1b1=0;
+}
+var x=_1b1;
+var self=MochiKit.Iter;
+_1b0=self.iter(_1b0);
+try{
+while(true){
+x+=_1b0.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},exhaust:function(_1b4){
+var self=MochiKit.Iter;
+_1b4=self.iter(_1b4);
+try{
+while(true){
+_1b4.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+},forEach:function(_1b6,func,self){
+var m=MochiKit.Base;
+if(arguments.length>2){
+func=m.bind(func,self);
+}
+if(m.isArrayLike(_1b6)){
+try{
+for(var i=0;i<_1b6.length;i++){
+func(_1b6[i]);
+}
+}
+catch(e){
+if(e!=MochiKit.Iter.StopIteration){
+throw e;
+}
+}
+}else{
+self=MochiKit.Iter;
+self.exhaust(self.imap(func,_1b6));
+}
+},every:function(_1bb,func){
+var self=MochiKit.Iter;
+try{
+self.ifilterfalse(func,_1bb).next();
+return false;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return true;
+}
+},sorted:function(_1be,cmp){
+var rval=MochiKit.Iter.list(_1be);
+if(arguments.length==1){
+cmp=MochiKit.Base.compare;
+}
+rval.sort(cmp);
+return rval;
+},reversed:function(_1c1){
+var rval=MochiKit.Iter.list(_1c1);
+rval.reverse();
+return rval;
+},some:function(_1c3,func){
+var self=MochiKit.Iter;
+try{
+self.ifilter(func,_1c3).next();
+return true;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return false;
+}
+},iextend:function(lst,_1c7){
+if(MochiKit.Base.isArrayLike(_1c7)){
+for(var i=0;i<_1c7.length;i++){
+lst.push(_1c7[i]);
+}
+}else{
+var self=MochiKit.Iter;
+_1c7=self.iter(_1c7);
+try{
+while(true){
+lst.push(_1c7.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+}
+return lst;
+},groupby:function(_1ca,_1cb){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_1cb=m.operator.identity;
+}
+_1ca=self.iter(_1ca);
+var pk=undefined;
+var k=undefined;
+var v;
+function fetch(){
+v=_1ca.next();
+k=_1cb(v);
+}
+function eat(){
+var ret=v;
+v=undefined;
+return ret;
+}
+var _1d2=true;
+var _1d3=m.compare;
+return {repr:function(){
+return "groupby(...)";
+},next:function(){
+while(_1d3(k,pk)===0){
+fetch();
+if(_1d2){
+_1d2=false;
+break;
+}
+}
+pk=k;
+return [k,{next:function(){
+if(v==undefined){
+fetch();
+}
+if(_1d3(k,pk)!==0){
+throw self.StopIteration;
+}
+return eat();
+}}];
+}};
+},groupby_as_array:function(_1d4,_1d5){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_1d5=m.operator.identity;
+}
+_1d4=self.iter(_1d4);
+var _1d8=[];
+var _1d9=true;
+var _1da;
+var _1db=m.compare;
+while(true){
+try{
+var _1dc=_1d4.next();
+var key=_1d5(_1dc);
+}
+catch(e){
+if(e==self.StopIteration){
+break;
+}
+throw e;
+}
+if(_1d9||_1db(key,_1da)!==0){
+var _1de=[];
+_1d8.push([key,_1de]);
+}
+_1de.push(_1dc);
+_1d9=false;
+_1da=key;
+}
+return _1d8;
+},arrayLikeIter:function(_1df){
+var i=0;
+return {repr:function(){
+return "arrayLikeIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+if(i>=_1df.length){
+throw MochiKit.Iter.StopIteration;
+}
+return _1df[i++];
+}};
+},hasIterateNext:function(_1e1){
+return (_1e1&&typeof (_1e1.iterateNext)=="function");
+},iterateNextIter:function(_1e2){
+return {repr:function(){
+return "iterateNextIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=_1e2.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;
+if(typeof (StopIteration)!="undefined"){
+this.StopIteration=StopIteration;
+}else{
+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.__export__){
+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.4";
+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,_1e6,info){
+this.num=num;
+this.level=_1e6;
+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(_1e9){
+var self=MochiKit.Logging;
+if(typeof (_1e9)=="string"){
+_1e9=self.LogLevel[_1e9];
+}
+return function(msg){
+var _1ec=msg.level;
+if(typeof (_1ec)=="string"){
+_1ec=self.LogLevel[_1ec];
+}
+return _1ec>=_1e9;
+};
+},isLogMessage:function(){
+var _1ed=MochiKit.Logging.LogMessage;
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof _1ed)){
+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(_1f2){
+this.counter=0;
+if(typeof (_1f2)=="undefined"||_1f2===null){
+_1f2=-1;
+}
+this.maxSize=_1f2;
+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.replace(/%/g,"\uff05"));
+}else{
+if(typeof (opera)!="undefined"&&opera.postError){
+opera.postError(msg);
+}else{
+if(typeof (printfire)=="function"){
+printfire(msg);
+}else{
+if(typeof (Debug)!="undefined"&&Debug.writeln){
+Debug.writeln(msg);
+}else{
+if(typeof (debug)!="undefined"&&debug.trace){
+debug.trace(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(_1f7,_1f8,_1f9){
+if(typeof (_1f8)=="string"){
+_1f8=MochiKit.Logging.logLevelAtLeast(_1f8);
+}
+var _1fa=[_1f8,_1f9];
+_1fa.ident=_1f7;
+this.listeners[_1f7]=_1fa;
+},removeListener:function(_1fb){
+delete this.listeners[_1fb];
+},baseLog:function(_1fc,_1fd){
+var msg=new MochiKit.Logging.LogMessage(this.counter,_1fc,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(_1ff){
+var _200=0;
+if(!(typeof (_1ff)=="undefined"||_1ff===null)){
+_200=Math.max(0,this._messages.length-_1ff);
+}
+return this._messages.slice(_200);
+},getMessageText:function(_201){
+if(typeof (_201)=="undefined"||_201===null){
+_201=30;
+}
+var _202=this.getMessages(_201);
+if(_202.length){
+var lst=map(function(m){
+return "\n  ["+m.num+"] "+m.level+": "+m.info.join(" ");
+},_202);
+lst.unshift("LAST "+_202.length+" MESSAGES:");
+return lst.join("");
+}
+return "";
+},debuggingBookmarklet:function(_205){
+if(typeof (MochiKit.LoggingPane)=="undefined"){
+alert(this.getMessageText());
+}else{
+MochiKit.LoggingPane.createLoggingPane(_205||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 _207=m.partial;
+var _208=this.Logger;
+var _209=_208.prototype.baseLog;
+m.update(this.Logger.prototype,{debug:_207(_209,"DEBUG"),log:_207(_209,"INFO"),error:_207(_209,"ERROR"),fatal:_207(_209,"FATAL"),warning:_207(_209,"WARNING")});
+var self=this;
+var _20b=function(name){
+return function(){
+self.logger[name].apply(self.logger,arguments);
+};
+};
+this.log=_20b("log");
+this.logError=_20b("error");
+this.logDebug=_20b("debug");
+this.logFatal=_20b("fatal");
+this.logWarning=_20b("warning");
+this.logger=new _208();
+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.4";
+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,_213,day,hour,min,sec,msec;
+year=parseInt(res[1],10);
+if(typeof (res[2])=="undefined"||res[2]===""){
+return new Date(year);
+}
+_213=parseInt(res[2],10)-1;
+day=parseInt(res[3],10);
+if(typeof (res[4])=="undefined"||res[4]===""){
+return new Date(year,_213,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,_213,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,_213,day,hour,min,sec,msec)-ofs);
+};
+MochiKit.DateTime.toISOTime=function(date,_21b){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var hh=date.getHours();
+var mm=date.getMinutes();
+var ss=date.getSeconds();
+var lst=[((_21b&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];
+return lst.join(":");
+};
+MochiKit.DateTime.toISOTimestamp=function(date,_221){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var sep=_221?"T":" ";
+var foot=_221?"Z":"";
+if(_221){
+date=new Date(date.getTime()+(date.getTimezoneOffset()*60000));
+}
+return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_221)+foot;
+};
+MochiKit.DateTime.toISODate=function(date){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var _225=MochiKit.DateTime._padTwo;
+return [date.getFullYear(),_225(date.getMonth()+1),_225(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 _22a=MochiKit.DateTime._padTwo;
+return [_22a(d.getMonth()+1),_22a(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(_22f,_230){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_230.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_22f[all[i]]=_230[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.4";
+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,_23a,_23b){
+return function(num){
+num=parseFloat(num);
+if(typeof (num)=="undefined"||num===null||isNaN(num)){
+return _233;
+}
+var _23d=_234;
+var _23e=_235;
+if(num<0){
+num=-num;
+}else{
+_23d=_23d.replace(/-/,"");
+}
+var me=arguments.callee;
+var fmt=MochiKit.Format.formatLocale(_236);
+if(_237){
+num=num*100;
+_23e=fmt.percent+_23e;
+}
+num=MochiKit.Format.roundToFixed(num,_238);
+var _241=num.split(/\./);
+var _242=_241[0];
+var frac=(_241.length==1)?"":_241[1];
+var res="";
+while(_242.length<_239){
+_242="0"+_242;
+}
+if(_23a){
+while(_242.length>_23a){
+var i=_242.length-_23a;
+res=fmt.separator+_242.substring(i,_242.length)+res;
+_242=_242.substring(0,i);
+}
+}
+res=_242+res;
+if(_238>0){
+while(frac.length<_23b){
+frac=frac+"0";
+}
+res=res+fmt.decimal+frac;
+}
+return _23d+res+_23e;
+};
+};
+MochiKit.Format.numberFormatter=function(_246,_247,_248){
+if(typeof (_247)=="undefined"){
+_247="";
+}
+var _249=_246.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
+if(!_249){
+throw TypeError("Invalid pattern");
+}
+var _24a=_246.substr(0,_249.index);
+var _24b=_246.substr(_249.index+_249[0].length);
+if(_24a.search(/-/)==-1){
+_24a=_24a+"-";
+}
+var _24c=_249[1];
+var frac=(typeof (_249[2])=="string"&&_249[2]!="")?_249[2]:"";
+var _24e=(typeof (_249[3])=="string"&&_249[3]!="");
+var tmp=_24c.split(/,/);
+var _250;
+if(typeof (_248)=="undefined"){
+_248="default";
+}
+if(tmp.length==1){
+_250=null;
+}else{
+_250=tmp[1].length;
+}
+var _251=_24c.length-_24c.replace(/0/g,"").length;
+var _252=frac.length-frac.replace(/0/g,"").length;
+var _253=frac.length;
+var rval=MochiKit.Format._numberFormatter(_247,_24a,_24b,_248,_24e,_253,_251,_250,_252);
+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(_258){
+if(typeof (_258)=="undefined"||_258===null){
+_258="default";
+}
+if(typeof (_258)=="string"){
+var rval=MochiKit.Format.LOCALE[_258];
+if(typeof (rval)=="string"){
+rval=arguments.callee(rval);
+MochiKit.Format.LOCALE[_258]=rval;
+}
+return rval;
+}else{
+return _258;
+}
+};
+MochiKit.Format.twoDigitAverage=function(_25a,_25b){
+if(_25b){
+var res=_25a/_25b;
+if(!isNaN(res)){
+return MochiKit.Format.twoDigitFloat(_25a/_25b);
+}
+}
+return "0";
+};
+MochiKit.Format.twoDigitFloat=function(_25d){
+var sign=(_25d<0?"-":"");
+var s=Math.floor(Math.abs(_25d)*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,_263){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_263){
+return str.replace(/^\s+/,"");
+}else{
+return str.replace(new RegExp("^["+_263+"]+"),"");
+}
+};
+MochiKit.Format.rstrip=function(str,_265){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_265){
+return str.replace(/\s+$/,"");
+}else{
+return str.replace(new RegExp("["+_265+"]+$"),"");
+}
+};
+MochiKit.Format.strip=function(str,_267){
+var self=MochiKit.Format;
+return self.rstrip(self.lstrip(str,_267),_267);
+};
+MochiKit.Format.truncToFixed=function(_269,_26a){
+_269=Math.floor(_269*Math.pow(10,_26a));
+var res=(_269*Math.pow(10,-_26a)).toFixed(_26a);
+if(res.charAt(0)=="."){
+res="0"+res;
+}
+return res;
+};
+MochiKit.Format.roundToFixed=function(_26c,_26d){
+return MochiKit.Format.truncToFixed(_26c+0.5*Math.pow(10,-_26d),_26d);
+};
+MochiKit.Format.percentFormat=function(_26e){
+return MochiKit.Format.twoDigitFloat(100*_26e)+"%";
+};
+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(_273,_274){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_274.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_273[all[i]]=_274[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.4";
+MochiKit.Async.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Async.toString=function(){
+return this.__repr__();
+};
+MochiKit.Async.Deferred=function(_277){
+this.chain=[];
+this.id=this._nextId();
+this.fired=-1;
+this.paused=0;
+this.results=[null,null];
+this.canceller=_277;
+this.silentlyCancelled=false;
+this.chained=false;
+};
+MochiKit.Async.Deferred.prototype={repr:function(){
+var _278;
+if(this.fired==-1){
+_278="unfired";
+}else{
+if(this.fired===0){
+_278="success";
+}else{
+_278="error";
+}
+}
+return "Deferred("+this.id+", "+_278+")";
+},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();
+}
+}
+},_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 _283=this.chain;
+var _284=this.fired;
+var res=this.results[_284];
+var self=this;
+var cb=null;
+while(_283.length>0&&this.paused===0){
+var pair=_283.shift();
+var f=pair[_284];
+if(f===null){
+continue;
+}
+try{
+res=f(res);
+_284=((res instanceof Error)?1:0);
+if(res instanceof MochiKit.Async.Deferred){
+cb=function(res){
+self._resback(res);
+self.paused--;
+if((self.paused===0)&&(self.fired>=0)){
+self._fire();
+}
+};
+this.paused++;
+}
+}
+catch(err){
+_284=1;
+if(!(err instanceof Error)){
+err=new MochiKit.Async.GenericError(err);
+}
+res=err;
+}
+}
+this.fired=_284;
+this.results[_284]=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(_28b){
+var d=new MochiKit.Async.Deferred();
+d.callback.apply(d,arguments);
+return d;
+},fail:function(_28d){
+var d=new MochiKit.Async.Deferred();
+d.errback.apply(d,arguments);
+return d;
+},getXMLHttpRequest:function(){
+var self=arguments.callee;
+if(!self.XMLHttpRequest){
+var _290=[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<_290.length;i++){
+var func=_290[i];
+try{
+self.XMLHttpRequest=func;
+return func();
+}
+catch(e){
+}
+}
+}
+return self.XMLHttpRequest();
+},_xhr_onreadystatechange:function(d){
+var m=MochiKit.Base;
+if(this.readyState==4){
+try{
+this.onreadystatechange=null;
+}
+catch(e){
+try{
+this.onreadystatechange=m.noop;
+}
+catch(e){
+}
+}
+var _295=null;
+try{
+_295=this.status;
+if(!_295&&m.isNotEmpty(this.responseText)){
+_295=304;
+}
+}
+catch(e){
+}
+if(_295==200||_295==201||_295==204||_295==304||_295==1223){
+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.Base.noop;
+}
+catch(e){
+}
+}
+req.abort();
+},sendXMLHttpRequest:function(req,_299){
+if(typeof (_299)=="undefined"||_299===null){
+_299="";
+}
+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(_299);
+}
+catch(e){
+try{
+req.onreadystatechange=null;
+}
+catch(ignore){
+}
+d.errback(e);
+}
+return d;
+},doXHR:function(url,opts){
+var self=MochiKit.Async;
+return self.callLater(0,self._doXHR,url,opts);
+},_doXHR:function(url,opts){
+var m=MochiKit.Base;
+opts=m.update({method:"GET",sendContent:""},opts);
+var self=MochiKit.Async;
+var req=self.getXMLHttpRequest();
+if(opts.queryString){
+var qs=m.queryString(opts.queryString);
+if(qs){
+url+="?"+qs;
+}
+}
+if("username" in opts){
+req.open(opts.method,url,true,opts.username,opts.password);
+}else{
+req.open(opts.method,url,true);
+}
+if(req.overrideMimeType&&opts.mimeType){
+req.overrideMimeType(opts.mimeType);
+}
+if(opts.headers){
+var _2a6=opts.headers;
+if(!m.isArrayLike(_2a6)){
+_2a6=m.items(_2a6);
+}
+for(var i=0;i<_2a6.length;i++){
+var _2a8=_2a6[i];
+var name=_2a8[0];
+var _2aa=_2a8[1];
+req.setRequestHeader(name,_2aa);
+}
+}
+return self.sendXMLHttpRequest(req,opts.sendContent);
+},_buildURL:function(url){
+if(arguments.length>1){
+var m=MochiKit.Base;
+var qs=m.queryString.apply(null,m.extend(null,arguments,1));
+if(qs){
+return url+"?"+qs;
+}
+}
+return url;
+},doSimpleXMLHttpRequest:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+return self.doXHR(url);
+},loadJSONDoc:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+var d=self.doXHR(url,{"mimeType":"text/plain","headers":[["Accept","application/json"]]});
+d=d.addCallback(self.evalJSONRequest);
+return d;
+},wait:function(_2b3,_2b4){
+var d=new MochiKit.Async.Deferred();
+var m=MochiKit.Base;
+if(typeof (_2b4)!="undefined"){
+d.addCallback(function(){
+return _2b4;
+});
+}
+var _2b7=setTimeout(m.bind("callback",d),Math.floor(_2b3*1000));
+d.canceller=function(){
+try{
+clearTimeout(_2b7);
+}
+catch(e){
+}
+};
+return d;
+},callLater:function(_2b8,func){
+var m=MochiKit.Base;
+var _2bb=m.partial.apply(m,m.extend(null,arguments,1));
+return MochiKit.Async.wait(_2b8).addCallback(function(res){
+return _2bb();
+});
+}});
+MochiKit.Async.DeferredLock=function(){
+this.waiting=[];
+this.locked=false;
+this.id=this._nextId();
+};
+MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){
+var 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 _2be;
+if(this.locked){
+_2be="locked, "+this.waiting.length+" waiting";
+}else{
+_2be="unlocked";
+}
+return "DeferredLock("+this.id+", "+_2be+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Async.DeferredList=function(list,_2c0,_2c1,_2c2,_2c3){
+MochiKit.Async.Deferred.apply(this,[_2c3]);
+this.list=list;
+var _2c4=[];
+this.resultList=_2c4;
+this.finishedCount=0;
+this.fireOnOneCallback=_2c0;
+this.fireOnOneErrback=_2c1;
+this.consumeErrors=_2c2;
+var cb=MochiKit.Base.bind(this._cbDeferred,this);
+for(var i=0;i<list.length;i++){
+var d=list[i];
+_2c4.push(undefined);
+d.addCallback(cb,i,true);
+d.addErrback(cb,i,false);
+}
+if(list.length===0&&!_2c0){
+this.callback(this.resultList);
+}
+};
+MochiKit.Async.DeferredList.prototype=new MochiKit.Async.Deferred();
+MochiKit.Async.DeferredList.prototype._cbDeferred=function(_2c8,_2c9,_2ca){
+this.resultList[_2c8]=[_2c9,_2ca];
+this.finishedCount+=1;
+if(this.fired==-1){
+if(_2c9&&this.fireOnOneCallback){
+this.callback([_2c8,_2ca]);
+}else{
+if(!_2c9&&this.fireOnOneErrback){
+this.errback(_2ca);
+}else{
+if(this.finishedCount==this.list.length){
+this.callback(this.resultList);
+}
+}
+}
+}
+if(!_2c9&&this.consumeErrors){
+_2ca=null;
+}
+return _2ca;
+};
+MochiKit.Async.gatherResults=function(_2cb){
+var d=new MochiKit.Async.DeferredList(_2cb,false,true,false);
+d.addCallback(function(_2cd){
+var ret=[];
+for(var i=0;i<_2cd.length;i++){
+ret.push(_2cd[i][1]);
+}
+return ret;
+});
+return d;
+};
+MochiKit.Async.maybeDeferred=function(func){
+var self=MochiKit.Async;
+var _2d2;
+try{
+var r=func.apply(null,MochiKit.Base.extend([],arguments,1));
+if(r instanceof self.Deferred){
+_2d2=r;
+}else{
+if(r instanceof Error){
+_2d2=self.fail(r);
+}else{
+_2d2=self.succeed(r);
+}
+}
+}
+catch(e){
+_2d2=self.fail(e);
+}
+return _2d2;
+};
+MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred","doXHR"];
+MochiKit.Async.EXPORT_OK=["evalJSONRequest"];
+MochiKit.Async.__new__=function(){
+var m=MochiKit.Base;
+var ne=m.partial(m._newNamedError,this);
+ne("AlreadyCalledError",function(_2d6){
+this.deferred=_2d6;
+});
+ne("CancelledError",function(_2d7){
+this.deferred=_2d7;
+});
+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.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.DOM depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.DOM)=="undefined"){
+MochiKit.DOM={};
+}
+MochiKit.DOM.NAME="MochiKit.DOM";
+MochiKit.DOM.VERSION="1.4";
+MochiKit.DOM.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DOM.toString=function(){
+return this.__repr__();
+};
+MochiKit.DOM.EXPORT=["removeEmptyTextNodes","formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","isChildNode","getNodeAttribute","removeNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","insertSiblingNodesAfter","insertSiblingNodesBefore","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","$","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","escapeHTML","toHTML","emitHTML","scrapeText","isParent","getFirstParentByTagAndClassName","makeClipping","undoClipping","makePositioned","undoPositioned","getFirstElementByTagAndClassName"];
+MochiKit.DOM.EXPORT_OK=["domConverters"];
+MochiKit.DOM.DEPRECATED=[["computedStyle","MochiKit.Style.getStyle","1.4"],["elementDimensions","MochiKit.Style.getElementDimensions","1.4"],["elementPosition","MochiKit.Style.getElementPosition","1.4"],["hideElement","MochiKit.Style.hideElement","1.4"],["setElementDimensions","MochiKit.Style.setElementDimensions","1.4"],["setElementPosition","MochiKit.Style.setElementPosition","1.4"],["setDisplayForElement","MochiKit.Style.setDisplayForElement","1.4"],["setOpacity","MochiKit.Style.setOpacity","1.4"],["showElement","MochiKit.Style.showElement","1.4"],["Coordinates","MochiKit.Style.Coordinates","1.4"],["Dimensions","MochiKit.Style.Dimensions","1.4"]];
+MochiKit.DOM.getViewportDimensions=new Function(""+"if (!MochiKit[\"Style\"]) {"+"    throw new Error(\"This function has been deprecated and depends on MochiKit.Style.\");"+"}"+"return MochiKit.Style.getViewportDimensions.apply(this, arguments);");
+MochiKit.Base.update(MochiKit.DOM,{currentWindow:function(){
+return MochiKit.DOM._window;
+},currentDocument:function(){
+return MochiKit.DOM._document;
+},withWindow:function(win,func){
+var self=MochiKit.DOM;
+var _2df=self._document;
+var _2e0=self._window;
+var rval;
+try{
+self._window=win;
+self._document=win.document;
+rval=func();
+}
+catch(e){
+self._window=_2e0;
+self._document=_2df;
+throw e;
+}
+self._window=_2e0;
+self._document=_2df;
+return rval;
+},formContents:function(elem){
+var _2e3=[];
+var _2e4=[];
+var m=MochiKit.Base;
+var self=MochiKit.DOM;
+if(typeof (elem)=="undefined"||elem===null){
+elem=self._document.body;
+}else{
+elem=self.getElement(elem);
+}
+m.nodeWalk(elem,function(elem){
+var name=elem.name;
+if(m.isNotEmpty(name)){
+var _2e9=elem.tagName.toUpperCase();
+if(_2e9==="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){
+return null;
+}
+if(_2e9==="SELECT"){
+if(elem.type=="select-one"){
+if(elem.selectedIndex>=0){
+var opt=elem.options[elem.selectedIndex];
+var v=opt.value;
+if(!v){
+var h=opt.outerHTML;
+if(h&&!h.match(/^[^>]+\svalue\s*=/i)){
+v=opt.text;
+}
+}
+_2e3.push(name);
+_2e4.push(v);
+return null;
+}
+_2e3.push(name);
+_2e4.push("");
+return null;
+}else{
+var opts=elem.options;
+if(!opts.length){
+_2e3.push(name);
+_2e4.push("");
+return null;
+}
+for(var i=0;i<opts.length;i++){
+var opt=opts[i];
+if(!opt.selected){
+continue;
+}
+var v=opt.value;
+if(!v){
+var h=opt.outerHTML;
+if(h&&!h.match(/^[^>]+\svalue\s*=/i)){
+v=opt.text;
+}
+}
+_2e3.push(name);
+_2e4.push(v);
+}
+return null;
+}
+}
+if(_2e9==="FORM"||_2e9==="P"||_2e9==="SPAN"||_2e9==="DIV"){
+return elem.childNodes;
+}
+_2e3.push(name);
+_2e4.push(elem.value||"");
+return null;
+}
+return elem.childNodes;
+});
+return [_2e3,_2e4];
+},withDocument:function(doc,func){
+var self=MochiKit.DOM;
+var _2f2=self._document;
+var rval;
+try{
+self._document=doc;
+rval=func();
+}
+catch(e){
+self._document=_2f2;
+throw e;
+}
+self._document=_2f2;
+return rval;
+},registerDOMConverter:function(name,_2f5,wrap,_2f7){
+MochiKit.DOM.domConverters.register(name,_2f5,wrap,_2f7);
+},coerceToDOM:function(node,ctx){
+var m=MochiKit.Base;
+var im=MochiKit.Iter;
+var self=MochiKit.DOM;
+if(im){
+var iter=im.iter;
+var _2fe=im.repeat;
+var map=m.map;
+}
+var _300=self.domConverters;
+var _301=arguments.callee;
+var _302=m.NotFound;
+while(true){
+if(typeof (node)=="undefined"||node===null){
+return null;
+}
+if(typeof (node)=="function"&&typeof (node.length)=="number"&&!(node instanceof Function)){
+node=im.list(node);
+}
+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.__dom__)=="function"){
+node=node.__dom__(ctx);
+continue;
+}
+if(typeof (node.dom)=="function"){
+node=node.dom(ctx);
+continue;
+}
+if(typeof (node)=="function"){
+node=node.apply(ctx,[ctx]);
+continue;
+}
+if(im){
+var _303=null;
+try{
+_303=iter(node);
+}
+catch(e){
+}
+if(_303){
+return map(_301,_303,_2fe(ctx));
+}
+}
+try{
+node=_300.match(node,ctx);
+continue;
+}
+catch(e){
+if(e!=_302){
+throw e;
+}
+}
+return self._document.createTextNode(node.toString());
+}
+return undefined;
+},isChildNode:function(node,_305){
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+node=self.getElement(node);
+}
+if(typeof (_305)=="string"){
+_305=self.getElement(_305);
+}
+if(node===_305){
+return true;
+}
+while(node&&node.tagName.toUpperCase()!="BODY"){
+node=node.parentNode;
+if(node===_305){
+return true;
+}
+}
+return false;
+},setNodeAttribute:function(node,attr,_309){
+var o={};
+o[attr]=_309;
+try{
+return MochiKit.DOM.updateNodeAttributes(node,o);
+}
+catch(e){
+}
+return null;
+},getNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _30e=self.attributeArray.renames[attr];
+node=self.getElement(node);
+try{
+if(_30e){
+return node[_30e];
+}
+return node.getAttribute(attr);
+}
+catch(e){
+}
+return null;
+},removeNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _312=self.attributeArray.renames[attr];
+node=self.getElement(node);
+try{
+if(_312){
+return node[_312];
+}
+return node.removeAttribute(attr);
+}
+catch(e){
+}
+return null;
+},updateNodeAttributes:function(node,_314){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+if(_314){
+var _317=MochiKit.Base.updatetree;
+if(self.attributeArray.compliant){
+for(var k in _314){
+var v=_314[k];
+if(typeof (v)=="object"&&typeof (elem[k])=="object"){
+if(k=="style"&&MochiKit.Style){
+MochiKit.Style.setStyle(elem,v);
+}else{
+_317(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 _31a=self.attributeArray.renames;
+for(var k in _314){
+v=_314[k];
+var _31b=_31a[k];
+if(k=="style"&&typeof (v)=="string"){
+elem.style.cssText=v;
+}else{
+if(typeof (_31b)=="string"){
+elem[_31b]=v;
+}else{
+if(typeof (elem[k])=="object"&&typeof (v)=="object"){
+if(k=="style"&&MochiKit.Style){
+MochiKit.Style.setStyle(elem,v);
+}else{
+_317(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 _31f=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _320=MochiKit.Base.concat;
+while(_31f.length){
+var n=_31f.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+elem.appendChild(n);
+}else{
+_31f=_320(n,_31f);
+}
+}
+}
+return elem;
+},insertSiblingNodesBefore:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _325=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _326=elem.parentNode;
+var _327=MochiKit.Base.concat;
+while(_325.length){
+var n=_325.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+_326.insertBefore(n,elem);
+}else{
+_325=_327(n,_325);
+}
+}
+}
+return _326;
+},insertSiblingNodesAfter:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _32c=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+if(elem.nextSibling){
+return self.insertSiblingNodesBefore(elem.nextSibling,_32c);
+}else{
+return self.appendChildNodes(elem.parentNode,_32c);
+}
+},replaceChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+arguments[0]=elem;
+}
+var _330;
+while((_330=elem.firstChild)){
+elem.removeChild(_330);
+}
+if(arguments.length<2){
+return elem;
+}else{
+return self.appendChildNodes.apply(this,arguments);
+}
+},createDOM:function(name,_332){
+var elem;
+var self=MochiKit.DOM;
+var m=MochiKit.Base;
+if(typeof (_332)=="string"||typeof (_332)=="number"){
+var args=m.extend([name,null],arguments,1);
+return arguments.callee.apply(this,args);
+}
+if(typeof (name)=="string"){
+var _337=self._xhtml;
+if(_332&&!self.attributeArray.compliant){
+var _338="";
+if("name" in _332){
+_338+=" name=\""+self.escapeHTML(_332.name)+"\"";
+}
+if(name=="input"&&"type" in _332){
+_338+=" type=\""+self.escapeHTML(_332.type)+"\"";
+}
+if(_338){
+name="<"+name+_338+">";
+_337=false;
+}
+}
+var d=self._document;
+if(_337&&d===document){
+elem=d.createElementNS("http://www.w3.org/1999/xhtml",name);
+}else{
+elem=d.createElement(name);
+}
+}else{
+elem=name;
+}
+if(_332){
+self.updateNodeAttributes(elem,_332);
+}
+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));
+},removeElement:function(elem){
+var e=MochiKit.DOM.getElement(elem);
+e.parentNode.removeChild(e);
+return e;
+},swapDOM:function(dest,src){
+var self=MochiKit.DOM;
+dest=self.getElement(dest);
+var _340=dest.parentNode;
+if(src){
+src=self.getElement(src);
+_340.replaceChild(src,dest);
+}else{
+_340.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);
+}
+},getElementsByTagAndClassName:function(_343,_344,_345){
+var self=MochiKit.DOM;
+if(typeof (_343)=="undefined"||_343===null){
+_343="*";
+}
+if(typeof (_345)=="undefined"||_345===null){
+_345=self._document;
+}
+_345=self.getElement(_345);
+var _347=(_345.getElementsByTagName(_343)||self._document.all);
+if(typeof (_344)=="undefined"||_344===null){
+return MochiKit.Base.extend(null,_347);
+}
+var _348=[];
+for(var i=0;i<_347.length;i++){
+var _34a=_347[i];
+var cls=_34a.className;
+if(!cls){
+continue;
+}
+var _34c=cls.split(" ");
+for(var j=0;j<_34c.length;j++){
+if(_34c[j]==_344){
+_348.push(_34a);
+break;
+}
+}
+}
+return _348;
+},_newCallStack:function(path,once){
+var rval=function(){
+var _351=arguments.callee.callStack;
+for(var i=0;i<_351.length;i++){
+if(_351[i].apply(this,arguments)===false){
+break;
+}
+}
+if(once){
+try{
+this[path]=null;
+}
+catch(e){
+}
+}
+};
+rval.callStack=[];
+return rval;
+},addToCallStack:function(_353,path,func,once){
+var self=MochiKit.DOM;
+var _358=_353[path];
+var _359=_358;
+if(!(typeof (_358)=="function"&&typeof (_358.callStack)=="object"&&_358.callStack!==null)){
+_359=self._newCallStack(path,once);
+if(typeof (_358)=="function"){
+_359.callStack.push(_358);
+}
+_353[path]=_359;
+}
+_359.callStack.push(func);
+},addLoadEvent:function(func){
+var self=MochiKit.DOM;
+self.addToCallStack(self._window,"onload",func,true);
+},focusOnLoad:function(_35c){
+var self=MochiKit.DOM;
+self.addLoadEvent(function(){
+_35c=self.getElement(_35c);
+if(_35c){
+_35c.focus();
+}
+});
+},setElementClass:function(_35e,_35f){
+var self=MochiKit.DOM;
+var obj=self.getElement(_35e);
+if(self.attributeArray.compliant){
+obj.setAttribute("class",_35f);
+}else{
+obj.setAttribute("className",_35f);
+}
+},toggleElementClass:function(_362){
+var self=MochiKit.DOM;
+for(var i=1;i<arguments.length;i++){
+var obj=self.getElement(arguments[i]);
+if(!self.addElementClass(obj,_362)){
+self.removeElementClass(obj,_362);
+}
+}
+},addElementClass:function(_366,_367){
+var self=MochiKit.DOM;
+var obj=self.getElement(_366);
+var cls=obj.className;
+if(cls==undefined||cls.length===0){
+self.setElementClass(obj,_367);
+return true;
+}
+if(cls==_367){
+return false;
+}
+var _36b=cls.split(" ");
+for(var i=0;i<_36b.length;i++){
+if(_36b[i]==_367){
+return false;
+}
+}
+self.setElementClass(obj,cls+" "+_367);
+return true;
+},removeElementClass:function(_36d,_36e){
+var self=MochiKit.DOM;
+var obj=self.getElement(_36d);
+var cls=obj.className;
+if(cls==undefined||cls.length===0){
+return false;
+}
+if(cls==_36e){
+self.setElementClass(obj,"");
+return true;
+}
+var _372=cls.split(" ");
+for(var i=0;i<_372.length;i++){
+if(_372[i]==_36e){
+_372.splice(i,1);
+self.setElementClass(obj,_372.join(" "));
+return true;
+}
+}
+return false;
+},swapElementClass:function(_374,_375,_376){
+var obj=MochiKit.DOM.getElement(_374);
+var res=MochiKit.DOM.removeElementClass(obj,_375);
+if(res){
+MochiKit.DOM.addElementClass(obj,_376);
+}
+return res;
+},hasElementClass:function(_379,_37a){
+var obj=MochiKit.DOM.getElement(_379);
+var cls=obj.className;
+if(!cls){
+return false;
+}
+var _37d=cls.split(" ");
+for(var i=1;i<arguments.length;i++){
+var good=false;
+for(var j=0;j<_37d.length;j++){
+if(_37d[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 _385=[dom];
+var self=MochiKit.DOM;
+var _387=self.escapeHTML;
+var _388=self.attributeArray;
+while(_385.length){
+dom=_385.pop();
+if(typeof (dom)=="string"){
+lst.push(dom);
+}else{
+if(dom.nodeType==1){
+lst.push("<"+dom.tagName.toLowerCase());
+var _389=[];
+var _38a=_388(dom);
+for(var i=0;i<_38a.length;i++){
+var a=_38a[i];
+_389.push([" ",a.name,"=\"",_387(a.value),"\""]);
+}
+_389.sort();
+for(i=0;i<_389.length;i++){
+var _38d=_389[i];
+for(var j=0;j<_38d.length;j++){
+lst.push(_38d[j]);
+}
+}
+if(dom.hasChildNodes()){
+lst.push(">");
+_385.push("</"+dom.tagName.toLowerCase()+">");
+var _38f=dom.childNodes;
+for(i=_38f.length-1;i>=0;i--){
+_385.push(_38f[i]);
+}
+}else{
+lst.push("/>");
+}
+}else{
+if(dom.nodeType==3){
+lst.push(_387(dom.nodeValue));
+}
+}
+}
+}
+return lst;
+},scrapeText:function(node,_391){
+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 _396=node.nodeValue;
+if(typeof (_396)=="string"){
+rval.push(_396);
+}
+})(MochiKit.DOM.getElement(node));
+if(_391){
+return rval;
+}else{
+return rval.join("");
+}
+},removeEmptyTextNodes:function(_397){
+_397=MochiKit.DOM.getElement(_397);
+for(var i=0;i<_397.childNodes.length;i++){
+var node=_397.childNodes[i];
+if(node.nodeType==3&&!/\S/.test(node.nodeValue)){
+node.parentNode.removeChild(node);
+}
+}
+},makeClipping:function(_39a){
+_39a=MochiKit.DOM.getElement(_39a);
+var _39b=_39a.style.overflow;
+if((MochiKit.Style.getStyle(_39a,"overflow")||"visible")!="hidden"){
+_39a.style.overflow="hidden";
+}
+return _39b;
+},undoClipping:function(_39c,_39d){
+_39c=MochiKit.DOM.getElement(_39c);
+if(!_39d){
+return;
+}
+_39c.style.overflow=_39d;
+},makePositioned:function(_39e){
+_39e=MochiKit.DOM.getElement(_39e);
+var pos=MochiKit.Style.getStyle(_39e,"position");
+if(pos=="static"||!pos){
+_39e.style.position="relative";
+if(/Opera/.test(navigator.userAgent)){
+_39e.style.top=0;
+_39e.style.left=0;
+}
+}
+},undoPositioned:function(_3a0){
+_3a0=MochiKit.DOM.getElement(_3a0);
+if(_3a0.style.position=="relative"){
+_3a0.style.position=_3a0.style.top=_3a0.style.left=_3a0.style.bottom=_3a0.style.right="";
+}
+},getFirstElementByTagAndClassName:function(_3a1,_3a2,_3a3){
+var self=MochiKit.DOM;
+if(typeof (_3a1)=="undefined"||_3a1===null){
+_3a1="*";
+}
+if(typeof (_3a3)=="undefined"||_3a3===null){
+_3a3=self._document;
+}
+_3a3=self.getElement(_3a3);
+var _3a5=(_3a3.getElementsByTagName(_3a1)||self._document.all);
+if(typeof (_3a2)=="undefined"||_3a2===null){
+return _3a5[0];
+}
+for(var i=0;i<_3a5.length;i++){
+var _3a7=_3a5[i];
+var _3a8=_3a7.className.split(" ");
+for(var j=0;j<_3a8.length;j++){
+if(_3a8[j]==_3a2){
+return _3a7;
+}
+}
+}
+},getFirstParentByTagAndClassName:function(elem,_3ab,_3ac){
+var self=MochiKit.DOM;
+elem=self.getElement(elem);
+if(typeof (_3ab)=="undefined"||_3ab===null){
+_3ab="*";
+}else{
+_3ab=_3ab.toUpperCase();
+}
+if(typeof (_3ac)=="undefined"||_3ac===null){
+_3ac=null;
+}
+var _3ae="";
+var _3af="";
+while(elem&&elem.tagName){
+elem=elem.parentNode;
+if(_3ab=="*"&&_3ac===null){
+return elem;
+}
+_3ae=elem.className.split(" ");
+_3af=elem.tagName.toUpperCase();
+if(_3ac===null&&_3ab==_3af){
+return elem;
+}else{
+if(_3ac!==null){
+for(var i=0;i<_3ae.length;i++){
+if(_3ab=="*"&&_3ae[i]==_3ac){
+return elem;
+}else{
+if(_3ab==_3af&&_3ae[i]==_3ac){
+return elem;
+}
+}
+}
+}
+}
+}
+return elem;
+},isParent:function(_3b1,_3b2){
+if(!_3b1.parentNode||_3b1==_3b2){
+return false;
+}
+if(_3b1.parentNode==_3b2){
+return true;
+}
+return MochiKit.DOM.isParent(_3b1.parentNode,_3b2);
+},__new__:function(win){
+var m=MochiKit.Base;
+if(typeof (document)!="undefined"){
+this._document=document;
+var _3b5="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+this._xhtml=(document.documentElement&&document.createElementNS&&document.documentElement.namespaceURI===_3b5);
+}else{
+if(MochiKit.MockDOM){
+this._document=MochiKit.MockDOM.document;
+}
+}
+this._window=win;
+this.domConverters=new m.AdapterRegistry();
+var _3b6=this._document.createElement("span");
+var _3b7;
+if(_3b6&&_3b6.attributes&&_3b6.attributes.length>0){
+var _3b8=m.filter;
+_3b7=function(node){
+return _3b8(_3b7.ignoreAttrFilter,node.attributes);
+};
+_3b7.ignoreAttr={};
+var _3ba=_3b6.attributes;
+var _3bb=_3b7.ignoreAttr;
+for(var i=0;i<_3ba.length;i++){
+var a=_3ba[i];
+_3bb[a.name]=a.value;
+}
+_3b7.ignoreAttrFilter=function(a){
+return (_3b7.ignoreAttr[a.name]!=a.value);
+};
+_3b7.compliant=false;
+_3b7.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor","readonly":"readOnly","colspan":"colSpan","bgcolor":"bgColor","cellspacing":"cellSpacing","cellpadding":"cellPadding"};
+}else{
+_3b7=function(node){
+return node.attributes;
+};
+_3b7.compliant=true;
+_3b7.renames={};
+}
+this.attributeArray=_3b7;
+var _3c0=function(_3c1,arr){
+var _3c3=arr[1].split(".");
+var str="";
+var obj={};
+str+="if (!MochiKit."+_3c3[1]+") { throw new Error(\"";
+str+="This function has been deprecated and depends on MochiKit.";
+str+=_3c3[1]+".\");}";
+str+="return MochiKit."+_3c3[1]+"."+arr[0];
+str+=".apply(this, arguments);";
+obj[_3c3[2]]=new Function(str);
+MochiKit.Base.update(MochiKit[_3c1],obj);
+};
+for(var i;i<MochiKit.DOM.DEPRECATED.length;i++){
+_3c0("DOM",MochiKit.DOM.DEPRECATED[i]);
+}
+var _3c6=this.createDOMFunc;
+this.UL=_3c6("ul");
+this.OL=_3c6("ol");
+this.LI=_3c6("li");
+this.TD=_3c6("td");
+this.TR=_3c6("tr");
+this.TBODY=_3c6("tbody");
+this.THEAD=_3c6("thead");
+this.TFOOT=_3c6("tfoot");
+this.TABLE=_3c6("table");
+this.TH=_3c6("th");
+this.INPUT=_3c6("input");
+this.SPAN=_3c6("span");
+this.A=_3c6("a");
+this.DIV=_3c6("div");
+this.IMG=_3c6("img");
+this.BUTTON=_3c6("button");
+this.TT=_3c6("tt");
+this.PRE=_3c6("pre");
+this.H1=_3c6("h1");
+this.H2=_3c6("h2");
+this.H3=_3c6("h3");
+this.BR=_3c6("br");
+this.HR=_3c6("hr");
+this.LABEL=_3c6("label");
+this.TEXTAREA=_3c6("textarea");
+this.FORM=_3c6("form");
+this.P=_3c6("p");
+this.SELECT=_3c6("select");
+this.OPTION=_3c6("option");
+this.OPTGROUP=_3c6("optgroup");
+this.LEGEND=_3c6("legend");
+this.FIELDSET=_3c6("fieldset");
+this.STRONG=_3c6("strong");
+this.CANVAS=_3c6("canvas");
+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.__export__){
+withWindow=MochiKit.DOM.withWindow;
+withDocument=MochiKit.DOM.withDocument;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.DOM);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Selector");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Iter");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Iter",[]);
+}
+try{
+if(typeof (MochiKit.Base)==="undefined"||typeof (MochiKit.DOM)==="undefined"||typeof (MochiKit.Iter)==="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Selector depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
+}
+if(typeof (MochiKit.Selector)=="undefined"){
+MochiKit.Selector={};
+}
+MochiKit.Selector.NAME="MochiKit.Selector";
+MochiKit.Selector.VERSION="1.4";
+MochiKit.Selector.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Selector.toString=function(){
+return this.__repr__();
+};
+MochiKit.Selector.EXPORT=["Selector","findChildElements","findDocElements","$$"];
+MochiKit.Selector.EXPORT_OK=[];
+MochiKit.Selector.Selector=function(_3c7){
+this.params={classNames:[],pseudoClassNames:[]};
+this.expression=_3c7.toString().replace(/(^\s+|\s+$)/g,"");
+this.parseExpression();
+this.compileMatcher();
+};
+MochiKit.Selector.Selector.prototype={__class__:MochiKit.Selector.Selector,parseExpression:function(){
+function abort(_3c8){
+throw "Parse error in selector: "+_3c8;
+}
+if(this.expression==""){
+abort("empty expression");
+}
+var repr=MochiKit.Base.repr;
+var _3ca=this.params;
+var expr=this.expression;
+var _3cc,_3cd,_3ce,rest;
+while(_3cc=expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)){
+_3ca.attributes=_3ca.attributes||[];
+_3ca.attributes.push({name:_3cc[2],operator:_3cc[3],value:_3cc[4]||_3cc[5]||""});
+expr=_3cc[1];
+}
+if(expr=="*"){
+return this.params.wildcard=true;
+}
+while(_3cc=expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)){
+_3cd=_3cc[1];
+_3ce=_3cc[2];
+rest=_3cc[3];
+switch(_3cd){
+case "#":
+_3ca.id=_3ce;
+break;
+case ".":
+_3ca.classNames.push(_3ce);
+break;
+case ":":
+_3ca.pseudoClassNames.push(_3ce);
+break;
+case "":
+case undefined:
+_3ca.tagName=_3ce.toUpperCase();
+break;
+default:
+abort(repr(expr));
+}
+expr=rest;
+}
+if(expr.length>0){
+abort(repr(expr));
+}
+},buildMatchExpression:function(){
+var repr=MochiKit.Base.repr;
+var _3d1=this.params;
+var _3d2=[];
+var _3d3,i;
+function childElements(_3d5){
+return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, "+_3d5+".childNodes)";
+}
+if(_3d1.wildcard){
+_3d2.push("true");
+}
+if(_3d3=_3d1.id){
+_3d2.push("element.id == "+repr(_3d3));
+}
+if(_3d3=_3d1.tagName){
+_3d2.push("element.tagName.toUpperCase() == "+repr(_3d3));
+}
+if((_3d3=_3d1.classNames).length>0){
+for(i=0;i<_3d3.length;i++){
+_3d2.push("MochiKit.DOM.hasElementClass(element, "+repr(_3d3[i])+")");
+}
+}
+if((_3d3=_3d1.pseudoClassNames).length>0){
+for(i=0;i<_3d3.length;i++){
+var _3d6=_3d3[i].match(/^([^(]+)(?:\((.*)\))?$/);
+var _3d7=_3d6[1];
+var _3d8=_3d6[2];
+switch(_3d7){
+case "root":
+_3d2.push("element.nodeType == 9 || element === element.ownerDocument.documentElement");
+break;
+case "nth-child":
+case "nth-last-child":
+case "nth-of-type":
+case "nth-last-of-type":
+_3d6=_3d8.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
+if(!_3d6){
+throw "Invalid argument to pseudo element nth-child: "+_3d8;
+}
+var a,b;
+if(_3d6[0]=="odd"){
+a=2;
+b=1;
+}else{
+if(_3d6[0]=="even"){
+a=2;
+b=0;
+}else{
+a=_3d6[2]&&parseInt(_3d6)||null;
+b=parseInt(_3d6[3]);
+}
+}
+_3d2.push("this.nthChild(element,"+a+","+b+","+!!_3d7.match("^nth-last")+","+!!_3d7.match("of-type$")+")");
+break;
+case "first-child":
+_3d2.push("this.nthChild(element, null, 1)");
+break;
+case "last-child":
+_3d2.push("this.nthChild(element, null, 1, true)");
+break;
+case "first-of-type":
+_3d2.push("this.nthChild(element, null, 1, false, true)");
+break;
+case "last-of-type":
+_3d2.push("this.nthChild(element, null, 1, true, true)");
+break;
+case "only-child":
+_3d2.push(childElements("element.parentNode")+".length == 1");
+break;
+case "only-of-type":
+_3d2.push("MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, "+childElements("element.parentNode")+").length == 1");
+break;
+case "empty":
+_3d2.push("element.childNodes.length == 0");
+break;
+case "enabled":
+_3d2.push("(this.isUIElement(element) && element.disabled === false)");
+break;
+case "disabled":
+_3d2.push("(this.isUIElement(element) && element.disabled === true)");
+break;
+case "checked":
+_3d2.push("(this.isUIElement(element) && element.checked === true)");
+break;
+case "not":
+var _3db=new MochiKit.Selector.Selector(_3d8);
+_3d2.push("!( "+_3db.buildMatchExpression()+")");
+break;
+}
+}
+}
+if(_3d3=_3d1.attributes){
+MochiKit.Base.map(function(_3dc){
+var _3dd="MochiKit.DOM.getNodeAttribute(element, "+repr(_3dc.name)+")";
+var _3de=function(_3df){
+return _3dd+".split("+repr(_3df)+")";
+};
+switch(_3dc.operator){
+case "=":
+_3d2.push(_3dd+" == "+repr(_3dc.value));
+break;
+case "~=":
+_3d2.push(_3dd+" && MochiKit.Base.findValue("+_3de(" ")+", "+repr(_3dc.value)+") > -1");
+break;
+case "^=":
+_3d2.push(_3dd+".substring(0, "+_3dc.value.length+") == "+repr(_3dc.value));
+break;
+case "$=":
+_3d2.push(_3dd+".substring("+_3dd+".length - "+_3dc.value.length+") == "+repr(_3dc.value));
+break;
+case "*=":
+_3d2.push(_3dd+".match("+repr(_3dc.value)+")");
+break;
+case "|=":
+_3d2.push(_3dd+" && "+_3de("-")+"[0].toUpperCase() == "+repr(_3dc.value.toUpperCase()));
+break;
+case "!=":
+_3d2.push(_3dd+" != "+repr(_3dc.value));
+break;
+case "":
+case undefined:
+_3d2.push(_3dd+" != null");
+break;
+default:
+throw "Unknown operator "+_3dc.operator+" in selector";
+}
+},_3d3);
+}
+return _3d2.join(" && ");
+},compileMatcher:function(){
+this.match=new Function("element","if (!element.tagName) return false;                 return "+this.buildMatchExpression());
+},nthChild:function(_3e0,a,b,_3e3,_3e4){
+var _3e5=MochiKit.Base.filter(function(node){
+return node.nodeType==1;
+},_3e0.parentNode.childNodes);
+if(_3e4){
+_3e5=MochiKit.Base.filter(function(node){
+return node.tagName==_3e0.tagName;
+},_3e5);
+}
+if(_3e3){
+_3e5=MochiKit.Iter.reversed(_3e5);
+}
+if(a){
+var _3e8=MochiKit.Base.findIdentical(_3e5,_3e0);
+return ((_3e8+1-b)/a)%1==0;
+}else{
+return b==MochiKit.Base.findIdentical(_3e5,_3e0)+1;
+}
+},isUIElement:function(_3e9){
+return MochiKit.Base.findValue(["input","button","select","option","textarea","object"],_3e9.tagName.toLowerCase())>-1;
+},findElements:function(_3ea,axis){
+var _3ec;
+if(axis==undefined){
+axis="";
+}
+function inScope(_3ed,_3ee){
+if(axis==""){
+return MochiKit.DOM.isChildNode(_3ed,_3ee);
+}else{
+if(axis==">"){
+return _3ed.parentNode==_3ee;
+}else{
+if(axis=="+"){
+return _3ed==nextSiblingElement(_3ee);
+}else{
+if(axis=="~"){
+var _3ef=_3ee;
+while(_3ef=nextSiblingElement(_3ef)){
+if(_3ed==_3ef){
+return true;
+}
+}
+return false;
+}else{
+throw "Invalid axis: "+axis;
+}
+}
+}
+}
+}
+if(_3ec=MochiKit.DOM.getElement(this.params.id)){
+if(this.match(_3ec)){
+if(!_3ea||inScope(_3ec,_3ea)){
+return [_3ec];
+}
+}
+}
+function nextSiblingElement(node){
+node=node.nextSibling;
+while(node&&node.nodeType!=1){
+node=node.nextSibling;
+}
+return node;
+}
+if(axis==""){
+_3ea=(_3ea||MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName||"*");
+}else{
+if(axis==">"){
+if(!_3ea){
+throw "> combinator not allowed without preceeding expression";
+}
+_3ea=MochiKit.Base.filter(function(node){
+return node.nodeType==1;
+},_3ea.childNodes);
+}else{
+if(axis=="+"){
+if(!_3ea){
+throw "+ combinator not allowed without preceeding expression";
+}
+_3ea=nextSiblingElement(_3ea)&&[nextSiblingElement(_3ea)];
+}else{
+if(axis=="~"){
+if(!_3ea){
+throw "~ combinator not allowed without preceeding expression";
+}
+var _3f2=[];
+while(nextSiblingElement(_3ea)){
+_3ea=nextSiblingElement(_3ea);
+_3f2.push(_3ea);
+}
+_3ea=_3f2;
+}
+}
+}
+}
+if(!_3ea){
+return [];
+}
+var _3f3=MochiKit.Base.filter(MochiKit.Base.bind(function(_3f4){
+return this.match(_3f4);
+},this),_3ea);
+return _3f3;
+},repr:function(){
+return "Selector("+this.expression+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Base.update(MochiKit.Selector,{findChildElements:function(_3f5,_3f6){
+return MochiKit.Base.flattenArray(MochiKit.Base.map(function(_3f7){
+var _3f8="";
+return MochiKit.Iter.reduce(function(_3f9,expr){
+if(match=expr.match(/^[>+~]$/)){
+_3f8=match[0];
+return _3f9;
+}else{
+var _3fb=new MochiKit.Selector.Selector(expr);
+var _3fc=MochiKit.Iter.reduce(function(_3fd,_3fe){
+return MochiKit.Base.extend(_3fd,_3fb.findElements(_3fe||_3f5,_3f8));
+},_3f9,[]);
+_3f8="";
+return _3fc;
+}
+},_3f7.replace(/(^\s+|\s+$)/g,"").split(/\s+/),[null]);
+},_3f6));
+},findDocElements:function(){
+return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(),arguments);
+},__new__:function(){
+var m=MochiKit.Base;
+this.$$=this.findDocElements;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.Selector.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Selector);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Style");
+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.Style depends on MochiKit.Base!";
+}
+try{
+if(typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Style depends on MochiKit.DOM!";
+}
+if(typeof (MochiKit.Style)=="undefined"){
+MochiKit.Style={};
+}
+MochiKit.Style.NAME="MochiKit.Style";
+MochiKit.Style.VERSION="1.4";
+MochiKit.Style.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Style.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.EXPORT_OK=[];
+MochiKit.Style.EXPORT=["setStyle","setOpacity","getStyle","getElementDimensions","elementDimensions","setElementDimensions","getElementPosition","elementPosition","setElementPosition","setDisplayForElement","hideElement","showElement","getViewportDimensions","getViewportPosition","Dimensions","Coordinates"];
+MochiKit.Style.Dimensions=function(w,h){
+this.w=w;
+this.h=h;
+};
+MochiKit.Style.Dimensions.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}";
+};
+MochiKit.Style.Dimensions.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.Coordinates=function(x,y){
+this.x=x;
+this.y=y;
+};
+MochiKit.Style.Coordinates.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}";
+};
+MochiKit.Style.Coordinates.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Base.update(MochiKit.Style,{getStyle:function(elem,_407){
+var dom=MochiKit.DOM;
+var d=dom._document;
+elem=dom.getElement(elem);
+_407=MochiKit.Base.camelize(_407);
+if(!elem||elem==d){
+return undefined;
+}
+if(_407=="opacity"&&elem.filters){
+var _40a=(MochiKit.Style.getStyle(elem,"filter")||"").match(/alpha\(opacity=(.*)\)/);
+if(_40a&&_40a[1]){
+return parseFloat(_40a[1])/100;
+}
+return 1;
+}
+var _40b=elem.style?elem.style[_407]:null;
+if(!_40b){
+if(d.defaultView&&d.defaultView.getComputedStyle){
+var css=d.defaultView.getComputedStyle(elem,null);
+_407=_407.replace(/([A-Z])/g,"-$1").toLowerCase();
+_40b=css?css.getPropertyValue(_407):null;
+}else{
+if(elem.currentStyle){
+_40b=elem.currentStyle[_407];
+}
+}
+}
+if(_407=="opacity"){
+_40b=parseFloat(_40b);
+}
+if(/Opera/.test(navigator.userAgent)&&(MochiKit.Base.find(["left","top","right","bottom"],_407)!=-1)){
+if(MochiKit.Style.getStyle(elem,"position")=="static"){
+_40b="auto";
+}
+}
+return _40b=="auto"?null:_40b;
+},setStyle:function(elem,_40e){
+elem=MochiKit.DOM.getElement(elem);
+for(var name in _40e){
+if(name=="opacity"){
+MochiKit.Style.setOpacity(elem,_40e[name]);
+}else{
+elem.style[MochiKit.Base.camelize(name)]=_40e[name];
+}
+}
+},setOpacity:function(elem,o){
+elem=MochiKit.DOM.getElement(elem);
+var self=MochiKit.Style;
+if(o==1){
+var _413=/Gecko/.test(navigator.userAgent)&&!(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
+elem.style["opacity"]=_413?0.999999:1;
+if(/MSIE/.test(navigator.userAgent)){
+elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"");
+}
+}else{
+if(o<0.00001){
+o=0;
+}
+elem.style["opacity"]=o;
+if(/MSIE/.test(navigator.userAgent)){
+elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"")+"alpha(opacity="+o*100+")";
+}
+}
+},getElementPosition:function(elem,_415){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+elem=dom.getElement(elem);
+if(!elem||(!(elem.x&&elem.y)&&(!elem.parentNode===null||self.getStyle(elem,"display")=="none"))){
+return undefined;
+}
+var c=new self.Coordinates(0,0);
+var box=null;
+var _41a=null;
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var b=d.body;
+if(!elem.parentNode&&elem.x&&elem.y){
+c.x+=elem.x||0;
+c.y+=elem.y||0;
+}else{
+if(elem.getBoundingClientRect){
+box=elem.getBoundingClientRect();
+c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
+c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}else{
+if(elem.offsetParent){
+c.x+=elem.offsetLeft;
+c.y+=elem.offsetTop;
+_41a=elem.offsetParent;
+if(_41a!=elem){
+while(_41a){
+c.x+=_41a.offsetLeft;
+c.y+=_41a.offsetTop;
+_41a=_41a.offsetParent;
+}
+}
+var ua=navigator.userAgent.toLowerCase();
+if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("AppleWebKit")!=-1&&self.getStyle(elem,"position")=="absolute")){
+c.x-=b.offsetLeft;
+c.y-=b.offsetTop;
+}
+}
+}
+}
+if(typeof (_415)!="undefined"){
+_415=arguments.callee(_415);
+if(_415){
+c.x-=(_415.x||0);
+c.y-=(_415.y||0);
+}
+}
+if(elem.parentNode){
+_41a=elem.parentNode;
+}else{
+_41a=null;
+}
+while(_41a){
+var _41f=_41a.tagName.toUpperCase();
+if(_41f==="BODY"||_41f==="HTML"){
+break;
+}
+var disp=self.getStyle(_41a,"display");
+if(disp!="inline"&&disp!="table-row"){
+c.x-=_41a.scrollLeft;
+c.y-=_41a.scrollTop;
+}
+if(_41a.parentNode){
+_41a=_41a.parentNode;
+}else{
+_41a=null;
+}
+}
+return c;
+},setElementPosition:function(elem,_422,_423){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_423)=="undefined"){
+_423="px";
+}
+var _424={};
+var _425=MochiKit.Base.isUndefinedOrNull;
+if(!_425(_422.x)){
+_424["left"]=_422.x+_423;
+}
+if(!_425(_422.y)){
+_424["top"]=_422.y+_423;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_424});
+},getElementDimensions:function(elem){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){
+return new self.Dimensions(elem.w||0,elem.h||0);
+}
+elem=dom.getElement(elem);
+if(!elem){
+return undefined;
+}
+var disp=self.getStyle(elem,"display");
+if(disp!="none"&&disp!==""&&typeof (disp)!="undefined"){
+return new self.Dimensions(elem.offsetWidth||0,elem.offsetHeight||0);
+}
+var s=elem.style;
+var _42b=s.visibility;
+var _42c=s.position;
+s.visibility="hidden";
+s.position="absolute";
+s.display="";
+var _42d=elem.offsetWidth;
+var _42e=elem.offsetHeight;
+s.display="none";
+s.position=_42c;
+s.visibility=_42b;
+return new self.Dimensions(_42d,_42e);
+},setElementDimensions:function(elem,_430,_431){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_431)=="undefined"){
+_431="px";
+}
+var _432={};
+var _433=MochiKit.Base.isUndefinedOrNull;
+if(!_433(_430.w)){
+_432["width"]=_430.w+_431;
+}
+if(!_433(_430.h)){
+_432["height"]=_430.h+_431;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_432});
+},setDisplayForElement:function(_434,_435){
+var _436=MochiKit.Base.extend(null,arguments,1);
+var _437=MochiKit.DOM.getElement;
+for(var i=0;i<_436.length;i++){
+_435=_437(_436[i]);
+if(_435){
+_435.style.display=_434;
+}
+}
+},getViewportDimensions:function(){
+var d=new MochiKit.Style.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;
+},getViewportPosition:function(){
+var c=new MochiKit.Style.Coordinates(0,0);
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var db=d.body;
+if(de&&(de.scrollTop||de.scrollLeft)){
+c.x=de.scrollLeft;
+c.y=de.scrollTop;
+}else{
+if(db){
+c.x=db.scrollLeft;
+c.y=db.scrollTop;
+}
+}
+return c;
+},__new__:function(){
+var m=MochiKit.Base;
+this.elementPosition=this.getElementPosition;
+this.elementDimensions=this.getElementDimensions;
+this.hideElement=m.partial(this.setDisplayForElement,"none");
+this.showElement=m.partial(this.setDisplayForElement,"block");
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.Style.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Style);
+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.4";
+MochiKit.LoggingPane.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.LoggingPane.toString=function(){
+return this.__repr__();
+};
+MochiKit.LoggingPane.createLoggingPane=function(_441){
+var m=MochiKit.LoggingPane;
+_441=!(!_441);
+if(m._loggingPane&&m._loggingPane.inline!=_441){
+m._loggingPane.closePane();
+m._loggingPane=null;
+}
+if(!m._loggingPane||m._loggingPane.closed){
+m._loggingPane=new m.LoggingPane(_441,MochiKit.Logging.logger);
+}
+return m._loggingPane;
+};
+MochiKit.LoggingPane.LoggingPane=function(_443,_444){
+if(typeof (_444)=="undefined"||_444===null){
+_444=MochiKit.Logging.logger;
+}
+this.logger=_444;
+var _445=MochiKit.Base.update;
+var _446=MochiKit.Base.updatetree;
+var bind=MochiKit.Base.bind;
+var _448=MochiKit.Base.clone;
+var win=window;
+var uid="_MochiKit_LoggingPane";
+if(typeof (MochiKit.DOM)!="undefined"){
+win=MochiKit.DOM.currentWindow();
+}
+if(!_443){
+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 _44f=doc.getElementById(uid);
+var _450=!!_44f;
+if(_44f&&typeof (_44f.loggingPane)!="undefined"){
+_44f.loggingPane.logger=this.logger;
+_44f.loggingPane.buildAndApplyFilter();
+return _44f.loggingPane;
+}
+if(_450){
+var _451;
+while((_451=_44f.firstChild)){
+_44f.removeChild(_451);
+}
+}else{
+_44f=doc.createElement("div");
+_44f.id=uid;
+}
+_44f.loggingPane=this;
+var _452=doc.createElement("input");
+var _453=doc.createElement("input");
+var _454=doc.createElement("button");
+var _455=doc.createElement("button");
+var _456=doc.createElement("button");
+var _457=doc.createElement("button");
+var _458=doc.createElement("div");
+var _459=doc.createElement("div");
+var _45a=uid+"_Listener";
+this.colorTable=_448(this.colorTable);
+var _45b=[];
+var _45c=null;
+var _45d=function(msg){
+var _45f=msg.level;
+if(typeof (_45f)=="number"){
+_45f=MochiKit.Logging.LogLevel[_45f];
+}
+return _45f;
+};
+var _460=function(msg){
+return msg.info.join(" ");
+};
+var _462=bind(function(msg){
+var _464=_45d(msg);
+var text=_460(msg);
+var c=this.colorTable[_464];
+var p=doc.createElement("span");
+p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_464;
+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(_464+": "+text));
+_459.appendChild(p);
+_459.appendChild(doc.createElement("br"));
+if(_458.offsetHeight>_458.scrollHeight){
+_458.scrollTop=0;
+}else{
+_458.scrollTop=_458.scrollHeight;
+}
+},this);
+var _468=function(msg){
+_45b[_45b.length]=msg;
+_462(msg);
+};
+var _46a=function(){
+var _46b,_46c;
+try{
+_46b=new RegExp(_452.value);
+_46c=new RegExp(_453.value);
+}
+catch(e){
+logDebug("Error in filter regex: "+e.message);
+return null;
+}
+return function(msg){
+return (_46b.test(_45d(msg))&&_46c.test(_460(msg)));
+};
+};
+var _46e=function(){
+while(_459.firstChild){
+_459.removeChild(_459.firstChild);
+}
+};
+var _46f=function(){
+_45b=[];
+_46e();
+};
+var _470=bind(function(){
+if(this.closed){
+return;
+}
+this.closed=true;
+if(MochiKit.LoggingPane._loggingPane==this){
+MochiKit.LoggingPane._loggingPane=null;
+}
+this.logger.removeListener(_45a);
+try{
+try{
+_44f.loggingPane=null;
+}
+catch(e){
+logFatal("Bookmarklet was closed incorrectly.");
+}
+if(_443){
+_44f.parentNode.removeChild(_44f);
+}else{
+this.win.close();
+}
+}
+catch(e){
+}
+},this);
+var _471=function(){
+_46e();
+for(var i=0;i<_45b.length;i++){
+var msg=_45b[i];
+if(_45c===null||_45c(msg)){
+_462(msg);
+}
+}
+};
+this.buildAndApplyFilter=function(){
+_45c=_46a();
+_471();
+this.logger.removeListener(_45a);
+this.logger.addListener(_45a,_45c,_468);
+};
+var _474=bind(function(){
+_45b=this.logger.getMessages();
+_471();
+},this);
+var _475=bind(function(_476){
+_476=_476||window.event;
+key=_476.which||_476.keyCode;
+if(key==13){
+this.buildAndApplyFilter();
+}
+},this);
+var _477="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont;
+if(_443){
+_477+="; height: 10em; border-top: 2px solid black";
+}else{
+_477+="; height: 100%;";
+}
+_44f.style.cssText=_477;
+if(!_450){
+doc.body.appendChild(_44f);
+}
+_477={"cssText":"width: 33%; display: inline; font: "+this.logFont};
+_446(_452,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_475,"style":_477});
+_44f.appendChild(_452);
+_446(_453,{"value":".*","onkeypress":_475,"style":_477});
+_44f.appendChild(_453);
+_477="width: 8%; display:inline; font: "+this.logFont;
+_454.appendChild(doc.createTextNode("Filter"));
+_454.onclick=bind("buildAndApplyFilter",this);
+_454.style.cssText=_477;
+_44f.appendChild(_454);
+_455.appendChild(doc.createTextNode("Load"));
+_455.onclick=_474;
+_455.style.cssText=_477;
+_44f.appendChild(_455);
+_456.appendChild(doc.createTextNode("Clear"));
+_456.onclick=_46f;
+_456.style.cssText=_477;
+_44f.appendChild(_456);
+_457.appendChild(doc.createTextNode("Close"));
+_457.onclick=_470;
+_457.style.cssText=_477;
+_44f.appendChild(_457);
+_458.style.cssText="overflow: auto; width: 100%";
+_459.style.cssText="width: 100%; height: "+(_443?"8em":"100%");
+_458.appendChild(_459);
+_44f.appendChild(_458);
+this.buildAndApplyFilter();
+_474();
+if(_443){
+this.win=undefined;
+}else{
+this.win=win;
+}
+this.inline=_443;
+this.closePane=_470;
+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");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.Base";
+}
+try{
+if(typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.DOM";
+}
+try{
+if(typeof (MochiKit.Style)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.Style";
+}
+if(typeof (MochiKit.Color)=="undefined"){
+MochiKit.Color={};
+}
+MochiKit.Color.NAME="MochiKit.Color";
+MochiKit.Color.VERSION="1.4";
+MochiKit.Color.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Color.toString=function(){
+return this.__repr__();
+};
+MochiKit.Color.Color=function(red,_479,blue,_47b){
+if(typeof (_47b)=="undefined"||_47b===null){
+_47b=1;
+}
+this.rgb={r:red,g:_479,b:blue,a:_47b};
+};
+MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_47c){
+var rgb=this.rgb;
+var m=MochiKit.Color;
+return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_47c);
+},colorWithHue:function(hue){
+var hsl=this.asHSL();
+hsl.h=hue;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithSaturation:function(_482){
+var hsl=this.asHSL();
+hsl.s=_482;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithLightness:function(_485){
+var hsl=this.asHSL();
+hsl.l=_485;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},darkerColorWithLevel:function(_488){
+var hsl=this.asHSL();
+hsl.l=Math.max(hsl.l-_488,0);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},lighterColorWithLevel:function(_48b){
+var hsl=this.asHSL();
+hsl.l=Math.min(hsl.l+_48b,1);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},blendedColor:function(_48e,_48f){
+if(typeof (_48f)=="undefined"||_48f===null){
+_48f=0.5;
+}
+var sf=1-_48f;
+var s=this.rgb;
+var d=_48e.rgb;
+var df=_48f;
+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(_494){
+var a=this.asRGB();
+var b=_494.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,_4ab,blue,_4ad){
+var _4ae=MochiKit.Color.Color;
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_4ab=rgb.g;
+blue=rgb.b;
+if(typeof (rgb.a)=="undefined"){
+_4ad=undefined;
+}else{
+_4ad=rgb.a;
+}
+}
+return new _4ae(red,_4ab,blue,_4ad);
+},fromHSL:function(hue,_4b1,_4b2,_4b3){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hslToRGB.apply(m,arguments));
+},fromHSV:function(hue,_4b6,_4b7,_4b8){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments));
+},fromName:function(name){
+var _4bb=MochiKit.Color.Color;
+if(name.charAt(0)=="\""){
+name=name.substr(1,name.length-2);
+}
+var _4bc=_4bb._namedColors[name.toLowerCase()];
+if(typeof (_4bc)=="string"){
+return _4bb.fromHexString(_4bc);
+}else{
+if(name=="transparent"){
+return _4bb.transparentColor();
+}
+}
+return null;
+},fromString:function(_4bd){
+var self=MochiKit.Color.Color;
+var _4bf=_4bd.substr(0,3);
+if(_4bf=="rgb"){
+return self.fromRGBString(_4bd);
+}else{
+if(_4bf=="hsl"){
+return self.fromHSLString(_4bd);
+}else{
+if(_4bd.charAt(0)=="#"){
+return self.fromHexString(_4bd);
+}
+}
+}
+return self.fromName(_4bd);
+},fromHexString:function(_4c0){
+if(_4c0.charAt(0)=="#"){
+_4c0=_4c0.substring(1);
+}
+var _4c1=[];
+var i,hex;
+if(_4c0.length==3){
+for(i=0;i<3;i++){
+hex=_4c0.substr(i,1);
+_4c1.push(parseInt(hex+hex,16)/255);
+}
+}else{
+for(i=0;i<6;i+=2){
+hex=_4c0.substr(i,2);
+_4c1.push(parseInt(hex,16)/255);
+}
+}
+var _4c4=MochiKit.Color.Color;
+return _4c4.fromRGB.apply(_4c4,_4c1);
+},_fromColorString:function(pre,_4c6,_4c7,_4c8){
+if(_4c8.indexOf(pre)===0){
+_4c8=_4c8.substring(_4c8.indexOf("(",3)+1,_4c8.length-1);
+}
+var _4c9=_4c8.split(/\s*,\s*/);
+var _4ca=[];
+for(var i=0;i<_4c9.length;i++){
+var c=_4c9[i];
+var val;
+var _4ce=c.substring(c.length-3);
+if(c.charAt(c.length-1)=="%"){
+val=0.01*parseFloat(c.substring(0,c.length-1));
+}else{
+if(_4ce=="deg"){
+val=parseFloat(c)/360;
+}else{
+if(_4ce=="rad"){
+val=parseFloat(c)/(Math.PI*2);
+}else{
+val=_4c7[i]*parseFloat(c);
+}
+}
+}
+_4ca.push(val);
+}
+return this[_4c6].apply(this,_4ca);
+},fromComputedStyle:function(elem,_4d0){
+var d=MochiKit.DOM;
+var cls=MochiKit.Color.Color;
+for(elem=d.getElement(elem);elem;elem=elem.parentNode){
+var _4d3=MochiKit.Style.getStyle.apply(d,arguments);
+if(!_4d3){
+continue;
+}
+var _4d4=cls.fromString(_4d3);
+if(!_4d4){
+break;
+}
+if(_4d4.asRGB().a>0){
+return _4d4;
+}
+}
+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,_4da){
+v*=_4da;
+if(v<0){
+return 0;
+}else{
+if(v>_4da){
+return _4da;
+}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,_4e0,_4e1,_4e2){
+if(arguments.length==1){
+var hsv=hue;
+hue=hsv.h;
+_4e0=hsv.s;
+_4e1=hsv.v;
+_4e2=hsv.a;
+}
+var red;
+var _4e5;
+var blue;
+if(_4e0===0){
+red=_4e1;
+_4e5=_4e1;
+blue=_4e1;
+}else{
+var i=Math.floor(hue*6);
+var f=(hue*6)-i;
+var p=_4e1*(1-_4e0);
+var q=_4e1*(1-(_4e0*f));
+var t=_4e1*(1-(_4e0*(1-f)));
+switch(i){
+case 1:
+red=q;
+_4e5=_4e1;
+blue=p;
+break;
+case 2:
+red=p;
+_4e5=_4e1;
+blue=t;
+break;
+case 3:
+red=p;
+_4e5=q;
+blue=_4e1;
+break;
+case 4:
+red=t;
+_4e5=p;
+blue=_4e1;
+break;
+case 5:
+red=_4e1;
+_4e5=p;
+blue=q;
+break;
+case 6:
+case 0:
+red=_4e1;
+_4e5=t;
+blue=p;
+break;
+}
+}
+return {r:red,g:_4e5,b:blue,a:_4e2};
+},hslToRGB:function(hue,_4ed,_4ee,_4ef){
+if(arguments.length==1){
+var hsl=hue;
+hue=hsl.h;
+_4ed=hsl.s;
+_4ee=hsl.l;
+_4ef=hsl.a;
+}
+var red;
+var _4f2;
+var blue;
+if(_4ed===0){
+red=_4ee;
+_4f2=_4ee;
+blue=_4ee;
+}else{
+var m2;
+if(_4ee<=0.5){
+m2=_4ee*(1+_4ed);
+}else{
+m2=_4ee+_4ed-(_4ee*_4ed);
+}
+var m1=(2*_4ee)-m2;
+var f=MochiKit.Color._hslValue;
+var h6=hue*6;
+red=f(m1,m2,h6+2);
+_4f2=f(m1,m2,h6);
+blue=f(m1,m2,h6-2);
+}
+return {r:red,g:_4f2,b:blue,a:_4ef};
+},rgbToHSV:function(red,_4f9,blue,_4fb){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_4f9=rgb.g;
+blue=rgb.b;
+_4fb=rgb.a;
+}
+var max=Math.max(Math.max(red,_4f9),blue);
+var min=Math.min(Math.min(red,_4f9),blue);
+var hue;
+var _500;
+var _501=max;
+if(min==max){
+hue=0;
+_500=0;
+}else{
+var _502=(max-min);
+_500=_502/max;
+if(red==max){
+hue=(_4f9-blue)/_502;
+}else{
+if(_4f9==max){
+hue=2+((blue-red)/_502);
+}else{
+hue=4+((red-_4f9)/_502);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_500,v:_501,a:_4fb};
+},rgbToHSL:function(red,_504,blue,_506){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_504=rgb.g;
+blue=rgb.b;
+_506=rgb.a;
+}
+var max=Math.max(red,Math.max(_504,blue));
+var min=Math.min(red,Math.min(_504,blue));
+var hue;
+var _50b;
+var _50c=(max+min)/2;
+var _50d=max-min;
+if(_50d===0){
+hue=0;
+_50b=0;
+}else{
+if(_50c<=0.5){
+_50b=_50d/(max+min);
+}else{
+_50b=_50d/(2-max-min);
+}
+if(red==max){
+hue=(_504-blue)/_50d;
+}else{
+if(_504==max){
+hue=2+((blue-red)/_50d);
+}else{
+hue=4+((red-_504)/_50d);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_50b,l:_50c,a:_506};
+},toColorPart:function(num){
+num=Math.round(num);
+var _50f=num.toString(16);
+if(num<16){
+return "0"+_50f;
+}
+return _50f;
+},__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 _511=1/3;
+var _512={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_511,_511,_511],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_511,2*_511,2*_511],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 _513=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 _512){
+var name=k+"Color";
+var _51c=m.concat([_513,this.Color,name],_512[k]);
+this.Color[name]=m.bind.apply(null,_51c);
+}
+var _51d=function(){
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof Color)){
+return false;
+}
+}
+return true;
+};
+var _51f=function(a,b){
+return a.compareRGB(b);
+};
+m.nameFunctions(this);
+m.registerComparator(this.Color.NAME,_51d,_51f);
+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");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+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!";
+}
+try{
+if(typeof (MochiKit.Style)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Signal depends on MochiKit.Style!";
+}
+if(typeof (MochiKit.Signal)=="undefined"){
+MochiKit.Signal={};
+}
+MochiKit.Signal.NAME="MochiKit.Signal";
+MochiKit.Signal.VERSION="1.4";
+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());
+if(this.type()&&this.type().indexOf("key")===0||this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu"){
+str+=", 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:null,relatedTarget:function(){
+if(this._relatedTarget!==null){
+return this._relatedTarget;
+}
+var elem=null;
+if(this.type()=="mouseover"){
+elem=(this._event.relatedTarget||this._event.fromElement);
+}else{
+if(this.type()=="mouseout"){
+elem=(this._event.relatedTarget||this._event.toElement);
+}
+}
+if(elem!==null){
+this._relatedTarget=elem;
+return elem;
+}
+return undefined;
+},_modifier:null,modifier:function(){
+if(this._modifier!==null){
+return this._modifier;
+}
+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;
+this._modifier=m;
+return m;
+},_key:null,key:function(){
+if(this._key!==null){
+return this._key;
+}
+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");
+this._key=k;
+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);
+}
+}
+this._key=k;
+return k;
+}
+}
+}
+return undefined;
+},_mouse:null,mouse:function(){
+if(this._mouse!==null){
+return this._mouse;
+}
+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.Style.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.Style.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||0);
+m.page.y=e.clientY+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}
+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);
+}
+}
+this._mouse=m;
+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{
+if(this._confirmUnload===null){
+this._event.returnValue=false;
+}
+}
+},_confirmUnload:null,confirmUnload:function(msg){
+if(this.type()=="beforeunload"){
+this._confirmUnload=msg;
+this._event.returnValue=msg;
+}
+}});
+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"};
+(function(){
+var _52e=MochiKit.Signal._specialMacKeys;
+for(i=63236;i<=63242;i++){
+_52e[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"};
+(function(){
+var _52f=MochiKit.Signal._specialKeys;
+for(var i=48;i<=57;i++){
+_52f[i]="KEY_"+(i-48);
+}
+for(i=65;i<=90;i++){
+_52f[i]="KEY_"+String.fromCharCode(i);
+}
+for(i=96;i<=105;i++){
+_52f[i]="KEY_NUM_PAD_"+(i-96);
+}
+for(i=112;i<=123;i++){
+_52f[i]="KEY_F"+(i-112+1);
+}
+})();
+MochiKit.Signal.Ident=function(_531){
+this.source=_531.source;
+this.signal=_531.signal;
+this.listener=_531.listener;
+this.isDOM=_531.isDOM;
+this.objOrFunc=_531.objOrFunc;
+this.funcOrStr=_531.funcOrStr;
+this.connected=_531.connected;
+};
+MochiKit.Signal.Ident.prototype={};
+MochiKit.Base.update(MochiKit.Signal,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},_unloadCache:function(){
+var self=MochiKit.Signal;
+var _533=self._observers;
+for(var i=0;i<_533.length;i++){
+if(_533[i].signal!=="onload"&&_533[i].signal!=="onunload"){
+self._disconnect(_533[i]);
+}
+}
+},_listener:function(src,sig,func,obj,_539){
+var self=MochiKit.Signal;
+var E=self.Event;
+if(!_539){
+return MochiKit.Base.bind(func,obj);
+}
+obj=obj||src;
+if(typeof (func)=="string"){
+if(sig==="onload"||sig==="onunload"){
+return function(_53c){
+obj[func].apply(obj,[new E(src,_53c)]);
+var _53d=new MochiKit.Signal.Ident({source:src,signal:sig,objOrFunc:obj,funcOrStr:func});
+MochiKit.Signal._disconnect(_53d);
+};
+}else{
+return function(_53e){
+obj[func].apply(obj,[new E(src,_53e)]);
+};
+}
+}else{
+if(sig==="onload"||sig==="onunload"){
+return function(_53f){
+func.apply(obj,[new E(src,_53f)]);
+MochiKit.Signal.disconnect(src,sig,func);
+var _540=new MochiKit.Signal.Ident({source:src,signal:sig,objOrFunc:func});
+MochiKit.Signal._disconnect(_540);
+};
+}else{
+return function(_541){
+func.apply(obj,[new E(src,_541)]);
+};
+}
+}
+},_browserAlreadyHasMouseEnterAndLeave:function(){
+return /MSIE/.test(navigator.userAgent);
+},_mouseEnterListener:function(src,sig,func,obj){
+var E=MochiKit.Signal.Event;
+return function(_547){
+var e=new E(src,_547);
+try{
+e.relatedTarget().nodeName;
+}
+catch(err){
+return;
+}
+e.stop();
+if(MochiKit.DOM.isChildNode(e.relatedTarget(),src)){
+return;
+}
+e.type=function(){
+return sig;
+};
+if(typeof (func)=="string"){
+return obj[func].apply(obj,[e]);
+}else{
+return func.apply(obj,[e]);
+}
+};
+},_getDestPair:function(_549,_54a){
+var obj=null;
+var func=null;
+if(typeof (_54a)!="undefined"){
+obj=_549;
+func=_54a;
+if(typeof (_54a)=="string"){
+if(typeof (_549[_54a])!="function"){
+throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
+}
+}else{
+if(typeof (_54a)!="function"){
+throw new Error("'funcOrStr' must be a function or string");
+}
+}
+}else{
+if(typeof (_549)!="function"){
+throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
+}else{
+func=_549;
+}
+}
+return [obj,func];
+},connect:function(src,sig,_54f,_550){
+src=MochiKit.DOM.getElement(src);
+var self=MochiKit.Signal;
+if(typeof (sig)!="string"){
+throw new Error("'sig' must be a string");
+}
+var _552=self._getDestPair(_54f,_550);
+var obj=_552[0];
+var func=_552[1];
+if(typeof (obj)=="undefined"||obj===null){
+obj=src;
+}
+var _555=!!(src.addEventListener||src.attachEvent);
+if(_555&&(sig==="onmouseenter"||sig==="onmouseleave")&&!self._browserAlreadyHasMouseEnterAndLeave()){
+var _556=self._mouseEnterListener(src,sig.substr(2),func,obj);
+if(sig==="onmouseenter"){
+sig="onmouseover";
+}else{
+sig="onmouseout";
+}
+}else{
+var _556=self._listener(src,sig,func,obj,_555);
+}
+if(src.addEventListener){
+src.addEventListener(sig.substr(2),_556,false);
+}else{
+if(src.attachEvent){
+src.attachEvent(sig,_556);
+}
+}
+var _557=new MochiKit.Signal.Ident({source:src,signal:sig,listener:_556,isDOM:_555,objOrFunc:_54f,funcOrStr:_550,connected:true});
+self._observers.push(_557);
+if(!_555&&typeof (src.__connect__)=="function"){
+var args=MochiKit.Base.extend([_557],arguments,1);
+src.__connect__.apply(src,args);
+}
+return _557;
+},_disconnect:function(_559){
+if(!_559.connected){
+return;
+}
+_559.connected=false;
+if(!_559.isDOM){
+return;
+}
+var src=_559.source;
+var sig=_559.signal;
+var _55c=_559.listener;
+if(src.removeEventListener){
+src.removeEventListener(sig.substr(2),_55c,false);
+}else{
+if(src.detachEvent){
+src.detachEvent(sig,_55c);
+}else{
+throw new Error("'src' must be a DOM element");
+}
+}
+},disconnect:function(_55d){
+var self=MochiKit.Signal;
+var _55f=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=_55f.length-1;i>=0;i--){
+var o=_55f[i];
+if(o.source===src&&o.signal===sig&&o.objOrFunc===obj&&o.funcOrStr===func){
+self._disconnect(o);
+if(!self._lock){
+_55f.splice(i,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+}else{
+var idx=m.findIdentical(_55f,_55d);
+if(idx>=0){
+self._disconnect(_55d);
+if(!self._lock){
+_55f.splice(idx,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+return false;
+},disconnectAllTo:function(_568,_569){
+var self=MochiKit.Signal;
+var _56b=self._observers;
+var _56c=self._disconnect;
+var _56d=self._lock;
+var _56e=self._dirty;
+if(typeof (_569)==="undefined"){
+_569=null;
+}
+for(var i=_56b.length-1;i>=0;i--){
+var _570=_56b[i];
+if(_570.objOrFunc===_568&&(_569===null||_570.funcOrStr===_569)){
+_56c(_570);
+if(_56d){
+_56e=true;
+}else{
+_56b.splice(i,1);
+}
+}
+}
+self._dirty=_56e;
+},disconnectAll:function(src,sig){
+src=MochiKit.DOM.getElement(src);
+var m=MochiKit.Base;
+var _574=m.flattenArguments(m.extend(null,arguments,1));
+var self=MochiKit.Signal;
+var _576=self._disconnect;
+var _577=self._observers;
+var i,_579;
+var _57a=self._lock;
+var _57b=self._dirty;
+if(_574.length===0){
+for(i=_577.length-1;i>=0;i--){
+_579=_577[i];
+if(_579.source===src){
+_576(_579);
+if(!_57a){
+_577.splice(i,1);
+}else{
+_57b=true;
+}
+}
+}
+}else{
+var sigs={};
+for(i=0;i<_574.length;i++){
+sigs[_574[i]]=true;
+}
+for(i=_577.length-1;i>=0;i--){
+_579=_577[i];
+if(_579.source===src&&_579.signal in sigs){
+_576(_579);
+if(!_57a){
+_577.splice(i,1);
+}else{
+_57b=true;
+}
+}
+}
+}
+self._dirty=_57b;
+},signal:function(src,sig){
+var self=MochiKit.Signal;
+var _580=self._observers;
+src=MochiKit.DOM.getElement(src);
+var args=MochiKit.Base.extend(null,arguments,2);
+var _582=[];
+self._lock=true;
+for(var i=0;i<_580.length;i++){
+var _584=_580[i];
+if(_584.source===src&&_584.signal===sig){
+try{
+_584.listener.apply(src,args);
+}
+catch(e){
+_582.push(e);
+}
+}
+}
+self._lock=false;
+if(self._dirty){
+self._dirty=false;
+for(var i=_580.length-1;i>=0;i--){
+if(!_580[i].connected){
+_580.splice(i,1);
+}
+}
+}
+if(_582.length==1){
+throw _582[0];
+}else{
+if(_582.length>1){
+var e=new Error("Multiple errors thrown in handling 'sig', see errors property");
+e.errors=_582;
+throw e;
+}
+}
+}});
+MochiKit.Signal.EXPORT_OK=[];
+MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll","disconnectAllTo"];
+MochiKit.Signal.__new__=function(win){
+var m=MochiKit.Base;
+this._document=document;
+this._window=win;
+this._lock=false;
+this._dirty=false;
+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.__export__){
+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.Position");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.Style)=="undefined"||typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!";
+}
+if(typeof (MochiKit.Position)=="undefined"){
+MochiKit.Position={};
+}
+MochiKit.Position.NAME="MochiKit.Position";
+MochiKit.Position.VERSION="1.4";
+MochiKit.Position.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Position.toString=function(){
+return this.__repr__();
+};
+MochiKit.Position.EXPORT_OK=[];
+MochiKit.Position.EXPORT=[];
+MochiKit.Base.update(MochiKit.Position,{includeScrollOffsets:false,prepare:function(){
+var _588=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
+var _589=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;
+this.windowOffset=new MochiKit.Style.Coordinates(_588,_589);
+},cumulativeOffset:function(_58a){
+var _58b=0;
+var _58c=0;
+do{
+_58b+=_58a.offsetTop||0;
+_58c+=_58a.offsetLeft||0;
+_58a=_58a.offsetParent;
+}while(_58a);
+return new MochiKit.Style.Coordinates(_58c,_58b);
+},realOffset:function(_58d){
+var _58e=0;
+var _58f=0;
+do{
+_58e+=_58d.scrollTop||0;
+_58f+=_58d.scrollLeft||0;
+_58d=_58d.parentNode;
+}while(_58d);
+return new MochiKit.Style.Coordinates(_58f,_58e);
+},within:function(_590,x,y){
+if(this.includeScrollOffsets){
+return this.withinIncludingScrolloffsets(_590,x,y);
+}
+this.xcomp=x;
+this.ycomp=y;
+this.offset=this.cumulativeOffset(_590);
+if(_590.style.position=="fixed"){
+this.offset.x+=this.windowOffset.x;
+this.offset.y+=this.windowOffset.y;
+}
+return (y>=this.offset.y&&y<this.offset.y+_590.offsetHeight&&x>=this.offset.x&&x<this.offset.x+_590.offsetWidth);
+},withinIncludingScrolloffsets:function(_593,x,y){
+var _596=this.realOffset(_593);
+this.xcomp=x+_596.x-this.windowOffset.x;
+this.ycomp=y+_596.y-this.windowOffset.y;
+this.offset=this.cumulativeOffset(_593);
+return (this.ycomp>=this.offset.y&&this.ycomp<this.offset.y+_593.offsetHeight&&this.xcomp>=this.offset.x&&this.xcomp<this.offset.x+_593.offsetWidth);
+},overlap:function(mode,_598){
+if(!mode){
+return 0;
+}
+if(mode=="vertical"){
+return ((this.offset.y+_598.offsetHeight)-this.ycomp)/_598.offsetHeight;
+}
+if(mode=="horizontal"){
+return ((this.offset.x+_598.offsetWidth)-this.xcomp)/_598.offsetWidth;
+}
+},absolutize:function(_599){
+_599=MochiKit.DOM.getElement(_599);
+if(_599.style.position=="absolute"){
+return;
+}
+MochiKit.Position.prepare();
+var _59a=MochiKit.Position.positionedOffset(_599);
+var _59b=_599.clientWidth;
+var _59c=_599.clientHeight;
+var _59d={"position":_599.style.position,"left":_59a.x-parseFloat(_599.style.left||0),"top":_59a.y-parseFloat(_599.style.top||0),"width":_599.style.width,"height":_599.style.height};
+_599.style.position="absolute";
+_599.style.top=_59a.y+"px";
+_599.style.left=_59a.x+"px";
+_599.style.width=_59b+"px";
+_599.style.height=_59c+"px";
+return _59d;
+},positionedOffset:function(_59e){
+var _59f=0,_5a0=0;
+do{
+_59f+=_59e.offsetTop||0;
+_5a0+=_59e.offsetLeft||0;
+_59e=_59e.offsetParent;
+if(_59e){
+p=MochiKit.Style.getStyle(_59e,"position");
+if(p=="relative"||p=="absolute"){
+break;
+}
+}
+}while(_59e);
+return new MochiKit.Style.Coordinates(_5a0,_59f);
+},relativize:function(_5a1,_5a2){
+_5a1=MochiKit.DOM.getElement(_5a1);
+if(_5a1.style.position=="relative"){
+return;
+}
+MochiKit.Position.prepare();
+var top=parseFloat(_5a1.style.top||0)-(_5a2["top"]||0);
+var left=parseFloat(_5a1.style.left||0)-(_5a2["left"]||0);
+_5a1.style.position=_5a2["position"];
+_5a1.style.top=top+"px";
+_5a1.style.left=left+"px";
+_5a1.style.width=_5a2["width"];
+_5a1.style.height=_5a2["height"];
+},clone:function(_5a5,_5a6){
+_5a5=MochiKit.DOM.getElement(_5a5);
+_5a6=MochiKit.DOM.getElement(_5a6);
+_5a6.style.position="absolute";
+var _5a7=this.cumulativeOffset(_5a5);
+_5a6.style.top=_5a7.y+"px";
+_5a6.style.left=_5a7.x+"px";
+_5a6.style.width=_5a5.offsetWidth+"px";
+_5a6.style.height=_5a5.offsetHeight+"px";
+},page:function(_5a8){
+var _5a9=0;
+var _5aa=0;
+var _5ab=_5a8;
+do{
+_5a9+=_5ab.offsetTop||0;
+_5aa+=_5ab.offsetLeft||0;
+if(_5ab.offsetParent==document.body&&MochiKit.Style.getStyle(_5ab,"position")=="absolute"){
+break;
+}
+}while(_5ab=_5ab.offsetParent);
+_5ab=_5a8;
+do{
+_5a9-=_5ab.scrollTop||0;
+_5aa-=_5ab.scrollLeft||0;
+}while(_5ab=_5ab.parentNode);
+return new MochiKit.Style.Coordinates(_5aa,_5a9);
+}});
+MochiKit.Position.__new__=function(win){
+var m=MochiKit.Base;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Position.__new__(this);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Visual");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+dojo.require("MochiKit.Color");
+dojo.require("MochiKit.Position");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+JSAN.use("MochiKit.Color",[]);
+JSAN.use("MochiKit.Position",[]);
+}
+try{
+if(typeof (MochiKit.Base)==="undefined"||typeof (MochiKit.DOM)==="undefined"||typeof (MochiKit.Style)==="undefined"||typeof (MochiKit.Position)==="undefined"||typeof (MochiKit.Color)==="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style, MochiKit.Position and MochiKit.Color!";
+}
+if(typeof (MochiKit.Visual)=="undefined"){
+MochiKit.Visual={};
+}
+MochiKit.Visual.NAME="MochiKit.Visual";
+MochiKit.Visual.VERSION="1.4";
+MochiKit.Visual.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Visual.toString=function(){
+return this.__repr__();
+};
+MochiKit.Visual._RoundCorners=function(e,_5af){
+e=MochiKit.DOM.getElement(e);
+this._setOptions(_5af);
+if(this.options.__unstable__wrapElement){
+e=this._doWrap(e);
+}
+var _5b0=this.options.color;
+var C=MochiKit.Color.Color;
+if(this.options.color==="fromElement"){
+_5b0=C.fromBackground(e);
+}else{
+if(!(_5b0 instanceof C)){
+_5b0=C.fromString(_5b0);
+}
+}
+this.isTransparent=(_5b0.asRGB().a<=0);
+var _5b2=this.options.bgColor;
+if(this.options.bgColor==="fromParent"){
+_5b2=C.fromBackground(e.offsetParent);
+}else{
+if(!(_5b2 instanceof C)){
+_5b2=C.fromString(_5b2);
+}
+}
+this._roundCornersImpl(e,_5b0,_5b2);
+};
+MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){
+var _5b4=e.parentNode;
+var doc=MochiKit.DOM.currentDocument();
+if(typeof (doc.defaultView)==="undefined"||doc.defaultView===null){
+return e;
+}
+var _5b6=doc.defaultView.getComputedStyle(e,null);
+if(typeof (_5b6)==="undefined"||_5b6===null){
+return e;
+}
+var _5b7=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_5b6.getPropertyValue("padding-top"),marginRight:_5b6.getPropertyValue("padding-right"),marginBottom:_5b6.getPropertyValue("padding-bottom"),marginLeft:_5b6.getPropertyValue("padding-left"),padding:"0px"}});
+_5b7.innerHTML=e.innerHTML;
+e.innerHTML="";
+e.appendChild(_5b7);
+return e;
+},_roundCornersImpl:function(e,_5b9,_5ba){
+if(this.options.border){
+this._renderBorder(e,_5ba);
+}
+if(this._isTopRounded()){
+this._roundTopCorners(e,_5b9,_5ba);
+}
+if(this._isBottomRounded()){
+this._roundBottomCorners(e,_5b9,_5ba);
+}
+},_renderBorder:function(el,_5bc){
+var _5bd="1px solid "+this._borderColor(_5bc);
+var _5be="border-left: "+_5bd;
+var _5bf="border-right: "+_5bd;
+var _5c0="style='"+_5be+";"+_5bf+"'";
+el.innerHTML="<div "+_5c0+">"+el.innerHTML+"</div>";
+},_roundTopCorners:function(el,_5c2,_5c3){
+var _5c4=this._createCorner(_5c3);
+for(var i=0;i<this.options.numSlices;i++){
+_5c4.appendChild(this._createCornerSlice(_5c2,_5c3,i,"top"));
+}
+el.style.paddingTop=0;
+el.insertBefore(_5c4,el.firstChild);
+},_roundBottomCorners:function(el,_5c7,_5c8){
+var _5c9=this._createCorner(_5c8);
+for(var i=(this.options.numSlices-1);i>=0;i--){
+_5c9.appendChild(this._createCornerSlice(_5c7,_5c8,i,"bottom"));
+}
+el.style.paddingBottom=0;
+el.appendChild(_5c9);
+},_createCorner:function(_5cb){
+var dom=MochiKit.DOM;
+return dom.DIV({style:{backgroundColor:_5cb.toString()}});
+},_createCornerSlice:function(_5cd,_5ce,n,_5d0){
+var _5d1=MochiKit.DOM.SPAN();
+var _5d2=_5d1.style;
+_5d2.backgroundColor=_5cd.toString();
+_5d2.display="block";
+_5d2.height="1px";
+_5d2.overflow="hidden";
+_5d2.fontSize="1px";
+var _5d3=this._borderColor(_5cd,_5ce);
+if(this.options.border&&n===0){
+_5d2.borderTopStyle="solid";
+_5d2.borderTopWidth="1px";
+_5d2.borderLeftWidth="0px";
+_5d2.borderRightWidth="0px";
+_5d2.borderBottomWidth="0px";
+_5d2.height="0px";
+_5d2.borderColor=_5d3.toString();
+}else{
+if(_5d3){
+_5d2.borderColor=_5d3.toString();
+_5d2.borderStyle="solid";
+_5d2.borderWidth="0px 1px";
+}
+}
+if(!this.options.compact&&(n==(this.options.numSlices-1))){
+_5d2.height="2px";
+}
+this._setMargin(_5d1,n,_5d0);
+this._setBorder(_5d1,n,_5d0);
+return _5d1;
+},_setOptions:function(_5d4){
+this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false};
+MochiKit.Base.update(this.options,_5d4);
+this.options.numSlices=(this.options.compact?2:4);
+},_whichSideTop:function(){
+var _5d5=this.options.corners;
+if(this._hasString(_5d5,"all","top")){
+return "";
+}
+var _5d6=(_5d5.indexOf("tl")!=-1);
+var _5d7=(_5d5.indexOf("tr")!=-1);
+if(_5d6&&_5d7){
+return "";
+}
+if(_5d6){
+return "left";
+}
+if(_5d7){
+return "right";
+}
+return "";
+},_whichSideBottom:function(){
+var _5d8=this.options.corners;
+if(this._hasString(_5d8,"all","bottom")){
+return "";
+}
+var _5d9=(_5d8.indexOf("bl")!=-1);
+var _5da=(_5d8.indexOf("br")!=-1);
+if(_5d9&&_5da){
+return "";
+}
+if(_5d9){
+return "left";
+}
+if(_5da){
+return "right";
+}
+return "";
+},_borderColor:function(_5db,_5dc){
+if(_5db=="transparent"){
+return _5dc;
+}else{
+if(this.options.border){
+return this.options.border;
+}else{
+if(this.options.blend){
+return _5dc.blendedColor(_5db);
+}
+}
+}
+return "";
+},_setMargin:function(el,n,_5df){
+var _5e0=this._marginSize(n)+"px";
+var _5e1=(_5df=="top"?this._whichSideTop():this._whichSideBottom());
+var _5e2=el.style;
+if(_5e1=="left"){
+_5e2.marginLeft=_5e0;
+_5e2.marginRight="0px";
+}else{
+if(_5e1=="right"){
+_5e2.marginRight=_5e0;
+_5e2.marginLeft="0px";
+}else{
+_5e2.marginLeft=_5e0;
+_5e2.marginRight=_5e0;
+}
+}
+},_setBorder:function(el,n,_5e5){
+var _5e6=this._borderSize(n)+"px";
+var _5e7=(_5e5=="top"?this._whichSideTop():this._whichSideBottom());
+var _5e8=el.style;
+if(_5e7=="left"){
+_5e8.borderLeftWidth=_5e6;
+_5e8.borderRightWidth="0px";
+}else{
+if(_5e7=="right"){
+_5e8.borderRightWidth=_5e6;
+_5e8.borderLeftWidth="0px";
+}else{
+_5e8.borderLeftWidth=_5e6;
+_5e8.borderRightWidth=_5e6;
+}
+}
+},_marginSize:function(n){
+if(this.isTransparent){
+return 0;
+}
+var o=this.options;
+if(o.compact&&o.blend){
+var _5eb=[1,0];
+return _5eb[n];
+}else{
+if(o.compact){
+var _5ec=[2,1];
+return _5ec[n];
+}else{
+if(o.blend){
+var _5ed=[3,2,1,0];
+return _5ed[n];
+}else{
+var _5ee=[5,3,2,1];
+return _5ee[n];
+}
+}
+}
+},_borderSize:function(n){
+var o=this.options;
+var _5f1;
+if(o.compact&&(o.blend||this.isTransparent)){
+return 1;
+}else{
+if(o.compact){
+_5f1=[1,0];
+}else{
+if(o.blend){
+_5f1=[2,1,1,1];
+}else{
+if(o.border){
+_5f1=[0,2,0,0];
+}else{
+if(this.isTransparent){
+_5f1=[5,3,2,1];
+}else{
+return 0;
+}
+}
+}
+}
+}
+return _5f1[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,_5f6){
+new MochiKit.Visual._RoundCorners(e,_5f6);
+};
+MochiKit.Visual.roundClass=function(_5f7,_5f8,_5f9){
+var _5fa=MochiKit.DOM.getElementsByTagAndClassName(_5f7,_5f8);
+for(var i=0;i<_5fa.length;i++){
+MochiKit.Visual.roundElement(_5fa[i],_5f9);
+}
+};
+MochiKit.Visual.tagifyText=function(_5fc,_5fd){
+_5fd=_5fd||"position:relative";
+if(/MSIE/.test(navigator.userAgent)){
+_5fd+=";zoom:1";
+}
+_5fc=MochiKit.DOM.getElement(_5fc);
+var ma=MochiKit.Base.map;
+ma(function(_5ff){
+if(_5ff.nodeType==3){
+ma(function(_600){
+_5fc.insertBefore(MochiKit.DOM.SPAN({style:_5fd},_600==" "?String.fromCharCode(160):_600),_5ff);
+},_5ff.nodeValue.split(""));
+MochiKit.DOM.removeElement(_5ff);
+}
+},_5fc.childNodes);
+};
+MochiKit.Visual.forceRerendering=function(_601){
+try{
+_601=MochiKit.DOM.getElement(_601);
+var n=document.createTextNode(" ");
+_601.appendChild(n);
+_601.removeChild(n);
+}
+catch(e){
+}
+};
+MochiKit.Visual.multiple=function(_603,_604,_605){
+_605=MochiKit.Base.update({speed:0.1,delay:0},_605||{});
+var _606=_605.delay;
+var _607=0;
+MochiKit.Base.map(function(_608){
+_605.delay=_607*_605.speed+_606;
+new _604(_608,_605);
+_607+=1;
+},_603);
+};
+MochiKit.Visual.PAIRS={"slide":["slideDown","slideUp"],"blind":["blindDown","blindUp"],"appear":["appear","fade"],"size":["grow","shrink"]};
+MochiKit.Visual.toggle=function(_609,_60a,_60b){
+_609=MochiKit.DOM.getElement(_609);
+_60a=(_60a||"appear").toLowerCase();
+_60b=MochiKit.Base.update({queue:{position:"end",scope:(_609.id||"global"),limit:1}},_60b||{});
+var v=MochiKit.Visual;
+v[_609.style.display!="none"?v.PAIRS[_60a][1]:v.PAIRS[_60a][0]](_609,_60b);
+};
+MochiKit.Visual.Transitions={};
+MochiKit.Visual.Transitions.linear=function(pos){
+return pos;
+};
+MochiKit.Visual.Transitions.sinoidal=function(pos){
+return (-Math.cos(pos*Math.PI)/2)+0.5;
+};
+MochiKit.Visual.Transitions.reverse=function(pos){
+return 1-pos;
+};
+MochiKit.Visual.Transitions.flicker=function(pos){
+return ((-Math.cos(pos*Math.PI)/4)+0.75)+Math.random()/4;
+};
+MochiKit.Visual.Transitions.wobble=function(pos){
+return (-Math.cos(pos*Math.PI*(9*pos))/2)+0.5;
+};
+MochiKit.Visual.Transitions.pulse=function(pos,_613){
+if(!_613){
+return (Math.floor(pos*10)%2===0?(pos*10-Math.floor(pos*10)):1-(pos*10-Math.floor(pos*10)));
+}
+return (Math.round((pos%(1/_613))*_613)==0?((pos*_613*2)-Math.floor(pos*_613*2)):1-((pos*_613*2)-Math.floor(pos*_613*2)));
+};
+MochiKit.Visual.Transitions.none=function(pos){
+return 0;
+};
+MochiKit.Visual.Transitions.full=function(pos){
+return 1;
+};
+MochiKit.Visual.ScopedQueue=function(){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls();
+}
+this.__init__();
+};
+MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype,{__init__:function(){
+this.effects=[];
+this.interval=null;
+},add:function(_617){
+var _618=new Date().getTime();
+var _619=(typeof (_617.options.queue)=="string")?_617.options.queue:_617.options.queue.position;
+var ma=MochiKit.Base.map;
+switch(_619){
+case "front":
+ma(function(e){
+if(e.state=="idle"){
+e.startOn+=_617.finishOn;
+e.finishOn+=_617.finishOn;
+}
+},this.effects);
+break;
+case "end":
+var _61c;
+ma(function(e){
+var i=e.finishOn;
+if(i>=(_61c||i)){
+_61c=i;
+}
+},this.effects);
+_618=_61c||_618;
+break;
+case "break":
+ma(function(e){
+e.finalize();
+},this.effects);
+break;
+}
+_617.startOn+=_618;
+_617.finishOn+=_618;
+if(!_617.options.queue.limit||this.effects.length<_617.options.queue.limit){
+this.effects.push(_617);
+}
+if(!this.interval){
+this.interval=this.startLoop(MochiKit.Base.bind(this.loop,this),40);
+}
+},startLoop:function(func,_621){
+return setInterval(func,_621);
+},remove:function(_622){
+this.effects=MochiKit.Base.filter(function(e){
+return e!=_622;
+},this.effects);
+if(!this.effects.length){
+this.stopLoop(this.interval);
+this.interval=null;
+}
+},stopLoop:function(_624){
+clearInterval(_624);
+},loop:function(){
+var _625=new Date().getTime();
+MochiKit.Base.map(function(_626){
+_626.loop(_625);
+},this.effects);
+}});
+MochiKit.Visual.Queues={instances:{},get:function(_627){
+if(typeof (_627)!="string"){
+return _627;
+}
+if(!this.instances[_627]){
+this.instances[_627]=new MochiKit.Visual.ScopedQueue();
+}
+return this.instances[_627];
+}};
+MochiKit.Visual.Queue=MochiKit.Visual.Queues.get("global");
+MochiKit.Visual.DefaultOptions={transition:MochiKit.Visual.Transitions.sinoidal,duration:1,fps:25,sync:false,from:0,to:1,delay:0,queue:"parallel"};
+MochiKit.Visual.Base=function(){
+};
+MochiKit.Visual.Base.prototype={__class__:MochiKit.Visual.Base,start:function(_628){
+var v=MochiKit.Visual;
+this.options=MochiKit.Base.setdefault(_628||{},v.DefaultOptions);
+this.currentFrame=0;
+this.state="idle";
+this.startOn=this.options.delay*1000;
+this.finishOn=this.startOn+(this.options.duration*1000);
+this.event("beforeStart");
+if(!this.options.sync){
+v.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).add(this);
+}
+},loop:function(_62a){
+if(_62a>=this.startOn){
+if(_62a>=this.finishOn){
+return this.finalize();
+}
+var pos=(_62a-this.startOn)/(this.finishOn-this.startOn);
+var _62c=Math.round(pos*this.options.fps*this.options.duration);
+if(_62c>this.currentFrame){
+this.render(pos);
+this.currentFrame=_62c;
+}
+}
+},render:function(pos){
+if(this.state=="idle"){
+this.state="running";
+this.event("beforeSetup");
+this.setup();
+this.event("afterSetup");
+}
+if(this.state=="running"){
+if(this.options.transition){
+pos=this.options.transition(pos);
+}
+pos*=(this.options.to-this.options.from);
+pos+=this.options.from;
+this.event("beforeUpdate");
+this.update(pos);
+this.event("afterUpdate");
+}
+},cancel:function(){
+if(!this.options.sync){
+MochiKit.Visual.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).remove(this);
+}
+this.state="finished";
+},finalize:function(){
+this.render(1);
+this.cancel();
+this.event("beforeFinish");
+this.finish();
+this.event("afterFinish");
+},setup:function(){
+},finish:function(){
+},update:function(_62e){
+},event:function(_62f){
+if(this.options[_62f+"Internal"]){
+this.options[_62f+"Internal"](this);
+}
+if(this.options[_62f]){
+this.options[_62f](this);
+}
+},repr:function(){
+return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]";
+}};
+MochiKit.Visual.Parallel=function(_630,_631){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_630,_631);
+}
+this.__init__(_630,_631);
+};
+MochiKit.Visual.Parallel.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,{__class__:MochiKit.Visual.Parallel,__init__:function(_633,_634){
+this.effects=_633||[];
+this.start(_634);
+},update:function(_635){
+MochiKit.Base.map(function(_636){
+_636.render(_635);
+},this.effects);
+},finish:function(){
+MochiKit.Base.map(function(_637){
+_637.finalize();
+},this.effects);
+}});
+MochiKit.Visual.Opacity=function(_638,_639){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_638,_639);
+}
+this.__init__(_638,_639);
+};
+MochiKit.Visual.Opacity.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Opacity.prototype,{__class__:MochiKit.Visual.Opacity,__init__:function(_63b,_63c){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+this.element=MochiKit.DOM.getElement(_63b);
+if(this.element.currentStyle&&(!this.element.currentStyle.hasLayout)){
+s.setStyle(this.element,{zoom:1});
+}
+_63c=b.update({from:s.getStyle(this.element,"opacity")||0,to:1},_63c||{});
+this.start(_63c);
+},update:function(_63f){
+MochiKit.Style.setStyle(this.element,{"opacity":_63f});
+}});
+MochiKit.Visual.Move=function(_640,_641){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_640,_641);
+}
+this.__init__(_640,_641);
+};
+MochiKit.Visual.Move.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Move.prototype,{__class__:MochiKit.Visual.Move,__init__:function(_643,_644){
+this.element=MochiKit.DOM.getElement(_643);
+_644=MochiKit.Base.update({x:0,y:0,mode:"relative"},_644||{});
+this.start(_644);
+},setup:function(){
+MochiKit.DOM.makePositioned(this.element);
+var s=this.element.style;
+var _646=s.visibility;
+var _647=s.display;
+if(_647=="none"){
+s.visibility="hidden";
+s.display="";
+}
+this.originalLeft=parseFloat(MochiKit.Style.getStyle(this.element,"left")||"0");
+this.originalTop=parseFloat(MochiKit.Style.getStyle(this.element,"top")||"0");
+if(this.options.mode=="absolute"){
+this.options.x-=this.originalLeft;
+this.options.y-=this.originalTop;
+}
+if(_647=="none"){
+s.visibility=_646;
+s.display=_647;
+}
+},update:function(_648){
+MochiKit.Style.setStyle(this.element,{left:Math.round(this.options.x*_648+this.originalLeft)+"px",top:Math.round(this.options.y*_648+this.originalTop)+"px"});
+}});
+MochiKit.Visual.Scale=function(_649,_64a,_64b){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_649,_64a,_64b);
+}
+this.__init__(_649,_64a,_64b);
+};
+MochiKit.Visual.Scale.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Scale.prototype,{__class__:MochiKit.Visual.Scale,__init__:function(_64d,_64e,_64f){
+this.element=MochiKit.DOM.getElement(_64d);
+_64f=MochiKit.Base.update({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:_64e},_64f||{});
+this.start(_64f);
+},setup:function(){
+this.restoreAfterFinish=this.options.restoreAfterFinish||false;
+this.elementPositioning=MochiKit.Style.getStyle(this.element,"position");
+var ma=MochiKit.Base.map;
+var b=MochiKit.Base.bind;
+this.originalStyle={};
+ma(b(function(k){
+this.originalStyle[k]=this.element.style[k];
+},this),["top","left","width","height","fontSize"]);
+this.originalTop=this.element.offsetTop;
+this.originalLeft=this.element.offsetLeft;
+var _653=MochiKit.Style.getStyle(this.element,"font-size")||"100%";
+ma(b(function(_654){
+if(_653.indexOf(_654)>0){
+this.fontSize=parseFloat(_653);
+this.fontSizeType=_654;
+}
+},this),["em","px","%"]);
+this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;
+if(/^content/.test(this.options.scaleMode)){
+this.dims=[this.element.scrollHeight,this.element.scrollWidth];
+}else{
+if(this.options.scaleMode=="box"){
+this.dims=[this.element.offsetHeight,this.element.offsetWidth];
+}else{
+this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth];
+}
+}
+},update:function(_655){
+var _656=(this.options.scaleFrom/100)+(this.factor*_655);
+if(this.options.scaleContent&&this.fontSize){
+MochiKit.Style.setStyle(this.element,{fontSize:this.fontSize*_656+this.fontSizeType});
+}
+this.setDimensions(this.dims[0]*_656,this.dims[1]*_656);
+},finish:function(){
+if(this.restoreAfterFinish){
+MochiKit.Style.setStyle(this.element,this.originalStyle);
+}
+},setDimensions:function(_657,_658){
+var d={};
+var r=Math.round;
+if(/MSIE/.test(navigator.userAgent)){
+r=Math.ceil;
+}
+if(this.options.scaleX){
+d.width=r(_658)+"px";
+}
+if(this.options.scaleY){
+d.height=r(_657)+"px";
+}
+if(this.options.scaleFromCenter){
+var topd=(_657-this.dims[0])/2;
+var _65c=(_658-this.dims[1])/2;
+if(this.elementPositioning=="absolute"){
+if(this.options.scaleY){
+d.top=this.originalTop-topd+"px";
+}
+if(this.options.scaleX){
+d.left=this.originalLeft-_65c+"px";
+}
+}else{
+if(this.options.scaleY){
+d.top=-topd+"px";
+}
+if(this.options.scaleX){
+d.left=-_65c+"px";
+}
+}
+}
+MochiKit.Style.setStyle(this.element,d);
+}});
+MochiKit.Visual.Highlight=function(_65d,_65e){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_65d,_65e);
+}
+this.__init__(_65d,_65e);
+};
+MochiKit.Visual.Highlight.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,{__class__:MochiKit.Visual.Highlight,__init__:function(_660,_661){
+this.element=MochiKit.DOM.getElement(_660);
+_661=MochiKit.Base.update({startcolor:"#ffff99"},_661||{});
+this.start(_661);
+},setup:function(){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+if(s.getStyle(this.element,"display")=="none"){
+this.cancel();
+return;
+}
+this.oldStyle={backgroundImage:s.getStyle(this.element,"background-image")};
+s.setStyle(this.element,{backgroundImage:"none"});
+if(!this.options.endcolor){
+this.options.endcolor=MochiKit.Color.Color.fromBackground(this.element).toHexString();
+}
+if(b.isUndefinedOrNull(this.options.restorecolor)){
+this.options.restorecolor=s.getStyle(this.element,"background-color");
+}
+this._base=b.map(b.bind(function(i){
+return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+this._delta=b.map(b.bind(function(i){
+return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i];
+},this),[0,1,2]);
+},update:function(_666){
+var m="#";
+MochiKit.Base.map(MochiKit.Base.bind(function(i){
+m+=MochiKit.Color.toColorPart(Math.round(this._base[i]+this._delta[i]*_666));
+},this),[0,1,2]);
+MochiKit.Style.setStyle(this.element,{backgroundColor:m});
+},finish:function(){
+MochiKit.Style.setStyle(this.element,MochiKit.Base.update(this.oldStyle,{backgroundColor:this.options.restorecolor}));
+}});
+MochiKit.Visual.ScrollTo=function(_669,_66a){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_669,_66a);
+}
+this.__init__(_669,_66a);
+};
+MochiKit.Visual.ScrollTo.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,{__class__:MochiKit.Visual.ScrollTo,__init__:function(_66c,_66d){
+this.element=MochiKit.DOM.getElement(_66c);
+this.start(_66d||{});
+},setup:function(){
+var p=MochiKit.Position;
+p.prepare();
+var _66f=p.cumulativeOffset(this.element);
+if(this.options.offset){
+_66f.y+=this.options.offset;
+}
+var max;
+if(window.innerHeight){
+max=window.innerHeight-window.height;
+}else{
+if(document.documentElement&&document.documentElement.clientHeight){
+max=document.documentElement.clientHeight-document.body.scrollHeight;
+}else{
+if(document.body){
+max=document.body.clientHeight-document.body.scrollHeight;
+}
+}
+}
+this.scrollStart=p.windowOffset.y;
+this.delta=(_66f.y>max?max:_66f.y)-this.scrollStart;
+},update:function(_671){
+var p=MochiKit.Position;
+p.prepare();
+window.scrollTo(p.windowOffset.x,this.scrollStart+(_671*this.delta));
+}});
+MochiKit.Visual.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+MochiKit.Visual.Morph=function(_673,_674){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_673,_674);
+}
+this.__init__(_673,_674);
+};
+MochiKit.Visual.Morph.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Morph.prototype,{__class__:MochiKit.Visual.Morph,__init__:function(_676,_677){
+this.element=MochiKit.DOM.getElement(_676);
+this.start(_677||{});
+},setup:function(){
+var b=MochiKit.Base;
+var _679=this.options.style;
+this.styleStart={};
+this.styleEnd={};
+this.units={};
+var _67a,unit;
+for(var s in _679){
+_67a=_679[s];
+s=b.camelize(s);
+if(MochiKit.Visual.CSS_LENGTH.test(_67a)){
+var _67d=_67a.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+_67a=parseFloat(_67d[1]);
+unit=(_67d.length==3)?_67d[2]:null;
+this.styleEnd[s]=_67a;
+this.units[s]=unit;
+_67a=MochiKit.Style.getStyle(this.element,s);
+_67d=_67a.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+_67a=parseFloat(_67d[1]);
+this.styleStart[s]=_67a;
+}else{
+var c=MochiKit.Color.Color;
+_67a=c.fromString(_67a);
+if(_67a){
+this.units[s]="color";
+this.styleEnd[s]=_67a.toHexString();
+_67a=MochiKit.Style.getStyle(this.element,s);
+this.styleStart[s]=c.fromString(_67a).toHexString();
+this.styleStart[s]=b.map(b.bind(function(i){
+return parseInt(this.styleStart[s].slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+this.styleEnd[s]=b.map(b.bind(function(i){
+return parseInt(this.styleEnd[s].slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+}
+}
+}
+},update:function(_681){
+var _682;
+for(var s in this.styleStart){
+if(this.units[s]=="color"){
+var m="#";
+var _685=this.styleStart[s];
+var end=this.styleEnd[s];
+MochiKit.Base.map(MochiKit.Base.bind(function(i){
+m+=MochiKit.Color.toColorPart(Math.round(_685[i]+(end[i]-_685[i])*_681));
+},this),[0,1,2]);
+this.element.style[s]=m;
+}else{
+_682=this.styleStart[s]+Math.round((this.styleEnd[s]-this.styleStart[s])*_681*1000)/1000+this.units[s];
+this.element.style[s]=_682;
+}
+}
+}});
+MochiKit.Visual.fade=function(_688,_689){
+var s=MochiKit.Style;
+var _68b=s.getStyle(_688,"opacity");
+_689=MochiKit.Base.update({from:s.getStyle(_688,"opacity")||1,to:0,afterFinishInternal:function(_68c){
+if(_68c.options.to!==0){
+return;
+}
+s.hideElement(_68c.element);
+s.setStyle(_68c.element,{"opacity":_68b});
+}},_689||{});
+return new MochiKit.Visual.Opacity(_688,_689);
+};
+MochiKit.Visual.appear=function(_68d,_68e){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_68e=MochiKit.Base.update({from:(s.getStyle(_68d,"display")=="none"?0:s.getStyle(_68d,"opacity")||0),to:1,afterFinishInternal:function(_691){
+v.forceRerendering(_691.element);
+},beforeSetupInternal:function(_692){
+s.setStyle(_692.element,{"opacity":_692.options.from});
+s.showElement(_692.element);
+}},_68e||{});
+return new v.Opacity(_68d,_68e);
+};
+MochiKit.Visual.puff=function(_693,_694){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_693=MochiKit.DOM.getElement(_693);
+var _697={position:s.getStyle(_693,"position"),top:_693.style.top,left:_693.style.left,width:_693.style.width,height:_693.style.height,opacity:s.getStyle(_693,"opacity")};
+_694=MochiKit.Base.update({beforeSetupInternal:function(_698){
+MochiKit.Position.absolutize(_698.effects[0].element);
+},afterFinishInternal:function(_699){
+s.hideElement(_699.effects[0].element);
+s.setStyle(_699.effects[0].element,_697);
+},scaleContent:true,scaleFromCenter:true},_694||{});
+return new v.Parallel([new v.Scale(_693,200,{sync:true,scaleFromCenter:_694.scaleFromCenter,scaleContent:_694.scaleContent,restoreAfterFinish:true}),new v.Opacity(_693,{sync:true,to:0})],_694);
+};
+MochiKit.Visual.blindUp=function(_69a,_69b){
+var d=MochiKit.DOM;
+_69a=d.getElement(_69a);
+var _69d=d.makeClipping(_69a);
+_69b=MochiKit.Base.update({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(_69e){
+MochiKit.Style.hideElement(_69e.element);
+d.undoClipping(_69e.element,_69d);
+}},_69b||{});
+return new MochiKit.Visual.Scale(_69a,0,_69b);
+};
+MochiKit.Visual.blindDown=function(_69f,_6a0){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_69f=d.getElement(_69f);
+var _6a3=s.getElementDimensions(_69f);
+var _6a4;
+_6a0=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_6a3.h,originalWidth:_6a3.w},restoreAfterFinish:true,afterSetupInternal:function(_6a5){
+_6a4=d.makeClipping(_6a5.element);
+s.setStyle(_6a5.element,{height:"0px"});
+s.showElement(_6a5.element);
+},afterFinishInternal:function(_6a6){
+d.undoClipping(_6a6.element,_6a4);
+}},_6a0||{});
+return new MochiKit.Visual.Scale(_69f,100,_6a0);
+};
+MochiKit.Visual.switchOff=function(_6a7,_6a8){
+var d=MochiKit.DOM;
+_6a7=d.getElement(_6a7);
+var _6aa=MochiKit.Style.getStyle(_6a7,"opacity");
+var _6ab;
+_6a8=MochiKit.Base.update({duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetupInternal:function(_6ac){
+d.makePositioned(_6ac.element);
+_6ab=d.makeClipping(_6ac.element);
+},afterFinishInternal:function(_6ad){
+MochiKit.Style.hideElement(_6ad.element);
+d.undoClipping(_6ad.element,_6ab);
+d.undoPositioned(_6ad.element);
+MochiKit.Style.setStyle(_6ad.element,{"opacity":_6aa});
+}},_6a8||{});
+var v=MochiKit.Visual;
+return new v.appear(_6a7,{duration:0.4,from:0,transition:v.Transitions.flicker,afterFinishInternal:function(_6af){
+new v.Scale(_6af.element,1,_6a8);
+}});
+};
+MochiKit.Visual.dropOut=function(_6b0,_6b1){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_6b0=d.getElement(_6b0);
+var _6b4={top:s.getStyle(_6b0,"top"),left:s.getStyle(_6b0,"left"),opacity:s.getStyle(_6b0,"opacity")};
+_6b1=MochiKit.Base.update({duration:0.5,distance:100,beforeSetupInternal:function(_6b5){
+d.makePositioned(_6b5.effects[0].element);
+},afterFinishInternal:function(_6b6){
+s.hideElement(_6b6.effects[0].element);
+d.undoPositioned(_6b6.effects[0].element);
+s.setStyle(_6b6.effects[0].element,_6b4);
+}},_6b1||{});
+var v=MochiKit.Visual;
+return new v.Parallel([new v.Move(_6b0,{x:0,y:_6b1.distance,sync:true}),new v.Opacity(_6b0,{sync:true,to:0})],_6b1);
+};
+MochiKit.Visual.shake=function(_6b8,_6b9){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_6b8=d.getElement(_6b8);
+_6b9=MochiKit.Base.update({x:-20,y:0,duration:0.05,afterFinishInternal:function(_6bd){
+d.undoPositioned(_6bd.element);
+s.setStyle(_6bd.element,_6be);
+}},_6b9||{});
+var _6be={top:s.getStyle(_6b8,"top"),left:s.getStyle(_6b8,"left")};
+return new v.Move(_6b8,{x:20,y:0,duration:0.05,afterFinishInternal:function(_6bf){
+new v.Move(_6bf.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_6c0){
+new v.Move(_6c0.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_6c1){
+new v.Move(_6c1.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_6c2){
+new v.Move(_6c2.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_6c3){
+new v.Move(_6c3.element,_6b9);
+}});
+}});
+}});
+}});
+}});
+};
+MochiKit.Visual.slideDown=function(_6c4,_6c5){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_6c4=d.getElement(_6c4);
+if(!_6c4.firstChild){
+throw "MochiKit.Visual.slideDown must be used on a element with a child";
+}
+d.removeEmptyTextNodes(_6c4);
+var _6c9=s.getStyle(_6c4.firstChild,"bottom")||0;
+var _6ca=s.getElementDimensions(_6c4);
+var _6cb;
+_6c5=b.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_6ca.h,originalWidth:_6ca.w},restoreAfterFinish:true,afterSetupInternal:function(_6cc){
+d.makePositioned(_6cc.element);
+d.makePositioned(_6cc.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_6cc.element,{top:""});
+}
+_6cb=d.makeClipping(_6cc.element);
+s.setStyle(_6cc.element,{height:"0px"});
+s.showElement(_6cc.element);
+},afterUpdateInternal:function(_6cd){
+s.setStyle(_6cd.element.firstChild,{bottom:(_6cd.dims[0]-_6cd.element.clientHeight)+"px"});
+},afterFinishInternal:function(_6ce){
+d.undoClipping(_6ce.element,_6cb);
+if(/MSIE/.test(navigator.userAgent)){
+d.undoPositioned(_6ce.element);
+d.undoPositioned(_6ce.element.firstChild);
+}else{
+d.undoPositioned(_6ce.element.firstChild);
+d.undoPositioned(_6ce.element);
+}
+s.setStyle(_6ce.element.firstChild,{bottom:_6c9});
+}},_6c5||{});
+return new MochiKit.Visual.Scale(_6c4,100,_6c5);
+};
+MochiKit.Visual.slideUp=function(_6cf,_6d0){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_6cf=d.getElement(_6cf);
+if(!_6cf.firstChild){
+throw "MochiKit.Visual.slideUp must be used on a element with a child";
+}
+d.removeEmptyTextNodes(_6cf);
+var _6d4=s.getStyle(_6cf.firstChild,"bottom");
+var _6d5;
+_6d0=b.update({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(_6d6){
+d.makePositioned(_6d6.element);
+d.makePositioned(_6d6.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_6d6.element,{top:""});
+}
+_6d5=d.makeClipping(_6d6.element);
+s.showElement(_6d6.element);
+},afterUpdateInternal:function(_6d7){
+s.setStyle(_6d7.element.firstChild,{bottom:(_6d7.dims[0]-_6d7.element.clientHeight)+"px"});
+},afterFinishInternal:function(_6d8){
+s.hideElement(_6d8.element);
+d.undoClipping(_6d8.element,_6d5);
+d.undoPositioned(_6d8.element.firstChild);
+d.undoPositioned(_6d8.element);
+s.setStyle(_6d8.element.firstChild,{bottom:_6d4});
+}},_6d0||{});
+return new MochiKit.Visual.Scale(_6cf,0,_6d0);
+};
+MochiKit.Visual.squish=function(_6d9,_6da){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var _6dd;
+_6da=b.update({restoreAfterFinish:true,beforeSetupInternal:function(_6de){
+_6dd=d.makeClipping(_6de.element);
+},afterFinishInternal:function(_6df){
+MochiKit.Style.hideElement(_6df.element);
+d.undoClipping(_6df.element,_6dd);
+}},_6da||{});
+return new MochiKit.Visual.Scale(_6d9,/Opera/.test(navigator.userAgent)?1:0,_6da);
+};
+MochiKit.Visual.grow=function(_6e0,_6e1){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_6e0=d.getElement(_6e0);
+_6e1=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.full,scaleContent:true,scaleFromCenter:false},_6e1||{});
+var _6e5={top:_6e0.style.top,left:_6e0.style.left,height:_6e0.style.height,width:_6e0.style.width,opacity:s.getStyle(_6e0,"opacity")};
+var dims=s.getElementDimensions(_6e0);
+var _6e7,_6e8;
+var _6e9,_6ea;
+switch(_6e1.direction){
+case "top-left":
+_6e7=_6e8=_6e9=_6ea=0;
+break;
+case "top-right":
+_6e7=dims.w;
+_6e8=_6ea=0;
+_6e9=-dims.w;
+break;
+case "bottom-left":
+_6e7=_6e9=0;
+_6e8=dims.h;
+_6ea=-dims.h;
+break;
+case "bottom-right":
+_6e7=dims.w;
+_6e8=dims.h;
+_6e9=-dims.w;
+_6ea=-dims.h;
+break;
+case "center":
+_6e7=dims.w/2;
+_6e8=dims.h/2;
+_6e9=-dims.w/2;
+_6ea=-dims.h/2;
+break;
+}
+var _6eb=MochiKit.Base.update({beforeSetupInternal:function(_6ec){
+s.setStyle(_6ec.effects[0].element,{height:"0px"});
+s.showElement(_6ec.effects[0].element);
+},afterFinishInternal:function(_6ed){
+d.undoClipping(_6ed.effects[0].element);
+d.undoPositioned(_6ed.effects[0].element);
+s.setStyle(_6ed.effects[0].element,_6e5);
+}},_6e1||{});
+return new v.Move(_6e0,{x:_6e7,y:_6e8,duration:0.01,beforeSetupInternal:function(_6ee){
+s.hideElement(_6ee.element);
+d.makeClipping(_6ee.element);
+d.makePositioned(_6ee.element);
+},afterFinishInternal:function(_6ef){
+new v.Parallel([new v.Opacity(_6ef.element,{sync:true,to:1,from:0,transition:_6e1.opacityTransition}),new v.Move(_6ef.element,{x:_6e9,y:_6ea,sync:true,transition:_6e1.moveTransition}),new v.Scale(_6ef.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:/Opera/.test(navigator.userAgent)?1:0,transition:_6e1.scaleTransition,scaleContent:_6e1.scaleContent,scaleFromCenter:_6e1.scaleFromCenter,restoreAfterFinish:true})],_6eb);
+}});
+};
+MochiKit.Visual.shrink=function(_6f0,_6f1){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_6f0=d.getElement(_6f0);
+_6f1=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none,scaleContent:true,scaleFromCenter:false},_6f1||{});
+var _6f5={top:_6f0.style.top,left:_6f0.style.left,height:_6f0.style.height,width:_6f0.style.width,opacity:s.getStyle(_6f0,"opacity")};
+var dims=s.getElementDimensions(_6f0);
+var _6f7,_6f8;
+switch(_6f1.direction){
+case "top-left":
+_6f7=_6f8=0;
+break;
+case "top-right":
+_6f7=dims.w;
+_6f8=0;
+break;
+case "bottom-left":
+_6f7=0;
+_6f8=dims.h;
+break;
+case "bottom-right":
+_6f7=dims.w;
+_6f8=dims.h;
+break;
+case "center":
+_6f7=dims.w/2;
+_6f8=dims.h/2;
+break;
+}
+var _6f9;
+var _6fa=MochiKit.Base.update({beforeStartInternal:function(_6fb){
+_6f9=d.makePositioned(_6fb.effects[0].element);
+d.makeClipping(_6fb.effects[0].element);
+},afterFinishInternal:function(_6fc){
+s.hideElement(_6fc.effects[0].element);
+d.undoClipping(_6fc.effects[0].element,_6f9);
+d.undoPositioned(_6fc.effects[0].element);
+s.setStyle(_6fc.effects[0].element,_6f5);
+}},_6f1||{});
+return new v.Parallel([new v.Opacity(_6f0,{sync:true,to:0,from:1,transition:_6f1.opacityTransition}),new v.Scale(_6f0,/Opera/.test(navigator.userAgent)?1:0,{sync:true,transition:_6f1.scaleTransition,scaleContent:_6f1.scaleContent,scaleFromCenter:_6f1.scaleFromCenter,restoreAfterFinish:true}),new v.Move(_6f0,{x:_6f7,y:_6f8,sync:true,transition:_6f1.moveTransition})],_6fa);
+};
+MochiKit.Visual.pulsate=function(_6fd,_6fe){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var b=MochiKit.Base;
+var _702=MochiKit.Style.getStyle(_6fd,"opacity");
+_6fe=b.update({duration:3,from:0,afterFinishInternal:function(_703){
+MochiKit.Style.setStyle(_703.element,{"opacity":_702});
+}},_6fe||{});
+var _704=_6fe.transition||v.Transitions.sinoidal;
+var _705=b.bind(function(pos){
+return _704(1-v.Transitions.pulse(pos,_6fe.pulses));
+},_704);
+b.bind(_705,_704);
+return new v.Opacity(_6fd,b.update({transition:_705},_6fe));
+};
+MochiKit.Visual.fold=function(_707,_708){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_707=d.getElement(_707);
+var _70c={top:_707.style.top,left:_707.style.left,width:_707.style.width,height:_707.style.height};
+var _70d=d.makeClipping(_707);
+_708=MochiKit.Base.update({scaleContent:false,scaleX:false,afterFinishInternal:function(_70e){
+new v.Scale(_707,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(_70f){
+s.hideElement(_70f.element);
+d.undoClipping(_70f.element,_70d);
+s.setStyle(_70f.element,_70c);
+}});
+}},_708||{});
+return new v.Scale(_707,5,_708);
+};
+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","tagifyText","multiple","toggle","Parallel","Opacity","Move","Scale","Highlight","ScrollTo","Morph","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"];
+MochiKit.Visual.EXPORT_OK=["Base","PAIRS"];
+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.4";
+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","Selector","Style","LoggingPane","Color","Signal","Position","Visual"];
+if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.MochiKit");
+dojo.require("MochiKit.*");
+}
+if(typeof (JSAN)!="undefined"){
+(function(lst){
+for(var i=0;i<lst.length;i++){
+JSAN.use("MochiKit."+lst[i],[]);
+}
+})(MochiKit.MochiKit.SUBMODULES);
+}
+(function(){
+var _713=MochiKit.Base.extend;
+var self=MochiKit.MochiKit;
+var _715=self.SUBMODULES;
+var _716=[];
+var _717=[];
+var _718={};
+var i,k,m,all;
+for(i=0;i<_715.length;i++){
+m=MochiKit[_715[i]];
+_713(_716,m.EXPORT);
+_713(_717,m.EXPORT_OK);
+for(k in m.EXPORT_TAGS){
+_718[k]=_713(_718[k],m.EXPORT_TAGS[k]);
+}
+all=m.EXPORT_TAGS[":all"];
+if(!all){
+all=_713(null,m.EXPORT,m.EXPORT_OK);
+}
+var j;
+for(j=0;j<all.length;j++){
+k=all[j];
+self[k]=m[k];
+}
+}
+self.EXPORT=_716;
+self.EXPORT_OK=_717;
+self.EXPORT_TAGS=_718;
+}());
+}else{
+if(typeof (MochiKit.__compat__)=="undefined"){
+MochiKit.__compat__=true;
+}
+(function(){
+if(typeof (document)=="undefined"){
+return;
+}
+var _71e=document.getElementsByTagName("script");
+var _71f="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+var base=null;
+var _721=null;
+var _722={};
+var i;
+for(i=0;i<_71e.length;i++){
+var src=_71e[i].getAttribute("src");
+if(!src){
+continue;
+}
+_722[src]=true;
+if(src.match(/MochiKit.js$/)){
+base=src.substring(0,src.lastIndexOf("MochiKit.js"));
+_721=_71e[i];
+}
+}
+if(base===null){
+return;
+}
+var _725=MochiKit.MochiKit.SUBMODULES;
+for(var i=0;i<_725.length;i++){
+if(MochiKit[_725[i]]){
+continue;
+}
+var uri=base+_725[i]+".js";
+if(uri in _722){
+continue;
+}
+if(document.documentElement&&document.documentElement.namespaceURI==_71f){
+var s=document.createElementNS(_71f,"script");
+s.setAttribute("id","MochiKit_"+base+_725[i]);
+s.setAttribute("src",uri);
+s.setAttribute("type","application/x-javascript");
+_721.parentNode.appendChild(s);
+}else{
+document.write("<script src=\""+uri+"\" type=\"text/javascript\"></script>");
+}
+}
+})();
+}
+
+
diff --git a/mochikit_v14/packed/MochiKit/__package__.js b/mochikit_v14/packed/MochiKit/__package__.js
new file mode 100644 (file)
index 0000000..2f5be0d
--- /dev/null
@@ -0,0 +1,2 @@
+dojo.hostenv.conditionalLoadModule({"common": ["MochiKit.MochiKit"]});
+dojo.hostenv.moduleLoaded("MochiKit.*");
diff --git a/mochikit_v14/scripts/build.py b/mochikit_v14/scripts/build.py
new file mode 100755 (executable)
index 0000000..c9c5c91
--- /dev/null
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+execfile('scripts/make_docs.py')
+execfile('scripts/pack.py')
+import os
+import sys
+import glob
+import zipfile
+import re
+def json_encode(o, indent=0):
+    if isinstance(o, dict):
+        if len(o) == 0:
+            yield '{}'
+        else:
+            yield '{\n'
+            first = True
+            for key, value in o.iteritems():
+                if first:
+                    first = False
+                else:
+                    yield ',\n'
+                yield ' ' * (indent + 4)
+                assert isinstance(key, (basestring, float, int, long))
+                for chunk in json_encode(key):
+                    yield chunk
+                yield ': '
+                for chunk in json_encode(value, indent + 4):
+                    yield chunk
+            yield '\n' + (' ' * indent) + '}'
+    elif isinstance(o, list):
+        if len(o) == 0:
+            yield '[]'
+        else:
+            yield '[\n'
+            first = True
+            for value in o:
+                if first:
+                    first = False
+                else:
+                    yield ',\n'
+                yield ' ' * (indent + 4)
+                for chunk in json_encode(value, indent + 4):
+                    yield chunk
+            yield '\n' + (' ' * indent) + ']'
+    elif isinstance(o, basestring):
+        yield '"' + o.replace('\\', '\\\\').replace('"', '\\"') + '"'
+    elif isinstance(o, (float, int, long)):
+        yield str(o)
+    else:
+        raise NotImplementedError
+VERSION = re.search(
+    r"""(?mxs)MochiKit.MochiKit.VERSION\s*=\s*['"]([^'"]+)""",
+    file('MochiKit/MochiKit.js').read()
+).group(1)
+META = dict(
+    name='MochiKit',
+    author=['Bob Ippolito <bob@redivi.com>'],
+    abstract='Python-inspired JavaScript kit',
+    license='mit',
+    version=VERSION,
+    build_requires={'Test.Simple': '0.11'},
+    recommends={'JSAN': '0.10'},
+    provides={},
+    generated_by="MochiKit's build script",
+)
+FILES = glob.glob('lib/MochiKit/*.js')
+for fn in FILES:
+    modname = os.path.splitext(os.path.basename(fn))[0]
+    META['provides'][modname] = dict(file=fn, version=VERSION)
+if not os.path.exists('dist'):
+    os.makedirs('dist')
+
+pkg = '%(name)s-%(version)s' % META
+z = zipfile.ZipFile(
+    os.path.join('dist', pkg) + '.zip',
+    'w',
+    zipfile.ZIP_DEFLATED
+)
+MANIFEST = ['Changes', 'META.json', 'MANIFEST\t\t\tThis list of files']
+z.writestr(os.path.join(pkg, 'META.json'), ''.join(json_encode(META)))
+z.write(
+    os.path.join('doc', 'rst', 'MochiKit', 'VersionHistory.rst'),
+    os.path.join(pkg, 'Changes')
+)
+
+IGNOREDIRS = ['.svn', 'dist', 'scripts']
+src = os.path.join('.', '')
+dst = os.path.join(pkg, '')
+
+for root, dirs, files in os.walk(src):
+    for ex in IGNOREDIRS:
+        if ex in dirs:
+            dirs.remove(ex)
+    for fn in files:
+        if fn.startswith('.'):
+            continue
+        fn = os.path.join(root, fn)
+        mfn = fn[len(src):]
+        MANIFEST.append(mfn)
+        if mfn.startswith('MochiKit/'):
+            mfn = 'lib/' + mfn
+        dstfn = os.path.join(dst, mfn)
+        if os.path.splitext(fn)[1] == '.html':
+            s = file(fn).read()
+            s = s.replace('/MochiKit/', '/lib/MochiKit/')
+            s = s.replace(
+                "JSAN.addRepository('..');",
+                'JSAN.addRepository("../lib");',
+            )
+            z.writestr(dstfn, s)
+        else:
+            z.write(fn, dstfn)
+
+z.writestr(os.path.join(pkg, 'MANIFEST'), '\n'.join(MANIFEST + ['']))
+
+z.close()
diff --git a/mochikit_v14/scripts/custom_rhino.jar b/mochikit_v14/scripts/custom_rhino.jar
new file mode 100755 (executable)
index 0000000..21777b9
Binary files /dev/null and b/mochikit_v14/scripts/custom_rhino.jar differ
diff --git a/mochikit_v14/scripts/js.jar b/mochikit_v14/scripts/js.jar
new file mode 100755 (executable)
index 0000000..e0dba1c
Binary files /dev/null and b/mochikit_v14/scripts/js.jar differ
diff --git a/mochikit_v14/scripts/jscriptmochi.js b/mochikit_v14/scripts/jscriptmochi.js
new file mode 100644 (file)
index 0000000..a1e3959
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+
+run with:
+cscript.exe //nologo scripts\jscriptmochi.js
+
+**/
+if (typeof(print) == "undefined" && typeof(WScript) != "undefined") {
+    // Make JScript look like SpiderMonkey and Rhino
+    var print = WScript.Echo;
+    var load = function (fn) {
+        var fso = new ActiveXObject("Scripting.FileSystemObject");
+        var textStream = fso.OpenTextFile(fn, 1);
+        var namespace = undefined;
+        if (typeof(JSAN) != "undefined") {
+            namespace = JSAN.global;
+        }
+        arguments.callee.do_eval.apply(namespace, [textStream.ReadAll()]);
+    };
+    load.do_eval = function () {
+        eval(arguments[0]);
+    };
+}
+
+load('tests/standalone.js');
diff --git a/mochikit_v14/scripts/make_docs.py b/mochikit_v14/scripts/make_docs.py
new file mode 100755 (executable)
index 0000000..dd53eae
--- /dev/null
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+import os
+import sys
+try:
+    from pkg_resources import require
+    require("docutils>0.3.9")
+except ImportError:
+    pass
+from docutils import nodes, utils
+from docutils.core import publish_parts
+from docutils.parsers.rst import roles
+
+TEMPLATE = u"""%(html_prolog)s
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+%(html_head)s
+<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
+<script type="text/javascript" src="../../../packed/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="../../js/toc.js"></script>
+</head>
+<body>
+%(html_body)s
+</body>
+</html>
+"""
+def mochi_name(text):
+    name = text.split('(', 1)[0].split()[0]
+    base = ''
+    if name.startswith('MochiKit.'):
+        # cross-reference
+        parts = name.split('.')
+        base = parts[1] + '.html'
+        if parts[-1] in ("call", "apply"):
+            parts.pop()
+        name = '.'.join(parts[2:])
+    return base, name
+
+def role_mochiref(role, rawtext, text, lineno, inliner, options=None, content=[]):
+    if options is None:
+        options = {}
+    base, name = mochi_name(text)
+    ref = base
+    if name:
+        ref += '#fn-' + name.lower()
+    roles.set_classes(options)
+    options.setdefault('classes', []).append('mochiref')
+    node = nodes.reference(
+        text, utils.unescape(text), refuri=ref, **options)
+    return [node], []
+
+roles.register_canonical_role('mochiref', role_mochiref)
+
+def role_mochidef(role, rawtext, text, lineno, inliner, options=None, content=[]):
+    if options is None:
+        options = {}
+    base, name = mochi_name(text)
+    assert base == ''
+    ref = 'fn-' + utils.unescape(name.lower())
+    anchor = nodes.raw('', '\n<a name="%s"></a>\n' % (ref,), format='html')
+    roles.set_classes(options)
+    options.setdefault('classes', []).append('mochidef')
+    node = nodes.reference(
+        text, utils.unescape(text), refuri='#' + ref, **options)
+    return [anchor, node], []
+
+roles.register_canonical_role('mochidef', role_mochidef)
+        
+
+
+def main():
+    basepath = os.path.join('doc/rst', '')
+    destpath = os.path.join('doc/html', '')
+    for root, dirs, files in os.walk(basepath):
+        if '.svn' in dirs:
+            dirs.remove('.svn')
+        destroot = destpath + root[len(basepath):]
+        if not os.path.exists(destroot):
+            os.makedirs(destroot)
+        for fn in files:
+            basefn, ext = os.path.splitext(fn)
+            if ext == '.rst':
+                srcfn = os.path.join(root, fn)
+                dest = os.path.join(destroot, basefn + '.html')
+                if basefn != "index":
+                    try:
+                        if os.path.getmtime(dest) >= os.path.getmtime(srcfn):
+                            print srcfn, "not changed"
+                            continue
+                    except OSError:
+                        pass
+                print srcfn
+                parts = publish_parts(
+                    source_path=srcfn,
+                    source=file(srcfn, 'rb').read().decode('utf8'),
+                    destination_path=dest,
+                    writer_name='html',
+                    settings_overrides=dict(
+                        embed_stylesheet=False,
+                        stylesheet_path='include/css/documentation.css',
+                    ),
+                )
+                parts['html_head'] = parts['html_head'] % ('utf-8',)
+                parts['html_prolog'] = parts['html_prolog'] % ('utf-8',)
+                doc = (TEMPLATE % parts).encode("utf8")
+                out = file(dest, 'wb')
+                out.write(doc)
+                out.close()
+
+if __name__ == '__main__':
+    main()
diff --git a/mochikit_v14/scripts/pack.py b/mochikit_v14/scripts/pack.py
new file mode 100755 (executable)
index 0000000..7ef81da
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# custom_rhino.jar from:
+#   http://dojotoolkit.org/svn/dojo/buildscripts/lib/custom_rhino.jar
+#
+import os
+import re
+import sys
+import shutil
+import subprocess
+mk = file('MochiKit/MochiKit.js').read()
+if len(sys.argv) > 1:
+    outf = sys.stdout
+else:
+    outf = file('packed/MochiKit/MochiKit.js', 'w')
+VERSION = re.search(
+    r"""(?mxs)MochiKit.MochiKit.VERSION\s*=\s*['"]([^'"]+)""",
+    mk
+).group(1)
+if len(sys.argv) > 1:
+    SUBMODULES = sys.argv[1:]
+else:
+    SUBMODULES = map(str.strip, re.search(
+        r"""(?mxs)MochiKit.MochiKit.SUBMODULES\s*=\s*\[([^\]]+)""",
+        mk
+    ).group(1).replace(' ', '').replace('"', '').split(','))
+    SUBMODULES.append('MochiKit')
+alltext = '\n'.join(
+    [file('MochiKit/%s.js' % m).read() for m in SUBMODULES])
+
+tf = file('packed/_scratch.js', 'w')
+tf.write(alltext)
+tf.flush()
+p = subprocess.Popen(
+    ['java', '-jar', 'scripts/custom_rhino.jar', '-c', tf.name],
+    stdout=subprocess.PIPE,
+)
+print >>outf, """/***
+
+    MochiKit.MochiKit %(VERSION)s : 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.
+
+***/
+""" % locals()
+shutil.copyfileobj(p.stdout, outf)
+outf.write('\n')
+outf.flush()
+outf.close()
+tf.close()
+os.remove(tf.name)
diff --git a/mochikit_v14/scripts/rhinomochi.js b/mochikit_v14/scripts/rhinomochi.js
new file mode 100644 (file)
index 0000000..e19f06e
--- /dev/null
@@ -0,0 +1,2 @@
+#!/usr/bin/env java -jar scripts/js.jar
+load('tests/standalone.js');
diff --git a/mochikit_v14/scripts/spidermochi.js b/mochikit_v14/scripts/spidermochi.js
new file mode 100644 (file)
index 0000000..35e395c
--- /dev/null
@@ -0,0 +1,2 @@
+#!/usr/bin/env js -w
+load('tests/standalone.js');
diff --git a/mochikit_v14/tests/FakeJSAN.js b/mochikit_v14/tests/FakeJSAN.js
new file mode 100644 (file)
index 0000000..639519e
--- /dev/null
@@ -0,0 +1,40 @@
+var JSAN = {
+    global: this,
+    use: function (module, symbols) {
+        var components = module.split(/\./);
+        var fn = components.join('/') + '.js';
+        var o = JSAN.global;
+        var i, c;
+        for (i = 0; i < components.length; i++) {
+            o = o[components[i]];
+            if (typeof(o) == 'undefined') {
+                break;
+            }
+        }
+        if (typeof(o) != 'undefined') {
+            return o;
+        }
+
+        load(fn);
+        o = JSAN.global;
+        for (i = 0; i < components.length; i++) {
+            o = o[components[i]];
+            if (typeof(o) == 'undefined') {
+                return undefined;
+            }
+        }
+        if (!symbols) {
+            var tags = o.EXPORT_TAGS;
+            if (tags) {
+                symbols = tags[':common'] || tags[':all'];
+            }
+        }
+        if (symbols) {
+            for (i = 0; i < symbols.length; i++) {
+                c = symbols[i];
+                JSAN.global[c] = o[c];
+            }
+        }
+        return o;
+    }
+};
diff --git a/mochikit_v14/tests/SimpleTest/SimpleTest.js b/mochikit_v14/tests/SimpleTest/SimpleTest.js
new file mode 100644 (file)
index 0000000..06954a0
--- /dev/null
@@ -0,0 +1,366 @@
+/**
+ * SimpleTest, a partial Test.Simple/Test.More API compatible test library.
+ *
+ * Why?
+ *
+ * Test.Simple doesn't work on IE < 6.
+ * TODO:
+ *  * Support the Test.Simple API used by MochiKit, to be able to test MochiKit 
+ * itself against IE 5.5
+ *
+**/
+
+if (typeof(SimpleTest) == "undefined") {
+    var SimpleTest = {};
+}
+
+// Check to see if the TestRunner is present and has logging
+if (typeof(parent) != "undefined" && parent.TestRunner) {
+    SimpleTest._logEnabled = parent.TestRunner.logEnabled;
+}
+
+SimpleTest._tests = [];
+SimpleTest._stopOnLoad = true;
+
+/**
+ * Something like assert.
+**/
+SimpleTest.ok = function (condition, name, diag) {
+    var test = {'result': !!condition, 'name': name, 'diag': diag || ""};
+    if (SimpleTest._logEnabled) {
+        var msg = test.result ? "PASS" : "FAIL";
+        msg += " | " + test.name;
+        if (test.result) {
+            parent.TestRunner.logger.log(msg);
+        } else {
+            msg += " | " + test.diag;
+            parent.TestRunner.logger.error(msg);
+        }
+    }
+    SimpleTest._tests.push(test);
+};
+
+/**
+ * Roughly equivalent to ok(a==b, name)
+**/
+SimpleTest.is = function (a, b, name) {
+    var repr = MochiKit.Base.repr;
+    SimpleTest.ok(a == b, name, "got " + repr(a) + ", expected " + repr(b));
+};
+
+
+/**
+ * Makes a test report, returns it as a DIV element.
+**/
+SimpleTest.report = function () {
+    var DIV = MochiKit.DOM.DIV;
+    var passed = 0;
+    var failed = 0;
+    var results = MochiKit.Base.map(
+        function (test) {
+            var cls, msg;
+            if (test.result) {
+                passed++;
+                cls = "test_ok";
+                msg = "ok - " + test.name;
+            } else {
+                failed++;
+                cls = "test_not_ok";
+                msg = "not ok - " + test.name + " " + test.diag;
+            }
+            return DIV({"class": cls}, msg);
+        },
+        SimpleTest._tests
+    );
+    var summary_class = ((failed == 0) ? 'all_pass' : 'some_fail');
+    return DIV({'class': 'tests_report'},
+        DIV({'class': 'tests_summary ' + summary_class},
+            DIV({'class': 'tests_passed'}, "Passed: " + passed),
+            DIV({'class': 'tests_failed'}, "Failed: " + failed)),
+        results
+    );
+};
+
+/**
+ * Toggle element visibility
+**/
+SimpleTest.toggle = function(el) {
+    if (MochiKit.Style.getStyle(el, 'display') == 'block') {
+        el.style.display = 'none';
+    } else {
+        el.style.display = 'block';
+    }
+};
+
+/**
+ * Toggle visibility for divs with a specific class.
+**/
+SimpleTest.toggleByClass = function (cls) {
+    var elems = getElementsByTagAndClassName('div', cls);
+    MochiKit.Base.map(SimpleTest.toggle, elems);
+};
+
+/**
+ * Shows the report in the browser
+**/
+
+SimpleTest.showReport = function() {
+    var togglePassed = A({'href': '#'}, "Toggle passed tests");
+    var toggleFailed = A({'href': '#'}, "Toggle failed tests");
+    togglePassed.onclick = partial(SimpleTest.toggleByClass, 'test_ok');
+    toggleFailed.onclick = partial(SimpleTest.toggleByClass, 'test_not_ok');
+    var body = document.getElementsByTagName("body")[0];
+    var firstChild = body.childNodes[0];
+    var addNode;
+    if (firstChild) {
+        addNode = function (el) {
+            body.insertBefore(el, firstChild);
+        };
+    } else {
+        addNode = function (el) {
+            body.appendChild(el)
+        };
+    }
+    addNode(togglePassed);
+    addNode(SPAN(null, " "));
+    addNode(toggleFailed);
+    addNode(SimpleTest.report());
+};
+
+/**
+ * Tells SimpleTest to don't finish the test when the document is loaded,
+ * useful for asynchronous tests.
+ *
+ * When SimpleTest.waitForExplicitFinish is called,
+ * explicit SimpleTest.finish() is required.
+**/
+SimpleTest.waitForExplicitFinish = function () {
+    SimpleTest._stopOnLoad = false;
+};
+
+/**
+ * Talks to the TestRunner if being ran on a iframe and the parent has a 
+ * TestRunner object.
+**/
+SimpleTest.talkToRunner = function () {
+    if (typeof(parent) != "undefined" && parent.TestRunner) {
+        parent.TestRunner.testFinished(document);
+    }
+};
+
+/**
+ * Finishes the tests. This is automatically called, except when 
+ * SimpleTest.waitForExplicitFinish() has been invoked.
+**/
+SimpleTest.finish = function () {
+    SimpleTest.showReport();
+    SimpleTest.talkToRunner();
+};
+
+
+addLoadEvent(function() {
+    if (SimpleTest._stopOnLoad) {
+        SimpleTest.finish();
+    }
+});
+
+//  --------------- Test.Builder/Test.More isDeeply() -----------------
+
+
+SimpleTest.DNE = {dne: 'Does not exist'};
+SimpleTest.LF = "\r\n";
+SimpleTest._isRef = function (object) {
+    var type = typeof(object);
+    return type == 'object' || type == 'function';
+};
+
+
+SimpleTest._deepCheck = function (e1, e2, stack, seen) {
+    var ok = false;
+    // Either they're both references or both not.
+    var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2));
+    if (e1 == null && e2 == null) {
+        ok = true;
+    } else if (e1 != null ^ e2 != null) {
+        ok = false;
+    } else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) {
+        ok = false;
+    } else if (sameRef && e1 == e2) {
+        // Handles primitives and any variables that reference the same
+        // object, including functions.
+        ok = true;
+    } else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) {
+        ok = SimpleTest._eqArray(e1, e2, stack, seen);
+    } else if (typeof e1 == "object" && typeof e2 == "object") {
+        ok = SimpleTest._eqAssoc(e1, e2, stack, seen);
+    } else {
+        // If we get here, they're not the same (function references must
+        // always simply rererence the same function).
+        stack.push({ vals: [e1, e2] });
+        ok = false;
+    }
+    return ok;
+};
+
+SimpleTest._eqArray = function (a1, a2, stack, seen) {
+    // Return if they're the same object.
+    if (a1 == a2) return true;
+
+    // JavaScript objects have no unique identifiers, so we have to store
+    // references to them all in an array, and then compare the references
+    // directly. It's slow, but probably won't be much of an issue in
+    // practice. Start by making a local copy of the array to as to avoid
+    // confusing a reference seen more than once (such as [a, a]) for a
+    // circular reference.
+    for (var j = 0; j < seen.length; j++) {
+        if (seen[j][0] == a1) {
+            return seen[j][1] == a2;
+        }
+    }
+
+    // If we get here, we haven't seen a1 before, so store it with reference
+    // to a2.
+    seen.push([ a1, a2 ]);
+
+    var ok = true;
+    // Only examines enumerable attributes. Only works for numeric arrays!
+    // Associative arrays return 0. So call _eqAssoc() for them, instead.
+    var max = a1.length > a2.length ? a1.length : a2.length;
+    if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen);
+    for (var i = 0; i < max; i++) {
+        var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i];
+        var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i];
+        stack.push({ type: 'Array', idx: i, vals: [e1, e2] });
+        if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+            stack.pop();
+        } else {
+            break;
+        }
+    }
+    return ok;
+};
+
+SimpleTest._eqAssoc = function (o1, o2, stack, seen) {
+    // Return if they're the same object.
+    if (o1 == o2) return true;
+
+    // JavaScript objects have no unique identifiers, so we have to store
+    // references to them all in an array, and then compare the references
+    // directly. It's slow, but probably won't be much of an issue in
+    // practice. Start by making a local copy of the array to as to avoid
+    // confusing a reference seen more than once (such as [a, a]) for a
+    // circular reference.
+    seen = seen.slice(0);
+    for (var j = 0; j < seen.length; j++) {
+        if (seen[j][0] == o1) {
+            return seen[j][1] == o2;
+        }
+    }
+
+    // If we get here, we haven't seen o1 before, so store it with reference
+    // to o2.
+    seen.push([ o1, o2 ]);
+
+    // They should be of the same class.
+
+    var ok = true;
+    // Only examines enumerable attributes.
+    var o1Size = 0; for (var i in o1) o1Size++;
+    var o2Size = 0; for (var i in o2) o2Size++;
+    var bigger = o1Size > o2Size ? o1 : o2;
+    for (var i in bigger) {
+        var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i];
+        var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i];
+        stack.push({ type: 'Object', idx: i, vals: [e1, e2] });
+        if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+            stack.pop();
+        } else {
+            break;
+        }
+    }
+    return ok;
+};
+
+SimpleTest._formatStack = function (stack) {
+    var variable = '$Foo';
+    for (var i = 0; i < stack.length; i++) {
+        var entry = stack[i];
+        var type = entry['type'];
+        var idx = entry['idx'];
+        if (idx != null) {
+            if (/^\d+$/.test(idx)) {
+                // Numeric array index.
+                variable += '[' + idx + ']';
+            } else {
+                // Associative array index.
+                idx = idx.replace("'", "\\'");
+                variable += "['" + idx + "']";
+            }
+        }
+    }
+
+    var vals = stack[stack.length-1]['vals'].slice(0, 2);
+    var vars = [
+        variable.replace('$Foo',     'got'),
+        variable.replace('$Foo',     'expected')
+    ];
+
+    var out = "Structures begin differing at:" + SimpleTest.LF;
+    for (var i = 0; i < vals.length; i++) {
+        var val = vals[i];
+        if (val == null) {
+            val = 'undefined';
+        } else {
+             val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'";
+        }
+    }
+
+    out += vars[0] + ' = ' + vals[0] + SimpleTest.LF;
+    out += vars[1] + ' = ' + vals[1] + SimpleTest.LF;
+    
+    return '    ' + out;
+};
+
+
+SimpleTest.isDeeply = function (it, as, name) {
+    var ok;
+    // ^ is the XOR operator.
+    if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) {
+        // One's a reference, one isn't.
+        ok = false;
+    } else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) {
+        // Neither is an object.
+        ok = SimpleTest.is(it, as, name);
+    } else {
+        // We have two objects. Do a deep comparison.
+        var stack = [], seen = [];
+        if ( SimpleTest._deepCheck(it, as, stack, seen)) {
+            ok = SimpleTest.ok(true, name);
+        } else {
+            ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack));
+        }
+    }
+    return ok;
+};
+
+SimpleTest.typeOf = function (object) {
+    var c = Object.prototype.toString.apply(object);
+    var name = c.substring(8, c.length - 1);
+    if (name != 'Object') return name;
+    // It may be a non-core class. Try to extract the class name from
+    // the constructor function. This may not work in all implementations.
+    if (/function ([^(\s]+)/.test(Function.toString.call(object.constructor))) {
+        return RegExp.$1;
+    }
+    // No idea. :-(
+    return name;
+};
+
+SimpleTest.isa = function (object, clas) {
+    return SimpleTest.typeOf(object) == clas;
+};
+
+// Global symbols:
+var ok = SimpleTest.ok;
+var is = SimpleTest.is;
+var isDeeply = SimpleTest.isDeeply;
diff --git a/mochikit_v14/tests/SimpleTest/TestRunner.js b/mochikit_v14/tests/SimpleTest/TestRunner.js
new file mode 100644 (file)
index 0000000..a12d891
--- /dev/null
@@ -0,0 +1,159 @@
+/**
+ * TestRunner: A test runner for SimpleTest
+ * TODO:
+ * 
+ *  * Avoid moving iframes: That causes reloads on mozilla and opera.
+ *
+ *
+**/
+var TestRunner = {};
+TestRunner.logEnabled = false;
+TestRunner._iframes = {};
+TestRunner._iframeDocuments = {};
+TestRunner._iframeRows = {};
+TestRunner._currentTest = 0;
+TestRunner._urls = [];
+TestRunner._testsDiv = DIV();
+TestRunner._progressDiv = DIV();
+TestRunner._summaryDiv = DIV(null, 
+    H1(null, "Tests Summary"),
+    TABLE(null, 
+        THEAD(null, 
+            TR(null,
+                TH(null, "Test"), 
+                TH(null, "Passed"), 
+                TH(null, "Failed")
+            )
+        ),
+        TBODY()
+    )
+);
+
+/**
+ * This function is called after generating the summary.
+**/
+TestRunner.onComplete = null;
+
+/**
+ * If logEnabled is true, this is the logger that will be used.
+**/
+TestRunner.logger = MochiKit.Logging.logger;
+
+/**
+ * Toggle element visibility
+**/
+TestRunner._toggle = function(el) {
+    if (el.className == "noshow") {
+        el.className = "";
+        el.style.cssText = "";
+    } else {
+        el.className = "noshow";
+        el.style.cssText = "width:0px; height:0px; border:0px;";
+    }
+};
+
+
+/**
+ * Creates the iframe that contains a test
+**/
+TestRunner._makeIframe = function (url) {
+    var iframe = document.createElement('iframe');
+    iframe.src = url;
+    iframe.name = url;
+    iframe.width = "500";
+    var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
+    var tr = TR(null, TD({'colspan': '3'}, iframe));
+    iframe._row = tr;
+    tbody.appendChild(tr);
+    return iframe;
+};
+
+/**
+ * TestRunner entry point.
+ *
+ * The arguments are the URLs of the test to be ran.
+ *
+**/
+TestRunner.runTests = function (/*url...*/) {
+    if (TestRunner.logEnabled)
+        TestRunner.logger.log("SimpleTest START");
+  
+    var body = document.getElementsByTagName("body")[0];
+    appendChildNodes(body,
+        TestRunner._testsDiv,
+        TestRunner._progressDiv,
+        TestRunner._summaryDiv
+    );
+    for (var i = 0; i < arguments.length; i++) {
+        TestRunner._urls.push(arguments[i]); 
+    }
+    TestRunner.runNextTest();
+};
+
+/**
+ * Run the next test. If no test remains, calls makeSummary
+**/
+TestRunner.runNextTest = function() {
+    if (TestRunner._currentTest < TestRunner._urls.length) {
+        var url = TestRunner._urls[TestRunner._currentTest];
+        var progress = SPAN(null,
+            "Running ", A({href:url}, url), "..."
+        );
+        
+        if (TestRunner.logEnabled)
+            TestRunner.logger.log(scrapeText(progress));
+        
+        TestRunner._progressDiv.appendChild(progress);
+        TestRunner._iframes[url] = TestRunner._makeIframe(url);
+    }  else {
+        TestRunner.makeSummary();
+        if (TestRunner.onComplete)
+            TestRunner.onComplete();
+    }
+};
+
+/**
+ * This stub is called by SimpleTest when a test is finished.
+**/
+TestRunner.testFinished = function (doc) {
+    appendChildNodes(TestRunner._progressDiv, SPAN(null, "Done"), BR());
+    var finishedURL = TestRunner._urls[TestRunner._currentTest];
+    
+    if (TestRunner.logEnabled)
+        TestRunner.logger.debug("SimpleTest finished " + finishedURL);
+    
+    TestRunner._iframeDocuments[finishedURL] = doc;
+    // TestRunner._iframes[finishedURL].style.display = "none";
+    TestRunner._toggle(TestRunner._iframes[finishedURL]);
+    TestRunner._currentTest++;
+    TestRunner.runNextTest();
+};
+
+/**
+ * Display the summary in the browser
+**/
+TestRunner.makeSummary = function() {
+    if (TestRunner.logEnabled)
+        TestRunner.logger.log("SimpleTest FINISHED");
+    var rows = [];
+    for (var url in TestRunner._iframeDocuments) {
+        var doc = TestRunner._iframeDocuments[url];
+        var nOK = withDocument(doc,
+            partial(getElementsByTagAndClassName, 'div', 'test_ok')
+        ).length;
+        var nNotOK = withDocument(doc,
+            partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
+        ).length;
+        var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]);
+        var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])";
+        var row = TR(
+            {'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}}, 
+            TD(null, url),
+            TD(null, nOK),
+            TD(null, nNotOK)
+        );
+        row.onclick = toggle;
+        var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
+        tbody.insertBefore(row, TestRunner._iframes[url]._row)
+    }
+};
diff --git a/mochikit_v14/tests/SimpleTest/test.css b/mochikit_v14/tests/SimpleTest/test.css
new file mode 100755 (executable)
index 0000000..38a4014
--- /dev/null
@@ -0,0 +1,28 @@
+.test_ok {
+       color: green;
+       display: none;
+}
+.test_not_ok {
+       color: red;
+       display: block;
+}
+
+.test_ok, .test_not_ok {
+   border-bottom-width: 2px;
+   border-bottom-style: solid;
+   border-bottom-color: black;
+}
+
+.all_pass {
+    background-color: lime;
+}
+
+.some_fail {
+    background-color: red;
+}
+
+.tests_report {
+       border-width: 2px;
+       border-style: solid;
+       width: 20em;
+}
diff --git a/mochikit_v14/tests/cli.js b/mochikit_v14/tests/cli.js
new file mode 100644 (file)
index 0000000..1843460
--- /dev/null
@@ -0,0 +1,6 @@
+MochiKit = {__export__: true};
+load('tests/FakeJSAN.js')
+JSAN.use('MochiKit.MockDOM');
+var window = this;
+var document = MochiKit.MockDOM.document;
+JSAN.use('MochiKit.MochiKit');
diff --git a/mochikit_v14/tests/index.html b/mochikit_v14/tests/index.html
new file mode 100644 (file)
index 0000000..f3b4a46
--- /dev/null
@@ -0,0 +1,25 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="SimpleTest/TestRunner.js"></script>
+</head>
+<body>
+<script type="text/javascript">
+TestRunner.runTests(
+    'test_MochiKit-Async.html',
+    'test_MochiKit-Base.html',
+    'test_MochiKit-DateTime.html',
+    'test_MochiKit-DOM.html',
+    'test_MochiKit-Style.html',
+    'test_MochiKit-Format.html',
+    'test_MochiKit-Iter.html',
+    'test_MochiKit-Logging.html',
+    'test_MochiKit-MochiKit.html',
+    'test_MochiKit-Color.html',
+    'test_MochiKit-Selector.html',
+    'test_MochiKit-Signal.html',
+    'test_MochiKit-Visual.html'
+);
+</script>
+</body>
+</html>
diff --git a/mochikit_v14/tests/standalone.js b/mochikit_v14/tests/standalone.js
new file mode 100644 (file)
index 0000000..d485712
--- /dev/null
@@ -0,0 +1,16 @@
+load('tests/cli.js');
+
+JSAN.use('MochiKit.Test');
+
+print("[[ MochiKit.Base ]]");
+runTests('tests.test_Base');
+print("[[ MochiKit.Color ]]");
+runTests('tests.test_Color');
+print("[[ MochiKit.DateTime ]]");
+runTests('tests.test_DateTime');
+print("[[ MochiKit.Format ]]");
+runTests('tests.test_Format');
+print("[[ MochiKit.Iter ]]");
+runTests('tests.test_Iter');
+print("[[ MochiKit.Logging ]]");
+runTests('tests.test_Logging');
diff --git a/mochikit_v14/tests/test_Base.js b/mochikit_v14/tests/test_Base.js
new file mode 100644 (file)
index 0000000..8d2cd6e
--- /dev/null
@@ -0,0 +1,507 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Base'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Base'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Base = function (t) {
+    // test bind
+    var not_self = {"toString": function () { return "not self"; } };
+    var self = {"toString": function () { return "self"; } };
+    var func = function (arg) { return this.toString() + " " + arg; };
+    var boundFunc = bind(func, self);
+    not_self.boundFunc = boundFunc;
+
+    t.is( isEmpty([], [], ""), true, "isEmpty true" )
+    t.is( isEmpty([], [1], ""), true, "isEmpty true" )
+    t.is( isNotEmpty([], [], ""), false, "isNotEmpty false" )
+    t.is( isNotEmpty([], [1], ""), false, "isNotEmpty false" )
+
+    t.is( isEmpty([1], [1], "1"), false, "isEmpty false" )
+    t.is( isEmpty([1], [1], "1"), false, "isEmpty false" )
+    t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" )
+    t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" )
+
+    t.is( boundFunc("foo"), "self foo", "boundFunc bound to self properly" );
+    t.is( not_self.boundFunc("foo"), "self foo", "boundFunc bound to self on another obj" );
+    t.is( bind(boundFunc, not_self)("foo"), "not self foo", "boundFunc successfully rebound!" );
+    t.is( bind(boundFunc, undefined, "foo")(), "self foo", "boundFunc partial no self change" );
+    t.is( bind(boundFunc, not_self, "foo")(), "not self foo", "boundFunc partial self change" );
+
+    // test method
+    not_self = {"toString": function () { return "not self"; } };
+    self = {"toString": function () { return "self"; } };
+    func = function (arg) { return this.toString() + " " + arg; };
+    var boundMethod = method(self, func);
+    not_self.boundMethod = boundMethod;
+
+    t.is( boundMethod("foo"), "self foo", "boundMethod bound to self properly" );
+    t.is( not_self.boundMethod("foo"), "self foo", "boundMethod bound to self on another obj" );
+    t.is( method(not_self, boundMethod)("foo"), "not self foo", "boundMethod successfully rebound!" );
+    t.is( method(undefined, boundMethod, "foo")(), "self foo", "boundMethod partial no self change" );
+    t.is( method(not_self, boundMethod, "foo")(), "not self foo", "boundMethod partial self change" );
+
+
+
+
+    // test bindMethods
+
+    var O = function (value) {
+        bindMethods(this);
+        this.value = value;
+    };
+    O.prototype.func = function () {
+        return this.value;
+    };
+
+    var o = new O("boring");
+    var p = {};
+    p.func = o.func;
+    var func = o.func;
+    t.is( o.func(), "boring", "bindMethods doesn't break shit" );
+    t.is( p.func(), "boring", "bindMethods works on other objects" );
+    t.is( func(), "boring", "bindMethods works on functions" );
+
+    var p = clone(o);
+    t.ok( p instanceof O, "cloned correct inheritance" );
+    var q = clone(p);
+    t.ok( q instanceof O, "clone-cloned correct inheritance" );
+    q.foo = "bar";
+    t.is( p.foo, undefined, "clone-clone is copy-on-write" );
+    p.bar = "foo";
+    t.is( o.bar, undefined, "clone is copy-on-write" );
+    t.is( q.bar, "foo", "clone-clone has proper delegation" );
+    // unbind
+    p.func = bind(p.func, null);
+    t.is( p.func(), "boring", "clone function calls correct" );
+    q.value = "awesome";
+    t.is( q.func(), "awesome", "clone really does work" );
+    
+    // test boring boolean funcs
+
+    t.is( isCallable(isCallable), true, "isCallable returns true on itself" );
+    t.is( isCallable(1), false, "isCallable returns false on numbers" );
+
+    t.is( isUndefined(null), false, "null is not undefined" );
+    t.is( isUndefined(""), false, "empty string is not undefined" );
+    t.is( isUndefined(undefined), true, "undefined is undefined" );
+    t.is( isUndefined({}.foo), true, "missing property is undefined" );
+
+    t.is( isUndefinedOrNull(null), true, "null is undefined or null" );
+    t.is( isUndefinedOrNull(""), false, "empty string is not undefined or null" );
+    t.is( isUndefinedOrNull(undefined), true, "undefined is undefined or null" );
+    t.is( isUndefinedOrNull({}.foo), true, "missing property is undefined or null" );
+
+    // test extension of arrays
+    var a = [];
+    var b = [];
+    var three = [1, 2, 3];
+
+    extend(a, three, 1);
+    t.ok( objEqual(a, [2, 3]), "extend to an empty array" );
+    extend(a, three, 1)
+    t.ok( objEqual(a, [2, 3, 2, 3]), "extend to a non-empty array" );
+
+    extend(b, three);
+    t.ok( objEqual(b, three), "extend of an empty array" );
+
+    t.is( compare(1, 2), -1, "numbers compare lt" );
+    t.is( compare(2, 1), 1, "numbers compare gt" );
+    t.is( compare(1, 1), 0, "numbers compare eq" );
+    t.is( compare([1], [1]), 0, "arrays compare eq" );
+    t.is( compare([1], [1, 2]), -1, "arrays compare lt (length)" );
+    t.is( compare([1, 2], [2, 1]), -1, "arrays compare lt (contents)" );
+    t.is( compare([1, 2], [1]), 1, "arrays compare gt (length)" );
+    t.is( compare([2, 1], [1, 1]), 1, "arrays compare gt (contents)" );
+    
+    // test partial application
+    var a = [];
+    var func = function (a, b) {
+        if (arguments.length != 2) {
+            return "bad args";
+        } else {
+            return this.value + a + b;
+        }
+    };
+    var self = {"value": 1, "func": func};
+    var self2 = {"value": 2};
+    t.is( self.func(2, 3), 6, "setup for test is correct" );
+    self.funcTwo = partial(self.func, 2);
+    t.is( self.funcTwo(3), 6, "partial application works" );
+    t.is( self.funcTwo(3), 6, "partial application works still" );
+    t.is( bind(self.funcTwo, self2)(3), 7, "rebinding partial works" );
+    self.funcTwo = bind(bind(self.funcTwo, self2), null);
+    t.is( self.funcTwo(3), 6, "re-unbinding partial application works" );
+
+    
+    // nodeWalk test
+    // ... looks a lot like a DOM tree on purpose
+    var tree = {
+        "id": "nodeWalkTestTree",
+        "test:int": "1",
+        "childNodes": [
+            {
+                "test:int": "2",
+                "childNodes": [
+                    {"test:int": "5"},
+                    "ignored string",
+                    {"ignored": "object"},
+                    ["ignored", "list"],
+                    {
+                        "test:skipchildren": "1",
+                        "childNodes": [{"test:int": 6}]
+                    }
+                ]
+            },
+            {"test:int": "3"},
+            {"test:int": "4"}
+        ]
+    }
+
+    var visitedNodes = [];
+    nodeWalk(tree, function (node) {
+        var attr = node["test:int"];
+        if (attr) {
+            visitedNodes.push(attr);
+        }
+        if (node["test:skipchildren"]) {
+                return;
+        }
+        return node.childNodes;
+    });
+
+    t.ok( objEqual(visitedNodes, ["1", "2", "3", "4", "5"]), "nodeWalk looks like it works");
+    
+    // test map
+    var minusOne = function (x) { return x - 1; };
+    var res = map(minusOne, [1, 2, 3]);
+    t.ok( objEqual(res, [0, 1, 2]), "map works" );
+
+    var res2 = xmap(minusOne, 1, 2, 3);
+    t.ok( objEqual(res2, res), "xmap works" );
+
+    res = map(operator.add, [1, 2, 3], [2, 4, 6]);
+    t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works" );
+
+    res = map(operator.add, [1, 2, 3], [2, 4, 6, 8]);
+    t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (q long)" );
+
+    res = map(operator.add, [1, 2, 3, 4], [2, 4, 6]);
+    t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (p long)" );
+
+    res = map(null, [1, 2, 3], [2, 4, 6]);
+    t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "map(null, p, q) works" );
+
+    res = zip([1, 2, 3], [2, 4, 6]);
+    t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "zip(p, q) works" );
+
+    res = map(null, [1, 2, 3]);
+    t.ok( objEqual(res, [1, 2, 3]), "map(null, lst) works" );
+
+
+    
+    
+    t.is( isNotEmpty("foo"), true, "3 char string is not empty" );
+    t.is( isNotEmpty(""), false, "0 char string is empty" );
+    t.is( isNotEmpty([1, 2, 3]), true, "3 element list is not empty" );
+    t.is( isNotEmpty([]), false, "0 element list is empty" );
+
+    // test filter
+    var greaterThanThis = function (x) { return x > this; };
+    var greaterThanOne = function (x) { return x > 1; };
+    var res = filter(greaterThanOne, [-1, 0, 1, 2, 3]);
+    t.ok( objEqual(res, [2, 3]), "filter works" );
+    var res = filter(greaterThanThis, [-1, 0, 1, 2, 3], 1);
+    t.ok( objEqual(res, [2, 3]), "filter self works" );
+    var res2 = xfilter(greaterThanOne, -1, 0, 1, 2, 3);
+    t.ok( objEqual(res2, res), "xfilter works" );
+    t.is(objMax(1, 2, 9, 12, 42, -16, 16), 42, "objMax works (with numbers)");
+    t.is(objMin(1, 2, 9, 12, 42, -16, 16), -16, "objMin works (with numbers)");
+    
+    // test adapter registry
+
+    var R = new AdapterRegistry();
+    R.register("callable", isCallable, function () { return "callable"; });
+    R.register("arrayLike", isArrayLike, function () { return "arrayLike"; });
+    t.is( R.match(function () {}), "callable", "registry found callable" );
+    t.is( R.match([]), "arrayLike", "registry found ArrayLike" );
+    try {
+        R.match(null);
+        t.ok( false, "non-matching didn't raise!" );
+    } catch (e) {
+        t.is( e, NotFound, "non-matching raised correctly" );
+    }
+    R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" });
+    R.register("undefined", isUndefined, function () { return "undefined" });
+    t.is( R.match(undefined), "undefinedOrNull", "priorities are as documented" );
+    t.ok( R.unregister("undefinedOrNull"), "removed adapter" );
+    t.is( R.match(undefined), "undefined", "adapter was removed" );
+    R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" }, true);
+    t.is( R.match(undefined), "undefinedOrNull", "override works" );
+    
+    var a1 = {"a": 1, "b": 2, "c": 2};
+    var a2 = {"a": 2, "b": 1, "c": 2};
+    t.is( keyComparator("a")(a1, a2), -1, "keyComparator 1 lt" );
+    t.is( keyComparator("c")(a1, a2), 0, "keyComparator 1 eq" );
+    t.is( keyComparator("c", "b")(a1, a2), 1, "keyComparator 2 eq gt" );
+    t.is( keyComparator("c", "a")(a1, a2), -1, "keyComparator 2 eq lt" );
+    t.is( reverseKeyComparator("a")(a1, a2), 1, "reverseKeyComparator" );
+    t.is( compare(concat([1], [2], [3]), [1, 2, 3]), 0, "concat" );
+    t.is( repr("foo"), '"foo"', "string repr" );
+    t.is( repr(1), '1', "number repr" );
+    t.is( listMin([1, 3, 5, 3, -1]), -1, "listMin" );
+    t.is( objMin(1, 3, 5, 3, -1), -1, "objMin" );
+    t.is( listMax([1, 3, 5, 3, -1]), 5, "listMax" );
+    t.is( objMax(1, 3, 5, 3, -1), 5, "objMax" );
+
+    var v = keys(a1);
+    v.sort();
+    t.is( compare(v, ["a", "b", "c"]), 0, "keys" );
+    v = items(a1);
+    v.sort();
+    t.is( compare(v, [["a", 1], ["b", 2], ["c", 2]]), 0, "items" );
+
+    var StringMap = function() {};
+    a = new StringMap();
+    a.foo = "bar";
+    b = new StringMap();
+    b.foo = "bar";
+    try {
+        compare(a, b);
+        t.ok( false, "bad comparison registered!?" );
+    } catch (e) {
+        t.ok( e instanceof TypeError, "bad comparison raised TypeError" );
+    }
+
+    t.is( repr(a), "[object Object]", "default repr for StringMap" );
+    var isStringMap = function () {
+        for (var i = 0; i < arguments.length; i++) {
+            if (!(arguments[i] instanceof StringMap)) {
+                return false;
+            }
+        }
+        return true;
+    };
+
+    registerRepr("stringMap",
+        isStringMap,
+        function (obj) {
+            return "StringMap(" + repr(items(obj)) + ")";
+        }
+    );
+
+    t.is( repr(a), 'StringMap([["foo", "bar"]])', "repr worked" );
+
+    // not public API
+    MochiKit.Base.reprRegistry.unregister("stringMap");
+    
+    t.is( repr(a), "[object Object]", "default repr for StringMap" );
+
+    registerComparator("stringMap",
+        isStringMap,
+        function (a, b) {
+            // no sorted(...) in base
+            a = items(a);
+            b = items(b);
+            a.sort(compare);
+            b.sort(compare);
+            return compare(a, b);
+        }
+    );
+
+    t.is( compare(a, b), 0, "registerComparator" );
+
+    update(a, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1});
+    t.is( a.foo, "bar", "update worked (first obj)" );
+    t.is( a.wibble, "baz", "update worked (second obj)" );
+    t.is( a.grr, 1, "update worked (skipped undefined and null)" );
+    t.is( compare(a, b), 1, "update worked (comparison)" );
+
+
+    setdefault(a, {"foo": "unf"}, {"bar": "web taco"} );
+    t.is( a.foo, "bar", "setdefault worked (skipped existing)" );
+    t.is( a.bar, "web taco", "setdefault worked (set non-existing)" );
+
+    var c = items(merge({"foo": "bar"}, {"wibble": "baz"}));
+    c.sort(compare);
+    t.is( compare(c, [["foo", "bar"], ["wibble", "baz"]]), 0, "merge worked" );
+    
+    // not public API
+    MochiKit.Base.comparatorRegistry.unregister("stringMap");
+    
+    try {
+        compare(a, b);
+        t.ok( false, "bad comparison registered!?" );
+    } catch (e) {
+        t.ok( e instanceof TypeError, "bad comparison raised TypeError" );
+    }
+    
+    var o = {"__repr__": function () { return "__repr__"; }};
+    t.is( repr(o), "__repr__", "__repr__ protocol" );
+    t.is( repr(MochiKit.Base), MochiKit.Base.__repr__(), "__repr__ protocol when repr is defined" );
+    var o = {"NAME": "NAME"};
+    t.is( repr(o), "NAME", "NAME protocol (obj)" );
+    o = function () { return "TACO" };
+    o.NAME = "NAME";
+    t.is( repr(o), "NAME", "NAME protocol (func)" );
+    
+    t.is( repr(MochiKit.Base.nameFunctions), "MochiKit.Base.nameFunctions", "test nameFunctions" );
+    // Done!
+
+    t.is( urlEncode("1+2=2").toUpperCase(), "1%2B2%3D2", "urlEncode" );
+    t.is( queryString(["a", "b"], [1, "two"]), "a=1&b=two", "queryString");
+    t.is( queryString({"a": 1}), "a=1", "one item alternate form queryString" );
+    var o = {"a": 1, "b": 2, "c": function() {}};
+    var res = queryString(o).split("&");
+    res.sort();
+    t.is( res.join("&"), "a=1&b=2", "two item alternate form queryString, function skip" );
+    var res = parseQueryString("1+1=2&b=3%3D2");
+    t.is( res["1 1"], "2", "parseQueryString pathological name" );
+    t.is( res.b, "3=2", "parseQueryString second name:value pair" );
+    var res = parseQueryString("foo=one&foo=two", true);
+    t.is( res["foo"].join(" "), "one two", "parseQueryString useArrays" );
+    var res = parseQueryString("?foo=2&bar=1");
+    t.is( res["foo"], "2", "parseQueryString strip leading question mark");
+
+    t.is( serializeJSON("foo\n\r\b\f\t"), "\"foo\\n\\r\\b\\f\\t\"", "string JSON" );
+    t.is( serializeJSON(null), "null", "null JSON");
+    try {
+        serializeJSON(undefined);
+        t.ok(false, "undefined should not be serializable");
+    } catch (e) {
+        t.ok(e instanceof TypeError, "undefined not serializable");
+    }
+    t.is( serializeJSON(1), "1", "1 JSON");
+    t.is( serializeJSON(1.23), "1.23", "1.23 JSON");
+    t.is( serializeJSON(serializeJSON), null, "function JSON (null, not string)" );
+    t.is( serializeJSON([1, "2", 3.3]), "[1, \"2\", 3.3]", "array JSON" );
+    var res = evalJSON(serializeJSON({"a":1, "b":2}));
+    t.is( res.a, 1, "evalJSON on an object (1)" );
+    t.is( res.b, 2, "evalJSON on an object (2)" );
+    var res = {"a": 1, "b": 2, "json": function () { return this; }};
+    var res = evalJSON(serializeJSON(res));
+    t.is( res.a, 1, "evalJSON on an object that jsons self (1)" );
+    t.is( res.b, 2, "evalJSON on an object that jsons self (2)" );
+    var strJSON = {"a": 1, "b": 2, "json": function () { return "json"; }};
+    t.is( serializeJSON(strJSON), "\"json\"", "json serialization calling" );
+    t.is( serializeJSON([strJSON]), "[\"json\"]", "json serialization calling in a structure" );
+    registerJSON("isDateLike",
+        isDateLike,
+        function (d) {
+            return "this was a date";
+        }
+    );
+    t.is( serializeJSON(new Date()), "\"this was a date\"", "json registry" );
+    MochiKit.Base.jsonRegistry.unregister("isDateLike");
+
+    var a = {"foo": {"bar": 12, "wibble": 13}};
+    var b = {"foo": {"baz": 4, "bar": 16}, "bar": 4};
+    updatetree(a, b);
+    var expect = [["bar", 16], ["baz", 4], ["wibble", 13]];
+    var got = items(a.foo);
+    got.sort(compare);
+    t.is( repr(got), repr(expect), "updatetree merge" );
+    t.is( a.bar, 4, "updatetree insert" );
+    
+    var c = counter();
+    t.is( c(), 1, "counter starts at 1" );
+    t.is( c(), 2, "counter increases" );
+    c = counter(2);
+    t.is( c(), 2, "counter starts at 2" );
+    t.is( c(), 3, "counter increases" );
+
+    t.is( findValue([1, 2, 3], 4), -1, "findValue returns -1 on not found");
+    t.is( findValue([1, 2, 3], 1), 0, "findValue returns correct index");
+    t.is( findValue([1, 2, 3], 1, 1), -1, "findValue honors start");
+    t.is( findValue([1, 2, 3], 2, 0, 1), -1, "findValue honors end");
+    t.is( findIdentical([1, 2, 3], 4), -1, "findIdentical returns -1");
+    t.is( findIdentical([1, 2, 3], 1), 0, "findIdentical returns correct index");
+    t.is( findIdentical([1, 2, 3], 1, 1), -1, "findIdentical honors start");
+    t.is( findIdentical([1, 2, 3], 2, 0, 1), -1, "findIdentical honors end");
+    t.is( isNull(undefined), false, "isNull doesn't match undefined" );
+
+    var flat = flattenArguments(1, "2", 3, [4, [5, [6, 7], 8, [], 9]]);
+    var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9];
+    t.is( repr(flat), repr(expect), "flattenArguments" );
+
+    var fn = function () {
+        return [this, concat(arguments)];
+    }
+    t.is( methodcaller("toLowerCase")("FOO"), "foo", "methodcaller with a method name" );
+    t.is( repr(methodcaller(fn, 2, 3)(1)), "[1, [2, 3]]", "methodcaller with a function" );
+
+    var f1 = function (x) { return [1, x]; };
+    var f2 = function (x) { return [2, x]; };
+    var f3 = function (x) { return [3, x]; };
+    t.is( repr(f1(f2(f3(4)))), "[1, [2, [3, 4]]]", "test the compose test" );
+    t.is( repr(compose(f1,f2,f3)(4)), "[1, [2, [3, 4]]]", "three fn composition works" );
+    t.is( repr(compose(compose(f1,f2),f3)(4)), "[1, [2, [3, 4]]]", "associative left" );
+    t.is( repr(compose(f1,compose(f2,f3))(4)), "[1, [2, [3, 4]]]", "associative right" );
+    
+    try {
+        compose(f1, "foo");
+        t.ok( false, "wrong compose argument not raised!" );
+    } catch (e) {
+        t.is( e.name, 'TypeError', "wrong compose argument raised correctly" );
+    }
+    
+    t.is(camelize('one'), 'one', 'one word');
+    t.is(camelize('one-two'), 'oneTwo', 'two words');
+    t.is(camelize('one-two-three'), 'oneTwoThree', 'three words');
+    t.is(camelize('1-one'), '1One', 'letter and word');
+    t.is(camelize('one-'), 'one', 'trailing hyphen');
+    t.is(camelize('-one'), 'One', 'starting hyphen');
+    t.is(camelize('o-two'), 'oTwo', 'one character and word');
+
+    var flat = flattenArray([1, "2", 3, [4, [5, [6, 7], 8, [], 9]]]);
+    var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9];
+    t.is( repr(flat), repr(expect), "flattenArray" );
+    
+    /* mean */
+    try {
+        mean();
+        t.ok( false, "no arguments didn't raise!" );
+    } catch (e) {
+        t.is( e.name, 'TypeError', "no arguments raised correctly" );
+    }    
+    t.is( mean(1), 1, 'single argument (arg list)');
+    t.is( mean([1]), 1, 'single argument (array)');
+    t.is( mean(1,2,3), 2, 'three arguments (arg list)');
+    t.is( mean([1,2,3]), 2, 'three arguments (array)');
+    t.is( average(1), 1, 'test the average alias');
+
+    /* median */
+    try {
+        median();
+        t.ok( false, "no arguments didn't raise!" );
+    } catch (e) {
+        t.is( e.name, 'TypeError', "no arguments raised correctly" );
+    }
+    t.is( median(1), 1, 'single argument (arg list)');
+    t.is( median([1]), 1, 'single argument (array)');
+    t.is( median(3,1,2), 2, 'three arguments (arg list)');
+    t.is( median([3,1,2]), 2, 'three arguments (array)');
+    t.is( median(3,1,2,4), 2.5, 'four arguments (arg list)');
+    t.is( median([3,1,2,4]), 2.5, 'four arguments (array)');
+
+    /* #185 */
+    t.is( serializeJSON(parseQueryString("")), "{}", "parseQueryString('')" );
+    t.is( serializeJSON(parseQueryString("", true)), "{}", "parseQueryString('', true)" );
+
+    /* #109 */
+    t.is( queryString({ids: [1,2,3]}), "ids=1&ids=2&ids=3", "queryString array value" );
+    t.is( queryString({ids: "123"}), "ids=123", "queryString string value" );
+
+    /* test values */
+    var o = {a: 1, b: 2, c: 4, d: -1};
+    var got = values(o);
+    got.sort();
+    t.is( repr(got), repr([-1, 1, 2, 4]), "values()" );
+
+    t.is( queryString([["foo", "bar"], ["baz", "wibble"]]), "foo=baz&bar=wibble" );
+    o = parseQueryString("foo=1=1=1&bar=2&baz&wibble=");
+    t.is( o.foo, "1=1=1", "parseQueryString multiple = first" );
+    t.is( o.bar, "2", "parseQueryString multiple = second" );
+    t.is( o.baz, "", "parseQueryString multiple = third" );
+    t.is( o.wibble, "", "parseQueryString multiple = fourth" );
+
+};
diff --git a/mochikit_v14/tests/test_Color.js b/mochikit_v14/tests/test_Color.js
new file mode 100644 (file)
index 0000000..17d418d
--- /dev/null
@@ -0,0 +1,137 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Color'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Color'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Color = function (t) {
+    var approx = function (a, b, msg) {
+        return t.is(a.toPrecision(4), b.toPrecision(4), msg);
+    };
+   
+    t.is( Color.whiteColor().toHexString(), "#ffffff", "whiteColor has right hex" );
+    t.is( Color.blackColor().toHexString(), "#000000", "blackColor has right hex" );
+    t.is( Color.blueColor().toHexString(), "#0000ff", "blueColor has right hex" );
+    t.is( Color.redColor().toHexString(), "#ff0000", "redColor has right hex" );
+    t.is( Color.greenColor().toHexString(), "#00ff00", "greenColor has right hex" );
+    t.is( compare(Color.whiteColor(), Color.whiteColor()), 0, "default colors compare right" );
+    t.ok( Color.whiteColor() == Color.whiteColor(), "default colors are interned" );
+    t.ok( Color.whiteColor().toRGBString(), "rgb(255,255,255)", "toRGBString white" );
+    t.ok( Color.blueColor().toRGBString(), "rgb(0,0,255)", "toRGBString blue" );
+    t.is( Color.fromRGB(190/255, 222/255, 173/255).toHexString(), "#bedead", "fromRGB works" );
+    t.is( Color.fromRGB(226/255, 15.9/255, 182/255).toHexString(), "#e210b6", "fromRGB < 16 works" );
+    t.is( Color.fromRGB({r:190/255,g:222/255,b:173/255}).toHexString(), "#bedead", "alt fromRGB works" );
+    t.is( Color.fromHexString("#bedead").toHexString(), "#bedead", "round-trip hex" );
+    t.is( Color.fromString("#bedead").toHexString(), "#bedead", "round-trip string(hex)" );
+    t.is( Color.fromRGBString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" );
+    t.is( Color.fromString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" );
+
+    var hsl = Color.redColor().asHSL();
+    approx( hsl.h, 0.0, "red hsl.h" );
+    approx( hsl.s, 1.0, "red hsl.s" );
+    approx( hsl.l, 0.5, "red hsl.l" );
+    hsl = Color.fromRGB(0, 0, 0.5).asHSL();
+    approx( hsl.h, 2/3, "darkblue hsl.h" );
+    approx( hsl.s, 1.0, "darkblue hsl.s" );
+    approx( hsl.l, 0.25, "darkblue hsl.l" );
+    hsl = Color.fromString("#4169E1").asHSL();
+    approx( hsl.h, (5/8), "4169e1 h");
+    approx( hsl.s, (8/11), "4169e1 s");
+    approx( hsl.l, (29/51), "4169e1 l");
+    hsl = Color.fromString("#555544").asHSL();
+    approx( hsl.h, (1/6), "555544 h" );
+    approx( hsl.s, (1/9), "555544 s" );
+    approx( hsl.l, (3/10), "555544 l" );
+    hsl = Color.fromRGB(0.5, 1, 0.5).asHSL();
+    approx( hsl.h, 1/3, "aqua hsl.h" );
+    approx( hsl.s, 1.0, "aqua hsl.s" );
+    approx( hsl.l, 0.75, "aqua hsl.l" );
+    t.is(
+        Color.fromHSL(hsl.h, hsl.s, hsl.l).toHexString(),
+        Color.fromRGB(0.5, 1, 0.5).toHexString(),
+        "fromHSL works with components"
+    );
+    t.is(
+        Color.fromHSL(hsl).toHexString(),
+        Color.fromRGB(0.5, 1, 0.5).toHexString(),
+        "fromHSL alt form"
+    );
+    t.is(
+        Color.fromString("hsl(120,100%,75%)").toHexString(),
+        "#80ff80",
+        "fromHSLString"
+    );
+    t.is( 
+        Color.fromRGB(0.5, 1, 0.5).toHSLString(),
+        "hsl(120,100.0%,75.00%)",
+        "toHSLString"
+    );
+    t.is( Color.fromHSL(0, 0, 0).toHexString(), "#000000", "fromHSL to black" );
+    hsl = Color.blackColor().asHSL();
+    approx( hsl.h, 0.0, "black hsl.h" );
+    approx( hsl.s, 0.0, "black hsl.s" );
+    approx( hsl.l, 0.0, "black hsl.l" );
+    hsl.h = 1.0;
+    hsl = Color.blackColor().asHSL();
+    approx( hsl.h, 0.0, "asHSL returns copy" );
+    var rgb = Color.brownColor().asRGB();
+    approx( rgb.r, 153/255, "brown rgb.r" );
+    approx( rgb.g, 102/255, "brown rgb.g" );
+    approx( rgb.b, 51/255, "brown rgb.b" );
+    rgb.r = 0;
+    rgb = Color.brownColor().asRGB();
+    approx( rgb.r, 153/255, "asRGB returns copy" );
+
+    t.is( Color.fromName("aqua").toHexString(), "#00ffff", "aqua fromName" );
+    t.is( Color.fromString("aqua").toHexString(), "#00ffff", "aqua fromString" );
+    t.is( Color.fromName("transparent"), Color.transparentColor(), "transparent fromName" );
+    t.is( Color.fromString("transparent"), Color.transparentColor(), "transparent fromString" );
+    t.is( Color.transparentColor().toRGBString(), "rgba(0,0,0,0)", "transparent toRGBString" );
+    t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").asRGB().a, 0.5, "rgba parsing alpha correctly" );
+    t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").toRGBString(), "rgba(0,255,255,0.5)", "rgba output correctly" );
+    t.is( Color.fromRGBString("rgba( 0, 255, 255, 1)").toHexString(), "#00ffff", "fromRGBString with spaces and alpha" );
+    t.is( Color.fromRGBString("rgb( 0, 255, 255)").toHexString(), "#00ffff", "fromRGBString with spaces" );
+    t.is( Color.fromRGBString("rgb( 0, 100%, 255)").toHexString(), "#00ffff", "fromRGBString with percents" );
+    
+    var hsv = Color.redColor().asHSV();
+    approx( hsv.h, 0.0, "red hsv.h" );
+    approx( hsv.s, 1.0, "red hsv.s" );
+    approx( hsv.v, 1.0, "red hsv.v" );
+    t.is( Color.fromHSV(hsv).toHexString(), Color.redColor().toHexString(), "red hexstring" );
+    hsv = Color.fromRGB(0, 0, 0.5).asHSV();
+    approx( hsv.h, 2/3, "darkblue hsv.h" );
+    approx( hsv.s, 1.0, "darkblue hsv.s" );
+    approx( hsv.v, 0.5, "darkblue hsv.v" );
+    t.is( Color.fromHSV(hsv).toHexString(), Color.fromRGB(0, 0, 0.5).toHexString(), "darkblue hexstring" );
+    hsv = Color.fromString("#4169E1").asHSV();
+    approx( hsv.h, 5/8, "4169e1 h");
+    approx( hsv.s, 32/45, "4169e1 s");
+    approx( hsv.v, 15/17, "4169e1 l");
+    t.is( Color.fromHSV(hsv).toHexString(), "#4169e1", "4169e1 hexstring" );
+    hsv = Color.fromString("#555544").asHSV();
+    approx( hsv.h, 1/6, "555544 h" );
+    approx( hsv.s, 1/5, "555544 s" );
+    approx( hsv.v, 1/3, "555544 l" );
+    t.is( Color.fromHSV(hsv).toHexString(), "#555544", "555544 hexstring" );
+    hsv = Color.fromRGB(0.5, 1, 0.5).asHSV();
+    approx( hsv.h, 1/3, "aqua hsv.h" );
+    approx( hsv.s, 0.5, "aqua hsv.s" );
+    approx( hsv.v, 1, "aqua hsv.v" );
+    t.is(
+        Color.fromHSV(hsv.h, hsv.s, hsv.v).toHexString(),
+        Color.fromRGB(0.5, 1, 0.5).toHexString(),
+        "fromHSV works with components"
+    );
+    t.is(
+        Color.fromHSV(hsv).toHexString(),
+        Color.fromRGB(0.5, 1, 0.5).toHexString(),
+        "fromHSV alt form"
+    );
+    hsv = Color.fromRGB(1, 1, 1).asHSV()
+    approx( hsv.h, 0, 'white hsv.h' );
+    approx( hsv.s, 0, 'white hsv.s' );
+    approx( hsv.v, 1, 'white hsv.v' );
+    t.is(
+        Color.fromHSV(0, 0, 1).toHexString(),
+        '#ffffff',
+        'HSV saturation'
+    );
+};
diff --git a/mochikit_v14/tests/test_DateTime.js b/mochikit_v14/tests/test_DateTime.js
new file mode 100644 (file)
index 0000000..cc2d958
--- /dev/null
@@ -0,0 +1,45 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.DateTime'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.DateTime'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_DateTime = function (t) {
+    var testDate = isoDate('2005-2-3');
+    t.is(testDate.getFullYear(), 2005, "isoDate year ok");
+    t.is(testDate.getDate(), 3, "isoDate day ok");
+    t.is(testDate.getMonth(), 1, "isoDate month ok");
+    t.ok(objEqual(testDate, new Date("February 3, 2005")), "matches string date");
+    t.is(toISODate(testDate), '2005-02-03', 'toISODate ok');
+
+    var testDate = isoDate('2005-06-08');
+    t.is(testDate.getFullYear(), 2005, "isoDate year ok");
+    t.is(testDate.getDate(), 8, "isoDate day ok");
+    t.is(testDate.getMonth(), 5, "isoDate month ok");
+    t.ok(objEqual(testDate, new Date("June 8, 2005")), "matches string date");
+    t.is(toISODate(testDate), '2005-06-08', 'toISODate ok');
+
+    t.is(compare(new Date("February 3, 2005"), new Date(2005, 1, 3)), 0, "dates compare eq");
+    t.is(compare(new Date("February 3, 2005"), new Date(2005, 2, 3)), -1, "dates compare lt");
+    t.is(compare(new Date("February 3, 2005"), new Date(2005, 0, 3)), 1, "dates compare gt");
+
+    var testDate = isoDate('2005-2-3');
+    t.is(compare(americanDate('2/3/2005'), testDate), 0, "americanDate eq");
+    t.is(compare('2/3/2005', toAmericanDate(testDate)), 0, "toAmericanDate eq");
+
+    var testTimestamp = isoTimestamp('2005-2-3 22:01:03');
+    t.is(compare(testTimestamp, new Date(2005,1,3,22,1,3)), 0, "isoTimestamp eq");
+    t.is(compare(testTimestamp, isoTimestamp('2005-2-3T22:01:03')), 0, "isoTimestamp (real ISO) eq");
+    t.is(compare(toISOTimestamp(testTimestamp), '2005-02-03 22:01:03'), 0, "toISOTimestamp eq");
+    testTimestamp = isoTimestamp('2005-2-3T22:01:03Z');
+    t.is(toISOTimestamp(testTimestamp, true), '2005-02-03T22:01:03Z', "toISOTimestamp (real ISO) eq");
+
+    var localTZ = Math.round((new Date(2005,1,3,22,1,3)).getTimezoneOffset()/60)
+    var direction = (localTZ < 0) ? "+" : "-";
+    localTZ = Math.abs(localTZ);
+    localTZ = direction + ((localTZ < 10) ? "0" : "") + localTZ;
+    testTimestamp = isoTimestamp("2005-2-3T22:01:03" + localTZ);
+    var testDateTimestamp = new Date(2005,1,3,22,1,3);
+    t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with local tz");
+    testTimestamp = isoTimestamp("2005-2-3T17:01:03-05");
+    var testDateTimestamp = new Date(Date.UTC(2005,1,3,22,1,3));
+    t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with specific tz");
+};
diff --git a/mochikit_v14/tests/test_DragAndDrop.js b/mochikit_v14/tests/test_DragAndDrop.js
new file mode 100644 (file)
index 0000000..d3a3c58
--- /dev/null
@@ -0,0 +1,30 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_DragAndDrop = function (t) {
+    
+    var drag1 = new MochiKit.DragAndDrop.Draggable('drag1', {'revert': true, 'ghosting': true});
+
+    var drop1 = new MochiKit.DragAndDrop.Droppable('drop1', {'hoverclass': 'drop-hover'});
+    drop1.activate();
+    t.is(hasElementClass('drop1', 'drop-hover'), true, "hoverclass ok");
+    drop1.deactivate();
+    t.is(hasElementClass('drop1', 'drop-hover'), false, "remove hoverclass ok");
+    drop1.destroy();
+    
+    t.is( isEmpty(MochiKit.DragAndDrop.Droppables.drops), true, "Unregister droppable ok");
+    
+    var onhover = function (element) {
+        t.is(element, getElement('drag1'), 'onhover ok');
+    };
+    var drop2 = new MochiKit.DragAndDrop.Droppable('drop1', {'onhover': onhover});
+    var pos = getElementPosition('drop1');
+    pos = {"x": pos.x + 5, "y": pos.y + 5};
+    MochiKit.DragAndDrop.Droppables.show({"page": pos}, getElement('drag1'));
+
+    drag1.destroy();
+    t.is( isEmpty(MochiKit.DragAndDrop.Draggables.drops), true, "Unregister draggable ok");
+    
+};
+
diff --git a/mochikit_v14/tests/test_Format.js b/mochikit_v14/tests/test_Format.js
new file mode 100644 (file)
index 0000000..785cebf
--- /dev/null
@@ -0,0 +1,80 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Format'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Format'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Format = function (t) {
+    t.is( truncToFixed(0.1234, 3), "0.123", "truncToFixed truncate" );
+    t.is( truncToFixed(0.12, 3), "0.120", "truncToFixed trailing zeros" );
+    t.is( truncToFixed(0.15, 1), "0.1", "truncToFixed no round" );
+    t.is( truncToFixed(0.15, 0), "0", "truncToFixed zero (edge case)" );
+
+    t.is( roundToFixed(0.1234, 3), "0.123", "roundToFixed truncate" );
+    t.is( roundToFixed(0.12, 3), "0.120", "roundToFixed trailing zeros" );
+    t.is( roundToFixed(0.15, 1), "0.2", "roundToFixed round" );
+    t.is( roundToFixed(0.15, 0), "0", "roundToFixed zero (edge case)" );
+
+    t.is( twoDigitFloat(-0.1234), "-0.12", "twoDigitFloat -0.1234 correct");
+    t.is( twoDigitFloat(-0.1), "-0.1", "twoDigitFloat -0.1 correct");
+    t.is( twoDigitFloat(-0), "0", "twoDigitFloat -0 correct");
+    t.is( twoDigitFloat(0), "0", "twoDigitFloat 0 correct");
+    t.is( twoDigitFloat(1), "1", "twoDigitFloat 1 correct");
+    t.is( twoDigitFloat(1.0), "1", "twoDigitFloat 1.0 correct");
+    t.is( twoDigitFloat(1.2), "1.2", "twoDigitFloat 1.2 correct");
+    t.is( twoDigitFloat(1.234), "1.23", "twoDigitFloat 1.234 correct");
+    t.is( percentFormat(123), "12300%", "percentFormat 123 correct");
+    t.is( percentFormat(1.23), "123%", "percentFormat 123 correct");
+    t.is( twoDigitAverage(1, 0), "0", "twoDigitAverage dbz correct");
+    t.is( twoDigitAverage(1, 1), "1", "twoDigitAverage 1 correct");
+    t.is( twoDigitAverage(1, 10), "0.1", "twoDigitAverage .1 correct");
+    function reprIs(a, b) {
+        arguments[0] = repr(a);
+        arguments[1] = repr(b);
+        t.is.apply(this, arguments);
+    }
+    reprIs( lstrip("\r\t\n foo \n\t\r"), "foo \n\t\r", "lstrip whitespace chars" );
+    reprIs( rstrip("\r\t\n foo \n\t\r"), "\r\t\n foo", "rstrip whitespace chars" );
+    reprIs( strip("\r\t\n foo \n\t\r"), "foo", "strip whitespace chars" );
+    reprIs( lstrip("\r\n\t \r", "\r"), "\n\t \r", "lstrip custom chars" );
+    reprIs( rstrip("\r\n\t \r", "\r"), "\r\n\t ", "rstrip custom chars" );
+    reprIs( strip("\r\n\t \r", "\r"), "\n\t ", "strip custom chars" );
+
+    var nf = numberFormatter("$###,###.00 footer");
+    t.is( nf(1000.1), "$1,000.10 footer", "trailing zeros" );
+    t.is( nf(1000000.1), "$1,000,000.10 footer", "two seps" );
+    t.is( nf(100), "$100.00 footer", "shorter than sep" );
+    t.is( nf(100.555), "$100.56 footer", "rounding" );
+    t.is( nf(-100.555), "$-100.56 footer", "default neg" );
+    nf = numberFormatter("-$###,###.00");
+    t.is( nf(-100.555), "-$100.56", "custom neg" );
+    nf = numberFormatter("0000.0000");
+    t.is( nf(0), "0000.0000", "leading and trailing" );
+    t.is( nf(1.1), "0001.1000", "leading and trailing" );
+    t.is( nf(12345.12345), "12345.1235", "no need for leading/trailing" );
+    nf = numberFormatter("0000.0000");
+    t.is( nf("taco"), "", "default placeholder" );
+    nf = numberFormatter("###,###.00", "foo", "de_DE");
+    t.is( nf("taco"), "foo", "custom placeholder" );
+    t.is( nf(12345.12345), "12.345,12", "de_DE locale" );
+    nf = numberFormatter("#%");
+    t.is( nf(1), "100%", "trivial percent" );
+    t.is( nf(0.55), "55%", "percent" );
+
+    var customLocale = {
+        separator: " apples and ",
+        decimal: " bagels at ",
+        percent: "am for breakfast"};
+    var customFormatter = numberFormatter("###,###.0%", "No breakfast", customLocale);
+    t.is( customFormatter(23.458), "2 apples and 345 bagels at 8am for breakfast", "custom locale" );
+
+    nf = numberFormatter("###,###");
+    t.is( nf(123), "123", "large number format" );
+    t.is( nf(1234), "1,234", "large number format" );
+    t.is( nf(12345), "12,345", "large number format" );
+    t.is( nf(123456), "123,456", "large number format" );
+    t.is( nf(1234567), "1,234,567", "large number format" );
+    t.is( nf(12345678), "12,345,678", "large number format" );
+    t.is( nf(123456789), "123,456,789", "large number format" );
+    t.is( nf(1234567890), "1,234,567,890", "large number format" );
+    t.is( nf(12345678901), "12,345,678,901", "large number format" );
+    t.is( nf(123456789012), "123,456,789,012", "large number format" );
+};
diff --git a/mochikit_v14/tests/test_Iter.js b/mochikit_v14/tests/test_Iter.js
new file mode 100644 (file)
index 0000000..d0ff146
--- /dev/null
@@ -0,0 +1,176 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Iter'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Iter'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Iter = function (t) {
+    t.is( sum([1, 2, 3, 4, 5]), 15, "sum works on Arrays" );
+    t.is( compare(list([1, 2, 3]), [1, 2, 3]), 0, "list([x]) == [x]" );
+    t.is( compare(list(range(6, 0, -1)), [6, 5, 4, 3, 2, 1]), 0, "list(range(6, 0, -1)");
+    t.is( compare(list(range(6)), [0, 1, 2, 3, 4, 5]), 0, "list(range(6))" );
+    var moreThanTwo = partial(operator.lt, 2);
+    t.is( sum(ifilter(moreThanTwo, range(6))), 12, "sum(ifilter(, range()))" ); 
+    t.is( sum(ifilterfalse(moreThanTwo, range(6))), 3, "sum(ifilterfalse(, range()))" ); 
+
+    var c = count(10);
+    t.is( compare([c.next(), c.next(), c.next()], [10, 11, 12]), 0, "count()" );
+    c = cycle([1, 2]);
+    t.is( compare([c.next(), c.next(), c.next()], [1, 2, 1]), 0, "cycle()" );
+    c = repeat("foo", 3);
+    t.is( compare(list(c), ["foo", "foo", "foo"]), 0, "repeat()" );
+    c = izip([1, 2], [3, 4, 5], repeat("foo"));
+    t.is( compare(list(c), [[1, 3, "foo"], [2, 4, "foo"]]), 0, "izip()" );
+
+    t.is( compare(list(range(5)), [0, 1, 2, 3, 4]), 0, "range(x)" );
+    c = islice(range(10), 0, 10, 2);
+    t.is( compare(list(c), [0, 2, 4, 6, 8]), 0, "islice(x, y, z)" );
+
+    c = imap(operator.add, [1, 2, 3], [2, 4, 6]);
+    t.is( compare(list(c), [3, 6, 9]), 0, "imap(fn, p, q)" );
+
+    c = filter(partial(operator.lt, 1), iter([1, 2, 3]));
+    t.is( compare(c, [2, 3]), 0, "filter(fn, iterable)" );
+
+    c = map(partial(operator.add, -1), iter([1, 2, 3]));
+    t.is( compare(c, [0, 1, 2]), 0, "map(fn, iterable)" );
+
+    c = map(operator.add, iter([1, 2, 3]), [2, 4, 6]);
+    t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, q)" );
+
+    c = map(operator.add, iter([1, 2, 3]), iter([2, 4, 6]));
+    t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, iterable)" );
+
+    c = applymap(operator.add, [[1, 2], [2, 4], [3, 6]]);
+    t.is( compare(list(c), [3, 6, 9]), 0, "applymap()" );
+
+    c = applymap(function (a) { return [this, a]; }, [[1], [2]], 1);
+    t.is( compare(list(c), [[1, 1], [1, 2]]), 0, "applymap(self)" );
+
+    c = chain(range(2), range(3));
+    t.is( compare(list(c), [0, 1, 0, 1, 2]), 0, "chain(p, q)" );
+
+    var lessThanFive = partial(operator.gt, 5);
+    c = takewhile(lessThanFive, count());
+    t.is( compare(list(c), [0, 1, 2, 3, 4]), 0, "takewhile()" );
+
+    c = dropwhile(lessThanFive, range(10));
+    t.is( compare(list(c), [5, 6, 7, 8, 9]), 0, "dropwhile()" );
+
+    c = tee(range(5), 3);
+    t.is( compare(list(c[0]), list(c[1])), 0, "tee(..., 3) p0 == p1" );
+    t.is( compare(list(c[2]), [0, 1, 2, 3, 4]), 0, "tee(..., 3) p2 == fixed" );
+
+    t.is( compare(reduce(operator.add, range(10)), 45), 0, "reduce(op.add)" );
+
+    try {
+        reduce(operator.add, []);
+        t.ok( false, "reduce didn't raise anything with empty list and no start?!" );
+    } catch (e) {
+        if (e instanceof TypeError) {
+            t.ok( true, "reduce raised TypeError correctly" );
+        } else {
+            t.ok( false, "reduce raised the wrong exception?" );
+        }
+    }
+
+    t.is( reduce(operator.add, [], 10), 10, "range initial value OK empty" );
+    t.is( reduce(operator.add, [1], 10), 11, "range initial value OK populated" );
+
+    t.is( compare(iextend([1], range(2)), [1, 0, 1]), 0, "iextend(...)" );
+
+    var x = [];
+    exhaust(imap(bind(x.push, x), range(5)));
+    t.is( compare(x, [0, 1, 2, 3, 4]), 0, "exhaust(...)" );
+
+    t.is( every([1, 2, 3, 4, 5, 4], lessThanFive), false, "every false" );
+    t.is( every([1, 2, 3, 4, 4], lessThanFive), true, "every true" );
+    t.is( some([1, 2, 3, 4, 4], lessThanFive), true, "some true" );
+    t.is( some([5, 6, 7, 8, 9], lessThanFive), false, "some false" );
+    t.is( some([5, 6, 7, 8, 4], lessThanFive), true, "some true" );
+
+    var rval = [];
+    forEach(range(2), rval.push, rval);
+    t.is( compare(rval, [0, 1]), 0, "forEach works bound" );
+
+    function foo(o) {
+        rval.push(o);
+    }
+    forEach(range(2), foo);
+    t.is( compare(rval, [0, 1, 0, 1]), 0, "forEach works unbound" );
+    
+    t.is( compare(sorted([3, 2, 1]), [1, 2, 3]), 0, "sorted default" );
+    rval = sorted(["aaa", "bb", "c"], keyComparator("length"));
+    t.is(compare(rval, ["c", "bb", "aaa"]), 0, "sorted custom");
+
+    t.is( compare(reversed(range(4)), [3, 2, 1, 0]), 0, "reversed iterator" );
+    t.is( compare(reversed([5, 6, 7]), [7, 6, 5]), 0, "reversed list" );
+
+    var o = {lst: [1, 2, 3], iterateNext: function () { return this.lst.shift(); }};
+    t.is( compare(list(o), [1, 2, 3]), 0, "iterateNext" );
+
+
+    function except(exc, func) {
+        try {
+            func();
+            t.ok(false, exc.name + " was not raised.");
+        } catch (e) {
+            if (e == exc) {
+                t.ok( true, "raised " + exc.name + " correctly" );
+            } else {
+                t.ok( false, "raised the wrong exception?" );
+            }
+        }
+    }
+
+    odd = partial(operator.and, 1)
+
+    // empty
+    grouped = groupby([]);
+    except(StopIteration, grouped.next);
+
+    // exhaust sub-iterator
+    grouped = groupby([2,4,6,7], odd);
+    kv = grouped.next(); k = kv[0], subiter = kv[1];
+    t.is(k, 0, "odd(2) = odd(4) = odd(6) == 0");
+    t.is(subiter.next(), 2, "sub-iterator.next() == 2");
+    t.is(subiter.next(), 4, "sub-iterator.next() == 4");
+    t.is(subiter.next(), 6, "sub-iterator.next() == 6");
+    except(StopIteration, subiter.next);
+    kv = grouped.next(); key = kv[0], subiter = kv[1];
+    t.is(key, 1, "odd(7) == 1");
+    t.is(subiter.next(), 7, "sub-iterator.next() == 7");
+    except(StopIteration, subiter.next);
+
+    // not consume sub-iterator
+    grouped = groupby([2,4,6,7], odd);
+    kv = grouped.next(); key = kv[0], subiter = kv[1];
+    t.is(key, 0, "0 = odd(2) = odd(4) = odd(6)");
+    kv = grouped.next(); key = kv[0], subiter = kv[1];
+    t.is(key, 1, "1 = odd(7)");
+    except(StopIteration, grouped.next);
+
+    // consume sub-iterator partially
+    grouped = groupby([3,1,1,2], odd);
+    kv = grouped.next(); key = kv[0], subiter = kv[1];
+    t.is(key, 1, "odd(1) == 1");
+    t.is(subiter.next(), 3, "sub-iterator.next() == 3");
+    kv = grouped.next(); key = kv[0], v = kv[1];
+    t.is(key, 0, "skip (1,1),  odd(2) == 0");
+    except(StopIteration, grouped.next);
+
+    // null
+    grouped = groupby([null,null]);
+    kv = grouped.next(); k = kv[0], v = kv[1];
+    t.is(k, null, "null ok");
+
+    // groupby - array version
+    isEqual = (t.isDeeply || function (a, b, msg) {
+        return t.ok(compare(a, b) == 0, msg);
+    });
+    isEqual(groupby_as_array([ ]    ), [                        ], "empty");
+    isEqual(groupby_as_array([1,1,1]), [ [1,[1,1,1]]            ], "[1,1,1]: [1,1,1]");
+    isEqual(groupby_as_array([1,2,2]), [ [1,[1]    ], [2,[2,2]] ], "[1,2,2]: [1], [2,2]");
+    isEqual(groupby_as_array([1,1,2]), [ [1,[1,1]  ], [2,[2  ]] ], "[1,1,2]: [1,1], [2]");
+    isEqual(groupby_as_array([null,null] ), [ [null,[null,null]] ], "[null,null]: [null,null]");
+    grouped = groupby_as_array([1,1,3,2,4,6,8], odd);
+    isEqual(grouped, [[1, [1,1,3]], [0,[2,4,6,8]]], "[1,1,3,2,4,6,7] odd: [1,1,3], [2,4,6,8]");
+};
diff --git a/mochikit_v14/tests/test_Logging.js b/mochikit_v14/tests/test_Logging.js
new file mode 100644 (file)
index 0000000..66f4989
--- /dev/null
@@ -0,0 +1,75 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Logging'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Logging'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Logging = function (t) {
+  
+    // just in case
+    logger.clear();
+
+    t.is( logLevelAtLeast('DEBUG')('INFO'), false, 'logLevelAtLeast false' );
+    t.is( logLevelAtLeast('WARNING')('INFO'), false, 'logLevelAtLeast true' );
+    t.ok( logger instanceof Logger, "global logger installed" );
+
+    var allMessages = [];
+    logger.addListener("allMessages", null,
+        bind(allMessages.push, allMessages));
+
+    var fatalMessages = [];
+    logger.addListener("fatalMessages", "FATAL",
+        bind(fatalMessages.push, fatalMessages));
+
+    var firstTwo = [];
+    logger.addListener("firstTwo", null,
+        bind(firstTwo.push, firstTwo));
+
+    
+    log("foo");
+    var msgs = logger.getMessages();
+    t.is( msgs.length, 1, 'global log() put one message in queue' );
+    t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+    var msg = msgs.pop();
+    t.is( compare(msg.info, ["foo"]), 0, "info matches" );
+    t.is( msg.level, "INFO", "level matches" );
+
+    logDebug("debugFoo");
+    t.is( msgs.length, 0, 'getMessages() returns copy' );
+    msgs = logger.getMessages();
+    t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+    t.is( msgs.length, 2, 'logDebug()' );
+    msg = msgs.pop();
+    t.is( compare(msg.info, ["debugFoo"]), 0, "info matches" );
+    t.is( msg.level, "DEBUG", "level matches" );
+
+    logger.removeListener("firstTwo");
+
+    logError("errorFoo");
+    msgs = logger.getMessages();
+    t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+    t.is( msgs.length, 3, 'logError()' );
+    msg = msgs.pop();
+    t.is( compare(msg.info, ["errorFoo"]), 0, "info matches" );
+    t.is( msg.level, "ERROR", "level matches" );
+
+    logWarning("warningFoo");
+    msgs = logger.getMessages();
+    t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+    t.is( msgs.length, 4, 'logWarning()' );
+    msg = msgs.pop();
+    t.is( compare(msg.info, ["warningFoo"]), 0, "info matches" );
+    t.is( msg.level, "WARNING", "level matches" );
+
+    logFatal("fatalFoo");
+    msgs = logger.getMessages();
+    t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+    t.is( msgs.length, 5, 'logFatal()' );
+    msg = msgs.pop();
+    t.is( compare(fatalMessages, [msg]), 0, "fatalMessages listener" );
+    t.is( compare(msg.info, ["fatalFoo"]), 0, "info matches" );
+    t.is( msg.level, "FATAL", "level matches" );
+
+    logger.removeListener("allMessages");
+    logger.removeListener("fatalMessages");
+
+    t.is( compare(firstTwo, logger.getMessages().slice(0, 2)), 0, "firstTwo" );
+};
diff --git a/mochikit_v14/tests/test_MochiKit-Async.html b/mochikit_v14/tests/test_MochiKit-Async.html
new file mode 100644 (file)
index 0000000..32889ea
--- /dev/null
@@ -0,0 +1,408 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Async.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript">
+try {
+        
+    var increment = function (res) {
+        return res + 1;
+    }
+
+    var throwStuff = function (res) {
+        throw new GenericError(res);
+    }
+
+    var catchStuff = function (res) {
+        return res.message;
+    }
+
+    var returnError = function (res) {
+        return new GenericError(res);
+    }
+
+    var anythingOkCallback = function (msg) {
+        return function (res) {
+            ok(true, msg);
+            return res;
+        }
+    }
+    
+    var testEqCallback = function () {
+        /* 
+            sort of emulate how deferreds work in Twisted 
+            for "convenient" testing
+        */
+        var args = [];
+        for (var i = 0; i < arguments.length; i++) {
+            args.push(arguments[i]);
+        }
+        return function (res) {
+            var nargs = args.slice();
+            nargs.unshift(res);
+            is.apply(this, nargs);
+            return res;
+        }
+    }
+
+    var neverHappen = function (d) {
+        ok(false, "this should never happen");
+    }
+    
+    /*
+        Test normal Deferred operation
+    */
+    var d = new Deferred();
+    d.addCallback(testEqCallback(1, "pre-deferred callback"));
+    d.callback(1);
+    d.addCallback(increment);
+    d.addCallback(testEqCallback(2, "post-deferred callback"));
+    d.addCallback(throwStuff);
+    d.addCallback(neverHappen);
+    d.addErrback(catchStuff);
+    d.addCallback(testEqCallback(2, "throw -> err, catch -> success"));
+    d.addCallback(returnError);
+    d.addCallback(neverHappen);
+    d.addErrback(catchStuff);
+    d.addCallback(testEqCallback(2, "return -> err, catch -> succcess"));
+
+    /*
+        Test Deferred cancellation
+    */
+    var cancelled = function (d) {
+        ok(true, "canceller called!");
+    }
+
+    var cancelledError = function (res) {
+        ok(res instanceof CancelledError, "CancelledError here");
+    }
+
+    d = new Deferred(cancelled);
+    d.addCallback(neverHappen);
+    d.addErrback(cancelledError);
+    d.cancel();
+
+    /*
+        Test succeed / fail
+    */
+
+    d = succeed(1).addCallback(testEqCallback(1, "succeed"));
+
+    // default error
+    d = fail().addCallback(neverHappen);
+    d = d.addErrback(anythingOkCallback("default fail"));
+
+    // default wrapped error
+    d = fail("web taco").addCallback(neverHappen).addErrback(catchStuff);
+    d = d.addCallback(testEqCallback("web taco", "wrapped fail"));
+
+    // default unwrapped error
+    d = fail(new GenericError("ugh")).addCallback(neverHappen).addErrback(catchStuff);
+    d = d.addCallback(testEqCallback("ugh", "unwrapped fail"));
+
+    /*
+        Test deferred dependencies
+    */
+
+    var deferredIncrement = function (res) {
+        var rval = succeed(res);
+        rval.addCallback(increment);
+        return rval;
+    }
+
+    d = succeed(1).addCallback(deferredIncrement);
+    d = d.addCallback(testEqCallback(2, "dependent deferred succeed"));
+
+    var deferredFailure = function (res) {
+        return fail(res);
+    }
+
+    d = succeed("ugh").addCallback(deferredFailure).addErrback(catchStuff);
+    d = d.addCallback(testEqCallback("ugh", "dependent deferred fail"));
+
+    /*
+        Test double-calling, double-failing, etc.
+    */
+    try {
+        succeed(1).callback(2);
+        neverHappen();
+    } catch (e) {
+        ok(e instanceof AlreadyCalledError, "double-call");
+    }
+    try {
+        fail(1).errback(2);
+        neverHappen();
+    } catch (e) {
+        ok(e instanceof AlreadyCalledError, "double-fail");
+    }
+    try {
+        d = succeed(1);
+        d.cancel();
+        d = d.callback(2);
+        ok(true, "swallowed one callback, no canceller");
+        d.callback(3);
+        neverHappen();
+    } catch (e) {
+        ok(e instanceof AlreadyCalledError, "swallow cancel");
+    }
+    try {
+        d = new Deferred(cancelled);
+        d.cancel();
+        d = d.callback(1);
+        neverHappen();
+    } catch (e) {
+        ok(e instanceof AlreadyCalledError, "non-swallowed cancel");
+    }
+    
+    /* Test incorrect Deferred usage */
+
+    d = new Deferred();
+    try {
+        d.callback(new Deferred());
+        neverHappen();
+    } catch (e) {
+        ok (e instanceof Error, "deferred not allowed for callback");
+    }
+    d = new Deferred();
+    try {
+        d.errback(new Deferred());
+        neverHappen();
+    } catch (e) {
+        ok (e instanceof Error, "deferred not allowed for errback");
+    }
+
+    d = new Deferred();
+    (new Deferred()).addCallback(function () { return d; }).callback(1);
+    try {
+        d.addCallback(function () {});
+        neverHappen();
+    } catch (e) {
+        ok (e instanceof Error, "chained deferred not allowed to be re-used");
+    }
+    /*
+        evalJSONRequest test
+    */
+    var fakeReq = {"responseText":'[1,2,3,4,"asdf",{"a":["b", "c"]}]'};
+    var obj = [1,2,3,4,"asdf",{"a":["b", "c"]}];
+    isDeeply(obj, evalJSONRequest(fakeReq), "evalJSONRequest");
+
+    try {
+        MochiKit.Async.getXMLHttpRequest();
+        ok(true, "getXMLHttpRequest");
+    } catch (e) {
+        ok(false, "no love from getXMLHttpRequest");
+    }
+    
+    var lock = new DeferredLock();
+    var lst = [];
+    var pushNumber = function (x) {
+        return function (res) { lst.push(x); }
+    };
+    lock.acquire().addCallback(pushNumber(1));
+    is( compare(lst, [1]), 0, "lock acquired" );
+    lock.acquire().addCallback(pushNumber(2));
+    is( compare(lst, [1]), 0, "lock waiting for release" );
+    lock.acquire().addCallback(pushNumber(3));
+    is( compare(lst, [1]), 0, "lock waiting for release" );
+    lock.release();
+    is( compare(lst, [1, 2]), 0, "lock passed on" );
+    lock.release();
+    is( compare(lst, [1, 2, 3]), 0, "lock passed on" );
+    lock.release();
+    try {
+        lock.release();
+        ok( false, "over-release didn't raise" );
+    } catch (e) {
+        ok( true, "over-release raised" );
+    }
+    lock.acquire().addCallback(pushNumber(1));
+    is( compare(lst, [1, 2, 3, 1]), 0, "lock acquired" );
+    lock.release();
+    is( compare(lst, [1, 2, 3, 1]), 0, "lock released" );
+
+    var d = new Deferred();
+    lst = [];
+    d.addCallback(operator.add, 2);
+    d.addBoth(operator.add, 4);
+    d.addCallback(bind(lst.push, lst));
+    d.callback(1);
+    is( lst[0], 7, "auto-partial addCallback addBoth" );
+    d.addCallback(function () { throw new Error(); });
+    ebTest = function(a, b) {
+        map(bind(lst.push, lst), arguments);
+    };
+    d.addErrback(ebTest, "foo");
+    is( lst[1], "foo", "auto-partial errback" );
+    is( lst.length, 3, "auto-partial errback" );
+    
+    /* 
+        Test DeferredList 
+    */ 
+     
+    var callList = [new Deferred(), new Deferred(), new Deferred()];
+    callList[0].addCallback(increment); 
+    callList[1].addCallback(increment); 
+    callList[2].addCallback(increment); 
+    var defList = new DeferredList(callList); 
+    ok(defList instanceof Deferred, "DeferredList looks like a Deferred");
+    
+    callList[0].callback(3); 
+    callList[1].callback(5); 
+    callList[2].callback(4); 
+     
+    defList.addCallback(function (lst) { 
+        is( arrayEqual(lst, [[true, 4], [true, 6], [true, 5]]), 1, 
+           "deferredlist result ok" ); 
+    }); 
+    
+    /* 
+        Test fireOnOneCallback 
+    */ 
+    
+    var callList2 = [new Deferred(), new Deferred(), new Deferred()];
+    callList2[0].addCallback(increment); 
+    callList2[1].addCallback(increment); 
+    callList2[2].addCallback(increment); 
+    var defList2 = new DeferredList(callList2, true); 
+    callList2[1].callback(5); 
+    callList2[0].callback(3); 
+    callList2[2].callback(4); 
+     
+    defList2.addCallback(function (lst) { 
+        is( arrayEqual(lst, [1, 6]), 1, "deferredlist fireOnOneCallback ok" ); 
+    }); 
+   
+    /* 
+        Test fireOnOneErrback 
+    */ 
+  
+    var callList3 = [new Deferred(), new Deferred(), new Deferred()];
+    callList3[0].addCallback(increment); 
+    callList3[1].addCallback(throwStuff); 
+    callList3[2].addCallback(increment); 
+    var defList3 = new DeferredList(callList3, false, true); 
+    defList3.callback = neverHappen;
+    callList3[0].callback(3); 
+    callList3[1].callback("foo"); 
+    callList3[2].callback(4); 
+     
+    defList3.addErrback(function (err) { 
+        is( err.message, "foo", "deferredlist fireOnOneErrback ok" ); 
+    }); 
+    /* 
+        Test consumeErrors 
+    */ 
+    var callList4 = [new Deferred(), new Deferred(), new Deferred()];
+    callList4[0].addCallback(increment); 
+    callList4[1].addCallback(throwStuff); 
+    callList4[2].addCallback(increment); 
+    var defList4 = new DeferredList(callList4, false, false, true); 
+    defList4.addErrback(neverHappen); 
+    callList4[1].addCallback(function (arg) { 
+        is(arg, null, "deferredlist consumeErrors ok" ); 
+    }); 
+    callList4[0].callback(3); 
+    callList4[1].callback("foo"); 
+    callList4[2].callback(4);
+
+    /*
+        Test gatherResults
+    */
+
+    var callList5 = [new Deferred(), new Deferred(), new Deferred()];
+    callList5[0].addCallback(increment); 
+    callList5[1].addCallback(increment); 
+    callList5[2].addCallback(increment); 
+    var gatherRet = gatherResults(callList5); 
+    callList5[0].callback(3); 
+    callList5[1].callback(5); 
+    callList5[2].callback(4); 
+     
+    gatherRet.addCallback(function (lst) { 
+        is( arrayEqual(lst, [4, 6, 5]), 1, 
+           "gatherResults result ok" ); 
+    }); 
+    
+    /*
+        Test maybeDeferred
+    */
+
+    var maybeDef = maybeDeferred(increment, 4);
+    maybeDef.addCallback(testEqCallback(5, "maybeDeferred sync ok"));
+
+    var maybeDef2 = deferredIncrement(8);
+    maybeDef2.addCallback(testEqCallback(9, "maybeDeferred async ok"));
+
+    ok( true, "synchronous test suite finished!");
+
+    var t = (new Date().getTime());
+    SimpleTest.waitForExplicitFinish();
+    checkCallLater = function (originalTime) {
+        is(originalTime, t, "argument passed in OK");
+        is(arguments.length, 1, "argument count right");
+    };
+    var lock = new DeferredLock();
+    withLock = function (msg) {
+        var cb = partial.apply(null, extend(null, arguments, 1));
+        var d = lock.acquire().addCallback(cb);
+        d.addErrback(ok, false, msg);
+        d.addCallback(function () {
+            ok(true, msg);
+            lock.release();
+        });
+        return d;
+    }
+    withLock("callLater", function () {
+        return callLater(0.05, checkCallLater, t);
+    });
+    withLock("wait", function () {
+        return wait(0.05, t).addCallback(checkCallLater);
+    });
+    withLock("loadJSONDoc", function () {
+        var d = loadJSONDoc("test_MochiKit-Async.json");
+        d.addCallback(function (doc) {
+            is(doc.passed,  true, "loadJSONDoc passed");
+        });
+        d.addErrback(function (doc) {
+            ok(false, "loadJSONDoc failed");
+        });
+        return d;
+    });
+    lock.acquire().addCallback(function () {
+        ok(true, "async suite finished");
+        SimpleTest.finish();
+    });
+            
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+    SimpleTest.finish();
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Async.json b/mochikit_v14/tests/test_MochiKit-Async.json
new file mode 100755 (executable)
index 0000000..037e18c
--- /dev/null
@@ -0,0 +1 @@
+{"passed": true}
diff --git a/mochikit_v14/tests/test_MochiKit-Base.html b/mochikit_v14/tests/test_MochiKit-Base.html
new file mode 100644 (file)
index 0000000..3db71e1
--- /dev/null
@@ -0,0 +1,34 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Base.js"></script>
+<script type="text/javascript">
+try {
+    tests.test_Base({ok:ok,is:is});
+    ok( true, "test suite finished!");
+} catch (err) {
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Color.html b/mochikit_v14/tests/test_MochiKit-Color.html
new file mode 100644 (file)
index 0000000..bad32df
--- /dev/null
@@ -0,0 +1,84 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>
+    <script type="text/javascript" src="../MochiKit/Logging.js"></script>
+    <script type="text/javascript" src="../MochiKit/Color.js"></script>
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+    <style type="text/css">.redtext {color: red}</style>
+</head>
+<body>
+<div style="position:absolute; top: 0px; left:0px; width:0px; height:0px">
+    <span style="color: red" id="c_direct"></span>
+    <span class="redtext" id="c_indirect"></span>
+</div>
+<pre id="test">
+<script type="text/javascript" src="test_Color.js"></script>
+<script type="text/javascript">
+try {
+        
+    var t = {ok:ok, is:is};
+    tests.test_Color({ok:ok, is:is});
+    is(
+        Color.fromText(SPAN()).toHexString(),
+        "#000000",
+        "fromText no style"
+    );
+
+    is(
+        Color.fromText("c_direct").toHexString(),
+        Color.fromName("red").toHexString(),
+        "fromText direct style"
+    );
+
+    is(
+        Color.fromText("c_indirect").toHexString(),
+        Color.fromName("red").toHexString(),
+        "fromText indirect style"
+    );
+
+    is(
+        Color.fromComputedStyle("c_direct", "color").toHexString(),
+        Color.fromName("red").toHexString(),
+        "fromComputedStyle direct style"
+    );
+
+    is(
+        Color.fromComputedStyle("c_indirect", "color").toHexString(),
+        Color.fromName("red").toHexString(),
+        "fromComputedStyle indirect style"
+    );
+
+    is(
+        Color.fromBackground((SPAN(null, 'test'))).toHexString(),
+        Color.fromName("white").toHexString(),
+        "fromBackground with DOM"
+    );
+
+
+    // Done!
+
+    ok( true, "test suite finished!");
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-DOM-Safari.html b/mochikit_v14/tests/test_MochiKit-DOM-Safari.html
new file mode 100644 (file)
index 0000000..6a88f91
--- /dev/null
@@ -0,0 +1,48 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript">
+try {
+
+    for (var i = 0; i < 10000; i++) {
+        var n = document.createElement("DIV");
+        n.appendChild(document.createTextNode(""));
+        var list = MochiKit.Iter.list(n.childNodes);
+        var n2 = document.createElement("DIV");
+        appendChildNodes(n2, n.childNodes);
+        var n3 = document.createElement("DIV");
+        replaceChildNodes(n3, n2.childNodes);
+    }
+    ok( true, "Safari didn't crash! #213" );
+    ok( true, "test suite finished!");
+    
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-DOM.html b/mochikit_v14/tests/test_MochiKit-DOM.html
new file mode 100644 (file)
index 0000000..45036d9
--- /dev/null
@@ -0,0 +1,316 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<div style="display: none;">
+    <form id="form_test">
+        <select name="select">
+            <option value="foo" selected="selected">foo</option>
+            <option value="bar">bar</option>
+            <option value="baz">baz</option>
+        </select>
+        <select name="selmultiple" multiple="multiple">
+            <option value="bar" selected="selected">bar</option>
+            <option value="baz" selected="selected">baz</option>
+            <option value="foo">foo</option>
+        </select>
+        <input type="hidden" name="hidden" value="test" />
+        <input type="radio" name="radio_off" value="1" />
+        <input type="radio" name="radio_off" value="2" />
+        <input type="radio" name="radio_off" value="3" />
+        <input type="radio" name="radio_on" value="1" />
+        <input type="radio" name="radio_on" value="2" checked="checked" />
+        <input type="radio" name="radio_on" value="3" />
+    </form>
+    <form id="form_test2">
+        <select name="selempty">
+            <option value="" selected="selected">foo</option>
+        </select>
+        <select name="selempty2">
+            <option selected="selected">foo</option>
+        </select>
+    </form>
+    <div id="parentTwo" class="two">
+        <div id="parentOne" class="one">
+            <div id="parentZero" class="zero">
+                <span id="child">child</span>
+            </div>
+        </div>
+    </div>
+</div>
+
+<pre id="test">
+<script type="text/javascript">
+try {
+
+    lst = [];
+    o = {"blah": function () { lst.push("original"); }};
+    addToCallStack(o, "blah", function () { lst.push("new"); }, true);
+    addToCallStack(o, "blah", function () { lst.push("stuff"); }, true);
+    is( typeof(o.blah), 'function', 'addToCallStack has a function' );
+    is( o.blah.callStack.length, 3, 'callStack length 3' );
+    o.blah();
+    is( lst.join(" "), "original new stuff", "callStack in correct order" );
+    is( o.blah, null, "set to null" );
+    lst = [];
+    o = {"blah": function () { lst.push("original"); }};
+    addToCallStack(o, "blah",
+        function () { lst.push("new"); return false;}, false);
+    addToCallStack(o, "blah", function () { lst.push("stuff"); }, false);
+    o.blah();
+    is( lst.join(" "), "original new", "callStack in correct order (abort)" );
+    o.blah();
+    is( lst.join(" "), "original new original new", "callStack in correct order (again)" );
+    
+    
+    is( escapeHTML("<>\"&bar"), "&lt;&gt;&quot;&amp;bar", "escapeHTML" ); // for emacs highlighting: "
+
+    var isDOM = function (value, expected, message) {
+        is( escapeHTML(toHTML(value)), escapeHTML(expected), message );
+    };
+
+    var d = document.createElement('span');
+    updateNodeAttributes(d, {"foo": "bar", "baz": "wibble"});
+    isDOM( d, '<span baz="wibble" foo="bar"/>', "updateNodeAttributes" );
+
+    var d = document.createElement('span');
+    appendChildNodes(d, 'word up', [document.createElement('span')]);
+    isDOM( d, '<span>word up<span/></span>', 'appendChildNodes' );
+
+    replaceChildNodes(d, 'Think Different');
+    isDOM( d, '<span>Think Different</span>', 'replaceChildNodes' );
+
+
+    insertSiblingNodesBefore(d.childNodes[0], 'word up', document.createElement('span'));
+    isDOM( d, '<span>word up<span/>Think Different</span>', 'insertSiblingNodesBefore' );
+
+    insertSiblingNodesAfter(d.childNodes[0], 'purple monkey', document.createElement('span'));
+    isDOM( d, '<span>word uppurple monkey<span/><span/>Think Different</span>', 'insertSiblingNodesAfter' ); 
+
+    d = createDOM("span");
+    isDOM( d, "<span/>", "createDOM empty" );
+
+
+    d = createDOM("span", {"foo": "bar", "baz": "wibble"});
+    isDOM( d, '<span baz="wibble" foo="bar"/>', "createDOM attributes" );
+
+    d = createDOM("span", {"foo": "bar", "baz": "wibble", "spam": "egg"}, "one", "two", "three");
+    is( getNodeAttribute(d, 'foo'), "bar", "createDOM attribute" );
+    is( getNodeAttribute(d, 'baz'), "wibble", "createDOM attribute" );
+    removeNodeAttribute(d, "spam");
+    is( scrapeText(d), "onetwothree", "createDOM contents" );
+    
+    isDOM( d, '<span baz="wibble" foo="bar">onetwothree</span>', "createDOM contents" );
+
+    d = createDOM("span", null, function (f) {
+            return this.nodeName.toLowerCase() + "hi" + f.nodeName.toLowerCase();});
+    isDOM( d, '<span>spanhispan</span>', 'createDOM function call' );
+
+    d = createDOM("span", null, {msg: "hi", dom: function (f) {
+            return f.nodeName.toLowerCase() + this.msg; }});
+    isDOM( d, '<span>spanhi</span>', 'createDOM this.dom() call' );
+
+    d = createDOM("span", null, {msg: "hi", __dom__: function (f) {
+            return f.nodeName.toLowerCase() + this.msg; }});
+    isDOM( d, '<span>spanhi</span>', 'createDOM this.__dom__() call' );
+
+    d = createDOM("span", null, range(4));
+    isDOM( d, '<span>0123</span>', 'createDOM iterable' );
+
+
+    var d = {"taco": "pork"};
+    registerDOMConverter("taco",
+        function (o) { return !isUndefinedOrNull(o.taco); },
+        function (o) { return "Goddamn, I like " + o.taco + " tacos"; }
+    );
+    d = createDOM("span", null, d);
+    // not yet public API
+    domConverters.unregister("taco");
+
+    isDOM( d, "<span>Goddamn, I like pork tacos</span>", "createDOM with custom converter" );
+    
+    is(
+        escapeHTML(toHTML(SPAN(null))),
+        escapeHTML(toHTML(createDOM("span", null))),
+        "createDOMFunc vs createDOM"
+    );
+
+    is( scrapeText(d), "Goddamn, I like pork tacos", "scrape OK" );
+    is( scrapeText(d, true).join(""), "Goddamn, I like pork tacos", "scrape Array OK" );
+
+    var st = DIV(null, STRONG(null, "d"), "oor ", STRONG(null, "f", SPAN(null, "r"), "a"), "me");
+    is( scrapeText(st), "door frame", "scrape in-order" );
+    
+    
+    ok( !isUndefinedOrNull(getElement("test")), "getElement might work" );
+    ok( !isUndefinedOrNull($("test")), "$alias$$ CASH MONEY alias might work" );
+
+    d = createDOM("span", null, "one", "two");
+    swapDOM(d.childNodes[0], document.createTextNode("uno"));
+    isDOM( d, "<span>unotwo</span>", "swapDOM" );
+
+    is( scrapeText(d, true).join(" "), "uno two", "multi-node scrapeText" );
+    /*
+
+        TODO:
+            addLoadEvent (async test?)
+
+    */
+
+    d = createDOM("span", {"class": "foo"});
+    setElementClass(d, "bar baz");
+    ok( d.className == "bar baz", "setElementClass");
+    toggleElementClass("bar", d);
+    ok( d.className == "baz", "toggleElementClass: " + d.className);
+    toggleElementClass("bar", d);
+    ok( hasElementClass(d, "baz", "bar"), 
+        "toggleElementClass 2: " + d.className);
+    addElementClass(d, "bar");
+    ok( hasElementClass(d, "baz", "bar"), 
+        "toggleElementClass 3: " + d.className);
+    ok( addElementClass(d, "blah"), "addElementClass return");
+    ok( hasElementClass(d, "baz", "bar", "blah"), "addElementClass action");
+    ok( !hasElementClass(d, "not"), "hasElementClass single");
+    ok( !hasElementClass(d, "baz", "not"), "hasElementClass multiple");
+    ok( removeElementClass(d, "blah"), "removeElementClass" );
+    ok( !removeElementClass(d, "blah"), "removeElementClass again" );
+    ok( !hasElementClass(d, "blah"), "removeElementClass again (hasElement)" );
+    removeElementClass(d, "baz");
+    ok( !swapElementClass(d, "blah", "baz"), "false swapElementClass" );
+    ok( !hasElementClass(d, "baz"), "false swapElementClass from" );
+    ok( !hasElementClass(d, "blah"), "false swapElementClass to" );
+    addElementClass(d, "blah");
+    ok( swapElementClass(d, "blah", "baz"), "swapElementClass" );
+    ok( hasElementClass(d, "baz"), "swapElementClass has toClass" );
+    ok( !hasElementClass(d, "blah"), "swapElementClass !has fromClass" );
+    ok( !swapElementClass(d, "blah", "baz"), "swapElementClass twice" );
+    ok( hasElementClass(d, "baz"), "swapElementClass has toClass" );
+    ok( !hasElementClass(d, "blah"), "swapElementClass !has fromClass" );
+
+    TABLE;
+    TBODY;
+    TR;
+    var t = TABLE(null,
+        TBODY({"class": "foo bar", "id":"tbody0"},
+            TR({"class": "foo", "id":"tr0"}),
+            TR({"class": "bar", "id":"tr1"})
+        )
+    );
+
+    var matchElements = getElementsByTagAndClassName;
+    is(
+        map(itemgetter("id"), matchElements(null, "foo", t)).join(" "),
+        "tbody0 tr0",
+        "getElementsByTagAndClassName found all tags with foo class"
+    );
+    is(
+        map(itemgetter("id"), matchElements("tr", "foo", t)).join(" "),
+        "tr0",
+        "getElementsByTagAndClassName found all tr tags with foo class"
+    );
+    is(
+        map(itemgetter("id"), matchElements("tr", null, t)).join(" "),
+        "tr0 tr1",
+        "getElementsByTagAndClassName found all tr tags"
+    );
+        
+    var oldDoc = document;
+    var doc = MochiKit.MockDOM.createDocument();
+    is( currentDocument(), document, "currentDocument() correct" );
+    withDocument(doc, function () {
+        ok( document != doc, "global doc unchanged" );
+        is( currentDocument(), doc, "currentDocument() correct" );
+        var h1 = H1();
+        var span = SPAN(null, "foo", h1);
+        appendChildNodes(currentDocument().body, span);
+    });
+    is( document, oldDoc, "doc restored" );
+    is( doc.childNodes.length, 1, "doc has one child" );
+    is( doc.body.childNodes.length, 1, "body has one child" );
+    var sp = doc.body.childNodes[0];
+    is( sp.nodeName, "SPAN", "only child is SPAN" );
+    is( sp.childNodes.length, 2, "SPAN has two childNodes" );
+    is( sp.childNodes[0].nodeValue, "foo", "first node is text" );
+    is( sp.childNodes[1].nodeName, "H1", "second child is H1" );
+
+    is( currentDocument(), document, "currentDocument() correct" );
+    try {
+        withDocument(doc, function () {
+            ok( document != doc, "global doc unchanged" );
+            is( currentDocument(), doc, "currentDocument() correct" );
+            throw new Error("foo");
+        });
+        ok( false, "didn't throw" );
+    } catch (e) {
+        ok( true, "threw" );
+    }
+
+    var mockWindow = {"foo": "bar"};
+    is (currentWindow(), window, "currentWindow ok");
+    withWindow(mockWindow, function () {
+        is(currentWindow(), mockWindow, "withWindow ok");
+    });
+    is (currentWindow(), window, "currentWindow ok");
+
+    doc = MochiKit.MockDOM.createDocument();
+    var frm;
+    withDocument(doc, function () {
+        frm = FORM({name: "ignore"},
+            INPUT({name:"foo", value:"bar"}),
+            INPUT({name:"foo", value:"bar"}),
+            INPUT({name:"baz", value:"bar"})
+        );
+    });
+    var kv = formContents(frm);
+    is( kv[0].join(","), "foo,foo,baz", "mock formContents names" );
+    is( kv[1].join(","), "bar,bar,bar", "mock formContents values" );
+    is( queryString(frm), "foo=bar&foo=bar&baz=bar", "mock queryString hook" );
+
+    var kv = formContents("form_test");
+    is( kv[0].join(","), "select,selmultiple,selmultiple,hidden,radio_on", "formContents names" );
+    is( kv[1].join(","), "foo,bar,baz,test,2", "formContents values" );
+    is( queryString("form_test"), "select=foo&selmultiple=bar&selmultiple=baz&hidden=test&radio_on=2", "queryString hook" );
+    kv = formContents("form_test2");
+    is( kv[0].join(","), "selempty,selempty2", "formContents names empty option values" );
+    is( kv[1].join(","), ",foo", "formContents empty option values" );
+    is( queryString("form_test2"), "selempty=&selempty2=foo", "queryString empty option values" );
+    
+    var d = DIV(null, SPAN(), " \n\t", SPAN(), "foo", SPAN(), " ");
+    is( d.childNodes.length, 6, "removeEmptyNodes test conditions correct" );
+    removeEmptyTextNodes(d);
+    is( d.childNodes.length, 4, "removeEmptyNodes" );
+
+    is( getFirstParentByTagAndClassName('child', 'div', 'two'), getElement("parentTwo"), "getFirstParentByTagAndClassName found parent" );
+    is( getFirstParentByTagAndClassName('child', 'div'), getElement("parentZero"), "getFirstParentByTagAndClassName found parent (any class)" );
+    is( getFirstParentByTagAndClassName('child', '*', 'two'), getElement("parentTwo"), "getFirstParentByTagAndClassName found parent (any tag)" );
+
+    ok( true, "test suite finished!");
+    
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-DateTime.html b/mochikit_v14/tests/test_MochiKit-DateTime.html
new file mode 100644 (file)
index 0000000..43ad9d4
--- /dev/null
@@ -0,0 +1,39 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/DateTime.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_DateTime.js"></script>
+<script type="text/javascript">
+try {
+        
+    tests.test_DateTime({ok:ok, is:is});
+    ok( true, "test suite finished!");
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-DragAndDrop.html b/mochikit_v14/tests/test_MochiKit-DragAndDrop.html
new file mode 100644 (file)
index 0000000..a191a53
--- /dev/null
@@ -0,0 +1,54 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>
+    <script type="text/javascript" src="../MochiKit/Color.js"></script>
+    <script type="text/javascript" src="../MochiKit/Signal.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Visual.js"></script>    
+    <script type="text/javascript" src="../MochiKit/DragAndDrop.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+    <style type="text/css">
+    .drop-hover {
+    }
+    #drag1 {
+        visibility: hidden;
+    }
+    #drop1 {
+        visibility: hidden;
+    }
+    </style>
+</head>
+<body>
+<div id='drag1'>drag1</div>
+<div id='drop1'>drop1</div>
+<pre id="test">
+<script type="text/javascript" src="test_DragAndDrop.js"></script>
+<script type="text/javascript">
+try {
+        
+    // Counting the number of tests is really lame
+    tests.test_DragAndDrop({ok:ok, is:is});
+    ok( true, "test suite finished!");
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Format.html b/mochikit_v14/tests/test_MochiKit-Format.html
new file mode 100644 (file)
index 0000000..58bffa6
--- /dev/null
@@ -0,0 +1,39 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Format.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Format.js"></script>
+<script type="text/javascript">
+try {
+        
+    tests.test_Format({ok:ok, is:is});
+    ok( true, "test suite finished!");
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Iter.html b/mochikit_v14/tests/test_MochiKit-Iter.html
new file mode 100644 (file)
index 0000000..8086acc
--- /dev/null
@@ -0,0 +1,38 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Iter.js"></script>
+<script type="text/javascript">
+try {
+        
+    tests.test_Iter({ok:ok, is:is});
+    ok( true, "test suite finished!");
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-JSAN.html b/mochikit_v14/tests/test_MochiKit-JSAN.html
new file mode 100644 (file)
index 0000000..53a0e0e
--- /dev/null
@@ -0,0 +1,32 @@
+<html>
+<head>
+    <script type="text/javascript" src="JSAN.js"></script>
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript">
+    // TODO: Make this a harness for the other tests
+    JSAN.use('Test.More');
+    JSAN.addRepository('..');
+    var lst = [];
+    plan({"tests": 1});
+    var wc = {};
+    wc['MochiKit'] = true;
+    for (var k in window) { wc[k] = true; }
+    for (var k in window) { wc[k] = true; }
+    JSAN.use('MochiKit.MochiKit', []);
+    for (var k in window) {
+        if (!(k in wc) && !(k.charAt(0) == '[')) {
+            lst.push(k);
+        }
+    }
+    lst.sort();
+    pollution = lst.join(" ");
+    is(pollution, "compare reduce", "namespace pollution?");
+    JSAN.use('MochiKit.MochiKit');
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Logging.html b/mochikit_v14/tests/test_MochiKit-Logging.html
new file mode 100644 (file)
index 0000000..d92229a
--- /dev/null
@@ -0,0 +1,40 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Logging.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Logging.js"></script>
+<script type="text/javascript">
+try {
+        
+    tests.test_Logging({ok:ok, is:is});
+    ok( true, "test suite finished!");
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-MochiKit.html b/mochikit_v14/tests/test_MochiKit-MochiKit.html
new file mode 100644 (file)
index 0000000..d1a8b60
--- /dev/null
@@ -0,0 +1,18 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/MochiKit.js"></script>
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript">
+    is( isUndefined(null), false, "null is not undefined" );
+    is( isUndefined(""), false, "empty string is not undefined" );
+    is( isUndefined(undefined), true, "undefined is undefined" );
+    is( isUndefined({}.foo), true, "missing property is undefined" );
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Selector.html b/mochikit_v14/tests/test_MochiKit-Selector.html
new file mode 100644 (file)
index 0000000..503acef
--- /dev/null
@@ -0,0 +1,274 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Selector.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+    <style type="text/css">
+        p, #sequence {
+            display: none;
+        } 
+    </style>
+</head>
+<body>
+    <p>Test originally from <a href="http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector" rel="bookmark">this blog entry</a>.</p>
+
+    <p>Here are some links in a normal paragraph: <a href="http://www.google.com/" title="Google!">Google</a>, <a href="http://groups.google.com/">Google Groups</a>. This link has <code>class="blog"</code>: <a href="http://diveintomark.org/" class="blog" fakeattribute="bla">diveintomark</a></p>
+    <div id="foo">
+    <p>Everything inside the red border is inside a div with <code>id="foo"</code>.</p>
+    <p>This is a normal link: <a href="http://www.yahoo.com/">Yahoo</a></p>
+    
+    <a style="display: none" href="http://www.example.com/outsidep">This a is not inside a p</a>
+
+    <p>This link has <code>class="blog"</code>: <a href="http://simon.incutio.com/" class="blog">Simon Willison's Weblog</a></p>
+    <p>This <span><a href="http://www.example.com/insidespan">link</a></span> is inside a span, not directly child of p</p>
+    <p lang="en-us">Nonninn</p>
+    <p lang="is-IS">Sniðugt</p>
+    <p>
+        <input type="button" name="enabled" value="enabled" id="enabled">
+        <input type="button" name="disabled" value="disabled" id="disabled" disabled="1" />
+        <input type="checkbox" name="checked" value="checked" id="checked" checked="1" />
+    </p>
+    </div>
+
+    <div id="sequence">
+        <a href="http://www.example.com/link1">Link 1</a>
+        <a href="http://www.example.com/link2">Link 2</a>
+        <a href="http://www.example.com/link3">Link 3</a>
+        <a href="http://www.example.com/link4">Link 4</a>
+        <p>Something else</p>
+        <a href="http://www.example.com/link5">Link 5</a>
+        <a href="http://www.example.com/link6">Link 6</a>
+        <a href="http://www.example.com/link7">Link 7</a>
+        <a href="http://www.example.com/link8">Link 8</a>
+    </div>
+    
+    <div id="multiclass" class="multiple classnames here"></div>
+<pre id="test">
+<script type="text/javascript">
+try {
+
+    var testExpected = function (res, exp, lbl) {
+        for (var i=0; i < res.length; i ++) {
+            is( res[i].href, exp[i], lbl + ' (' + i + ')');
+        }
+    };
+
+    var expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector',
+                    'http://www.google.com/',
+                    'http://groups.google.com/',
+                    'http://diveintomark.org/',
+                    'http://www.yahoo.com/',
+                    'http://www.example.com/outsidep',
+                    'http://simon.incutio.com/',
+                    'http://www.example.com/insidespan',
+                    'http://www.example.com/link1',
+                    'http://www.example.com/link2',
+                    'http://www.example.com/link3',
+                    'http://www.example.com/link4',
+                    'http://www.example.com/link5',
+                    'http://www.example.com/link6',
+                    'http://www.example.com/link7',
+                    'http://www.example.com/link8'];
+    var results = $$('a');
+    testExpected(results, expected, "'a' selector");
+
+    expected = ['http://diveintomark.org/', 'http://simon.incutio.com/'];
+    results = $$('p a.blog');    
+    testExpected(results, expected, "'p a.blog' selector");
+
+    expected = ['http://www.yahoo.com/',
+                'http://www.example.com/outsidep',
+                'http://simon.incutio.com/',
+                'http://www.example.com/insidespan',
+                'http://www.example.com/link1',
+                'http://www.example.com/link2',
+                'http://www.example.com/link3',
+                'http://www.example.com/link4',
+                'http://www.example.com/link5',
+                'http://www.example.com/link6',
+                'http://www.example.com/link7',
+                'http://www.example.com/link8'];
+    results = $$('div a');
+    testExpected(results, expected, "'div a' selector");
+
+    expected = ['http://www.yahoo.com/',
+                'http://www.example.com/outsidep',
+                'http://simon.incutio.com/',
+                'http://www.example.com/insidespan'];
+    results = $$('div#foo a');
+    testExpected(results, expected, "'div#foo a' selector");
+
+    expected = ['http://simon.incutio.com/',
+                'http://www.example.com/insidespan'];
+    results = $$('#foo a.blog');
+    testExpected(results, expected, "'#foo a.blog' selector");
+
+    expected = ['http://diveintomark.org/',
+                'http://simon.incutio.com/',
+                'http://www.example.com/insidespan'];
+    results = $$('.blog');
+    testExpected(results, expected, "'.blog' selector");
+
+    expected = ['http://www.google.com/',
+                'http://www.yahoo.com/',
+                'http://www.example.com/outsidep',
+                'http://www.example.com/insidespan',
+                'http://www.example.com/link1',
+                'http://www.example.com/link2',
+                'http://www.example.com/link3',
+                'http://www.example.com/link4',
+                'http://www.example.com/link5',
+                'http://www.example.com/link6',
+                'http://www.example.com/link7',
+                'http://www.example.com/link8'];
+    results = $$('a[href^="http://www"]');
+    testExpected(results, expected, "'a[href^=http://www]' selector");
+
+    expected = ['http://diveintomark.org/'];
+    results = $$('a[href$="org/"]');
+    testExpected(results, expected, "'a[href$=org/]' selector");
+
+    expected = ['http://www.google.com/',
+                'http://groups.google.com/'];
+    results = $$('a[href*="google"]');
+    testExpected(results, expected, "'a[href*=google]' selector");
+
+    expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector'];
+    results = $$('a[rel="bookmark"]');
+    testExpected(results, expected, "'a[rel=bookmark]' selector");
+
+    expected = ['http://diveintomark.org/'];
+    results = $$('a[fakeattribute]');
+    testExpected(results, expected, "'a[fakeattribute]' selector");
+
+    /* This doesn't work in IE due to silly DOM implementation
+    expected = ['http://www.google.com/'];
+    results = $$('a[title]');
+    testExpected(results, expected, "'a[title]' selector");
+    */
+
+    results = $$('p[lang|="en"]');
+    is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang|=en]' selector");
+
+    expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector',
+                'http://www.google.com/',
+                'http://groups.google.com/',
+                'http://diveintomark.org/',
+                'http://www.yahoo.com/',
+                'http://simon.incutio.com/',
+                'http://www.example.com/insidespan'];
+    results = $$('p > a');
+    testExpected(results, expected, "'p > a' selector");
+
+    expected = ['http://www.example.com/insidespan'];
+    results = $$('span > a');
+    testExpected(results, expected, "'span > a' selector");
+
+    expected = ['http://groups.google.com/',
+                'http://www.example.com/link2',
+                'http://www.example.com/link3',
+                'http://www.example.com/link4',
+                'http://www.example.com/link6',
+                'http://www.example.com/link7',
+                'http://www.example.com/link8'];
+    results = $$('a + a');
+    testExpected(results, expected, "'a + a' selector");
+
+    expected = ['http://www.example.com/link1',
+                'http://www.example.com/link3',
+                'http://www.example.com/link6',
+                'http://www.example.com/link8'];
+    results = $$('#sequence a:nth-child(odd)');
+    testExpected(results, expected, "'#sequence a:nth-child(odd)' selector");
+
+    expected = ['http://www.example.com/link1',
+                'http://www.example.com/link3',
+                'http://www.example.com/link5',
+                'http://www.example.com/link7'];
+    results = $$('#sequence a:nth-of-type(odd)');
+    testExpected(results, expected, "'#sequence a:nth-of-type(odd)' selector");
+    
+    expected = ['http://www.example.com/link1',
+                'http://www.example.com/link4',
+                'http://www.example.com/link7'];
+    results = $$('#sequence a:nth-of-type(3n+1)');
+    testExpected(results, expected, "'#sequence a:nth-of-type(3n+1)' selector");
+
+    expected = ['http://www.example.com/link5'];
+    results = $$('#sequence a:nth-child(6)');
+    testExpected(results, expected, "'#sequence a:nth-child(6)' selector");
+    
+    expected = ['http://www.example.com/link5'];
+    results = $$('#sequence a:nth-of-type(5)');
+    testExpected(results, expected, "'#sequence a:nth-of-type(5)' selector");
+    
+    expected =  [$('enabled'), $('checked')];
+    results = $$('body :enabled');
+    for (var i=0; i < results.length; i ++) {
+        is( results[i], expected[i], "'body :enabled" + ' (' + i + ')');
+    }
+    
+    expected =  [$('disabled')];
+    results = $$('body :disabled');
+    for (var i=0; i < results.length; i ++) {
+        is( results[i], expected[i], "'body :disabled" + ' (' + i + ')');
+    }
+
+    expected =  [$('checked')];
+    results = $$('body :checked');
+    for (var i=0; i < results.length; i ++) {
+        is( results[i], expected[i], "'body :checked" + ' (' + i + ')');
+    }
+    
+    expected = document.getElementsByTagName('p');
+    results = $$('a[href$=outsidep] ~ *');
+    for (var i=0; i < results.length; i ++) {
+        is( results[i], expected[i+4], "'a[href$=outsidep] ~ *' selector" + ' (' + i + ')');
+    }
+    
+    expected = [document.documentElement];
+    results = $$(':root');
+    for (var i=0; i < results.length; i ++) {
+        is( results[i], expected[i], "':root' selector" + ' (' + i + ')');
+    }
+    
+    expected = [$('multiclass')];
+    results = $$('[class~=classnames]');
+    for (var i=0; i < results.length; i ++) {
+        is( results[i], expected[i], "'~=' attribute test" + ' (' + i + ')');
+    }
+    
+    var doc = MochiKit.MockDOM.createDocument();
+    appendChildNodes(doc.body, A({"href": "http://www.example.com/insideAnotherDocument"}, "Inside a document"));
+    withDocument(doc, function(){
+        is( $$(":root")[0], doc, ":root on a different document" );
+        is( $$("a")[0], doc.body.firstChild, "a inside a different document" );
+    });
+
+    ok( true, "test suite finished!");
+    
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Signal.html b/mochikit_v14/tests/test_MochiKit-Signal.html
new file mode 100644 (file)
index 0000000..9c37416
--- /dev/null
@@ -0,0 +1,43 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>
+    <script type="text/javascript" src="../MochiKit/Signal.js"></script>    
+    <script type="text/javascript" src="../MochiKit/Logging.js"></script>    
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+
+</head>
+<body>
+
+Please ignore this button: <input type="submit" id="submit" /><br />
+
+<pre id="test">
+<script type="text/javascript" src="test_Signal.js"></script>
+<script type="text/javascript">
+try {
+        
+    tests.test_Signal({ok:ok, is:is});
+    ok(true, "test suite finished!");
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok(false, s);
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Style.html b/mochikit_v14/tests/test_MochiKit-Style.html
new file mode 100644 (file)
index 0000000..b01adc6
--- /dev/null
@@ -0,0 +1,141 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>
+    <script type="text/javascript" src="../MochiKit/Color.js"></script>
+    <script type="text/javascript" src="../MochiKit/Logging.js"></script>
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>        
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body style="border: 0; margin: 0; padding: 0;">
+
+<div id="styleTest" style="position: absolute; left: 400px; top: 100px; width: 100px; height: 100px; background: rgb(255, 0, 0); opacity: 0.5; filter: alpha(opacity=50); font-size: 10px">TEST<span id="styleSubTest">SUB</span></div>
+
+<pre id="test">
+<script type="text/javascript">
+
+try {
+
+    // initial
+    var pos = getElementPosition('styleTest');
+    is(pos.x, 400, 'initial x position');
+    is(pos.y, 100, 'initial y position');
+    
+    // moved
+    var newPos = new MochiKit.Style.Coordinates(500, 200);
+    setElementPosition('styleTest', newPos);
+    pos = getElementPosition('styleTest');
+    is(pos.x, 500, 'updated x position');
+    is(pos.y, 200, 'updated y position');
+
+    // moved with relativeTo
+    anotherPos = new MochiKit.Style.Coordinates(100, 100);
+    pos = getElementPosition('styleTest', anotherPos);
+    is(pos.x, 400, 'updated x position (using relativeTo parameter)');
+    is(pos.y, 100, 'updated y position (using relativeTo parameter)');
+    
+    // Coordinates object
+    pos = getElementPosition({x: 123, y: 321});
+    is(pos.x, 123, 'passthrough x position');
+    is(pos.y, 321, 'passthrough y position');
+    
+    // Coordinates object with relativeTo
+    pos = getElementPosition({x: 123, y: 321}, {x: 100, y: 50});
+    is(pos.x, 23, 'passthrough x position (using relativeTo parameter)');
+    is(pos.y, 271, 'passthrough y position (using relativeTo parameter)');
+    
+    pos = getElementPosition('garbage'); 
+    is(typeof(pos), 'undefined', 
+        'invalid element should return an undefined position');
+    
+    // Only set one coordinate
+    setElementPosition('styleTest', {'x': 300});
+    pos = getElementPosition('styleTest');
+    is(pos.x, 300, 'updated only x position');
+    is(pos.y, 200, 'not updated y position');
+    
+    var mc = MochiKit.Color.Color;
+    var red = mc.fromString('rgb(255,0,0)');
+    var color = null;
+    
+    color = mc.fromString(getStyle('styleTest', 'background-color'));
+    is(color.toHexString(), red.toHexString(), 
+        'test getStyle selector case');
+       
+    color = mc.fromString(getStyle('styleTest', 'backgroundColor'));
+    is(color.toHexString(), red.toHexString(), 
+        'test getStyle camel case');
+
+    is(getStyle('styleSubTest', 'font-size'), '10px', 
+        'test computed getStyle selector case');
+       
+    is(getStyle('styleSubTest', 'fontSize'), '10px', 
+        'test computed getStyle camel case');
+
+    is(eval(getStyle('styleTest', 'opacity')), 0.5, 
+        'test getStyle opacity');
+
+    is(getStyle('styleTest', 'opacity'), 0.5, 'test getOpacity');
+    
+    setStyle('styleTest', {'opacity': 0.2});
+    is(getStyle('styleTest', 'opacity'), 0.2, 'test setOpacity');
+
+    setStyle('styleTest', {'opacity': 0});
+    is(getStyle('styleTest', 'opacity'), 0, 'test setOpacity');
+
+    setStyle('styleTest', {'opacity': 1});
+    var t = getStyle('styleTest', 'opacity');
+    ok(t > 0.999 && t <= 1, 'test setOpacity');
+
+    var dims = getElementDimensions('styleTest');
+    is(dims.w, 100, 'getElementDimensions w ok');
+    is(dims.h, 100, 'getElementDimensions h ok');
+
+    setElementDimensions('styleTest', {'w': 200, 'h': 150});
+    dims = getElementDimensions('styleTest');
+    is(dims.w, 200, 'setElementDimensions w ok');
+    is(dims.h, 150, 'setElementDimensions h ok');
+
+    setElementDimensions('styleTest', {'w': 150});
+    dims = getElementDimensions('styleTest');
+    is(dims.w, 150, 'setElementDimensions only w ok');
+    is(dims.h, 150, 'setElementDimensions h not updated ok');
+
+    hideElement('styleTest');
+    dims = getElementDimensions('styleTest');
+    is(dims.w, 150, 'getElementDimensions w ok when display none');
+    is(dims.h, 150, 'getElementDimensions h ok when display none');
+
+    dims = getViewportDimensions();
+    is(dims.w > 0, true, 'test getViewportDimensions w');
+    is(dims.h > 0, true, 'test getViewportDimensions h');
+
+    pos = getViewportPosition();
+    is(pos.x, 0, 'test getViewportPosition x');
+    is(pos.y, 0, 'test getViewportPosition y');
+
+    ok( true, "test suite finished!");
+    
+    
+} catch (err) {
+    
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/mochikit_v14/tests/test_MochiKit-Visual.html b/mochikit_v14/tests/test_MochiKit-Visual.html
new file mode 100644 (file)
index 0000000..3ae510f
--- /dev/null
@@ -0,0 +1,176 @@
+<html>
+<head>
+    <script type="text/javascript" src="../MochiKit/Base.js"></script>
+    <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+    <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+    <script type="text/javascript" src="../MochiKit/Async.js"></script>
+    <script type="text/javascript" src="../MochiKit/Style.js"></script>
+    <script type="text/javascript" src="../MochiKit/Color.js"></script>
+    <script type="text/javascript" src="../MochiKit/Signal.js"></script>
+    <script type="text/javascript" src="../MochiKit/Position.js"></script>
+    <script type="text/javascript" src="../MochiKit/Visual.js"></script>
+    <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>     
+
+    <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+    <style type="text/css">
+    #elt1, #elt2, #ctn1 {
+        visibility: hidden;
+        font-size: 1em;
+        margin: 2px;
+    }
+    #ctn1 {
+        height: 2px;
+    }
+    </style>
+</head>
+<body>
+
+<div id='elt1'>elt1</div>
+<div id='ctn1'><div id='elt2'></div></div>
+<pre id="test">
+<script type="text/javascript">
+try {
+    var TestQueue = function () {
+    };
+
+    TestQueue.prototype = new MochiKit.Visual.ScopedQueue();
+    
+    MochiKit.Base.update(TestQueue.prototype, {
+        startLoop: function (func, interval) {
+            this.started = true;
+            var timePos = new Date().getTime();
+            while (this.started) {
+                timePos += interval;
+                MochiKit.Base.map(function (effect) {
+                    effect.loop(timePos);
+                }, this.effects);
+            }
+        },
+        stopLoop: function () {
+            this.started = false;
+        }
+    });
+    
+    var gl = new TestQueue();
+    MochiKit.Visual.Queues.instances['global'] = gl;
+    MochiKit.Visual.Queues.instances['elt1'] = gl;
+    MochiKit.Visual.Queues.instances['ctn1'] = gl;
+    MochiKit.Visual.Queue = gl;
+
+    pulsate("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display != 'none', true, "pulsate ok");
+    }});
+
+    pulsate("elt1", {pulses: 2, afterFinish: function () {
+        is(getElement('elt1').style.display != 'none', true, "pulsate with numbered pulses ok");
+    }});
+    
+    shake("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display != 'none', true, "shake ok");
+    }});
+    
+    fade("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "fade ok");
+    }});
+
+    appear("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display != 'none', true, "appear ok");
+    }});
+
+    toggle("elt1", "size", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "toggle size ok");
+    }});
+
+    toggle("elt1", "size", {afterFinish: function () {
+        is(getElement('elt1').style.display != 'none', true, "toggle size reverse ok");
+    }});
+
+    Morph("elt1", {"style": {"font-size": "2em"}, afterFinish: function () {
+        is(getStyle("elt1", "font-size"), "2em", "Morph OK");
+    }});
+
+    Morph("elt1", {"style": {"font-size": "1em", "margin-left": "4px"}, afterFinish: function () {
+        is(getStyle("elt1", "font-size"), "1em", "Morph multiple (font) OK");
+        is(getStyle("elt1", "margin-left"), "4px", "Morph multiple (margin) OK");
+    }});
+
+    switchOff("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "switchOff ok");
+    }});
+
+    grow("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display != 'none', true, "grow ok");
+    }});
+
+    shrink("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "shrink ok");
+    }});
+
+    showElement('elt1');
+    dropOut("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "dropOut ok");
+    }});
+
+    showElement('elt1');
+    puff("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "puff ok");
+    }});
+
+    showElement('elt1');
+    fold("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "fold ok");
+    }});
+
+    showElement('elt1');
+    squish("elt1", {afterFinish: function () {
+        is(getElement('elt1').style.display, 'none', "squish ok");
+    }});
+
+    slideUp("ctn1", {afterFinish: function () {
+        is(getElement('ctn1').style.display, 'none', "slideUp ok");
+    }});
+
+    slideDown("ctn1", {afterFinish: function () {
+        is(getElement('ctn1').style.display != 'none', true, "slideDown ok");
+    }});
+
+    blindDown("ctn1", {afterFinish: function () {
+        is(getElement('ctn1').style.display != 'none', true, "blindDown ok");
+    }});
+
+    blindUp("ctn1", {afterFinish: function () {
+        is(getElement('ctn1').style.display, 'none', "blindUp ok");
+    }});
+
+    multiple(["elt1", "ctn1"], appear, {afterFinish: function (effect) {
+        is(effect.element.style.display != 'none', true, "multiple ok");
+    }});
+
+    var toTests = [roundElement, roundClass, tagifyText, Opacity, Move, Scale, Highlight, ScrollTo, Morph];
+    for (var m in toTests) {
+        toTests[m]("elt1");
+        ok(true, toTests[m].NAME + " doesn't need 'new' keyword");
+    }
+    ok(true, "visual suite finished");
+
+} catch (err) {
+
+    var s = "test suite failure!\n";
+    var o = {};
+    var k = null;
+    for (k in err) {
+        // ensure unique keys?!
+        if (!o[k]) {
+            s +=  k + ": " + err[k] + "\n";
+            o[k] = err[k];
+        }
+    }
+    ok ( false, s );
+    SimpleTest.finish();
+
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/mochikit_v14/tests/test_Signal.js b/mochikit_v14/tests/test_Signal.js
new file mode 100644 (file)
index 0000000..ca9680e
--- /dev/null
@@ -0,0 +1,430 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Signal = function (t) {
+    
+    var submit = MochiKit.DOM.getElement('submit');
+    var ident = null;
+    var i = 0;
+    var aFunction = function() {
+        t.ok(this === submit, "aFunction should have 'this' as submit");
+        i++;
+        if (typeof(this.someVar) != 'undefined') {
+            i += this.someVar;
+        }
+    };
+    
+    var aObject = {};
+    aObject.aMethod = function() {
+        t.ok(this === aObject, "aMethod should have 'this' as aObject");
+        i++;
+    };
+
+    ident = connect('submit', 'onclick', aFunction);
+    MochiKit.DOM.getElement('submit').click();
+    t.is(i, 1, 'HTML onclick event can be connected to a function');
+
+    disconnect(ident);
+    MochiKit.DOM.getElement('submit').click();
+    t.is(i, 1, 'HTML onclick can be disconnected from a function');
+
+    var submit = MochiKit.DOM.getElement('submit');
+
+    ident = connect(submit, 'onclick', aFunction);
+    submit.click();
+    t.is(i, 2, 'Checking that a DOM element can be connected to a function');
+
+    disconnect(ident);
+    submit.click();
+    t.is(i, 2, '...and then disconnected');    
+    
+    if (MochiKit.DOM.getElement('submit').fireEvent || 
+        (document.createEvent && 
+        typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) {
+        
+        /* 
+        
+            Adapted from: 
+            http://www.devdaily.com/java/jwarehouse/jforum/tests/selenium/javascript/htmlutils.js.shtml
+            License: Apache
+            Copyright: Copyright 2004 ThoughtWorks, Inc
+            
+        */
+        var triggerMouseEvent = function(element, eventType, canBubble) {
+            element = MochiKit.DOM.getElement(element);
+            canBubble = (typeof(canBubble) == 'undefined') ? true : canBubble;
+            if (element.fireEvent) {
+                var newEvt = document.createEventObject();
+                newEvt.clientX = 1;
+                newEvt.clientY = 1;
+                newEvt.button = 1;
+                element.fireEvent('on' + eventType, newEvt);
+            } else if (document.createEvent && (typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) {
+                var evt = document.createEvent('MouseEvents');
+                evt.initMouseEvent(eventType, canBubble, true, // event, bubbles, cancelable
+                    document.defaultView, 1, // view, # of clicks
+                    1, 0, 0, 0, // screenX, screenY, clientX, clientY
+                    false, false, false, false, // ctrlKey, altKey, shiftKey, metaKey
+                    0, null); // buttonCode, relatedTarget
+                element.dispatchEvent(evt);
+            }
+        };
+
+        var eventTest = function(e) {
+            i++;
+            t.ok((typeof(e.event()) === 'object'), 'checking that event() is an object');
+            t.ok((typeof(e.type()) === 'string'), 'checking that type() is a string');
+            t.ok((e.target() === MochiKit.DOM.getElement('submit')), 'checking that target is "submit"');
+            t.ok((typeof(e.modifier()) === 'object'), 'checking that modifier() is an object');
+            t.ok(e.modifier().alt === false, 'checking that modifier().alt is defined, but false');
+            t.ok(e.modifier().ctrl === false, 'checking that modifier().ctrl is defined, but false');
+            t.ok(e.modifier().meta === false, 'checking that modifier().meta is defined, but false');
+            t.ok(e.modifier().shift === false, 'checking that modifier().shift is defined, but  false');
+            t.ok((typeof(e.mouse()) === 'object'), 'checking that mouse() is an object');
+            t.ok((typeof(e.mouse().button) === 'object'), 'checking that mouse().button is an object');
+            t.ok(e.mouse().button.left === true, 'checking that mouse().button.left is true');
+            t.ok(e.mouse().button.middle === false, 'checking that mouse().button.middle is false');
+            t.ok(e.mouse().button.right === false, 'checking that mouse().button.right is false');
+            t.ok((typeof(e.mouse().page) === 'object'), 'checking that mouse().page is an object');
+            t.ok((typeof(e.mouse().page.x) === 'number'), 'checking that mouse().page.x is a number');
+            t.ok((typeof(e.mouse().page.y) === 'number'), 'checking that mouse().page.y is a number');
+            t.ok((typeof(e.mouse().client) === 'object'), 'checking that mouse().client is an object');
+            t.ok((typeof(e.mouse().client.x) === 'number'), 'checking that mouse().client.x is a number');
+            t.ok((typeof(e.mouse().client.y) === 'number'), 'checking that mouse().client.y is a number');
+
+            /* these should not be defined */
+            t.ok((typeof(e.relatedTarget()) === 'undefined'), 'checking that relatedTarget() is undefined');
+            t.ok((typeof(e.key()) === 'undefined'), 'checking that key() is undefined');
+        };
+
+        
+        ident = connect('submit', 'onmousedown', eventTest);
+        triggerMouseEvent('submit', 'mousedown', false);
+        t.is(i, 3, 'Connecting an event to an HTML object and firing a synthetic event');
+
+        disconnect(ident);
+        triggerMouseEvent('submit', 'mousedown', false);
+        t.is(i, 3, 'Disconnecting an event to an HTML object and firing a synthetic event');
+
+
+        
+    }    
+
+    // non-DOM tests
+
+    var hasNoSignals = {};
+    
+    var hasSignals = {someVar: 1};
+
+    var i = 0;
+        
+    var aFunction = function() {
+        i++;
+        if (typeof(this.someVar) != 'undefined') {
+            i += this.someVar;
+        }
+    };
+    
+    var bFunction = function(someArg, someOtherArg) {
+        i += someArg + someOtherArg;
+    };
+
+    
+    var aObject = {};
+    aObject.aMethod = function() {
+        i++;
+    };
+    
+    aObject.bMethod = function() {
+        i++;
+    };
+    
+    var bObject = {};
+    bObject.bMethod = function() {
+        i++;
+    };
+
+
+    ident = connect(hasSignals, 'signalOne', aFunction);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 2, 'Connecting function');
+    i = 0;
+
+    disconnect(ident);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'New style disconnecting function');
+    i = 0;
+
+
+    ident = connect(hasSignals, 'signalOne', bFunction);
+    signal(hasSignals, 'signalOne', 1, 2);
+    t.is(i, 3, 'Connecting function');
+    i = 0;
+
+    disconnect(ident);
+    signal(hasSignals, 'signalOne', 1, 2);
+    t.is(i, 0, 'New style disconnecting function');
+    i = 0;
+
+
+    connect(hasSignals, 'signalOne', aFunction);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 2, 'Connecting function');
+    i = 0;
+
+    disconnect(hasSignals, 'signalOne', aFunction);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'Old style disconnecting function');
+    i = 0;
+
+
+    ident = connect(hasSignals, 'signalOne', aObject, aObject.aMethod);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 1, 'Connecting obj-function');
+    i = 0;
+
+    disconnect(ident);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'New style disconnecting obj-function');
+    i = 0;
+
+    connect(hasSignals, 'signalOne', aObject, aObject.aMethod);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 1, 'Connecting obj-function');
+    i = 0;
+
+    disconnect(hasSignals, 'signalOne', aObject, aObject.aMethod);
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'Disconnecting obj-function');
+    i = 0;
+
+
+    ident = connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 1, 'Connecting obj-string');
+    i = 0;
+
+    disconnect(ident);
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 0, 'New style disconnecting obj-string');
+    i = 0;
+
+
+    connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 1, 'Connecting obj-string');
+    i = 0;
+
+    disconnect(hasSignals, 'signalTwo', aObject, 'aMethod');
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 0, 'Old style disconnecting obj-string');
+    i = 0;
+
+
+    var shouldRaise = function() { return undefined.attr; };
+
+    try {
+        connect(hasSignals, 'signalOne', shouldRaise);
+        signal(hasSignals, 'signalOne');
+        t.ok(false, 'An exception was not raised');
+    } catch (e) {
+        t.ok(true, 'An exception was raised');
+    }
+    disconnect(hasSignals, 'signalOne', shouldRaise);
+    t.is(i, 0, 'Exception raised, signal should not have fired');
+    i = 0;
+
+    
+    connect(hasSignals, 'signalOne', aObject, 'aMethod');
+    connect(hasSignals, 'signalOne', aObject, 'bMethod');
+    signal(hasSignals, 'signalOne');
+    t.is(i, 2, 'Connecting one signal to two slots in one object');
+    i = 0;
+    
+    disconnect(hasSignals, 'signalOne', aObject, 'aMethod');
+    disconnect(hasSignals, 'signalOne', aObject, 'bMethod');
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'Disconnecting one signal from two slots in one object');
+    i = 0;
+
+
+    connect(hasSignals, 'signalOne', aObject, 'aMethod');
+    connect(hasSignals, 'signalOne', bObject, 'bMethod');
+    signal(hasSignals, 'signalOne');
+    t.is(i, 2, 'Connecting one signal to two slots in two objects');
+    i = 0;
+
+    disconnect(hasSignals, 'signalOne', aObject, 'aMethod');
+    disconnect(hasSignals, 'signalOne', bObject, 'bMethod');
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'Disconnecting one signal from two slots in two objects');
+    i = 0;
+    
+
+    try {
+        connect(nothing, 'signalOne', aObject, 'aMethod');
+        signal(nothing, 'signalOne');
+        t.ok(false, 'An exception was not raised when connecting undefined');
+    } catch (e) {
+        t.ok(true, 'An exception was raised when connecting undefined');
+    }
+
+    try {
+        disconnect(nothing, 'signalOne', aObject, 'aMethod');
+        t.ok(false, 'An exception was not raised when disconnecting undefined');
+    } catch (e) {
+        t.ok(true, 'An exception was raised when disconnecting undefined');
+    }
+    
+    
+    try {
+        connect(hasSignals, 'signalOne', nothing);
+        signal(hasSignals, 'signalOne');
+        t.ok(false, 'An exception was not raised when connecting an undefined function');
+    } catch (e) {
+        t.ok(true, 'An exception was raised when connecting an undefined function');
+    }
+
+    try {
+        disconnect(hasSignals, 'signalOne', nothing);
+        t.ok(false, 'An exception was not raised when disconnecting an undefined function');
+    } catch (e) {
+        t.ok(true, 'An exception was raised when disconnecting an undefined function');
+    }
+    
+    
+    try {
+        connect(hasSignals, 'signalOne', aObject, aObject.nothing);
+        signal(hasSignals, 'signalOne');
+        t.ok(false, 'An exception was not raised when connecting an undefined method');
+    } catch (e) {
+        t.ok(true, 'An exception was raised when connecting an undefined method');
+    }
+    
+    try {
+        connect(hasSignals, 'signalOne', aObject, 'nothing');
+        signal(hasSignals, 'signalOne');
+        t.ok(false, 'An exception was not raised when connecting an undefined method (as string)');
+    } catch (e) {
+        t.ok(true, 'An exception was raised when connecting an undefined method (as string)');
+    }
+
+    t.is(i, 0, 'Signals should not have fired');
+
+    connect(hasSignals, 'signalOne', aFunction);
+    connect(hasSignals, 'signalOne', aObject, 'aMethod');
+    disconnectAll(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'disconnectAll works with single explicit signal');
+    i = 0;
+
+    connect(hasSignals, 'signalOne', aFunction);
+    connect(hasSignals, 'signalOne', aObject, 'aMethod');
+    connect(hasSignals, 'signalTwo', aFunction);
+    connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+    disconnectAll(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalOne');
+    t.is(i, 0, 'disconnectAll works with single explicit signal');
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 3, 'disconnectAll does not disconnect unrelated signals');
+    i = 0;
+
+    connect(hasSignals, 'signalOne', aFunction);
+    connect(hasSignals, 'signalOne', aObject, 'aMethod');
+    connect(hasSignals, 'signalTwo', aFunction);
+    connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+    disconnectAll(hasSignals, 'signalOne', 'signalTwo');
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 0, 'disconnectAll works with two explicit signals');
+    i = 0;
+
+    connect(hasSignals, 'signalOne', aFunction);
+    connect(hasSignals, 'signalOne', aObject, 'aMethod');
+    connect(hasSignals, 'signalTwo', aFunction);
+    connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+    disconnectAll(hasSignals, ['signalOne', 'signalTwo']);
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 0, 'disconnectAll works with two explicit signals as a list');
+    i = 0;
+
+    connect(hasSignals, 'signalOne', aFunction);
+    connect(hasSignals, 'signalOne', aObject, 'aMethod');
+    connect(hasSignals, 'signalTwo', aFunction);
+    connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+    disconnectAll(hasSignals);
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(i, 0, 'disconnectAll works with implicit signals');
+    i = 0;
+    
+       var toggle = function() {
+               disconnectAll(hasSignals, 'signalOne');
+               connect(hasSignals, 'signalOne', aFunction);
+               i++;
+       };
+    
+       connect(hasSignals, 'signalOne', aFunction);
+       connect(hasSignals, 'signalTwo', function() { i++; });
+       connect(hasSignals, 'signalTwo', toggle);
+       connect(hasSignals, 'signalTwo', function() { i++; }); // #147
+       connect(hasSignals, 'signalTwo', function() { i++; });
+       signal(hasSignals, 'signalTwo');
+    t.is(i, 4, 'disconnectAll fired in a signal loop works');
+    i = 0;
+    disconnectAll('signalOne');
+    disconnectAll('signalTwo');
+
+    var testfunc = function () { arguments.callee.count++; };
+    testfunc.count = 0;
+    var testObj = {
+        methOne: function () { this.countOne++; }, countOne: 0,
+        methTwo: function () { this.countTwo++; }, countTwo: 0
+    };
+    connect(hasSignals, 'signalOne', testfunc);
+    connect(hasSignals, 'signalTwo', testfunc);
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(testfunc.count, 2, 'disconnectAllTo func precondition');
+    disconnectAllTo(testfunc);
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(testfunc.count, 2, 'disconnectAllTo func');
+
+    connect(hasSignals, 'signalOne', testObj, 'methOne');
+    connect(hasSignals, 'signalTwo', testObj, 'methTwo');
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(testObj.countOne, 1, 'disconnectAllTo obj precondition');
+    t.is(testObj.countTwo, 1, 'disconnectAllTo obj precondition');
+    disconnectAllTo(testObj);
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(testObj.countOne, 1, 'disconnectAllTo obj');
+    t.is(testObj.countTwo, 1, 'disconnectAllTo obj');
+
+    testObj.countOne = testObj.countTwo = 0;
+    connect(hasSignals, 'signalOne', testObj, 'methOne');
+    connect(hasSignals, 'signalTwo', testObj, 'methTwo');
+    disconnectAllTo(testObj, 'methOne');
+    signal(hasSignals, 'signalOne');
+    signal(hasSignals, 'signalTwo');
+    t.is(testObj.countOne, 0, 'disconnectAllTo obj+str');
+    t.is(testObj.countTwo, 1, 'disconnectAllTo obj+str');
+    has__Connect = {
+          count: 0,
+          __connect__: function (ident) {
+              this.count += arguments.length;
+              disconnect(ident);
+          }
+    };
+
+    connect(has__Connect, 'signalOne', aFunction);
+    t.is(has__Connect.count, 3, '__connect__ is called when it exists');
+    signal(has__Connect, 'signalOne');
+    t.is(has__Connect.count, 3, '__connect__ can disconnect the signal');
+    
+};
diff --git a/plotkit_v091/COPYING b/plotkit_v091/COPYING
new file mode 100644 (file)
index 0000000..b6153f2
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright (c) 2006, Alastair Tse
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of the Alastair Tse nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/plotkit_v091/PlotKit/Base.js b/plotkit_v091/PlotKit/Base.js
new file mode 100644 (file)
index 0000000..49988c9
--- /dev/null
@@ -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);
+
diff --git a/plotkit_v091/PlotKit/Canvas.js b/plotkit_v091/PlotKit/Canvas.js
new file mode 100644 (file)
index 0000000..1e88e3c
--- /dev/null
@@ -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);
+
diff --git a/plotkit_v091/PlotKit/EasyPlot.js b/plotkit_v091/PlotKit/EasyPlot.js
new file mode 100644 (file)
index 0000000..7607731
--- /dev/null
@@ -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);
+
+
diff --git a/plotkit_v091/PlotKit/Layout.js b/plotkit_v091/PlotKit/Layout.js
new file mode 100644 (file)
index 0000000..ff1c9db
--- /dev/null
@@ -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);
+
+
diff --git a/plotkit_v091/PlotKit/PlotKit.js b/plotkit_v091/PlotKit/PlotKit.js
new file mode 100644 (file)
index 0000000..e79abf7
--- /dev/null
@@ -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>');
+            }
+        };
+    })();
+}
diff --git a/plotkit_v091/PlotKit/PlotKit_Packed.js b/plotkit_v091/PlotKit/PlotKit_Packed.js
new file mode 100644 (file)
index 0000000..363042a
--- /dev/null
@@ -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);
+
+
diff --git a/plotkit_v091/PlotKit/SVG.js b/plotkit_v091/PlotKit/SVG.js
new file mode 100644 (file)
index 0000000..3687bc0
--- /dev/null
@@ -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);
+
diff --git a/plotkit_v091/PlotKit/SweetCanvas.js b/plotkit_v091/PlotKit/SweetCanvas.js
new file mode 100644 (file)
index 0000000..bb6fe5c
--- /dev/null
@@ -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);
+
diff --git a/plotkit_v091/PlotKit/SweetSVG.js b/plotkit_v091/PlotKit/SweetSVG.js
new file mode 100644 (file)
index 0000000..4183058
--- /dev/null
@@ -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);
diff --git a/plotkit_v091/PlotKit/dummy.svg b/plotkit_v091/PlotKit/dummy.svg
new file mode 100644 (file)
index 0000000..6a82bd4
--- /dev/null
@@ -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>
diff --git a/plotkit_v091/PlotKit/excanvas.js b/plotkit_v091/PlotKit/excanvas.js
new file mode 100644 (file)
index 0000000..ca77da2
--- /dev/null
@@ -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
diff --git a/plotkit_v091/README b/plotkit_v091/README
new file mode 100644 (file)
index 0000000..7e77bac
--- /dev/null
@@ -0,0 +1 @@
+For more information, go to http://www.liquidx.net/plotkit/.
diff --git a/plotkit_v091/doc/MochiKitAdditions.html b/plotkit_v091/doc/MochiKitAdditions.html
new file mode 100644 (file)
index 0000000..d21b157
--- /dev/null
@@ -0,0 +1,2 @@
+.. title: MochiKit Additions
+
diff --git a/plotkit_v091/doc/MochiKitAdditions.txt b/plotkit_v091/doc/MochiKitAdditions.txt
new file mode 100644 (file)
index 0000000..d21b157
--- /dev/null
@@ -0,0 +1,2 @@
+.. title: MochiKit Additions
+
diff --git a/plotkit_v091/doc/PlotKit.Base.html b/plotkit_v091/doc/PlotKit.Base.html
new file mode 100644 (file)
index 0000000..3cb0f7c
--- /dev/null
@@ -0,0 +1,302 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.Base | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc api">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.Layout.html">&gt;&gt;</a> 
+</p>
+
+<h1> PlotKit Base</h1>
+<p>PlotKit Base contains a number of simple functions that are needed for the rest of the PlotKit libraries.
+</p>
+
+<h2> PlotKit.Base Functions</h2>
+<ul>
+ <li>
+      <code>collapse()</code> 
+ </li>
+</ul>
+<p>   Given an array, it will collapse all the values from the passed array into one big array.
+</p>
+<p> <code>[[1,2], [3,4], [5,6]] --&gt; [1, 2, 3, 4, 5, 6]</code> 
+</p>
+<ul>
+ <li>
+      <code>findPosX(element)</code> 
+ </li>
+</ul>
+<p>  Returns the X value of the element relative to the document in a browser independent way.
+</p>
+<ul>
+ <li>
+      <code>findPosY(element)</code> 
+ </li>
+</ul>
+<p>  Returns the Y value of the element relative to the document in a browser independent way.
+</p>
+<ul>
+ <li>
+      <code>palette(baseColor, fromLevel = -0.2, toLevel = 0.2, increment = 0.1)</code> 
+ </li>
+</ul>
+<p>  Takes in a base colour and generates a palette of colours based on the intensive levels.
+</p>
+<ul>
+ <li>
+      <code>roundInterval(value, precision)</code> 
+ </li>
+</ul>
+<p>  Rounds a number to a specified precision. <strong>TODO: make more robust</strong> 
+</p>
+<ul>
+ <li>
+      <code>uniq(array)</code> 
+ </li>
+</ul>
+<p>  Acts like the UNIX uniq, takes a sorted array and returns a new array that only contains uniq elements.
+</p>
+<ul>
+ <li>
+      <code>isFuncLike(obj)</code> (PlotKit 0.9+)
+ </li>
+</ul>
+<p>  Returns true if it is of type <code>function</code>.
+</p>
+<ul>
+ <li>
+      <code>usingPrototype()</code>  (PlotKit 0.9+)
+ </li>
+</ul>
+<p>  Checks whether the javascript runtime is polluted by prototype.js
+</p>
+<ul>
+ <li>
+      <code>items(lst)</code>  (PlotKit 0.9+)
+ </li>
+</ul>
+<p>  A version of <code>MochiKit.Base.items()</code> that is aware of prototype.js
+</p>
+<ul>
+ <li>
+      <code>keys(lst)</code>  (PlotKit 0.9+)
+ </li>
+</ul>
+<p>  A version of <code>MochiKit.Base.keys()</code> that is aware of prototype.js
+</p>
+<ul>
+ <li>
+      <code>map(fn, lst)</code>  (PlotKit 0.9+)
+ </li>
+</ul>
+<p>  A version of <code>MochiKit.Base.map()</code> that is aware of prototype.js
+</p>
+
+<h1> Preset Styles</h1>
+
+<h2> Color Schemes</h2>
+<p>There are some colour schemes, which are an array of
+   MochiKit.Color.Colors.
+</p>
+<ul>
+ <li>
+      <code>colorScheme()</code> 
+ </li>
+</ul>
+<p>A default colour scheme that consists of red, orange, yellow, green, cyan, blue, purple and magenta.
+</p>
+<ul>
+ <li>
+      <code>baseDarkPrimaryColors()</code> 
+ </li>
+</ul>
+<p>A set of five dark colours.
+</p>
+<ul>
+ <li>
+      <code>basePrimaryColors()</code> 
+ </li>
+</ul>
+<p>A set of five bright primary colours.
+</p>
+<ul>
+ <li>
+      <code>baseBlueColors()</code> 
+ </li>
+</ul>
+<p>Three colour set that have a nice professional blue hue.
+</p>
+
+<h2> Office Style</h2>
+<p>These are base styles that were inspired by charts in Office 12. The
+   color schemes are fairly similar to those found in screenshots of
+   charts available online.
+</p>
+<ul>
+ <li>
+      <code>officeBaseStyle</code> 
+ </li>
+</ul>
+<p>  Contains the basic style independent of colours.
+</p>
+<ul>
+ <li>
+      <code>officeBlue()</code> 
+ </li>
+</ul>
+<p>  Blue colors: <img src="blue.png" alt="bluecolors"/> 
+</p>
+<ul>
+ <li>
+      <code>officeRed()</code> 
+ </li>
+</ul>
+<p>  Red colors: <img src="red.png" alt="redcolors"/> 
+</p>
+<ul>
+ <li>
+      <code>officeGreen()</code> 
+ </li>
+</ul>
+<p>  Green colors: <img src="green.png" alt="greencolors"/> 
+</p>
+<ul>
+ <li>
+      <code>officePurple()</code> 
+ </li>
+</ul>
+<p>  Purple colors: <img src="purple.png" alt="purplecolors"/> 
+</p>
+<ul>
+ <li>
+      <code>officeCyan()</code> 
+ </li>
+</ul>
+<p>  Cyan colors: <img src="cyan.png" alt="cyancolors"/> 
+</p>
+<ul>
+ <li>
+      <code>officeOrange()</code> 
+ </li>
+</ul>
+<p>  Orange colors: <img src="orange.png" alt="orangecolors"/> 
+</p>
+<ul>
+ <li>
+      <code>officeBlack()</code> 
+ </li>
+</ul>
+<p>  Black colors: <img src="black.png" alt="blackcolors"/> 
+</p>
+
+<h2> Usage</h2>
+<p>  <code>var layout = PlotKit.Layout(&quot;bar&quot;, officeOrange());</code> 
+</p>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.Base.txt b/plotkit_v091/doc/PlotKit.Base.txt
new file mode 100644 (file)
index 0000000..c0d8c3a
--- /dev/null
@@ -0,0 +1,139 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.Base{% endblock %}
+
+{% block content %}
+<div class="page doc api">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [>>](PlotKit.Layout.html)
+
+PlotKit Base
+============
+
+PlotKit Base contains a number of simple functions that are needed for the rest of the PlotKit libraries.
+
+PlotKit.Base Functions
+----------------------
+
+* ``collapse()``
+   Given an array, it will collapse all the values from the passed array into one big array.
+
+ ``[[1,2], [3,4], [5,6]] --> [1, 2, 3, 4, 5, 6]``
+
+* ``findPosX(element)``
+
+  Returns the X value of the element relative to the document in a browser independent way.
+
+* ``findPosY(element)``
+
+  Returns the Y value of the element relative to the document in a browser independent way.
+
+* ``palette(baseColor, fromLevel = -0.2, toLevel = 0.2, increment = 0.1)``
+
+  Takes in a base colour and generates a palette of colours based on the intensive levels.
+
+* ``roundInterval(value, precision)``
+  Rounds a number to a specified precision. __TODO: make more robust__
+
+* ``uniq(array)``
+
+  Acts like the UNIX uniq, takes a sorted array and returns a new array that only contains uniq elements.
+  
+* ``isFuncLike(obj)`` (PlotKit 0.9+)
+
+  Returns true if it is of type ``function``.
+
+* ``usingPrototype()``  (PlotKit 0.9+)
+
+  Checks whether the javascript runtime is polluted by prototype.js
+  
+* ``items(lst)``  (PlotKit 0.9+)
+
+  A version of ``MochiKit.Base.items()`` that is aware of prototype.js
+
+* ``keys(lst)``  (PlotKit 0.9+)
+
+  A version of ``MochiKit.Base.keys()`` that is aware of prototype.js
+
+* ``map(fn, lst)``  (PlotKit 0.9+)
+
+  A version of ``MochiKit.Base.map()`` that is aware of prototype.js
+
+Preset Styles
+=============
+
+Color Schemes
+-------------
+
+There are some colour schemes, which are an array of
+MochiKit.Color.Colors.
+
+* ``colorScheme()``
+
+A default colour scheme that consists of red, orange, yellow, green, cyan, blue, purple and magenta.
+
+* ``baseDarkPrimaryColors()``
+
+A set of five dark colours.
+
+* ``basePrimaryColors()``
+
+A set of five bright primary colours.
+
+* ``baseBlueColors()``
+
+Three colour set that have a nice professional blue hue.
+
+Office Style
+------------
+
+These are base styles that were inspired by charts in Office 12. The
+color schemes are fairly similar to those found in screenshots of
+charts available online.
+
+* ``officeBaseStyle``
+
+  Contains the basic style independent of colours.
+
+* ``officeBlue()``
+
+  Blue colors: ![bluecolors](blue.png)
+
+* ``officeRed()``
+
+  Red colors: ![redcolors](red.png)
+
+* ``officeGreen()``
+
+  Green colors: ![greencolors](green.png)
+
+* ``officePurple()``
+
+  Purple colors: ![purplecolors](purple.png)
+
+* ``officeCyan()``
+
+  Cyan colors: ![cyancolors](cyan.png)
+
+* ``officeOrange()``
+
+  Orange colors: ![orangecolors](orange.png)
+
+* ``officeBlack()``
+
+  Black colors: ![blackcolors](black.png)
+
+Usage
+-----
+
+  ``var layout = PlotKit.Layout("bar", officeOrange());``
+
+{% endfilter %}
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/plotkit_v091/doc/PlotKit.Canvas.html b/plotkit_v091/doc/PlotKit.Canvas.html
new file mode 100644 (file)
index 0000000..4689952
--- /dev/null
@@ -0,0 +1,172 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.Canvas | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc api">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.Renderer.html">&lt;&lt;</a> | <a href="PlotKit.SVG.html">&gt;&gt;</a> 
+</p>
+
+<h1> PlotKit Canvas</h1>
+<p>This contains the CanvasRenderer, the default renderer and most well supported one used in PlotKit.
+</p>
+<p>It supports Safari 2, Firefox 1.5, Opera 9 and IE 6. Note that for IE6
+   support, you will need iecanvas.htc which is included with PlotKit. 
+</p>
+<p>Please see the <a href="SVGCanvasCompat.html">Canvas/SVG Browser Support Status</a> for bugs
+   with the Canvas implementation on different browsers.
+</p>
+
+<h2> PlotKit Canvas Extra Options</h2>
+<p>In addition to the options outlined in <a href="PlotKit.Renderer.html">PlotKit.Renderer</a>, here are additional options that the CanvasRenderer supports.
+</p>
+<table>
+  <thead>
+    <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+ <tbody>
+    <tr>
+        <th>IECanvasHTC</th>
+        <td>Path relative to the HTML document of the iecanvas.htc file.</td>
+        <td>string</td>
+        <td>iecanvas.htc</td>
+    </tr>
+    </tbody>
+</table>
+
+
+<h2> PlotKit Canvas Example</h2>
+<pre><code>var options = {
+    &quot;drawsBackground&quot;: true,
+    &quot;drawYAxis&quot;: false,
+    &quot;IECanvasHTC&quot;: &quot;contrib/iecanvas.htc&quot;
+};
+
+var layout = new Layout(&quot;bar&quot;, {});
+layout.addDataset(&quot;squares&quot;, [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16]]);
+layout.evaluate()
+var renderer = new CanvasRenderer($('canvas'), layout, options);
+layout.render();
+</code></pre>
+<h2> PlotKit Canvas Events/Signals</h2>
+<p>There is preliminary support for events in the CanvasRenderer. If <code>enableEvents</code> is set <code>true</code> in the options, you can hook into the <code>onmousemove</code>, <code>onclick</code>, <code>onmouseover</code> and <code>onmouseout</code> events via the MochiKit.Signal.connect. Note that you must have included MochiKit/Signal.js before instantiating the CanvasRenderer
+</p>
+
+<h2> PlotKit Canvas Notes</h2>
+
+<h3> IE Support</h3>
+<p>IE Support is done thanks to webfx's great iecanvas.htc which emulates
+   part of the WHATWG canvas specification. Note that alpha values and
+   clear() does not work in IE.
+</p>
+<p>Remember that iecanvas.htc <strong>must</strong> reside on the same domain as the
+   HTML page itself.
+</p>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.Canvas.txt b/plotkit_v091/doc/PlotKit.Canvas.txt
new file mode 100644 (file)
index 0000000..c1e383c
--- /dev/null
@@ -0,0 +1,81 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.Canvas{% endblock %}
+
+{% block content %}
+<div class="page doc api">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [<<](PlotKit.Renderer.html) | [>>](PlotKit.SVG.html)
+
+PlotKit Canvas
+==============
+
+This contains the CanvasRenderer, the default renderer and most well supported one used in PlotKit.
+
+It supports Safari 2, Firefox 1.5, Opera 9 and IE 6. Note that for IE6
+support, you will need iecanvas.htc which is included with PlotKit. 
+
+Please see the [Canvas/SVG Browser Support Status][Browser] for bugs
+with the Canvas implementation on different browsers.
+
+PlotKit Canvas Extra Options
+----------------------------
+
+In addition to the options outlined in [PlotKit.Renderer][], here are additional options that the CanvasRenderer supports.
+
+<table>
+  <thead>
+       <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+ <tbody>
+       <tr>
+               <th>IECanvasHTC</th>
+               <td>Path relative to the HTML document of the iecanvas.htc file.</td>
+               <td>string</td>
+               <td>iecanvas.htc</td>
+       </tr>
+       </tbody>
+</table>
+
+PlotKit Canvas Example
+----------------------
+
+       var options = {
+               "drawsBackground": true,
+               "drawYAxis": false,
+               "IECanvasHTC": "contrib/iecanvas.htc"
+       };
+
+       var layout = new Layout("bar", {});
+       layout.addDataset("squares", [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16]]);
+       layout.evaluate()
+       var renderer = new CanvasRenderer($('canvas'), layout, options);
+       layout.render();
+
+PlotKit Canvas Events/Signals
+-----------------------------
+
+There is preliminary support for events in the CanvasRenderer. If ``enableEvents`` is set ``true`` in the options, you can hook into the ``onmousemove``, ``onclick``, ``onmouseover`` and ``onmouseout`` events via the MochiKit.Signal.connect. Note that you must have included MochiKit/Signal.js before instantiating the CanvasRenderer
+
+PlotKit Canvas Notes
+--------------------
+
+### IE Support
+
+IE Support is done thanks to webfx's great iecanvas.htc which emulates
+part of the WHATWG canvas specification. Note that alpha values and
+clear() does not work in IE.
+
+Remember that iecanvas.htc __must__ reside on the same domain as the
+HTML page itself.
+
+[PlotKit.Renderer]: PlotKit.Renderer.html
+[Browser]: SVGCanvasCompat.html
+
+{% endfilter %}
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/plotkit_v091/doc/PlotKit.EasyPlot.html b/plotkit_v091/doc/PlotKit.EasyPlot.html
new file mode 100644 (file)
index 0000000..a9a1549
--- /dev/null
@@ -0,0 +1,155 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.Canvas | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc api">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.SweetSVG.html">&lt;&lt;</a> 
+</p>
+
+<h1> PlotKit EasyPlot</h1>
+<p>EasyPlot is a wrapper around the various PlotKit classes to allow you to get a chart plotted as quick as possible with as little code as possible. Using EasyPlot, you will get a chart started with just a single line.
+</p>
+
+<h2> Constructor</h2>
+<p> <code>PlotKit.EasyPlot(style, options, divElement, datasourceArray)</code> 
+</p>
+<p>EasyPlot object will automatically choose the supported render method, currently Canvas or SVG in that order, and render the datasources given in <code>datasourceArray</code>.
+</p>
+
+<h3> Arguments:</h3>
+<ul>
+ <li>
+      <code>style</code> may be <code>line</code>, <code>bar</code> or <code>pie</code>.
+ </li>
+
+ <li>
+      <code>options</code> is an associative dictionary that is the combined options of both <code>Layout</code> and <code>Renderer</code>.
+ </li>
+
+ <li>
+      <code>divElement</code> is the container that the chart should be rendered in. It is best that the <code>width</code> and <code>height</code> attribute is set in the <code>DIV</code> element.
+ </li>
+
+ <li>
+      <code>datasourceArray</code> is an array of data sources. The elements of the array can either be a two dimensional array given in <code>Plotkit.Layout.addDataset</code> or it can be a string that points to the relative URL of a comma separated data file.
+ </li>
+</ul>
+
+<h2> EasyPlot Example</h2>
+<pre><code>&lt;div id=&quot;example&quot; style=&quot;margin: 0 auto 0 auto;&quot; width=&quot;400&quot; height=&quot;400&quot;&gt;&lt;/div&gt;
+
+&lt;script type=&quot;text/javascript&quot;&gt;
+var data = [[0,0], [1,2], [2,3], [3, 7], [4, 8], [5, 6]];
+var plotter = EasyPlot(&quot;line&quot;, {}, $(&quot;example&quot;), [data, &quot;sample.txt&quot;]);
+&lt;/script&gt;
+</code></pre><p>In this example, two datasets are passed, one defined as a 2D array and another which is a comma separated text file (CSV) at the location &quot;sample.txt&quot;.  A demonstration of this is found in the <a href="http://media.liquidx.net/js/plotkit-tests/quickstart-easy.html">QuickStartEasy</a> example.
+</p>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.EasyPlot.txt b/plotkit_v091/doc/PlotKit.EasyPlot.txt
new file mode 100644 (file)
index 0000000..b23bbe7
--- /dev/null
@@ -0,0 +1,50 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.Canvas{% endblock %}
+
+{% block content %}
+<div class="page doc api">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [<<](PlotKit.SweetSVG.html) 
+
+PlotKit EasyPlot
+================
+
+EasyPlot is a wrapper around the various PlotKit classes to allow you to get a chart plotted as quick as possible with as little code as possible. Using EasyPlot, you will get a chart started with just a single line.
+
+Constructor
+-----------
+``PlotKit.EasyPlot(style, options, divElement, datasourceArray)``
+
+EasyPlot object will automatically choose the supported render method, currently Canvas or SVG in that order, and render the datasources given in ``datasourceArray``.
+
+### Arguments:
+
+* ``style`` may be ``line``, ``bar`` or ``pie``.
+* ``options`` is an associative dictionary that is the combined options of both ``Layout`` and ``Renderer``.
+* ``divElement`` is the container that the chart should be rendered in. It is best that the ``width`` and ``height`` attribute is set in the ``DIV`` element.
+* ``datasourceArray`` is an array of data sources. The elements of the array can either be a two dimensional array given in ``Plotkit.Layout.addDataset`` or it can be a string that points to the relative URL of a comma separated data file.
+
+EasyPlot Example
+----------------
+
+    <div id="example" style="margin: 0 auto 0 auto;" width="400" height="400"></div>
+    
+    <script type="text/javascript">
+    var data = [[0,0], [1,2], [2,3], [3, 7], [4, 8], [5, 6]];
+    var plotter = EasyPlot("line", {}, $("example"), [data, "sample.txt"]);
+    </script>
+
+
+In this example, two datasets are passed, one defined as a 2D array and another which is a comma separated text file (CSV) at the location "sample.txt".  A demonstration of this is found in the [QuickStartEasy][] example.
+
+
+[QuickStartEasy]: http://media.liquidx.net/js/plotkit-tests/quickstart-easy.html
+
+{% endfilter %}
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/plotkit_v091/doc/PlotKit.Layout.html b/plotkit_v091/doc/PlotKit.Layout.html
new file mode 100644 (file)
index 0000000..72e99cf
--- /dev/null
@@ -0,0 +1,428 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.Layout | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc api">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.Base.html">&lt;&lt;</a> | <a href="PlotKit.Renderer.html">&gt;&gt;</a> 
+</p>
+
+<h1> PlotKit Layout</h1>
+<p>PlotKit Layout is the core of the plotting engine. It deals exclusively with laying objects out on a virtual canvas that has the dimension of 1.0 x 1.0.
+</p>
+<p>The layout engine abstracts away all the complex layout problems with plotting charts and presents a list of objects that need to rendered rather than mixing this with the rendering logic.
+</p>
+<p>PlotKit Layout also is responsible for simple chart state querying so renderers can implement basic event support for objects on the canvas.
+</p>
+
+<h1> Constructor</h1>
+<p>  <code>new Layout(style, options);</code> 
+</p>
+<p>Layout takes the following arguments:
+</p>
+<p> <strong>style</strong> which can be <code>bar</code>, <code>line</code> or <code>pie</code> which represnts the style of the graph that is desired.
+</p>
+<p> <strong>options</strong> is a dictionary/associative array of layout options. Unrecognised keys are ignored. The following options are supported:
+</p>
+
+<h1> Layout Options</h1>
+
+<h2> Bar and Line Chart layout options</h2>
+<table cellpadding="0" cellspacing="0">
+  <thead>
+    <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+ <tbody>
+    <tr>
+        <th>barWidthFillFraction</th>
+        <td>Amount of space the total amount of bars should consume per X value.</td>
+        <td>Real number</td>
+        <td>0.75</td>
+    </tr>
+    <tr>
+        <th>barOrientation</th>
+        <td>Orientation of a bar chart. <b>(PlotKit 0.9+ only)</b></td>
+        <td>String ("vertical", "horizontal")</td>
+        <td>vertical</td>
+    </tr>
+    
+    <tr>
+        <th>xAxis</th>
+        <td>Minimum and Maximum values on the X axis.</td>
+        <td>Array of 2 Real numbers. (eg. [0.0, 10.0])</td>
+        <td>null</td>
+    </tr>
+    <tr>
+        <th>xNumberOfTicks</th>
+        <td>Used when automatically calculating axis ticks. This denotes the number of ticks there should be in the graph.</td>
+        <td>integer</td>
+        <td>10</td>
+    </tr>
+    <tr>
+        <th>xOriginIsZero</th>
+        <td>Should graph have X axis origin at 0</td>
+        <td>boolean</td>
+        <td>true</td>
+    </tr>
+    <tr>
+        <th>xTickPrecision</th>
+        <td>The number of decimal places we should round to for tick values.</td>
+        <td>integer</td>
+        <td>1</td>
+    </tr>
+    <tr>
+        <th>xTicks</th>
+        <td>X values at which ticks should be drawn. Automatically calculated if not defined using the parameters `xNumberOfTicks` and ``xTickPrecision``.</td>
+        <td>Array of {label: "somelabel", v:value}.</td>
+        <td>null</td>
+    </tr>
+    
+    <tr>
+        <th>yAxis</th>
+        <td>Minimum and Maximum values on the Y axis.</td>
+        <td>Array of 2 Real numbers. (eg. [0.0, 10.0])</td>
+        <td>null</td>
+    </tr>
+    <tr>
+        <th>yNumberOfTicks</th>
+        <td>Used when automatically calculating axis ticks. This denotes the number of ticks there should be in the graph.</td>
+        <td>integer</td>
+        <td>5</td>
+    </tr>
+    <tr>
+        <th>yOriginIsZero</th>
+        <td>Should graph have Y axis origin at 0</td>
+        <td>true</td>
+    </tr>
+    <tr>
+        <th>yTickPrecision</th>
+        <td>The number of decimal places we should round to for tick values.</td>
+        <td>integer</td>
+        <td>1</td>
+    </tr>
+    <tr>
+        <th>yTicks</th>
+        <td>Y values at which ticks should be drawn. Automatically calculated if not defined using the parameters ``yNumberOfTicks`` and ``yTickPrecision``.</td>
+        <td>Array of {label: "somelabel", v:value}.</td>
+        <td>null</td>
+    </tr>
+    </tbody>
+</table>
+
+
+<h2> Pie Chart Layout Options</h2>
+<table>
+  <thead>
+    <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+ <tbody>
+    <tr>
+        <th>pieRadius</th>
+        <td>Radius of the circle to be drawn.</td>
+        <td>Real number</td>
+        <td>0.4</td>
+    </tr>
+  </tbody>
+</table>
+
+
+<h1> Layout Properties</h1>
+<p>There are some properties you can access, either because you are using a layout inside a renderer or if you would like additional information. Under normal operations, you will not need to, or should modify these parameters.
+</p>
+<table cellpadding="0" cellspacing="0">
+  <thead>
+    <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+    <tr>
+        <th>style</th>
+        <td>String</td>
+        <td>This denotes the type of chart this layout is using. Valid values are ``bar``, ``line`` or ``pie``. Renderers will use this to determine which parameter (``bars``, ``points`` or ``slices``) to access in order to get draw the chart.</td>
+    </tr>
+    <tr>
+        <th>bars</th>
+        <td>Array of Bar.</td>
+        <td>This is a list of rectangles with values that the renderer should plot. This will only be valid after ``evaluate()`` has run. The properties of ``bar`` is described here. This is only valid if style is ``bar``. This array is sorted by dataset and then x-values.</td>
+    </tr>
+    <tr>
+        <th>points</th>
+        <td>Array of Point.</td>
+        <td>This is a list of points with values that the renderer should plot. This will only be valid after ``evaluate()`` has run. The properties of ``bar`` is described here. This is only valid if style is ``line``. This array is sorted by dataset and then x-values.</td>
+    </tr>
+    <tr>
+        <th>slices</th>
+        <td>Array of Slice.</td>
+        <td>This is a list of pie slices with values that the renderer should plot. This will only be valid after ``evaluate()`` has run. The properties of ``bar`` is described here. This is only valid if style is ``pie``.</td>
+    </tr>
+    <tr>
+        <th>xticks</th>
+        <td>Array of Tick.</td>
+        <td>For style in ``bar`` or ``line``, these are the ticks on the X axis. A ``tick`` is represented as a two element array with the first element representing the x position of the tick and the second element representing the string value of the label at that position.</td>
+    </tr>
+    <tr>
+        <th>yticks</th>
+        <td>Array of Tick.</td>
+        <td>For style in ``bar`` or ``line``, these are the ticks on the Y axis. A ``tick`` is represented as a two element array with the first element representing the y position of the tick and the second element representing the string value of the label at that position.</td>
+    </tr>
+    <tr>
+        <th>datasets</th>
+        <td>Associative Array of datasets</td>
+        <td>This should normally only be used to find the number of datasets by performing ``keys(layout.datasets)``. If you are looking at this in a renderer, then the layout engine needs to be extended.</td>
+    </tr>
+  </tbody>
+</table>
+
+
+<h1> Layout Types</h1>
+<p>Here are the definition of the types that you will encounter if you access the properties of the Layout object, specifically <code>bars</code>, <code>points</code> and <code>slices</code>. If you are not writing a renderer, you do not need to know this.
+</p>
+
+<h2> Bar Type</h2>
+<p>Represents a bar that the renderer will draw. It contains the following properties.
+</p>
+<table cellpadding="0" cellspacing="0">
+  <thead>
+    <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+    <tr>
+        <th>x, y</th>
+        <td>float</td>
+        <td>top left position of the bar between 0.0 and 1.0.</td>
+    </tr>
+    <tr>
+        <th>w, h</th>
+        <td>float</td>
+        <td>width and height of the bar from (``x``, ``y``) between 0.0 and 1.0.</td>
+    </tr>
+    <tr>
+        <th>xval, yval</th>
+        <td>float</td>
+        <td>The actual x value and y value this bar represents.</td>
+    </tr>
+    <tr>
+        <th>name</th>
+        <td>string</td>
+        <td>Name of the dataset which this bar belongs to.</td>
+    </tr>
+  </tbody>
+</table>
+
+
+<h2> Point Type</h2>
+<p>This represents a point on a line chart.
+</p>
+<table cellpadding="0" cellspacing="0">
+  <thead>
+    <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+    <tr>
+        <th>x, y</th>
+        <td>float</td>
+        <td>top left position of the point between 0.0 and 1.0.</td>
+    </tr>
+    <tr>
+        <th>xval, yval</th>
+        <td>float</td>
+        <td>The actual x value and y value this bar represents.</td>
+    </tr>
+    <tr>
+        <th>name</th>
+        <td>string</td>
+        <td>Name of the dataset which this bar belongs to.</td>
+    </tr>
+  </tbody>
+</table>
+
+
+<h2> Slice Type</h2>
+<p>This represents a pie slice in a pie chart.
+</p>
+<table>
+  <thead>
+    <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+    <tr>
+        <th>fraction</th>
+        <td>float</td>
+        <td>The fractional value this slice represents. This number is between 0.0 and 1.0</td>
+    </tr>
+    <tr>
+        <th>xval, yval</th>
+        <td>float</td>
+        <td>The x and y values of this slice.</td>
+    </tr>
+    <tr>
+        <th>startAngle</th>
+        <td>float</td>
+        <td>This is the angle of the start of the slice, in radians.</td>
+    </tr>
+    <tr>
+        <th>endAngle</th>
+        <td>float</td>
+        <td>This is the angle of the end of the slice, in radians.</td>
+    </tr>
+  </tbody>
+</table>
+
+
+<h1> Layout Methods</h1>
+<ul>
+ <li>
+      <code>addDataset(name, values)</code> 
+ </li>
+</ul>
+<p>  Adds a dataset to the layout engine and assigns it with <code>name</code>. <code>values</code> is an array of <code>\[x, y\]</code> values.
+</p>
+<ul>
+ <li>
+      <code>removeDataset(name)</code> 
+ </li>
+</ul>
+<p> Removes a dataset from the layout engine. In order for the new data to take effect, you must run <code>evaluate()</code>.
+</p>
+<ul>
+ <li>
+      <code>addDatasetFromTable(name, tableElement, xcol = 0, ycol = 1, labelCol = -1)</code> 
+ </li>
+</ul>
+<p>  Handy function to read values off a table. <code>name</code> is the name to give to the dataset just like in <code>addDataset()</code>, <code>tableElement</code> is the table which contains the values. Optionally, the user may specify to extract alternative columns using <code>xcol</code> and <code>ycol</code>. 
+</p>
+<p>  <strong>New in 0.9.1:</strong> If <code>labelCol</code> is specified to a value greater than -1, it will take the contents of that column as the xTick labels.
+</p>
+<ul>
+ <li>
+      <code>evaluate()</code> 
+ </li>
+</ul>
+<p>  Performs the evaluation of the layout. It is not done automatically, and you <strong>must</strong> execute this before passing the layout to a renderer.
+</p>
+<ul>
+ <li>
+     hitTest(x, y)
+ </li>
+</ul>
+<p>  Used by renderers to see if a virtual canvas position corresponds to any data. The return value varies per style. For <code>bar</code> charts, it will return the Bar type if it is a hit, or null if not. For <code>line</code>  charts, it will return a value if the point is underneath the highest curve, otherwise null <strong>(TODO: expand this or change implementation)</strong>. For <code>pie</code> charts, it will return the Slice object that is at the point, otherwise null.
+</p>
+<p>  <strong>Note that the specification of this function is subject to change</strong>.
+</p>
+
+<h1> Layout Notes</h1>
+
+<h2> Pie Chart Data and Ticks Restrictions</h2>
+<p>Note that you can only use one dataset for pie charts. Only the y value of the dataset will be used, but the x value must be unique and set as it will correspond to the xTicks that are given.
+</p>
+<p>Labels for pie charts will only use xTicks.
+</p>
+
+<h1> Layout Examples</h1>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.Layout.txt b/plotkit_v091/doc/PlotKit.Layout.txt
new file mode 100644 (file)
index 0000000..ec692bb
--- /dev/null
@@ -0,0 +1,330 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.Layout{% endblock %}
+
+{% block content %}
+<div class="page doc api">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [<<](PlotKit.Base.html) | [>>](PlotKit.Renderer.html)
+
+PlotKit Layout
+==============
+
+PlotKit Layout is the core of the plotting engine. It deals exclusively with laying objects out on a virtual canvas that has the dimension of 1.0 x 1.0.
+
+The layout engine abstracts away all the complex layout problems with plotting charts and presents a list of objects that need to rendered rather than mixing this with the rendering logic.
+
+PlotKit Layout also is responsible for simple chart state querying so renderers can implement basic event support for objects on the canvas.
+
+Constructor
+===========
+  `new Layout(style, options);`
+
+Layout takes the following arguments:
+
+__style__ which can be `bar`, `line` or `pie` which represnts the style of the graph that is desired.
+
+__options__ is a dictionary/associative array of layout options. Unrecognised keys are ignored. The following options are supported:
+
+Layout Options
+==============
+
+Bar and Line Chart layout options
+---------------------------------
+
+<table cellpadding="0" cellspacing="0">
+  <thead>
+       <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+ <tbody>
+       <tr>
+               <th>barWidthFillFraction</th>
+               <td>Amount of space the total amount of bars should consume per X value.</td>
+               <td>Real number</td>
+               <td>0.75</td>
+       </tr>
+       <tr>
+               <th>barOrientation</th>
+               <td>Orientation of a bar chart. <b>(PlotKit 0.9+ only)</b></td>
+               <td>String ("vertical", "horizontal")</td>
+               <td>vertical</td>
+       </tr>
+       
+       <tr>
+               <th>xAxis</th>
+               <td>Minimum and Maximum values on the X axis.</td>
+               <td>Array of 2 Real numbers. (eg. [0.0, 10.0])</td>
+               <td>null</td>
+       </tr>
+       <tr>
+               <th>xNumberOfTicks</th>
+               <td>Used when automatically calculating axis ticks. This denotes the number of ticks there should be in the graph.</td>
+               <td>integer</td>
+               <td>10</td>
+       </tr>
+       <tr>
+               <th>xOriginIsZero</th>
+               <td>Should graph have X axis origin at 0</td>
+               <td>boolean</td>
+               <td>true</td>
+       </tr>
+       <tr>
+               <th>xTickPrecision</th>
+               <td>The number of decimal places we should round to for tick values.</td>
+               <td>integer</td>
+               <td>1</td>
+       </tr>
+       <tr>
+               <th>xTicks</th>
+               <td>X values at which ticks should be drawn. Automatically calculated if not defined using the parameters `xNumberOfTicks` and ``xTickPrecision``.</td>
+               <td>Array of {label: "somelabel", v:value}.</td>
+               <td>null</td>
+       </tr>
+       
+       <tr>
+               <th>yAxis</th>
+               <td>Minimum and Maximum values on the Y axis.</td>
+               <td>Array of 2 Real numbers. (eg. [0.0, 10.0])</td>
+               <td>null</td>
+       </tr>
+       <tr>
+               <th>yNumberOfTicks</th>
+               <td>Used when automatically calculating axis ticks. This denotes the number of ticks there should be in the graph.</td>
+               <td>integer</td>
+               <td>5</td>
+       </tr>
+       <tr>
+               <th>yOriginIsZero</th>
+               <td>Should graph have Y axis origin at 0</td>
+               <td>true</td>
+       </tr>
+       <tr>
+               <th>yTickPrecision</th>
+               <td>The number of decimal places we should round to for tick values.</td>
+               <td>integer</td>
+               <td>1</td>
+       </tr>
+       <tr>
+               <th>yTicks</th>
+               <td>Y values at which ticks should be drawn. Automatically calculated if not defined using the parameters ``yNumberOfTicks`` and ``yTickPrecision``.</td>
+               <td>Array of {label: "somelabel", v:value}.</td>
+               <td>null</td>
+       </tr>
+       </tbody>
+</table>
+
+Pie Chart Layout Options
+------------------------
+
+<table>
+  <thead>
+       <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+ <tbody>
+       <tr>
+               <th>pieRadius</th>
+               <td>Radius of the circle to be drawn.</td>
+               <td>Real number</td>
+               <td>0.4</td>
+       </tr>
+  </tbody>
+</table>       
+
+Layout Properties
+=================
+
+There are some properties you can access, either because you are using a layout inside a renderer or if you would like additional information. Under normal operations, you will not need to, or should modify these parameters.
+
+<table cellpadding="0" cellspacing="0">
+  <thead>
+       <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+       <tr>
+               <th>style</th>
+               <td>String</td>
+               <td>This denotes the type of chart this layout is using. Valid values are ``bar``, ``line`` or ``pie``. Renderers will use this to determine which parameter (``bars``, ``points`` or ``slices``) to access in order to get draw the chart.</td>
+       </tr>
+       <tr>
+               <th>bars</th>
+               <td>Array of Bar.</td>
+               <td>This is a list of rectangles with values that the renderer should plot. This will only be valid after ``evaluate()`` has run. The properties of ``bar`` is described here. This is only valid if style is ``bar``. This array is sorted by dataset and then x-values.</td>
+       </tr>
+       <tr>
+               <th>points</th>
+               <td>Array of Point.</td>
+               <td>This is a list of points with values that the renderer should plot. This will only be valid after ``evaluate()`` has run. The properties of ``bar`` is described here. This is only valid if style is ``line``. This array is sorted by dataset and then x-values.</td>
+       </tr>
+       <tr>
+               <th>slices</th>
+               <td>Array of Slice.</td>
+               <td>This is a list of pie slices with values that the renderer should plot. This will only be valid after ``evaluate()`` has run. The properties of ``bar`` is described here. This is only valid if style is ``pie``.</td>
+       </tr>
+       <tr>
+               <th>xticks</th>
+               <td>Array of Tick.</td>
+               <td>For style in ``bar`` or ``line``, these are the ticks on the X axis. A ``tick`` is represented as a two element array with the first element representing the x position of the tick and the second element representing the string value of the label at that position.</td>
+       </tr>
+       <tr>
+               <th>yticks</th>
+               <td>Array of Tick.</td>
+               <td>For style in ``bar`` or ``line``, these are the ticks on the Y axis. A ``tick`` is represented as a two element array with the first element representing the y position of the tick and the second element representing the string value of the label at that position.</td>
+       </tr>
+       <tr>
+               <th>datasets</th>
+               <td>Associative Array of datasets</td>
+               <td>This should normally only be used to find the number of datasets by performing ``keys(layout.datasets)``. If you are looking at this in a renderer, then the layout engine needs to be extended.</td>
+       </tr>
+  </tbody>
+</table>
+
+Layout Types
+============
+
+Here are the definition of the types that you will encounter if you access the properties of the Layout object, specifically ``bars``, ``points`` and ``slices``. If you are not writing a renderer, you do not need to know this.
+
+Bar Type
+--------
+
+Represents a bar that the renderer will draw. It contains the following properties.
+
+<table cellpadding="0" cellspacing="0">
+  <thead>
+       <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+       <tr>
+               <th>x, y</th>
+               <td>float</td>
+               <td>top left position of the bar between 0.0 and 1.0.</td>
+       </tr>
+       <tr>
+               <th>w, h</th>
+               <td>float</td>
+               <td>width and height of the bar from (``x``, ``y``) between 0.0 and 1.0.</td>
+       </tr>
+       <tr>
+               <th>xval, yval</th>
+               <td>float</td>
+               <td>The actual x value and y value this bar represents.</td>
+       </tr>
+       <tr>
+               <th>name</th>
+               <td>string</td>
+               <td>Name of the dataset which this bar belongs to.</td>
+       </tr>
+  </tbody>
+</table>
+
+Point Type
+----------
+
+This represents a point on a line chart.
+
+<table cellpadding="0" cellspacing="0">
+  <thead>
+       <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+       <tr>
+               <th>x, y</th>
+               <td>float</td>
+               <td>top left position of the point between 0.0 and 1.0.</td>
+       </tr>
+       <tr>
+               <th>xval, yval</th>
+               <td>float</td>
+               <td>The actual x value and y value this bar represents.</td>
+       </tr>
+       <tr>
+               <th>name</th>
+               <td>string</td>
+               <td>Name of the dataset which this bar belongs to.</td>
+       </tr>
+  </tbody>
+</table>
+
+Slice Type
+----------
+
+This represents a pie slice in a pie chart.
+
+<table>
+  <thead>
+       <tr><td>Property</td><td>Type</td><td>Description</td></tr>
+  </thead>
+ <tbody>
+       <tr>
+               <th>fraction</th>
+               <td>float</td>
+               <td>The fractional value this slice represents. This number is between 0.0 and 1.0</td>
+       </tr>
+       <tr>
+               <th>xval, yval</th>
+               <td>float</td>
+               <td>The x and y values of this slice.</td>
+       </tr>
+       <tr>
+               <th>startAngle</th>
+               <td>float</td>
+               <td>This is the angle of the start of the slice, in radians.</td>
+       </tr>
+       <tr>
+               <th>endAngle</th>
+               <td>float</td>
+               <td>This is the angle of the end of the slice, in radians.</td>
+       </tr>
+  </tbody>
+</table>
+
+Layout Methods
+==============
+
+* ``addDataset(name, values)``
+  
+  Adds a dataset to the layout engine and assigns it with ``name``. ``values`` is an array of ``\[x, y\]`` values.
+
+* ``removeDataset(name)``
+  
+ Removes a dataset from the layout engine. In order for the new data to take effect, you must run ``evaluate()``.
+
+* ``addDatasetFromTable(name, tableElement, xcol = 0, ycol = 1, labelCol = -1)``
+
+  Handy function to read values off a table. ``name`` is the name to give to the dataset just like in ``addDataset()``, ``tableElement`` is the table which contains the values. Optionally, the user may specify to extract alternative columns using ``xcol`` and ``ycol``. 
+  
+  **New in 0.9.1:** If ``labelCol`` is specified to a value greater than -1, it will take the contents of that column as the xTick labels.
+
+* ``evaluate()``
+  Performs the evaluation of the layout. It is not done automatically, and you __must__ execute this before passing the layout to a renderer.
+
+* hitTest(x, y)
+
+  Used by renderers to see if a virtual canvas position corresponds to any data. The return value varies per style. For ``bar`` charts, it will return the Bar type if it is a hit, or null if not. For ``line``  charts, it will return a value if the point is underneath the highest curve, otherwise null __(TODO: expand this or change implementation)__. For ``pie`` charts, it will return the Slice object that is at the point, otherwise null.
+
+  __Note that the specification of this function is subject to change__.
+   
+Layout Notes
+============
+
+Pie Chart Data and Ticks Restrictions
+-------------------------------------
+
+Note that you can only use one dataset for pie charts. Only the y value of the dataset will be used, but the x value must be unique and set as it will correspond to the xTicks that are given.
+
+Labels for pie charts will only use xTicks.
+
+Layout Examples
+===============
+
+{% endfilter %}
+</div>
+{% endblock %}
+
+
+
diff --git a/plotkit_v091/doc/PlotKit.QuickStart.html b/plotkit_v091/doc/PlotKit.QuickStart.html
new file mode 100644 (file)
index 0000000..20635c6
--- /dev/null
@@ -0,0 +1,368 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit Quick Start | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<script type="text/javascript" src="/js/mochi/MochiKit.js"></script>
+<script type="text/javascript" src="/js/plotkit/Base.js"></script>
+<script type="text/javascript" src="/js/plotkit/Layout.js"></script>
+<script type="text/javascript" src="/js/plotkit/Canvas.js"></script>
+<script type="text/javascript" src="/js/plotkit/SweetCanvas.js"></script>
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc">
+
+
+<h1> PlotKit Quick Start</h1>
+<p>This is just a quick guide on how to get started with PlotKit. If you
+   want to delve in deeper, be sure to check out the
+   <a href="PlotKit.html">documentation</a>.
+</p>
+
+<h1> Canvas or SVG</h1>
+<p>Before we start, you should know a little about HTML Canvas and SVG
+   support in the real browser world. For a more indepth coverage, please
+   check the <a href="SVGCanvasCompat.html">SVG/Canvas Browser Support Status</a>. 
+</p>
+<p>Basically, Canvas and SVG have similar support across modern
+   browsers. Canvas is supported by Opera 9, Safari 2 and Firefox 1.5,
+   which probably only accounts for 10% of browsers. PlotKit also supports
+   a degraded Emulated Canvas mode under IE which means you can achieve
+   nearly 90% browser support using this technology.
+</p>
+<p>However, the future is in SVG where Firefox 1.5 and Opera 8 have
+   support it, and IE6 with the Adobe SVG Viewer (ASV) install means you
+   get around the same coverage as HTML Canvas.
+</p>
+<p>PlotKit plans to support both to maximise compatiblity. Canvas has a
+   simplier rendering engine, but can do the equivalent to what SVG can
+   apart from animation. SVG has wider support, but is more complex and
+   support for key features varies widely across different
+   implementations.
+</p>
+
+<h1> Graphing with Canvas</h1>
+<p>Download the latest <a href="http://www.liquidx.net/plotkit/">PlotKit</a> and <a href="http://www.mochikit.com/">MochiKit</a> and extract it on to
+   your web server and make sure <code>plotkit-0.8/PlotKit</code> and
+   <code>mochikit/MochiKit</code> is visible.
+</p>
+
+<h2> Preparing the HTML</h2>
+<p>Add the script headers for PlotKit to work.
+</p>
+<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;/mochikit/MochiKit.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;/plotkit/Base.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;/plotkit/Layout.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;/plotkit/Canvas.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;/plotkit/SweetCanvas.js&quot;&gt;&lt;/script&gt;
+</code></pre><p>MochiKit.js is an autoloader for all the elements of MochiKit. You can
+   reduce the size of it by making your own packed version or just
+   including the script headers individually.
+</p>
+<p>The other four PlotKit javascript files deal with some basic
+   functionality, the layout engine and two renderers, Canvas and
+   SweetCanvas.
+</p>
+<p>Now we add the <code>&lt;canvas&gt;</code> tag to where we want the graph to
+   appear. Note PlotKit <strong>requires</strong> the <code>&lt;canvas&gt;</code> tag is enclosed
+   inside a <div> tags for labels to work.
+</p>
+<pre><code> &lt;div&gt;&lt;canvas id=&quot;graph&quot; height=&quot;300&quot; width=&quot;300&quot;&gt;&lt;/canvas&gt;&lt;/div&gt;
+</code></pre><p>This will create a blank canvas of 300 by 300 pixels.
+</p>
+
+<h2> Javascript</h2>
+<p>There are only two simple steps to draw a chart, first is the create a
+   layout with our data and second is to create the renderer. So lets
+   start off with creating the layout.
+</p>
+
+<h3> Layout and Data</h3>
+<pre><code>var layout = new PlotKit.Layout(&quot;bar&quot;, {});
+layout.addDataset(&quot;sqrt&quot;, [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+layout.evaluate();
+</code></pre><p>There, it is that simple. Lets explain what each line is doing:
+</p>
+<ol>
+ <li><p> <code>var layout = new PlotKit.Layout(&quot;bar&quot;, {});</code> 
+</p>
+<p>We create a new layout object, and tell it that we want a bar chart in the first parameter. The second parameter allows us to pass additional options, which we will go on to later. It can be left null, or in this case just an empty array.
+</p>
+
+ </li>
+
+ <li><p> <code>layout.addDataset(&quot;sqrt&quot;, [[0, 0], [1, 1]...)</code> 
+</p>
+<p>This will add a new dataset to the layout. You can add multiple datasets by specifying a different name in the first parameter for each dataset. The dataset consists of an array of (x, y) values. These must be numeric, either floating point or integers.
+</p>
+<p>Note that PlotKit does not deal with negative numbers at the moment.
+</p>
+
+ </li>
+
+ <li><p> <code>layout.evaluate();</code> 
+</p>
+<p>This will be the last command you make on the layout before passing it to the renderer. This will tell the layout to calculate the layout of the chart so the renderer can draw it. It is an expensive operation, so do not call it frequently, only unless the data or options have been changed.
+</p>
+
+ </li>
+</ol>
+
+<h3> Renderer</h3>
+<pre><code> var canvas = MochiKit.DOM.getElement(&quot;graph&quot;);
+ var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, {});
+ plotter.render();
+</code></pre><ol>
+ <li><p> <code>var canvas = MochiKit.DOM.getElement(&quot;graph&quot;);</code> 
+</p>
+<p>This line will get the HTML element we defined earlier.
+</p>
+
+ </li>
+
+ <li><p> <code>var plotter =  new PlotKit.SweetCanvasRenderer(canvas, layout, {});</code> 
+</p>
+<p>This will create the renderer to work on the object passed, and also with the data in the layout we created earlier. Again, the third parameter here is for options to relates to the look of the graph. We will show you some things you can do with this in the following section.
+</p>
+
+ </li>
+
+ <li><p> <code>plotter.render()</code> 
+</p>
+<p>This line will render the graph.
+</p>
+
+ </li>
+</ol>
+
+<h3> Putting it altogether</h3>
+<pre><code>function drawGraph() {
+    var layout = new PlotKit.Layout(&quot;bar&quot;, {});
+    layout.addDataset(&quot;sqrt&quot;, [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+    layout.evaluate();
+    var canvas = MochiKit.DOM.getElement(&quot;graph&quot;);
+    var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, {});
+    plotter.render();
+}
+MochiKit.DOM.addLoadEvent(drawGraph);
+</code></pre><p>This is a sample of what you would use to plot the graph of sqare roots for 0 to 4. Make sure you plot the graph on the load event because the DOM will not be ready if when the Javascript is first loaded.
+</p>
+<p>See this in an [HTML example here][example1].
+</p>
+
+<h3> Additional Options</h3>
+<p>We mentioned that both the layout and renderer may take some additional options. In order to take advantage of that, we can use a simple options dictionary to store options for both layout and the renderer, in this way:
+</p>
+<pre><code>var options = {
+   &quot;IECanvasHTC&quot;: &quot;/plotkit/iecanvas.htc&quot;,
+   &quot;colorScheme&quot;: PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),
+   &quot;padding&quot;: {left: 0, right: 0, top: 10, bottom: 30},
+   &quot;xTicks&quot;: [{v:0, label:&quot;zero&quot;}, 
+          {v:1, label:&quot;one&quot;}, 
+          {v:2, label:&quot;two&quot;},
+          {v:3, label:&quot;three&quot;},
+          {v:4, label:&quot;four&quot;}],
+   &quot;drawYAxis&quot;: false
+};
+
+function drawGraph() {
+    var layout = new PlotKit.Layout(&quot;bar&quot;, options);
+    layout.addDataset(&quot;sqrt&quot;, [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+    layout.evaluate();
+    var canvas = MochiKit.DOM.getElement(&quot;graph&quot;);
+    var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
+    plotter.render();
+}
+MochiKit.DOM.addLoadEvent(drawGraph);
+</code></pre><p>Here we define some additional options to affect how our graph is rendered.
+</p>
+<ol>
+ <li>
+     First line defines where the <code>IECanvasHTC</code> behaviour file is so that we can have IE support. 
+ </li>
+
+ <li>
+     Second line defines a new colorScheme to use. Here we are just using another preset color scheme that creates a palette out of the 6th preset base colour.
+ </li>
+
+ <li>
+     Third line defines some custom labels we would like by giving the mapping from X value to label.
+ </li>
+
+ <li>
+     Fourth line tells the renderer not to draw the Y axis.
+ </li>
+</ol>
+
+<h1> Demonstration</h1>
+<p>To show you that is how it works, below is the graph defined exactly how it is presented in this quick start guide. On the left is a PNG of what you should expect and on the right is what it actually renders to.
+</p>
+
+<h3> Bar charts</h3>
+<div>
+<div style="float: left; padding-right: 5px;" width="300" height="300"><img src="barsample.png" width="300" height="300" alt="screenshot of graph" /></div>
+<div style="float: left; padding-left: 5px;" width="300" height="300"><canvas id="bargraph" width="300" height="300"></canvas></div>
+<div style="clear: both; height: 1px; width: 1px;">&nbsp</div>
+</div>
+
+
+<h3> Pie Charts</h3>
+<div>
+<div style="float: left; padding-right: 5px;" width="300" height="300"><img src="piesample.png" width="300" height="300" alt="screenshot of graph" /></div>
+<div style="float: left; padding-left: 5px;" width="300" height="300"><canvas id="piegraph" width="300" height="300"></canvas></div>
+<div style="clear: both; height: 1px; width: 1px;">&nbsp</div>
+</div>
+
+
+<h1> Author</h1>
+<p>Alastair Tse - Last Updated: 17th March 2006
+</p>
+
+
+</div>
+<script type="text/javascript">
+<!--
+
+var options = {
+   "IECanvasHTC": "../plotkit/iecanvas.htc",
+   "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]), 
+   "padding": {left: 10, right: 10, top: 10, bottom: 30},
+   "xTicks": [{v:0, label:"zero"}, 
+              {v:1, label:"one"}, 
+              {v:2, label:"two"},
+              {v:3, label:"three"},
+              {v:4, label:"four"}],
+   "drawYAxis": false,
+   "pieRadius": 0.35
+};
+
+
+function drawBarGraph() {
+   var layout = new PlotKit.Layout("bar", options);
+   layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+   layout.evaluate();
+   var canvas = MochiKit.DOM.getElement("bargraph");
+   var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
+   plotter.render();
+}
+MochiKit.DOM.addLoadEvent(drawBarGraph);
+
+function drawPieGraph() {
+   var layout = new PlotKit.Layout("pie", options);
+   layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+   layout.evaluate();
+   var canvas = MochiKit.DOM.getElement("piegraph");
+   var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
+   plotter.render();
+}
+
+// Damn opera 9 has a bug with javascript subclassing??
+// but works in sweet.html, grr!!
+if (navigator.userAgent.toLowerCase().indexOf("opera") == -1) {
+   MochiKit.DOM.addLoadEvent(drawPieGraph);
+}
+
+//-->
+</script>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.QuickStart.txt b/plotkit_v091/doc/PlotKit.QuickStart.txt
new file mode 100644 (file)
index 0000000..44e6593
--- /dev/null
@@ -0,0 +1,256 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block title %}PlotKit Quick Start{% endblock %}
+{% block headers %}
+<script type="text/javascript" src="/js/mochi/MochiKit.js"></script>
+<script type="text/javascript" src="/js/plotkit/Base.js"></script>
+<script type="text/javascript" src="/js/plotkit/Layout.js"></script>
+<script type="text/javascript" src="/js/plotkit/Canvas.js"></script>
+<script type="text/javascript" src="/js/plotkit/SweetCanvas.js"></script>
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+
+
+{% block content %}
+<div class="page doc">
+{% filter markdown %}
+PlotKit Quick Start
+===================
+
+This is just a quick guide on how to get started with PlotKit. If you
+want to delve in deeper, be sure to check out the
+[documentation][docs].
+
+Canvas or SVG
+=============
+
+Before we start, you should know a little about HTML Canvas and SVG
+support in the real browser world. For a more indepth coverage, please
+check the [SVG/Canvas Browser Support Status][Browser]. 
+
+Basically, Canvas and SVG have similar support across modern
+browsers. Canvas is supported by Opera 9, Safari 2 and Firefox 1.5,
+which probably only accounts for 10% of browsers. PlotKit also supports
+a degraded Emulated Canvas mode under IE which means you can achieve
+nearly 90% browser support using this technology.
+
+However, the future is in SVG where Firefox 1.5 and Opera 8 have
+support it, and IE6 with the Adobe SVG Viewer (ASV) install means you
+get around the same coverage as HTML Canvas.
+
+PlotKit plans to support both to maximise compatiblity. Canvas has a
+simplier rendering engine, but can do the equivalent to what SVG can
+apart from animation. SVG has wider support, but is more complex and
+support for key features varies widely across different
+implementations.
+
+Graphing with Canvas
+====================
+
+Download the latest [PlotKit][] and [MochiKit][] and extract it on to
+your web server and make sure ``plotkit-0.8/PlotKit`` and
+``mochikit/MochiKit`` is visible.
+
+Preparing the HTML
+------------------
+
+Add the script headers for PlotKit to work.
+
+    <script type="text/javascript" src="/mochikit/MochiKit.js"></script>
+    <script type="text/javascript" src="/plotkit/Base.js"></script>
+    <script type="text/javascript" src="/plotkit/Layout.js"></script>
+    <script type="text/javascript" src="/plotkit/Canvas.js"></script>
+    <script type="text/javascript" src="/plotkit/SweetCanvas.js"></script>
+
+MochiKit.js is an autoloader for all the elements of MochiKit. You can
+reduce the size of it by making your own packed version or just
+including the script headers individually.
+
+The other four PlotKit javascript files deal with some basic
+functionality, the layout engine and two renderers, Canvas and
+SweetCanvas.
+
+Now we add the ``<canvas>`` tag to where we want the graph to
+appear. Note PlotKit __requires__ the ``<canvas>`` tag is enclosed
+inside a <div> tags for labels to work.
+
+     <div><canvas id="graph" height="300" width="300"></canvas></div>
+
+This will create a blank canvas of 300 by 300 pixels.
+
+Javascript
+----------
+
+There are only two simple steps to draw a chart, first is the create a
+layout with our data and second is to create the renderer. So lets
+start off with creating the layout.
+
+### Layout and Data
+
+    var layout = new PlotKit.Layout("bar", {});
+    layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+    layout.evaluate();
+    
+There, it is that simple. Lets explain what each line is doing:
+
+1. ``var layout = new PlotKit.Layout("bar", {});``
+
+    We create a new layout object, and tell it that we want a bar chart in the first parameter. The second parameter allows us to pass additional options, which we will go on to later. It can be left null, or in this case just an empty array.
+
+2. ``layout.addDataset("sqrt", [[0, 0], [1, 1]...)``
+
+    This will add a new dataset to the layout. You can add multiple datasets by specifying a different name in the first parameter for each dataset. The dataset consists of an array of (x, y) values. These must be numeric, either floating point or integers.
+
+    Note that PlotKit does not deal with negative numbers at the moment.
+
+3. ``layout.evaluate();``
+
+    This will be the last command you make on the layout before passing it to the renderer. This will tell the layout to calculate the layout of the chart so the renderer can draw it. It is an expensive operation, so do not call it frequently, only unless the data or options have been changed.
+
+### Renderer
+
+     var canvas = MochiKit.DOM.getElement("graph");
+     var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, {});
+     plotter.render();
+
+1.  ``var canvas = MochiKit.DOM.getElement("graph");``
+
+    This line will get the HTML element we defined earlier.
+
+2.  ``var plotter =  new PlotKit.SweetCanvasRenderer(canvas, layout, {});``
+
+    This will create the renderer to work on the object passed, and also with the data in the layout we created earlier. Again, the third parameter here is for options to relates to the look of the graph. We will show you some things you can do with this in the following section.
+
+3.  ``plotter.render()``
+
+    This line will render the graph.
+
+### Putting it altogether
+
+    function drawGraph() {
+        var layout = new PlotKit.Layout("bar", {});
+        layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+        layout.evaluate();
+        var canvas = MochiKit.DOM.getElement("graph");
+        var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, {});
+        plotter.render();
+    }
+    MochiKit.DOM.addLoadEvent(drawGraph);
+
+This is a sample of what you would use to plot the graph of sqare roots for 0 to 4. Make sure you plot the graph on the load event because the DOM will not be ready if when the Javascript is first loaded.
+
+See this in an [HTML example here][example1].
+
+### Additional Options
+
+We mentioned that both the layout and renderer may take some additional options. In order to take advantage of that, we can use a simple options dictionary to store options for both layout and the renderer, in this way:
+
+    var options = {
+       "IECanvasHTC": "/plotkit/iecanvas.htc",
+       "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),
+       "padding": {left: 0, right: 0, top: 10, bottom: 30},
+       "xTicks": [{v:0, label:"zero"}, 
+              {v:1, label:"one"}, 
+              {v:2, label:"two"},
+              {v:3, label:"three"},
+              {v:4, label:"four"}],
+       "drawYAxis": false
+    };
+    
+    function drawGraph() {
+        var layout = new PlotKit.Layout("bar", options);
+        layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+        layout.evaluate();
+        var canvas = MochiKit.DOM.getElement("graph");
+        var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
+        plotter.render();
+    }
+    MochiKit.DOM.addLoadEvent(drawGraph);
+
+
+Here we define some additional options to affect how our graph is rendered.
+
+1. First line defines where the ``IECanvasHTC`` behaviour file is so that we can have IE support. 
+2. Second line defines a new colorScheme to use. Here we are just using another preset color scheme that creates a palette out of the 6th preset base colour.
+3. Third line defines some custom labels we would like by giving the mapping from X value to label.
+4. Fourth line tells the renderer not to draw the Y axis.
+
+Demonstration
+=============
+
+To show you that is how it works, below is the graph defined exactly how it is presented in this quick start guide. On the left is a PNG of what you should expect and on the right is what it actually renders to.
+
+### Bar charts
+
+<div>
+<div style="float: left; padding-right: 5px;" width="300" height="300"><img src="barsample.png" width="300" height="300" alt="screenshot of graph" /></div>
+<div style="float: left; padding-left: 5px;" width="300" height="300"><canvas id="bargraph" width="300" height="300"></canvas></div>
+<div style="clear: both; height: 1px; width: 1px;">&nbsp</div>
+</div>
+
+### Pie Charts
+
+<div>
+<div style="float: left; padding-right: 5px;" width="300" height="300"><img src="piesample.png" width="300" height="300" alt="screenshot of graph" /></div>
+<div style="float: left; padding-left: 5px;" width="300" height="300"><canvas id="piegraph" width="300" height="300"></canvas></div>
+<div style="clear: both; height: 1px; width: 1px;">&nbsp</div>
+</div>
+
+Author
+======
+
+Alastair Tse - Last Updated: 17th March 2006
+
+[docs]: PlotKit.html
+[Browser]: SVGCanvasCompat.html
+[PlotKit]: http://www.liquidx.net/plotkit/
+[MochiKit]: http://www.mochikit.com/
+
+{% endfilter %}
+</div>
+<script type="text/javascript">
+<!--
+
+var options = {
+   "IECanvasHTC": "../plotkit/iecanvas.htc",
+   "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]), 
+   "padding": {left: 10, right: 10, top: 10, bottom: 30},
+   "xTicks": [{v:0, label:"zero"}, 
+              {v:1, label:"one"}, 
+              {v:2, label:"two"},
+              {v:3, label:"three"},
+              {v:4, label:"four"}],
+   "drawYAxis": false,
+   "pieRadius": 0.35
+};
+
+
+function drawBarGraph() {
+   var layout = new PlotKit.Layout("bar", options);
+   layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+   layout.evaluate();
+   var canvas = MochiKit.DOM.getElement("bargraph");
+   var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
+   plotter.render();
+}
+MochiKit.DOM.addLoadEvent(drawBarGraph);
+
+function drawPieGraph() {
+   var layout = new PlotKit.Layout("pie", options);
+   layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
+   layout.evaluate();
+   var canvas = MochiKit.DOM.getElement("piegraph");
+   var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
+   plotter.render();
+}
+
+// Damn opera 9 has a bug with javascript subclassing??
+// but works in sweet.html, grr!!
+if (navigator.userAgent.toLowerCase().indexOf("opera") == -1) {
+   MochiKit.DOM.addLoadEvent(drawPieGraph);
+}
+
+//-->
+</script>
+{% endblock %}
\ No newline at end of file
diff --git a/plotkit_v091/doc/PlotKit.Renderer.html b/plotkit_v091/doc/PlotKit.Renderer.html
new file mode 100644 (file)
index 0000000..49ad300
--- /dev/null
@@ -0,0 +1,436 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.Renderer | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc api">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.Layout.html">&lt;&lt;</a> | <a href="PlotKit.Canvas.html">&gt;&gt;</a> 
+</p>
+
+<h1> PlotKit Renderer</h1>
+<p>A Renderer is responsible for translating the layout calculated by PlotKit.Layout and draw it on to a HTML Canvas, SVG object or any other way. One way to use the renderer is to allow theming of graphs by tweaking the layout. 
+</p>
+<p>PlotKit includes some common basic renderers, so you do not need to customise anything if you just plan to change the spacing, colors, fonts, or layout.
+</p>
+<p>PlotKit Renderers should follow an informal protocol to allow users to plug and play different renderers. Below is the informal protocol:
+</p>
+
+<h2> PlotKit Renderer Protocol</h2>
+<ul>
+ <li>
+     Constructor: <code>new Renderer(element, layout, options = {})</code> 
+ </li>
+</ul>
+<p>  <code>element</code> is the element which this renderer will perform on, <code>layout</code> is the PlotKit.Layout object and <code>options</code> is an associative dictionary described below.
+</p>
+<ul>
+ <li>
+     class function: <code>isSupported()</code> 
+ </li>
+</ul>
+<p>  Optional check that returns <code>true</code> if the renderer is supported in the current browser.
+</p>
+<ul>
+ <li>
+     object method: <code>render()</code> 
+ </li>
+</ul>
+<p>  Renders to canvas, can be called multiple times, but <code>clear()</code> must be called between invokations.
+</p>
+<ul>
+ <li>
+     object method: <code>clear()</code> 
+ </li>
+</ul>
+<p>  Clear the canvas.
+</p>
+
+<h2> PlotKit Renderer Options</h2>
+<p>To allow some basic flexibility of the output, a renderer should
+   accept and act on the following options passed in the constructor. 
+</p>
+<table cellpadding="0" cellspacing="0">
+  <thead>
+    <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+  <tbody>
+    <tr>
+        <th>backgroundColor</th>
+        <td>color to use for background</td>
+        <td>MochiKit.Color.Color</td>
+        <td>Color.whiteColor()</td>
+    </tr>
+    <tr>
+        <th>colorScheme</th>
+        <td>Color scheme used</td>
+        <td>Array of MochiKit.Color.Color</td>
+        <td>output of PlotKit.Base.colorScheme()</td>
+    </tr>
+    <tr>
+        <th>strokeColor</th>
+        <td>Color used stroking. If set to null, the renderer will
+  attempt to use strokeColorTransform</td>
+        <td>MochiKit.Color.Color or null</td>
+        <td>null</td>
+    </tr>
+    <tr>
+        <th>strokeColorTransform</th>
+        <td>Name of the method to call to transform Color into stroke color.</td>
+        <td>string (name of a function that accepts no arguments)</td>
+        <td>"asStrokeColor"</td>
+    </tr>
+    <tr>
+        <th>drawBackground</th>
+        <td>Whether the background should be drawn</td>
+        <td>boolean</td>
+        <td>true</td>
+    </tr>
+    <tr>
+        <th>shouldFill</th>
+        <td>Should fill in area under chart</td>
+        <td>boolean</td>
+        <td>true</td>
+    </tr>
+    <tr>
+        <th>shouldStroke</th>
+        <td>Should stroke the borders of shapes in chart</td>
+        <td>boolean</td>
+        <td>true</td>
+    </tr>
+    <tr>
+        <th>strokeWidth</th>
+        <td>Width of stroke used (if shouldStroke is set)</td>
+        <td>float</td>
+        <td>0.1</td>
+    </tr>
+    <tr>
+        <th>padding</th>
+        <td>Padding of the graph drawn (excluding labels)</td>
+        <td>Object with properties: top, bottom, left, right.</td>
+        <td>{left: 30, right:20, top: 10, bottom: 10}</td>
+    </tr>
+    <tr>
+        <th>drawYAxis</th>
+        <td>draw Y Axis</td>
+        <td>boolean</td>
+        <td>true</td>
+    </tr>
+    <tr>
+        <th>drawXAxis</th>
+        <td>draw X Axis</td>
+        <td>boolean</td>
+        <td>true</td>
+    </tr>
+    <tr>
+        <th>axisLineColor</th>
+        <td>Color of axes line.</td>
+        <td>MochiKit.Color.Color</td>
+        <td>Color.blackColor()</td>
+    </tr>
+    <tr>
+        <th>axisLineWidth</th>
+        <td>axis line width</td>
+        <td>float</td>
+        <td>0.5</td>
+    </tr>
+    <tr>
+        <th>axisTickSize</th>
+        <td>length or height of a tick on the y and x axis respectively, in pixels</td>
+        <td>float</td>
+        <td>3.0</td>
+    </tr>
+    <tr>
+        <th>axisLabelColor</th>
+        <td>color of text label on axis.</td>
+        <td>MochiKit.Color.Color</td>
+        <td>Color.blackColor()</td>
+    </tr>
+    <tr>
+        <th>axisLabelFontSize</th>
+        <td>Font size of labels in pixels </td>
+        <td>integer</td>
+        <td>9</td>
+    </tr>
+    <tr>
+        <th>axisLabelWidth</th>
+        <td>Width of labels on ticks, in pixels</td>
+        <td>integer</td>
+        <td>50</td>
+    </tr>
+    <tr>
+        <th>enableEvents</th>
+        <td>Enable events (if supported)</td>
+        <td>boolean</td>
+        <td>true</td>
+    </tr>
+</tbody>
+</table>
+
+
+<h1> Internal Renderer Methods and Style</h1>
+<p>The default renderers that are available follow a rough structure. If
+   you plan to write a new renderer, you should think about using a
+   similar structure.
+</p>
+<p>Also, it is important that you follow an Object Orientated style and
+   split up the rendering methods as much as logically possible to allow
+   other developers to extend the work by using a &quot;psuedo subclassing&quot;
+   method described below.
+</p>
+
+<h2> Subclassing</h2>
+<p>PlotKit Renderers should adopt a Javascript subclassing structure to
+   allow developers/themers to customise certain aspects of the
+   rendering. Here is an example of what is expected:
+</p>
+<pre><code>MyRenderer = function(element, layout, options) {
+    if (arguments.length  &gt; 0)
+       this.__init__(element, layout, options);
+};
+
+MyRenderer.prototype.__init__ = function(element, layout, options) {
+  ....
+};
+</code></pre><p>In this case, the default javascript constructor acts only when passed
+   arguments. <code>MyRenderer.prototype.__init__</code> is the real
+   constructor. It is named in similar vein to Python's constructor.
+</p>
+<p>For users who would like to subclass, they will need to use the
+   following snippet of code:
+</p>
+<pre><code> MyAlternateRenderer = function(element, layout. options) {
+   if (arguments.length &gt; 0) 
+      this.__init__(element, layout, options);
+ };
+ MyAlternateRenderer.prototype = new MyRenderer();
+ MyAlternateRenderer.prototype.constructor = MyAlternateRenderer;
+ MyAlternateRenderer.__super__ = MyRenderer.prototype;
+
+ MyAlternateRenderer.prototype.__init__ = function(element, layout, options) {
+     MyAlternateRenderer.__super__.__init__.call(this, element, layout, options);
+ };
+</code></pre><p>For subclasses, they will need the following magic in order to
+   initialise their subclass. But after that, you can either override
+   <code>MyAlternateRenderer.prototype.__init__</code> with your own
+   implementation or just leave the superclass to deal with the
+   constructor. 
+</p>
+<p>A more thorough example can be found in the PlotKit source for
+   <code>Canvas.js</code> and <code>SweetCanvas.js</code> respectively.
+</p>
+
+<h2> Internal Renderer Properties</h2>
+<p>The bundled renderers are have the following common properties to
+   allow standard access by all subclasses:
+</p>
+<ul>
+ <li>
+      <code>this.layout</code> 
+ </li>
+</ul>
+<p>The PlotKit.Layout object passed by the user.
+</p>
+<ul>
+ <li>
+      <code>this.element</code> 
+ </li>
+</ul>
+<p>The HTML element to use, either a Canvas Element or SVG Element depending
+   on whether a Canvas Renderer or SVG Renderer is in use.
+</p>
+<ul>
+ <li>
+      <code>this.options</code> 
+ </li>
+</ul>
+<p>A dictionary of options that are applicable to the rendering style.
+</p>
+<ul>
+ <li>
+      <code>this.xlabels</code> 
+ </li>
+</ul>
+<p>A list of elements that represent the axis. Should be cleared whenever
+   <code>clear()</code> is executed.
+</p>
+<ul>
+ <li>
+      <code>this.ylabels</code> 
+ </li>
+</ul>
+<p>A list of elements that represent the axis. Should be cleared whenever
+   <code>clear()</code> is executed.
+</p>
+
+<h2> Internal Renderer Methods</h2>
+<ul>
+ <li>
+      <code>_renderBarChart()</code> 
+ </li>
+</ul>
+<p>Renders only the bars of a  bar chart on the element by looking at
+   <code>this.layout.bars</code> for the bars to render. Will only be called if
+   <code>this.layout.style == &quot;bars&quot;</code> 
+</p>
+<ul>
+ <li>
+      <code>_renderLineChart()</code> 
+ </li>
+</ul>
+<p>Renders only the lines of a  line chart on the element by looking at
+   <code>this.layout.points</code> for the points to render. Will only be called if
+   <code>this.layout.style == &quot;line&quot;</code> 
+</p>
+<ul>
+ <li>
+      <code>_renderPieChart()</code> 
+ </li>
+</ul>
+<p>Renders only the slices of the pie in <code>this.layout.slices</code>.
+   Will only be called if <code>this.layout.style == &quot;pie&quot;</code> 
+</p>
+<ul>
+ <li>
+      <code>_renderBarAxis()</code> 
+ </li>
+</ul>
+<p>Renders the axis for a bar chart by looking at the
+   <code>this.layout.xticks</code> and <code>this.layout.yticks</code>.
+</p>
+<ul>
+ <li>
+      <code>_renderLineAxis()</code> 
+ </li>
+</ul>
+<p>Renders the axis for a line chart by looking at the
+   <code>this.layout.xticks</code> and <code>this.layout.yticks</code>.
+</p>
+<ul>
+ <li>
+      <code>_renderPieAxis()</code> 
+ </li>
+</ul>
+<p>Renders the labels for a pie chart by looking at
+   <code>this.layout.xticks</code> only.
+</p>
+<ul>
+ <li>
+      <code>_renderBackground()</code> 
+ </li>
+</ul>
+<p>Called to render the background of the chart. Should check whether
+   <code>this.options.drawsBackground</code> is set before proceeding.
+</p>
+
+<h1> Events from the Chart</h1>
+<p>There is preliminary support for events from the chart for the Canvas
+   Renderer but the API is not stablised and subject to change. <strong>(TODO)</strong>.
+</p>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.Renderer.txt b/plotkit_v091/doc/PlotKit.Renderer.txt
new file mode 100644 (file)
index 0000000..6b58e87
--- /dev/null
@@ -0,0 +1,299 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.Renderer{% endblock %}
+
+{% block content %}
+<div class="page doc api">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [<<](PlotKit.Layout.html) | [>>](PlotKit.Canvas.html)
+
+PlotKit Renderer
+================
+
+A Renderer is responsible for translating the layout calculated by PlotKit.Layout and draw it on to a HTML Canvas, SVG object or any other way. One way to use the renderer is to allow theming of graphs by tweaking the layout. 
+
+PlotKit includes some common basic renderers, so you do not need to customise anything if you just plan to change the spacing, colors, fonts, or layout.
+
+PlotKit Renderers should follow an informal protocol to allow users to plug and play different renderers. Below is the informal protocol:
+
+PlotKit Renderer Protocol
+-------------------------
+* Constructor: ``new Renderer(element, layout, options = {})``
+
+  ``element`` is the element which this renderer will perform on, ``layout`` is the PlotKit.Layout object and ``options`` is an associative dictionary described below.
+
+* class function: ``isSupported()``
+
+  Optional check that returns ``true`` if the renderer is supported in the current browser.
+
+* object method: ``render()``
+
+  Renders to canvas, can be called multiple times, but ``clear()`` must be called between invokations.
+
+* object method: ``clear()``
+
+  Clear the canvas.
+
+PlotKit Renderer Options
+------------------------
+To allow some basic flexibility of the output, a renderer should
+accept and act on the following options passed in the constructor. 
+
+
+<table cellpadding="0" cellspacing="0">
+  <thead>
+       <tr><td>Option name</td><td>Description</td><td>Type</td><td>Default</td></tr>
+  </thead>
+  <tbody>
+       <tr>
+               <th>backgroundColor</th>
+               <td>color to use for background</td>
+               <td>MochiKit.Color.Color</td>
+               <td>Color.whiteColor()</td>
+       </tr>
+       <tr>
+               <th>colorScheme</th>
+               <td>Color scheme used</td>
+               <td>Array of MochiKit.Color.Color</td>
+               <td>output of PlotKit.Base.colorScheme()</td>
+       </tr>
+       <tr>
+               <th>strokeColor</th>
+               <td>Color used stroking. If set to null, the renderer will
+  attempt to use strokeColorTransform</td>
+               <td>MochiKit.Color.Color or null</td>
+               <td>null</td>
+       </tr>
+       <tr>
+               <th>strokeColorTransform</th>
+               <td>Name of the method to call to transform Color into stroke color.</td>
+               <td>string (name of a function that accepts no arguments)</td>
+               <td>"asStrokeColor"</td>
+       </tr>
+       <tr>
+               <th>drawBackground</th>
+               <td>Whether the background should be drawn</td>
+               <td>boolean</td>
+               <td>true</td>
+       </tr>
+       <tr>
+               <th>shouldFill</th>
+               <td>Should fill in area under chart</td>
+               <td>boolean</td>
+               <td>true</td>
+       </tr>
+       <tr>
+               <th>shouldStroke</th>
+               <td>Should stroke the borders of shapes in chart</td>
+               <td>boolean</td>
+               <td>true</td>
+       </tr>
+       <tr>
+               <th>strokeWidth</th>
+               <td>Width of stroke used (if shouldStroke is set)</td>
+               <td>float</td>
+               <td>0.1</td>
+       </tr>
+       <tr>
+               <th>padding</th>
+               <td>Padding of the graph drawn (excluding labels)</td>
+               <td>Object with properties: top, bottom, left, right.</td>
+               <td>{left: 30, right:20, top: 10, bottom: 10}</td>
+       </tr>
+       <tr>
+               <th>drawYAxis</th>
+               <td>draw Y Axis</td>
+               <td>boolean</td>
+               <td>true</td>
+       </tr>
+       <tr>
+               <th>drawXAxis</th>
+               <td>draw X Axis</td>
+               <td>boolean</td>
+               <td>true</td>
+       </tr>
+       <tr>
+               <th>axisLineColor</th>
+               <td>Color of axes line.</td>
+               <td>MochiKit.Color.Color</td>
+               <td>Color.blackColor()</td>
+       </tr>
+       <tr>
+               <th>axisLineWidth</th>
+               <td>axis line width</td>
+               <td>float</td>
+               <td>0.5</td>
+       </tr>
+       <tr>
+               <th>axisTickSize</th>
+               <td>length or height of a tick on the y and x axis respectively, in pixels</td>
+               <td>float</td>
+               <td>3.0</td>
+       </tr>
+       <tr>
+               <th>axisLabelColor</th>
+               <td>color of text label on axis.</td>
+               <td>MochiKit.Color.Color</td>
+               <td>Color.blackColor()</td>
+       </tr>
+       <tr>
+               <th>axisLabelFontSize</th>
+               <td>Font size of labels in pixels </td>
+               <td>integer</td>
+               <td>9</td>
+       </tr>
+       <tr>
+               <th>axisLabelWidth</th>
+               <td>Width of labels on ticks, in pixels</td>
+               <td>integer</td>
+               <td>50</td>
+       </tr>
+       <tr>
+               <th>enableEvents</th>
+               <td>Enable events (if supported)</td>
+               <td>boolean</td>
+               <td>true</td>
+       </tr>
+</tbody>
+</table>
+
+Internal Renderer Methods and Style
+===================================
+
+The default renderers that are available follow a rough structure. If
+you plan to write a new renderer, you should think about using a
+similar structure.
+
+Also, it is important that you follow an Object Orientated style and
+split up the rendering methods as much as logically possible to allow
+other developers to extend the work by using a "psuedo subclassing"
+method described below.
+
+Subclassing
+-----------
+
+PlotKit Renderers should adopt a Javascript subclassing structure to
+allow developers/themers to customise certain aspects of the
+rendering. Here is an example of what is expected:
+
+    MyRenderer = function(element, layout, options) {
+        if (arguments.length  > 0)
+           this.__init__(element, layout, options);
+    };
+    
+    MyRenderer.prototype.__init__ = function(element, layout, options) {
+      ....
+    };
+
+In this case, the default javascript constructor acts only when passed
+arguments. ``MyRenderer.prototype.__init__`` is the real
+constructor. It is named in similar vein to Python's constructor.
+
+For users who would like to subclass, they will need to use the
+following snippet of code:
+
+     MyAlternateRenderer = function(element, layout. options) {
+       if (arguments.length > 0) 
+          this.__init__(element, layout, options);
+     };
+     MyAlternateRenderer.prototype = new MyRenderer();
+     MyAlternateRenderer.prototype.constructor = MyAlternateRenderer;
+     MyAlternateRenderer.__super__ = MyRenderer.prototype;
+
+     MyAlternateRenderer.prototype.__init__ = function(element, layout, options) {
+         MyAlternateRenderer.__super__.__init__.call(this, element, layout, options);
+     };
+
+
+For subclasses, they will need the following magic in order to
+initialise their subclass. But after that, you can either override
+``MyAlternateRenderer.prototype.__init__`` with your own
+implementation or just leave the superclass to deal with the
+constructor. 
+
+A more thorough example can be found in the PlotKit source for
+``Canvas.js`` and ``SweetCanvas.js`` respectively.
+
+Internal Renderer Properties
+----------------------------
+
+The bundled renderers are have the following common properties to
+allow standard access by all subclasses:
+
+* ``this.layout`` 
+
+The PlotKit.Layout object passed by the user.
+
+* ``this.element``
+
+The HTML element to use, either a Canvas Element or SVG Element depending
+on whether a Canvas Renderer or SVG Renderer is in use.
+
+* ``this.options``
+
+A dictionary of options that are applicable to the rendering style.
+
+* ``this.xlabels``
+
+A list of elements that represent the axis. Should be cleared whenever
+``clear()`` is executed.
+
+* ``this.ylabels``
+
+A list of elements that represent the axis. Should be cleared whenever
+``clear()`` is executed.
+
+Internal Renderer Methods
+-------------------------
+
+* ``_renderBarChart()``
+
+Renders only the bars of a  bar chart on the element by looking at
+``this.layout.bars`` for the bars to render. Will only be called if
+``this.layout.style == "bars"``
+
+* ``_renderLineChart()``
+
+Renders only the lines of a  line chart on the element by looking at
+``this.layout.points`` for the points to render. Will only be called if
+``this.layout.style == "line"``
+
+* ``_renderPieChart()``
+
+Renders only the slices of the pie in ``this.layout.slices``.
+Will only be called if ``this.layout.style == "pie"``
+
+* ``_renderBarAxis()``
+
+Renders the axis for a bar chart by looking at the
+``this.layout.xticks`` and ``this.layout.yticks``.
+
+* ``_renderLineAxis()``
+
+Renders the axis for a line chart by looking at the
+``this.layout.xticks`` and ``this.layout.yticks``.
+
+* ``_renderPieAxis()``
+
+Renders the labels for a pie chart by looking at
+``this.layout.xticks`` only.
+
+* ``_renderBackground()``
+
+Called to render the background of the chart. Should check whether
+``this.options.drawsBackground`` is set before proceeding.
+
+
+Events from the Chart
+=====================
+
+There is preliminary support for events from the chart for the Canvas
+Renderer but the API is not stablised and subject to change. __(TODO)__.
+
+{% endfilter %}
+</div>
+{% endblock %}
diff --git a/plotkit_v091/doc/PlotKit.SVG.html b/plotkit_v091/doc/PlotKit.SVG.html
new file mode 100644 (file)
index 0000000..1ca29d1
--- /dev/null
@@ -0,0 +1,159 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.SVG | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc api">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.Canvas.html">&lt;&lt;</a> | <a href="PlotKit.SweetCanvas.html">&gt;&gt;</a> 
+</p>
+
+<h1> PlotKit SVG</h1>
+<p>PlotKit SVG includes the SVGRenderer which allows chart plotting on SVG capable browsers such as Firefox 1.5 and Opera 9.0. It should support Adobe SVG plugin, but is current untested.
+</p>
+
+<h2> Important Implementation Requirements</h2>
+<p>In order to use the SVG Renderer, the file and webserver must support inline SVG files. This means the following conditions must exist:
+</p>
+
+<h3>The HTML file must be XHTML compliant. </h3>
+<p>So it should start off with this:
+</p>
+<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
+&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
+&lt;html
+xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;
+xmlns:svg=&quot;http://www.w3.org/2000/svg&quot;
+xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;
+&lt;head&gt;        
+  &lt;object id=&quot;AdobeSVG&quot; classid=&quot;clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2&quot; width=&quot;1&quot; height=&quot;1&quot;&gt;&lt;/object&gt;
+  &lt;?import namespace=&quot;svg&quot; implementation=&quot;#AdobeSVG&quot;?&gt;
+...
+</code></pre>
+<h3>Correct XHTML Mime-Type</h3>
+<p>Firefox and MSIE are fussy about the mimetype to do in-line
+   SVG. Firefox requires that either the URL ends in .html or that the
+   file is returned as mime type <code>application/xhtml+xml</code> in the HTTP
+   headers.
+</p>
+<p>However, MSIE does not recognise <code>application/xhtml+xml</code> and will
+   work fine with regular <code>text/html</code> mimetype for XHTML.
+</p>
+
+<h3>Non XHTML Compliant javascript includes</h3>
+<p>You cannot use the autoloading MochiKit.js, but instead include all the JS files individually or use the packed MochiKit. This is because MochiKit's way of autoloading is not XHTML compliant.
+</p>
+<p>An example of this is in the tests.
+</p>
+
+<h2> PlotKit SVG Options</h2>
+<p>There are no additional options for the SVG Renderer apart from the default Renderer options.
+</p>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.SVG.txt b/plotkit_v091/doc/PlotKit.SVG.txt
new file mode 100644 (file)
index 0000000..a590d9a
--- /dev/null
@@ -0,0 +1,64 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.SVG{% endblock %}
+
+{% block content %}
+<div class="page doc api">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [<<](PlotKit.Canvas.html) | [>>](PlotKit.SweetCanvas.html)
+
+PlotKit SVG
+===========
+
+PlotKit SVG includes the SVGRenderer which allows chart plotting on SVG capable browsers such as Firefox 1.5 and Opera 9.0. It should support Adobe SVG plugin, but is current untested.
+
+Important Implementation Requirements
+-------------------------------------
+
+In order to use the SVG Renderer, the file and webserver must support inline SVG files. This means the following conditions must exist:
+
+###The HTML file must be XHTML compliant. 
+
+So it should start off with this:
+
+       <?xml version="1.0" encoding="UTF-8"?>
+       <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+    <html
+       xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
+       xmlns:svg="http://www.w3.org/2000/svg"
+       xmlns:xlink="http://www.w3.org/1999/xlink">
+       <head>        
+         <object id="AdobeSVG" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2" width="1" height="1"></object>
+         <?import namespace="svg" implementation="#AdobeSVG"?>
+       ...
+
+###Correct XHTML Mime-Type
+
+Firefox and MSIE are fussy about the mimetype to do in-line
+SVG. Firefox requires that either the URL ends in .html or that the
+file is returned as mime type ``application/xhtml+xml`` in the HTTP
+headers.
+
+However, MSIE does not recognise ``application/xhtml+xml`` and will
+work fine with regular ``text/html`` mimetype for XHTML.
+
+###Non XHTML Compliant javascript includes
+
+You cannot use the autoloading MochiKit.js, but instead include all the JS files individually or use the packed MochiKit. This is because MochiKit's way of autoloading is not XHTML compliant.
+
+An example of this is in the tests.
+
+
+PlotKit SVG Options
+-------------------
+
+There are no additional options for the SVG Renderer apart from the default Renderer options.
+
+{% endfilter %}
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/plotkit_v091/doc/PlotKit.SweetCanvas.html b/plotkit_v091/doc/PlotKit.SweetCanvas.html
new file mode 100644 (file)
index 0000000..ae170df
--- /dev/null
@@ -0,0 +1,131 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.SweetCanvas | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.SVG.html">&lt;&lt;</a> | <a href="PlotKit.SweetSVG.html">&gt;&gt;</a> 
+</p>
+
+<h1> PlotKit Sweet Canvas Renderer</h1>
+<p>This renderer is an extension of the basic Canvas Renderer to show off
+   what you can do to make graphs pretty without learning any graph
+   layout code.
+</p>
+<p>There are no extra methods or options to use. The interface is exactly
+   the same as <code>PlotKit.Canvas</code>'s CanvasRenderer.
+</p>
+<p>SweetCanvasRenderer adds a fake shadow around bars, lines and circles
+   along with a 2.0 width white outline and a etched light coloured
+   background.
+</p>
+
+<h1> Example</h1>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.SweetCanvas.txt b/plotkit_v091/doc/PlotKit.SweetCanvas.txt
new file mode 100644 (file)
index 0000000..6f9e6b0
--- /dev/null
@@ -0,0 +1,34 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.SweetCanvas{% endblock %}
+
+{% block content %}
+<div class="page doc">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [<<](PlotKit.SVG.html) | [>>](PlotKit.SweetSVG.html)
+
+PlotKit Sweet Canvas Renderer
+=============================
+
+This renderer is an extension of the basic Canvas Renderer to show off
+what you can do to make graphs pretty without learning any graph
+layout code.
+
+There are no extra methods or options to use. The interface is exactly
+the same as ``PlotKit.Canvas``'s CanvasRenderer.
+
+SweetCanvasRenderer adds a fake shadow around bars, lines and circles
+along with a 2.0 width white outline and a etched light coloured
+background.
+
+Example
+=======
+
+{% endfilter %}
+</div>
+{% endblock %}
+
diff --git a/plotkit_v091/doc/PlotKit.SweetSVG.html b/plotkit_v091/doc/PlotKit.SweetSVG.html
new file mode 100644 (file)
index 0000000..0e9c4ff
--- /dev/null
@@ -0,0 +1,131 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit.SweetSVG | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc">
+
+<p> <a href="PlotKit.html">PlotKit Home</a> | <a href="PlotKit.SweetCanvas.html">&lt;&lt;</a> | <a href="PlotKit.EasyPlot.html">&gt;&gt;</a> 
+</p>
+
+<h1> PlotKit Sweet SVG Renderer</h1>
+<p>This renderer is an extension of the basic SVG Renderer to show off
+   what you can do to make graphs pretty without learning any graph
+   layout code.
+</p>
+<p>There are no extra methods or options to use. The interface is exactly
+   the same as <code>PlotKit.SVG</code>'s SVGRenderer.
+</p>
+<p>SweetSVGRenderer adds a fake shadow around bars, lines and circles
+   along with a 2.0 width white outline and a etched light coloured
+   background.
+</p>
+
+<h1> Example</h1>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.SweetSVG.txt b/plotkit_v091/doc/PlotKit.SweetSVG.txt
new file mode 100644 (file)
index 0000000..0af13df
--- /dev/null
@@ -0,0 +1,34 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+{% block title %}PlotKit.SweetSVG{% endblock %}
+
+{% block content %}
+<div class="page doc">
+{% filter markdown %}
+[PlotKit Home](PlotKit.html) | [<<](PlotKit.SweetCanvas.html) | [>>](PlotKit.EasyPlot.html)
+
+PlotKit Sweet SVG Renderer
+=============================
+
+This renderer is an extension of the basic SVG Renderer to show off
+what you can do to make graphs pretty without learning any graph
+layout code.
+
+There are no extra methods or options to use. The interface is exactly
+the same as ``PlotKit.SVG``'s SVGRenderer.
+
+SweetSVGRenderer adds a fake shadow around bars, lines and circles
+along with a 2.0 width white outline and a etched light coloured
+background.
+
+Example
+=======
+
+{% endfilter %}
+</div>
+{% endblock %}
+
diff --git a/plotkit_v091/doc/PlotKit.html b/plotkit_v091/doc/PlotKit.html
new file mode 100644 (file)
index 0000000..5d9827c
--- /dev/null
@@ -0,0 +1,334 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>PlotKit Documentation | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc">
+
+
+<h1> PlotKit</h1>
+<p> <a href="http://www.liquidx.net/plotkit/">PlotKit</a> is a Javascript graph plotting library. It is aimed at web
+   applications that require plotting series of data in modern web
+   browsers. 
+</p>
+<p>PlotKit requires <a href="http://mochikit.com/">MochiKit</a>. (1.3 or higher)
+</p>
+<p>PlotKit supports both HTML Canvas and SVG, along with an 
+   <a href="http://me.eae.net/archive/2005/12/29/canvas-in-ie/">emulated canvas for Internet Explorer</a>.
+</p>
+<p>PlotKit is easily extensible to include other rendering engines,
+   styles and layouts. Please pursue the documentation for more
+   information.
+</p>
+<p>PlotKit is licensed under the BSD License, so you can include it in
+   your free or commercial applications without worrying.
+</p>
+
+<h1> PlotKit Components</h1>
+
+<h2> Base Classes</h2>
+<ul>
+ <li>
+      <a href="PlotKit.Base.html">Base</a> : Common functionality that is used in other classes,
+  including default styles.
+ </li>
+
+ <li>
+      <a href="PlotKit.Layout.html">Layout</a> : The default chart layout engine, supports bar, line and
+           pie charts.
+ </li>
+
+ <li>
+      <a href="PlotKit.Renderer.html">Renderer</a>: Customising the look of the output
+ </li>
+</ul>
+
+<h2> Renderer Specific Implementations</h2>
+<ul>
+ <li>
+      <a href="PlotKit.Canvas.html">CanvasRenderer</a>: Basic renderer using an HTML Canvas.
+ </li>
+
+ <li>
+      <a href="PlotKit.SVG.html">SVGRenderer</a>: Basic renderer using SVG.
+ </li>
+
+ <li>
+      <a href="PlotKit.SweetCanvas.html">SweetCanvasRenderer</a>: Customised Renderer that builds on CanvasRenderer to provide nicer looking charts.
+ </li>
+
+ <li>
+      <a href="PlotKit.SweetSVG.html">SweetSVGRenderer</a>: Customised renderer that builds on SVGRenderer to provide nicer looking charts.
+ </li>
+</ul>
+
+<h2> Utility Classes</h2>
+<ul>
+ <li>
+      <a href="PlotKit.EasyPlot.html">EasyPlot</a>: Simple Wrapper around classes to provide one-line plotting.
+ </li>
+</ul>
+
+<h1> Getting Started</h1>
+<ul>
+ <li>
+      <a href="PlotKit.QuickStart.html">PlotKit Quick Start</a> - A thorough quick start to getting charts working for Safari, Mozilla, Firefox, Opera and IE.
+ </li>
+
+ <li>
+      <a href="SVGCanvasCompat.html">SVG/Canvas Browser Support Status</a> - Quirks about browser support that you should know about.
+ </li>
+
+ <li>
+      <a href="http://media.liquidx.net/js/plotkit-tests/quickstart.html">Simple Canvas Demo</a> - Very basic Canvas demo all contained in an HTML file.
+ </li>
+
+ <li>
+      <a href="http://media.liquidx.net/js/plotkit-tests/quickstart-svg.html">Simple SVG Demo</a> - Very basic SVG demo all contained in an HTML file.
+ </li>
+</ul>
+
+<h1> More Demos</h1>
+<ul>
+ <li>
+     Unit Tests <a href="http://media.liquidx.net/js/plotkit-tests/basic.html">Canvas</a>, <a href="http://media.liquidx.net/js/plotkit-tests/svg.html">SVG</a>, <a href="http://media.liquidx.net/js/plotkit-tests/sweet.html">SweetCanvas</a>, <a href="http://media.liquidx.net/js/plotkit-tests/sweet-svg.html">SweetSVG</a>.
+ </li>
+
+ <li>
+      <a href="http://media.liquidx.net/js/plotkit-tests/dynamic.html">Dynamic Charting</a>.
+ </li>
+
+ <li>
+      <a href="http://media.liquidx.net/js/plotkit-tests/labels.html">Labels Example</a>. Thanks to Christopher Armstrong.
+ </li>
+
+ <li>
+      <a href="http://media.liquidx.net/js/plotkit-tests/labels-img.html">Labels with Images</a>.
+ </li>
+
+ <li>
+      <a href="http://media.liquidx.net/js/plotkit-tests/axis.html">Axis Restrictions</a>.
+ </li>
+</ul>
+
+<h1> Version History</h1>
+
+<h3>PlotKit 0.8</h3>
+<ul>
+ <li>
+     Total rewrite from <a href="http://www.liquidx.net/canvasgraphjs/">CanvasGraph 0.7</a> 
+ </li>
+</ul>
+
+<h3>PlotKit 0.9</h3>
+<ul>
+ <li>
+     Fixed some redraw issues with clear()
+ </li>
+
+ <li>
+     Replaced IECanvas.HTC with ExplorerCanvas
+ </li>
+
+ <li>
+     Added auto import and packed versions just like MochiKit.
+ </li>
+
+ <li>
+     Added horizontal bar chart rendering mode.
+ </li>
+
+ <li>
+     Added awareness of prototype.js and workaround Array/Object mutilation issues with MochiKit.
+ </li>
+
+ <li>
+     Added EasyPlot for single line plotting with Ajax support.
+ </li>
+
+ <li>
+     More tests, <a href="http://media.liquidx.net/js/plotkit-tests/dynamic.html">dynamic charting</a> and quickstart demos.
+ </li>
+</ul>
+
+<h3>PlotKit 0.9.1</h3>
+<ul>
+ <li>
+     Make Sweet{Canvas/SVG}Renderers respect shouldFill.
+ </li>
+
+ <li>
+     Fixed ignoring of maximum x and y values when setting xAxis/yAxis.
+ </li>
+
+ <li>
+     Fixed typo for calculating yrange in Layout.js (thanks to
+     HubrisSonic).
+ </li>
+
+ <li>
+     Changed SweetCanvasRenderer to use axisLineColor for drawing lines over 
+     background (thanks to HubrisSonic).
+ </li>
+
+ <li>
+     Fixed bug in y-axis tick drawing (thanks to Cliff).
+ </li>
+
+ <li>
+     Fixed x-axis calculation bug when xAxisIsZero is false (thanks to 
+     Loic Jeannin)
+ </li>
+
+ <li>
+     Fixed xTicks drawing that exceed the bounds of the chart (thanks to
+     Cliff)
+ </li>
+
+ <li>
+     Fixed barchart drawing with only 2 values (thanks to HubrisSonic)
+ </li>
+
+ <li>
+     Hide pie chart labels of 0% (thanks to Attiks)
+ </li>
+
+ <li>
+     Added optional field to addDatasetFromTable to include x-axis labels.
+ </li>
+
+ <li>
+     Updated excanvas.js version to fix possible printing issues.
+ </li>
+</ul>
+
+<h1> Road Map</h1>
+
+<h3>Version 0.9</h3>
+<ul>
+ <li>
+     AutoSelectRenderer, automatically choose Canvas or SVG by auto detecting browser support.
+ </li>
+</ul>
+
+<h3>Version 0.10</h3>
+<ul>
+ <li>
+     Point plots
+ </li>
+
+ <li>
+     Defined Event System Support
+ </li>
+
+ <li>
+     Animation support.
+ </li>
+</ul>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/PlotKit.txt b/plotkit_v091/doc/PlotKit.txt
new file mode 100644 (file)
index 0000000..03a5dd7
--- /dev/null
@@ -0,0 +1,151 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block title %}PlotKit Documentation{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+
+
+{% block content %}
+<div class="page doc">
+{% filter markdown %}
+PlotKit
+=======
+
+[PlotKit][] is a Javascript graph plotting library. It is aimed at web
+applications that require plotting series of data in modern web
+browsers. 
+
+PlotKit requires [MochiKit][]. (1.3 or higher)
+
+PlotKit supports both HTML Canvas and SVG, along with an 
+[emulated canvas for Internet Explorer][IECanvas].
+
+PlotKit is easily extensible to include other rendering engines,
+styles and layouts. Please pursue the documentation for more
+information.
+
+PlotKit is licensed under the BSD License, so you can include it in
+your free or commercial applications without worrying.
+
+PlotKit Components
+==================
+
+Base Classes
+------------
+
+* [Base][] : Common functionality that is used in other classes,
+  including default styles.
+* [Layout][] : The default chart layout engine, supports bar, line and
+               pie charts.
+* [Renderer][]: Customising the look of the output
+
+Renderer Specific Implementations
+---------------------------------
+
+* [CanvasRenderer][]: Basic renderer using an HTML Canvas.
+* [SVGRenderer][]: Basic renderer using SVG.
+* [SweetCanvasRenderer][]: Customised Renderer that builds on CanvasRenderer to provide nicer looking charts.
+* [SweetSVGRenderer][]: Customised renderer that builds on SVGRenderer to provide nicer looking charts.
+   
+Utility Classes
+---------------
+
+* [EasyPlot][]: Simple Wrapper around classes to provide one-line plotting.
+
+Getting Started
+===============
+
+* [PlotKit Quick Start][QuickStart] - A thorough quick start to getting charts working for Safari, Mozilla, Firefox, Opera and IE.
+* [SVG/Canvas Browser Support Status][Browser] - Quirks about browser support that you should know about.
+* [Simple Canvas Demo][QuickstartCanvasDemo] - Very basic Canvas demo all contained in an HTML file.
+* [Simple SVG Demo][QuickstartSVGDemo] - Very basic SVG demo all contained in an HTML file.
+
+More Demos
+==========
+
+* Unit Tests [Canvas][CanvasTest], [SVG][SVGTest], [SweetCanvas][SCanvasTest], [SweetSVG][SSVGTest].
+* [Dynamic Charting][DynamicTest].
+* [Labels Example][]. Thanks to Christopher Armstrong.
+* [Labels with Images][].
+* [Axis Restrictions][].
+
+Version History
+===============
+
+
+###PlotKit 0.8
+
+* Total rewrite from [CanvasGraph 0.7][CanvasGraph]
+
+###PlotKit 0.9
+
+* Fixed some redraw issues with clear()
+* Replaced IECanvas.HTC with ExplorerCanvas
+* Added auto import and packed versions just like MochiKit.
+* Added horizontal bar chart rendering mode.
+* Added awareness of prototype.js and workaround Array/Object mutilation issues with MochiKit.
+* Added EasyPlot for single line plotting with Ajax support.
+* More tests, [dynamic charting][DynamicTest] and quickstart demos.
+
+###PlotKit 0.9.1
+
+* Make Sweet{Canvas/SVG}Renderers respect shouldFill.
+* Fixed ignoring of maximum x and y values when setting xAxis/yAxis.
+* Fixed typo for calculating yrange in Layout.js (thanks to
+    HubrisSonic).
+* Changed SweetCanvasRenderer to use axisLineColor for drawing lines over 
+    background (thanks to HubrisSonic).
+* Fixed bug in y-axis tick drawing (thanks to Cliff).
+* Fixed x-axis calculation bug when xAxisIsZero is false (thanks to 
+    Loic Jeannin)
+* Fixed xTicks drawing that exceed the bounds of the chart (thanks to
+    Cliff)
+* Fixed barchart drawing with only 2 values (thanks to HubrisSonic)
+* Hide pie chart labels of 0% (thanks to Attiks)
+* Added optional field to addDatasetFromTable to include x-axis labels.
+* Updated excanvas.js version to fix possible printing issues.
+
+Road Map
+========
+###Version 0.9
+
+* AutoSelectRenderer, automatically choose Canvas or SVG by auto detecting browser support.
+
+###Version 0.10
+
+* Point plots
+* Defined Event System Support
+* Animation support.
+
+[QuickStart]: PlotKit.QuickStart.html
+[CanvasGraph]: http://www.liquidx.net/canvasgraphjs/
+[PlotKit]: http://www.liquidx.net/plotkit/
+[MochiKit]: http://mochikit.com/
+[IECanvas]: http://me.eae.net/archive/2005/12/29/canvas-in-ie/
+[Base]: PlotKit.Base.html
+[Styles]: PlotKit.Styles.html
+[Layout]: PlotKit.Layout.html
+[Renderer]: PlotKit.Renderer.html
+[CanvasRenderer]: PlotKit.Canvas.html
+[SVGRenderer]: PlotKit.SVG.html
+[SweetCanvasRenderer]: PlotKit.SweetCanvas.html
+[SweetSVGRenderer]: PlotKit.SweetSVG.html
+[EasyPlot]: PlotKit.EasyPlot.html
+[Browser]: SVGCanvasCompat.html
+[CanvasTest]: http://media.liquidx.net/js/plotkit-tests/basic.html
+[SVGTest]: http://media.liquidx.net/js/plotkit-tests/svg.html
+[SCanvasTest]: http://media.liquidx.net/js/plotkit-tests/sweet.html
+[SSVGTest]: http://media.liquidx.net/js/plotkit-tests/sweet-svg.html
+[QuickstartCanvasDemo]: http://media.liquidx.net/js/plotkit-tests/quickstart.html
+[QuickstartSVGDemo]: http://media.liquidx.net/js/plotkit-tests/quickstart-svg.html
+[QuickstartEasyDemo]: http://media.liquidx.net/js/plotkit-tests/quickstart-easy.html
+[DynamicTest]: http://media.liquidx.net/js/plotkit-tests/dynamic.html
+[Labels Example]: http://media.liquidx.net/js/plotkit-tests/labels.html
+[Labels with Images]: http://media.liquidx.net/js/plotkit-tests/labels-img.html
+[Axis Restrictions]: http://media.liquidx.net/js/plotkit-tests/axis.html
+
+{% endfilter %}
+</div>
+{% endblock %}
diff --git a/plotkit_v091/doc/SVGCanvasCompat.html b/plotkit_v091/doc/SVGCanvasCompat.html
new file mode 100644 (file)
index 0000000..58e7d64
--- /dev/null
@@ -0,0 +1,304 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
+<head>
+       <title>SVG and Canvas Support Status in Various Browsers. | liquidx</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <link href="http://media.liquidx.net/css/x_general.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_header.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link href="http://media.liquidx.net/css/x_layout.css" media="screen" rel="Stylesheet" type="text/css" />       
+       <link href="http://media.liquidx.net/css/x_blocks.css" media="screen" rel="Stylesheet" type="text/css" />
+       <link rel="icon" href="/favicon.png" type="image/x-png">
+       <link rel="shortcut icon" href="/favicon.png" type="image/x-png">
+       <!--[if lt IE 7.]>      
+       <script defer type="text/javascript" src="http://media.liquidx.net/js/pngfix.js"></script>
+       <![endif]-->
+       
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+
+</head>
+
+<body>
+    <div id="header">
+        <div id="logo"><a href="http://www.liquidx.net/"><img src="http://media.liquidx.net/imgx/logo.png" width="256" height="128" alt="liquidx.net" /></a></div>
+               <div id="menu-hack">
+                       <div id="menu-l"><img src="http://media.liquidx.net/imgx/menu_l.png" width="17" height="28" alt="menu cap" /></div><div id="menu-r"><img src="http://media.liquidx.net/imgx/menu_r.png" width="17" height="28" alt="menu cap" /></div>                  
+            <div id="menu-main">
+                       <ul id="menu" class="code">
+                       <li class="tab" id="blog"><a href="http://www.liquidx.net/" title="blog/home">blog</a></li>
+                       <li class="tab" id="code"><a href="http://www.liquidx.net/code/" title="software i have written">software</a></li>
+                       <li class="tab" id="dev"><a href="http://projects.liquidx.net/" title="source code for my open source projects">dev</a></li>
+                       <li class="tab" id="photos"><a href="http://al.tse.id.au/gallery/" title="photos and videos">photos</a></li>
+                       <li class="tab" id="research"><a href="http://al.tse.id.au/research/" title="research profile">research</a></li>
+                       <li class="tab" id="links"><a href="http://www.liquidx.net/links/" title="my bookmarks">linkblog</a></li>
+                       <li class="tab" id="stats"><a href="http://stats.liquidx.net/" title="stats for various parts of my website">stats</a></li>
+                       <li class="tab" id="status"><a href="http://www.liquidx.net/status/" title="weather report for alastair">status</a></li>
+                       <li class="tab" id="about"><a href="http://al.tse.id.au/" title="about alastair tse">aboutme</a></li>
+                       </ul>
+               </div>
+       </div>
+               <div id="quickbuttons">
+                       <span class="quickbutton"><a href="http://www.liquidx.net/albumartwidget/"><img src="http://media.liquidx.net/imgx/quick_widget.png" alt="album art widget" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/plotkit/"><img src="http://media.liquidx.net/imgx/quick_plotkit.png" alt="plotkit" /></a></span>
+                       <span class="quickbutton"><a href="http://www.liquidx.net/fruity/"><img src="http://media.liquidx.net/imgx/quick_fruity.png" alt="fruity" /></a></span>
+               </div>
+               
+       </div>
+    
+    <div id="body">
+<div class="page doc">
+
+
+<h1> State of SVG and Canvas in Modern Browsers</h1>
+<p> <strong>By: Alastair Tse - Last Updated: 27 April 2006</strong> 
+</p>
+<p>My friends, just like HTML and CSS, different browsers support
+   different subsections of the SVG and Canvas specification. As part of
+   my work on PlotKit, the next generation javascript plotting library,
+   I've decided to summarise all the quirks in SVG and Canvas support.
+</p>
+
+<h1> Browsers Considered</h1>
+<p>I am looking at browsers that are considered &quot;modern&quot; as of
+   March 2006. These include:
+</p>
+<ul>
+ <li>
+      <a href="http://apple.com/safari/">Safari 2.0.x</a> (W/ <a href="http://www.adobe.com/svg/">Adobe SVG Plugin</a>)
+ </li>
+
+ <li>
+      <a href="http://www.mozilla.com/firefox/">Firefox 1.5.x</a> 
+ </li>
+
+ <li>
+      <a href="http://snapshot.opera.com/">Opera 9.0 Preview 2</a> 
+ </li>
+
+ <li>
+      <a href="http://www.microsoft.com/windows/ie/">Internet Explorer 6</a> (w/ <a href="http://www.adobe.com/svg/">Adobe SVG Plugin</a>)
+ </li>
+</ul>
+<p>I am also looking at some experiemental browsers as of March 2006. 
+</p>
+<ul>
+ <li>
+      <a href="http://www.microsoft.com/windows/IE/ie7/default.mspx">Internet Explorer 7 beta 2 preview + ASV</a> 
+ </li>
+
+ <li>
+      <a href="http://nightly.webkit.org/">Safari WebKit+SVG Nightly 2006-03-11</a> 
+ </li>
+
+ <li>
+      <a href="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/">Firefox Deerpark Nightly 2006-03-11</a> 
+ </li>
+</ul>
+
+<h1> Canvas</h1>
+<ul>
+ <li>
+     Canvas is defined by the WHATWG in what is known as the 
+       <a href="http://whatwg.org/specs/web-apps/current-work/">Web Applications 1.0 specification</a> 
+ </li>
+</ul>
+
+<h2> Supporting Browsers</h2>
+<ul>
+ <li>
+     Safari 2.0 and above.
+ </li>
+
+ <li>
+     Opera 9.0 and above.
+ </li>
+
+ <li>
+     Firefox 1.5 and above.
+ </li>
+</ul>
+
+<h2> Quirks</h2>
+<ul>
+ <li><p> <strong>Safari</strong> will forget a path after <code>fill()</code> or <code>stroke()</code> has
+   been called. Therefore, if you need to fill and stroke the same
+   path, you must draw the path out twice.
+</p>
+
+ </li>
+
+ <li><p> <strong>Opera</strong> will not obey <code>stroke()</code> for arc paths.
+</p>
+
+ </li>
+
+ <li><p> <strong>Firefox</strong> and <strong>Opera</strong> will not draw shadows even with
+     <code>shadowStyle</code> or <code>shadowOffset</code> is set on the context object.
+</p>
+
+ </li>
+</ul>
+
+<h1> SVG</h1>
+<ul>
+ <li>
+     SVG support is either provided natively, or through the Adobe SVG
+       Viewer (ASV).
+ </li>
+</ul>
+
+<h2> Supporting Browsers (Inline)</h2>
+<ul>
+ <li>
+     Safari 2.0 + ASV
+ </li>
+
+ <li>
+     Internet Explorer 6 + ASV
+ </li>
+
+ <li>
+     Safari Webkit+SVG Nightly
+ </li>
+
+ <li>
+     Opera 9.0 and above
+ </li>
+
+ <li>
+     Mozilla Firefox 1.5 and above
+ </li>
+</ul>
+
+<h2> Quirks (Inline)</h2>
+<ul>
+ <li><p> <strong>Safari Nightly</strong> will not render any <code>text</code> elements when
+     inlined. (Will do so if using <code>embed</code>)
+</p>
+
+ </li>
+
+ <li><p> <strong>Safari 2.0 + ASV</strong> will not respect inlined SVG.
+</p>
+
+ </li>
+
+ <li><p> <strong>Internet Explorer 6 + ASV</strong> will only parse inlined SVG if the
+     following is added to the HTML and all SVG elements are in the
+     correct namespace <code>svg:</code>.
+</p>
+
+ </li>
+</ul>
+<p>  following is added to the HTML and all SVG elements are in the
+     correct namespace <code>svg:</code>.
+</p>
+<pre><code>&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;
+xmlns:svg=&quot;http://www.w3.org/2000/svg&quot;
+xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;
+...
+&lt;body&gt;
+&lt;!-- START Required for IE to support  inlined SVG --&gt;
+&lt;object id=&quot;AdobeSVG&quot;
+classid=&quot;clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2&quot; width=&quot;1&quot;
+height=&quot;1&quot;&gt;&lt;/object&gt;
+&lt;?import namespace=&quot;svg&quot; implementation=&quot;#AdobeSVG&quot;?&gt;
+&lt;!-- END   Required for IE to support inlined SVG --&gt;
+&lt;svg:svg width=&quot;300&quot; height=&quot;300&quot; baseProfile=&quot;full&quot; version=&quot;1.1&quot;&gt;&lt;/svg:svg&gt;
+&lt;/body&gt;
+&lt;/html&gt;
+</code></pre><ul>
+ <li><p> <strong>Mozilla Firefox (1.5 and nightly) on Mac</strong> will not render
+     <code>text</code> elements when inlined. Note that it does for Linux and Windows.
+</p>
+
+ </li>
+
+ <li><p> <strong>Opera 9</strong> will refuse to draw an element if attribute <code>filter</code>
+     is defined.
+</p>
+
+ </li>
+</ul>
+<p>  is defined.
+</p>
+<ul>
+ <li>
+      <strong>Internet Explorer 7b2p + ASV</strong> will not work with the Adobe SVG Viewer.
+ </li>
+</ul>
+
+<h1> Disclaimer</h1>
+<p>The above is presented as-is with my own findings. There may be
+   errors. Please do not use this to base your multi-million dollar
+   business decisions.
+</p>
+
+<h1> Contact</h1>
+<p>If you have anything to add or modify, please contact me at
+   <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#108;&#97;&#115;&#116;&#97;&#105;&#114;&#64;&#108;&#105;&#113;&#117;&#105;&#100;&#120;&#46;&#110;&#101;&#116;">&#97;&#108;&#97;&#115;&#116;&#97;&#105;&#114;&#64;&#108;&#105;&#113;&#117;&#105;&#100;&#120;&#46;&#110;&#101;&#116;</a>.
+</p>
+
+
+</div>
+</div>
+
+    
+       
+    
+    <div id="footer">
+               <div class="block">
+                       <h3>Syndication Feeds:</h3>
+                       <p>
+                               <ul class="tiny">
+                                       <li><a href="http://www.liquidx.net/blog/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Atom Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/blog/feed/rss/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />RSS Feed for the Blog Entries</a></li>
+                                       <li><a href="http://www.liquidx.net/comments/feed/atom/" class="feed" title="feed for all posts on liquidx.net"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for All Comments</a></li>
+                                       <li><a href="http://www.liquidx.net/links/feed/atom/" class="feed" title="feed for all bookmarked links"><img src="http://media.liquidx.net/imgx/feed.gif" class="feed" alt="feed" />Feed for Links</a></li>
+                               </ul>
+                       </p>
+               </div>
+               <div class="block">
+                       <h3>About this site:</h3>
+                       <p>Content on this site is licensed under <a href="http://creativecommons.org/licenses/by/2.5/">CC By Attribution</a> unless otherwise specified. 
+                       Copyright (c) 2002-2006, <a href="http://al.tse.id.au/">Alastair Tse</a>.</p>
+                       <p>For more information, see <a href="http://al.tse.id.au/">al.tse.id.au</a>.</p>
+                       <p><script type="text/javascript" src="http://technorati.com/embed/itwctkzez.js"></script></p>
+               </div>
+               <div class="block">
+                       <h3>Is Made Possible By:</h3>
+                       <p>
+                       <dl>
+                               <dt><a href="http://ecto.kung-foo.tv/" class="clean">ecto</a>. </dt>
+                               <dd>Blogging client for Mac</dd>
+                               <dt><a href="http://djangoproject.com/" class="clean">Django</a>. </dt>
+                               <dd>Python Web Framework</dd>
+                               <dt><a href="http://www.lighttpd.net/" class="clean">lighttpd</a>. </dt> 
+                               <dd>Really Fast Web Server</dd>
+                               <dt><a href="http://www.saddi.com/software/flup/" class="clean">flup</a>. </dt>
+                               <dd>FastCGI for Python</dd>
+                       </dl>
+                       </p>
+               </div>
+        <div class="block">
+            <h3>Search My Sites:</h3>
+            <p>
+           <div style='margin: 10px; text-align: center; width: 160px;'><form action='http://www.rollyo.com/search.html' ><fieldset style='margin: 0; padding: 4px 0 0 0; height: 60px; border: none; background: url(http://rollyo.com/remote/togo-bg4.png) no-repeat top left;'><div style="position: absolute; float:left; z-index:99; width: 46px; height: 50px;"><a href="http://rollyo.com"><img style="border: none;" height="50" width="46" src="http://rollyo.com/remote/x.gif"></a></div> <input type='text' size='30' style='float: left; width: 90px; margin: 2px 0 0 48px; padding: 0; font-size: 12px;' name='q' value='Search...' onclick='this.value="";' /><br /> <select name='sid' style='float: left; width: 78px; height: 15px; margin: 12px 0 0 46px; font-size: 7pt; padding: 0;'><option value='106081' selected='selected'>liquidx</option><option value='web'>Search The Web</option></select><input type='image' src='http://rollyo.com/remote/btn-togo.png' alt='Go' style='margin: 12px 0 0 3px; float: left;' /><input type='hidden' name='togo-v' value='1' /></fieldset></form></div>
+               </p>
+          </div>
+         
+    
+               <div class="clear">&nbsp;</div>
+        
+    </div>
+
+
+
+   <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+   <script type="text/javascript">
+   _uacct = "UA-58117-1";
+   urchinTracker();
+   </script>
+
+</body>
+</html>
diff --git a/plotkit_v091/doc/SVGCanvasCompat.txt b/plotkit_v091/doc/SVGCanvasCompat.txt
new file mode 100644 (file)
index 0000000..4be4cd3
--- /dev/null
@@ -0,0 +1,144 @@
+{% extends "basex.html" %}
+{% load markup %}
+{% block pageid %}code{% endblock %}
+{% block title %}SVG and Canvas Support Status in Various Browsers.{% endblock %}
+{% block headers %}
+<link href="doc.css" media="screen" rel="stylesheet" type="text/css" />
+{% endblock %}
+
+
+{% block content %}
+<div class="page doc">
+{% filter markdown %}
+State of SVG and Canvas in Modern Browsers
+==========================================
+
+__By: Alastair Tse - Last Updated: 27 April 2006__
+
+
+My friends, just like HTML and CSS, different browsers support
+different subsections of the SVG and Canvas specification. As part of
+my work on PlotKit, the next generation javascript plotting library,
+I've decided to summarise all the quirks in SVG and Canvas support.
+
+Browsers Considered
+===================
+
+I am looking at browsers that are considered "modern" as of
+March 2006. These include:
+
+* [Safari 2.0.x][Safari] (W/ [Adobe SVG Plugin][ASV])
+* [Firefox 1.5.x][Firefox]
+* [Opera 9.0 Preview 2][OperaSnapshot]
+* [Internet Explorer 6][IE6] (w/ [Adobe SVG Plugin][ASV])
+
+I am also looking at some experiemental browsers as of March 2006. 
+
+* [Internet Explorer 7 beta 2 preview + ASV][IE7]
+* [Safari WebKit+SVG Nightly 2006-03-11][WebkitNightly]
+* [Firefox Deerpark Nightly 2006-03-11][FirefoxNightly]
+
+[Safari]: http://apple.com/safari/
+[Firefox]: http://www.mozilla.com/firefox/
+[OperaSnapshot]: http://snapshot.opera.com/
+[IE6]: http://www.microsoft.com/windows/ie/
+[ASV]: http://www.adobe.com/svg/
+[IE7]: http://www.microsoft.com/windows/IE/ie7/default.mspx
+[WebkitNightly]: http://nightly.webkit.org/
+[FirefoxNightly]: http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/
+
+
+Canvas
+======
+
+* Canvas is defined by the WHATWG in what is known as the 
+  [Web Applications 1.0 specification][WHATWG]
+
+Supporting Browsers
+-------------------
+
+* Safari 2.0 and above.
+* Opera 9.0 and above.
+* Firefox 1.5 and above.
+
+Quirks
+------
+
+* __Safari__ will forget a path after ``fill()`` or ``stroke()`` has
+    been called. Therefore, if you need to fill and stroke the same
+    path, you must draw the path out twice.
+
+* __Opera__ will not obey ``stroke()`` for arc paths.
+
+* __Firefox__ and __Opera__ will not draw shadows even with
+  ``shadowStyle`` or ``shadowOffset`` is set on the context object.
+
+SVG
+===
+
+* SVG support is either provided natively, or through the Adobe SVG
+  Viewer (ASV).
+
+Supporting Browsers (Inline)
+----------------------------
+
+* Safari 2.0 + ASV
+* Internet Explorer 6 + ASV
+* Safari Webkit+SVG Nightly
+* Opera 9.0 and above
+* Mozilla Firefox 1.5 and above
+
+Quirks (Inline)
+---------------
+
+* __Safari Nightly__ will not render any ``text`` elements when
+  inlined. (Will do so if using ``embed``)
+
+* __Safari 2.0 + ASV__ will not respect inlined SVG.
+
+* __Internet Explorer 6 + ASV__ will only parse inlined SVG if the
+  following is added to the HTML and all SVG elements are in the
+  correct namespace ``svg:``.
+
+    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink">
+    ...
+    <body>
+    <!-- START Required for IE to support  inlined SVG -->
+    <object id="AdobeSVG"
+    classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2" width="1"
+    height="1"></object>
+    <?import namespace="svg" implementation="#AdobeSVG"?>
+    <!-- END   Required for IE to support inlined SVG -->
+    <svg:svg width="300" height="300" baseProfile="full" version="1.1"></svg:svg>
+    </body>
+    </html>
+
+* __Mozilla Firefox (1.5 and nightly) on Mac__ will not render
+  ``text`` elements when inlined. Note that it does for Linux and Windows.
+
+* __Opera 9__ will refuse to draw an element if attribute ``filter``
+  is defined.
+
+* __Internet Explorer 7b2p + ASV__ will not work with the Adobe SVG Viewer.
+
+
+Disclaimer
+==========
+
+The above is presented as-is with my own findings. There may be
+errors. Please do not use this to base your multi-million dollar
+business decisions.
+
+Contact
+=======
+
+If you have anything to add or modify, please contact me at
+<alastair@liquidx.net>.
+
+[WHATWG]: http://whatwg.org/specs/web-apps/current-work/
+
+{% endfilter %}
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/plotkit_v091/doc/barsample.png b/plotkit_v091/doc/barsample.png
new file mode 100644 (file)
index 0000000..f11e1ed
Binary files /dev/null and b/plotkit_v091/doc/barsample.png differ
diff --git a/plotkit_v091/doc/black.png b/plotkit_v091/doc/black.png
new file mode 100644 (file)
index 0000000..9825e8f
Binary files /dev/null and b/plotkit_v091/doc/black.png differ
diff --git a/plotkit_v091/doc/blue.png b/plotkit_v091/doc/blue.png
new file mode 100644 (file)
index 0000000..cde1bd3
Binary files /dev/null and b/plotkit_v091/doc/blue.png differ
diff --git a/plotkit_v091/doc/cyan.png b/plotkit_v091/doc/cyan.png
new file mode 100644 (file)
index 0000000..ff946d6
Binary files /dev/null and b/plotkit_v091/doc/cyan.png differ
diff --git a/plotkit_v091/doc/doc.css b/plotkit_v091/doc/doc.css
new file mode 100644 (file)
index 0000000..5fede59
--- /dev/null
@@ -0,0 +1,62 @@
+.doc h1 {
+   color: #335577;
+   padding-bottom: 5px;
+   border-bottom: 1px solid #ccc;
+   display: block;
+}
+
+.doc h2 {
+   font-size: medium;
+   padding-left: 0;
+}   
+
+.doc h3 {
+   padding-left: 0;
+   font-size: medium;
+   color: #666;
+}
+
+.doc ul {
+   padding-left: 10px;
+   margin-left: 10px;
+}
+
+.api li {
+   display: block;
+   border: 1px solid #eee;
+   background-color: #f9f9f9;
+   padding: 2px;
+   padding-left: 5px;
+   list-style: none;
+}
+
+.doc thead td {
+   border-bottom: 1px solid #eee;
+}
+
+.doc thead td, .doc thead th {
+   text-align: left;
+   font-weight: bold;
+}
+
+.doc tbody th {
+   text-align: left;
+   font-weight: bold;
+}
+
+.doc th, .doc td {
+   vertical-align: top;
+   padding: 4px;
+   margin: 0;
+   font-size: 9px;
+}
+
+.doc pre {
+     border: 1px solid #f0f0f0;
+     background-color: #f9f9ff;
+     padding: 4px;
+}
+
+.doc .demo {
+   padding-bottom: 20px;
+}
diff --git a/plotkit_v091/doc/generate.py b/plotkit_v091/doc/generate.py
new file mode 100755 (executable)
index 0000000..502e279
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+import sys
+import os
+import re
+sys.path.append('/home/al/sites')
+os.environ['DJANGO_SETTINGS_MODULE'] = '__main__'
+
+DEFAULT_CHARSET = "utf-8"
+TEMPLATE_DEBUG = False
+LANGUAGE_CODE = "en"
+
+INSTALLED_APPS = (
+    'django.contrib.markup',
+)    
+
+TEMPLATE_DIRS = (
+    '/home/al/sites/liquidx/templates',
+    '.'
+)
+
+from django.template import Template, Context, loader
+
+def make(src, dst):
+    print '%s -> %s' % (src, dst)
+    c = Context({})
+    filled = loader.render_to_string(src, {})
+    open(dst, 'w').write(filled)
+    
+if __name__ == "__main__":
+    for dirname, dirs, files in os.walk('.'):
+        if re.search('/\.svn', dirname):
+            continue
+        for f in files:
+            if f[-4:] == ".txt":
+                newname = f.replace('.txt', '.html')
+                make(os.path.join(dirname, f), os.path.join(dirname, newname))
diff --git a/plotkit_v091/doc/green.png b/plotkit_v091/doc/green.png
new file mode 100644 (file)
index 0000000..33f7da3
Binary files /dev/null and b/plotkit_v091/doc/green.png differ
diff --git a/plotkit_v091/doc/orange.png b/plotkit_v091/doc/orange.png
new file mode 100644 (file)
index 0000000..39c6825
Binary files /dev/null and b/plotkit_v091/doc/orange.png differ
diff --git a/plotkit_v091/doc/piesample.png b/plotkit_v091/doc/piesample.png
new file mode 100644 (file)
index 0000000..31255b1
Binary files /dev/null and b/plotkit_v091/doc/piesample.png differ
diff --git a/plotkit_v091/doc/purple.png b/plotkit_v091/doc/purple.png
new file mode 100644 (file)
index 0000000..952edf1
Binary files /dev/null and b/plotkit_v091/doc/purple.png differ
diff --git a/plotkit_v091/doc/red.png b/plotkit_v091/doc/red.png
new file mode 100644 (file)
index 0000000..678cacb
Binary files /dev/null and b/plotkit_v091/doc/red.png differ
diff --git a/plotkit_v091/scripts/custom_rhino.jar b/plotkit_v091/scripts/custom_rhino.jar
new file mode 100644 (file)
index 0000000..4391990
Binary files /dev/null and b/plotkit_v091/scripts/custom_rhino.jar differ
diff --git a/plotkit_v091/scripts/pack.py b/plotkit_v091/scripts/pack.py
new file mode 100755 (executable)
index 0000000..566bf33
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+#
+# custom_rhino.jar from:
+#   http://dojotoolkit.org/svn/dojo/buildscripts/lib/custom_rhino.jar
+#
+
+import os
+import re
+import sys
+import shutil
+import subprocess
+mk = file('PlotKit/PlotKit.js').read()
+if len(sys.argv) > 1:
+    outf = sys.stdout
+else:
+    outf = file('PlotKit/PlotKit_Packed.js', 'w')
+VERSION = re.search(
+    r"""(?mxs)PlotKit.PlotKit.VERSION\s*=\s*['"]([^'"]+)""",
+    mk
+).group(1)
+if len(sys.argv) > 1:
+    SUBMODULES = sys.argv[1:]
+else:
+    SUBMODULES = map(str.strip, re.search(
+        r"""(?mxs)PlotKit.PlotKit.SUBMODULES\s*=\s*\[([^\]]+)""",
+        mk
+    ).group(1).replace(' ', '').replace('"', '').split(','))
+
+alltext = '\n'.join(
+    [file('PlotKit/%s.js' % m).read() for m in SUBMODULES])
+
+tf = file('_scratch.js', 'w')
+tf.write(alltext)
+tf.flush()
+
+p = subprocess.Popen(
+    ['java', '-jar', 'scripts/custom_rhino.jar', '-c', tf.name],
+    stdout=subprocess.PIPE,
+)
+print >>outf, """/***
+
+    PlotKit.PlotKit %(VERSION)s : 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.
+
+***/
+""" % locals()
+shutil.copyfileobj(p.stdout, outf)
+outf.write('\n')
+outf.flush()
+outf.close()
+tf.close()
+os.remove(tf.name)
diff --git a/plotkit_v091/tests/axis.html b/plotkit_v091/tests/axis.html
new file mode 100644 (file)
index 0000000..b8fb420
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: Axis Test</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Axis Test</h2>
+    
+    <div id="example" style="margin: 0 auto 0 auto;" width="400" height="400"></div>
+    
+    <script type="text/javascript">
+        var data = [[0,0], [1,2], [2,3], [3, 7], [4, 8], [5, 6]];
+        var options = {"xAxis": [1,4], "yAxis":[1,6]};
+        var plotter = EasyPlot("line", options, $("example"), 
+                               [data, "sample.txt"]);
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/basic.html b/plotkit_v091/tests/basic.html
new file mode 100644 (file)
index 0000000..8c6d25c
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit : Basic Unit Tests</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+   <script src="/js/plotkit-tests/basic.js" type="text/javascript"></script>
+</head>
+
+<body>
+    <div id="body">
+    <h2>Basic Unit Tests for PlotKit</h2>
+    
+    <div id="tests">
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/basic.js b/plotkit_v091/tests/basic.js
new file mode 100644 (file)
index 0000000..147c0eb
--- /dev/null
@@ -0,0 +1,143 @@
+/* actual tests */
+
+var opts = {
+    "IECanvasHTC": "../plotkit/iecanvas.htc",
+    "enableEvents": true,
+    "strokeColor": null
+};
+
+function alert_val(e) {
+    alert("x:" + e.chart.xval + "y:" + e.chart.yval);
+}
+
+function genericTest(num, plotStyle) {
+       var l = new PlotKit.Layout(plotStyle, {});
+       var success = l.addDatasetFromTable("data" + num, $("test" + num));
+       l.evaluate();
+       var c = $("test" + num + "canvas");
+       var g = new PlotKit.CanvasRenderer(c, l, opts);
+       g.render();
+
+    // test events
+    MochiKit.Signal.connect(g, "onclick", alert_val);
+}
+
+function genericTestAndClear(num, plotStyle) {
+       var l = new PlotKit.Layout(plotStyle, {});
+       l.addDatasetFromTable("data" + num, $("test" + num));   
+       l.evaluate();
+       var c = $("test" + num + "canvas");
+       var g = new PlotKit.CanvasRenderer(c, l, opts);
+       g.render();
+       g.clear();
+}
+
+function dualDataSet(num, plotStyle) {
+       var l = new PlotKit.Layout(plotStyle, {});
+       l.addDatasetFromTable("data1." + num, $("test" + num), 0, 1);   
+       l.addDatasetFromTable("data2." + num, $("test" + num), 0, 2);   
+       l.evaluate();
+       var c = $("test" + num + "canvas");
+       var g = new PlotKit.CanvasRenderer(c, l, opts);
+       g.render();
+}
+
+
+/* create HTML for tests */
+
+function makeTableRow(list) {
+    return TR({}, map(partial(TD, null), list));
+}
+
+function generateTestTable(num, data) {
+    var tableid = "test" + num;
+    var tablehead = THEAD(null, map(makeTableRow, [["x", "y"]]));
+    var tablebody = TBODY(null, map(makeTableRow, data));
+    
+    var table = TABLE({"class": "data", "id": tableid}, [tablehead, tablebody]);
+    return table;
+}
+
+function generateCanvas(num) {
+    var canvasid = "test" + num + "canvas";
+    var canvas = CANVAS({"id":canvasid, "width": "400", "height": "200"}, "");
+    return canvas
+}
+
+function generateUnitTest(num, func, data, type, desc) {
+    var table = DIV({"class": "data"}, generateTestTable(num, data));
+    var canvas = DIV({"class": "canvas"}, generateCanvas(num));
+    var ending = DIV({"class":"ending"}, desc);
+    
+    addLoadEvent(partial(func, num, type));
+    
+    return DIV({"class": "unit"}, [table, canvas, ending]);
+}
+
+function generateTests() {
+    var tests = $('tests');
+    
+    // datasets 
+    var simpleData1 = [[0, 0], [1, 1], [2, 2], [3, 3]];
+    var simpleData2 = [[1, 2], [2, 3], [3, 4], [4, 5]];
+    var singleData = [[1, 1]];
+
+    var ninety = [[1, 9], [2, 1]];
+    
+    var floatData1 = [[0, 0.5], [1, 0.4], [2, 0.3]];
+    var missingData = [[0, 1], [1, 4], [3, 16], [5, 17]];
+    
+    var dualData = [[0,0,0], [1,2,1], [2,4,4], [3,8,9], [4,16,16], [5,32,25], [6, 64, 36], [7, 128, 49]];
+
+    tests.appendChild(H2(null, "Simple Tests"));
+
+    tests.appendChild(generateUnitTest(1, genericTest, simpleData1,
+    "bar", ""));
+
+    tests.appendChild(generateUnitTest(2, genericTest, simpleData1, 
+    "line", ""));
+
+    tests.appendChild(generateUnitTest(3, genericTest, simpleData2,
+    "pie", ""));
+
+    tests.appendChild(H2(null, "One Value Set"));
+
+    tests.appendChild(generateUnitTest(4, genericTest, singleData,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(5, genericTest, singleData, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(6, genericTest, singleData, 
+    "pie", ""));
+
+    tests.appendChild(H2(null, "Float Values Set"));
+    tests.appendChild(generateUnitTest(7, genericTest, floatData1,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(8, genericTest, floatData1, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(9, genericTest, floatData1, 
+    "pie", ""));    
+
+    tests.appendChild(H2(null, "Dual Value Set"));
+    tests.appendChild(generateUnitTest(10, dualDataSet, dualData,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(11, dualDataSet, dualData, 
+    "line", ""));
+
+    tests.appendChild(H2(null, "Drawing and Clearing"));
+    tests.appendChild(generateUnitTest(12, genericTest, floatData1,
+"bar", ""));    
+    tests.appendChild(generateUnitTest(13, genericTestAndClear, floatData1,
+"bar", ""));
+    tests.appendChild(generateUnitTest(14, genericTest, floatData1,
+    "pie", ""));    
+    tests.appendChild(generateUnitTest(15, genericTestAndClear, floatData1,
+    "pie", ""));        
+
+   tests.appendChild(H2(null, "Testing Circle Drawing"));
+
+    tests.appendChild(generateUnitTest(16, genericTest, ninety,
+    "pie", ""));
+
+}
+
+addLoadEvent(generateTests);
diff --git a/plotkit_v091/tests/debug.html b/plotkit_v091/tests/debug.html
new file mode 100644 (file)
index 0000000..e1ecd8b
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: Debug</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Base.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Layout.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Canvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/SweetCanvas.js" type="text/javascript"></script>
+   
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Debug</h2>
+
+    <div style="margin: 0 auto 0 auto; width: 500px;">
+    <div><canvas id="chart" width="500" height="300"></canvas></div>
+    
+    <script type="text/javascript">
+    var options = {
+       "padding": {left: 20, right: 0, top: 10, bottom: 30},
+       "yAxis": [0, 60]
+    }
+
+    function drawGraph() {
+        var layoutOptions = {
+         "xAxis"         : [1, 4],
+         "xOriginIsZero" : false,
+         "xTicks"        : [ {v: 0}, {v: 1}, {v: 2}, {v: 3}, {v: 4}, {v: 5} ], 
+         "yAxis"         : [1, 4],
+         "yOriginIsZero" : false,
+         "yTicks"        : [ {v: 0}, {v: 1}, {v: 2}, {v: 3}, {v: 4}, {v: 5} ] 
+        };
+        var layout = new PlotKit.Layout("line", layoutOptions);
+        layout.addDataset("myDataset", [ [1, 1], [2, 2], [3, 3], [4, 4] ]);
+        layout.evaluate();
+
+        var canvas = MochiKit.DOM.getElement("chart");
+        var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
+        plotter.render();
+    }
+    MochiKit.DOM.addLoadEvent(drawGraph);
+
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/demo-svg.html b/plotkit_v091/tests/demo-svg.html
new file mode 100644 (file)
index 0000000..1b2c114
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<head>
+       <object id="AdobeSVG" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2"></object>
+   <?import namespace="svg" implementation="#AdobeSVG"?>
+   <title>PlotKit: SVGRenderer Test</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   
+<script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+<script src="/js/plotkit/Base.js" type="text/javascript"></script>
+<script src="/js/plotkit/Layout.js" type="text/javascript"></script>
+<script src="/js/plotkit/SVG.js" type="text/javascript"></script>
+<script src="/js/plotkit-tests/demo-svg.js" type="text/javascript"></script>
+</head>
+
+<body>
+    <div id="body">
+    <h2>PlotKit Demo Page (SVG)</h2>
+    
+    <div id="tests">
+    <table class="matrix">
+      <tr>
+         <td><div><svg:svg id="test1" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test2" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test3" width="220" height="220"></svg:svg></div></td>
+      </tr>       
+      <tr>
+         <td><div><svg:svg id="test4" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test5" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test6" width="220" height="220"></svg:svg></div></td>
+      </tr>       
+      <tr>
+         <td><div><svg:svg id="test7" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test8" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test9" width="220" height="220"></svg:svg></div></td>
+      </tr>       
+      <tr>
+         <td><div><svg:svg id="test10" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test11" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test12" width="220" height="220"></svg:svg></div></td>
+      </tr>       
+      <tr>
+         <td><div><svg:svg id="test13" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test14" width="220" height="220"></svg:svg></div></td>
+         <td><div><svg:svg id="test15" width="220" height="220"></svg:svg></div></td>
+      </tr>       
+
+    </table>
+
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/demo-svg.js b/plotkit_v091/tests/demo-svg.js
new file mode 100644 (file)
index 0000000..2e58a46
--- /dev/null
@@ -0,0 +1,133 @@
+/* actual tests */
+
+function drawDemo(element, layout, options) {
+    var renderer = new PlotKit.SVGRenderer(element, layout, options);
+    renderer.render();
+}
+
+function demoWithStyle(style) {
+    // datasets 
+    var dataset = [
+       [0,1],
+       [1,4],
+       [2,16],
+       [3,8],
+       [4,16],
+       [5,4],
+       [6,1]
+    ];
+
+    var dataset_rev = [
+       [6,0],
+       [5,1],
+       [4,4],
+       [3,9],
+       [2,16],
+       [1,25],
+       [0,36]
+    ];
+
+    var options = {
+        "drawBackground": false,
+        "shouldFill": true,
+        "shouldStroke": true,
+        "drawXAxis": true,
+        "drawYAxis": true,
+        "padding": {left: 40, right: 10, top: 10, bottom: 20},
+        "axisLabelUseDiv": false
+    };
+
+    if (style == "pie") {
+        options["padding"] = {left: 50, right: 50, top: 50, bottom: 50}
+    }
+
+    var layout = new PlotKit.Layout(style, options);
+    layout.addDataset("noname", dataset);
+    layout.evaluate();
+
+    // stroke/fill toggle
+    drawDemo($('test1'),  layout, options);
+    options["shouldFill"] = false;
+    drawDemo($('test2'),  layout, options);
+    options["shouldStroke"] = false;
+    options["shouldFill"] = true;
+    drawDemo($('test3'),  layout, options);
+    
+    // drawing axis
+    options["shouldFill"] = true;
+    options["shouldStroke"] = true;
+    options["drawXAxis"] = false;
+    options["drawYAxis"] = false;
+    drawDemo($('test4'),  layout, options);
+    options["drawXAxis"] = true;
+    drawDemo($('test5'),  layout, options);
+    options["drawYAxis"] = true;
+    options["drawXAxis"] = false;
+    drawDemo($('test6'),  layout, options);    
+
+    // changing background color and axis color
+    options["drawXAxis"] = true;
+    options["colorScheme"] = PlotKit.Base.colorScheme().reverse()
+    drawDemo($('test7'),  layout, options);
+    options["drawBackground"] = true;
+    options["backgroundColor"] = Color.blueColor().lighterColorWithLevel(0.45);
+    drawDemo($('test8'),  layout, options);
+    options["drawBackground"] = false;
+    options["axisLineColor"] = Color.grayColor();
+    options["axisLabelColor"] = Color.grayColor();
+    options["axisLabelFontSize"] = 9;
+    drawDemo($('test9'),  layout, options);    
+
+    // layout customisation
+    options["colorScheme"] = PlotKit.Base.colorScheme();
+    options["axisLineColor"] = Color.blackColor();
+    options["axisLabelColor"] = Color.blackColor();
+    options["axisLabelFontSize"] = 9;
+    options["yNumberOfTicks"] = 3;
+
+    layout.options.yNumberOfTicks = 3;
+    layout.evaluate();
+    drawDemo($('test10'), layout, options);
+
+    layout.options.xNumberOfTicks = 3;
+    layout.evaluate();
+    drawDemo($('test11'), layout, options);
+
+    layout.options.barWidthFillFraction = 0.5;
+    layout.evaluate();
+    drawDemo($('test12'), layout, options);
+       
+
+    // custom labels
+    layout.options.barWidthFillFraction = 0.75;
+    layout.options.yTicks = [{v:10}, {v:20}, {v:30}, {v:40}];
+    layout.evaluate();
+    drawDemo($('test13'), layout, options);
+
+    layout.options.xTicks = [
+            {v:1, label:"one"}, 
+            {v:2, label:"two"}, 
+            {v:3, label:"three"}, 
+            {v:4, label:"four"},
+            {v:5, label:"five"},
+            {v:6, label:"six"}];
+    layout.evaluate();
+    drawDemo($('test14'), layout, options);
+
+    layout.addDataset("reversed", dataset_rev);
+    layout.options.yTicks = null;
+    layout.options.xTicks = null;
+    layout.options.xNumberOfTicks = 10;
+    layout.options.yNumberOfTicks = 5;
+    layout.options.xTicks = null;
+    layout.options.yTicks = null;
+    layout.evaluate();
+    drawDemo($('test15'), layout, options);
+
+}
+
+function demo() {
+    demoWithStyle("bar");
+}
+
+addLoadEvent(demo);
diff --git a/plotkit_v091/tests/demo.html b/plotkit_v091/tests/demo.html
new file mode 100644 (file)
index 0000000..dde591f
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit : Demo</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit/Base.js" type="text/javascript"></script>
+   <script src="/js/plotkit/Layout.js" type="text/javascript"></script>
+   <script src="/js/plotkit/Canvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit/SVG.js" type="text/javascript"></script>
+   <script src="/js/plotkit-tests/demo.js" type="text/javascript"></script>
+</head>
+
+<body>
+    <div id="body">
+    <h2>PlotKit Demo Page</h2>
+    
+    
+
+    <div id="tests">
+    <table class="matrix">
+      <tr>
+         <td><div><canvas id="test1" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test2" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test3" width="220" height="220"></canvas></div></td>
+      </tr>       
+      <tr>
+         <td><div><canvas id="test4" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test5" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test6" width="220" height="220"></canvas></div></td>
+      </tr>       
+      <tr>
+         <td><div><canvas id="test7" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test8" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test9" width="220" height="220"></canvas></div></td>
+      </tr>       
+      <tr>
+         <td><div><canvas id="test10" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test11" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test12" width="220" height="220"></canvas></div></td>
+      </tr>       
+      <tr>
+         <td><div><canvas id="test13" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test14" width="220" height="220"></canvas></div></td>
+         <td><div><canvas id="test15" width="220" height="220"></canvas></div></td>
+      </tr>       
+
+    </table>
+
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/demo.js b/plotkit_v091/tests/demo.js
new file mode 100644 (file)
index 0000000..c43d542
--- /dev/null
@@ -0,0 +1,136 @@
+/* actual tests */
+
+function drawDemo(element, layout, options) {
+    var renderer = new PlotKit.CanvasRenderer(element, layout, options);
+    renderer.render();
+}
+
+function demoWithStyle(style) {
+    // datasets 
+    var dataset = [
+       [0,1],
+       [1,4],
+       [2,16],
+       [3,8],
+       [4,16],
+       [5,4],
+       [6,1]
+    ];
+
+    var dataset_rev = [
+       [6,0],
+       [5,1],
+       [4,4],
+       [3,9],
+       [2,16],
+       [1,25],
+       [0,36]
+    ];
+
+
+    var options = {
+        "IECanvasHTC": "../plotkit/iecanvas.htc",
+        "drawBackground": false,
+        "shouldFill": true,
+        "shouldStroke": true,
+        "drawXAxis": true,
+        "drawYAxis": true,
+        "padding": {left: 40, right: 10, top: 10, bottom: 20},
+        "strokeColor": null,
+        "strokeColorTransform": "asStrokeColor"
+    };
+
+    if (style == "pie") {
+        options["padding"] = {left: 50, right: 50, top: 50, bottom: 50}
+    }
+
+    var layout = new PlotKit.Layout(style, options);
+    layout.addDataset("noname", dataset);
+    layout.evaluate();
+
+    // stroke/fill toggle
+    drawDemo($('test1'),  layout, options);
+    options["shouldFill"] = false;
+    drawDemo($('test2'),  layout, options);
+    options["shouldStroke"] = false;
+    options["shouldFill"] = true;
+    drawDemo($('test3'),  layout, options);
+    
+    // drawing axis
+    options["shouldFill"] = true;
+    options["shouldStroke"] = true;
+    options["drawXAxis"] = false;
+    options["drawYAxis"] = false;
+    drawDemo($('test4'),  layout, options);
+    options["drawXAxis"] = true;
+    drawDemo($('test5'),  layout, options);
+    options["drawYAxis"] = true;
+    options["drawXAxis"] = false;
+    drawDemo($('test6'),  layout, options);    
+
+    // changing background color and axis color
+    options["drawXAxis"] = true;
+    options["colorScheme"] = PlotKit.Base.colorScheme().reverse()
+    drawDemo($('test7'),  layout, options);
+    options["drawBackground"] = true;
+    options["backgroundColor"] = Color.blueColor().lighterColorWithLevel(0.4);
+    drawDemo($('test8'),  layout, options);
+    options["drawBackground"] = false;
+    options["axisLineColor"] = Color.grayColor();
+    options["axisLabelColor"] = Color.grayColor();
+    options["axisLabelFontSize"] = 8;
+    drawDemo($('test9'),  layout, options);    
+
+    // layout customisation
+    options["colorScheme"] = PlotKit.Base.colorScheme();
+    options["axisLineColor"] = Color.blackColor();
+    options["axisLabelColor"] = Color.blackColor();
+    options["axisLabelFontSize"] = 9;
+    options["yNumberOfTicks"] = 3;
+
+    layout.options.yNumberOfTicks = 3;
+    layout.evaluate();
+    drawDemo($('test10'), layout, options);
+
+    layout.options.xNumberOfTicks = 3;
+    layout.evaluate();
+    drawDemo($('test11'), layout, options);
+
+    layout.options.barWidthFillFraction = 0.5;
+    layout.evaluate();
+    drawDemo($('test12'), layout, options);
+       
+
+    // custom labels
+    layout.options.barWidthFillFraction = 0.75;
+    layout.options.yTicks = [{v:10}, {v:20}, {v:30}, {v:40}];
+    layout.evaluate();
+    drawDemo($('test13'), layout, options);
+
+    layout.options.xTicks = [
+            {v:1, label:"one"}, 
+            {v:2, label:"two"}, 
+            {v:3, label:"three"}, 
+            {v:4, label:"four"},
+            {v:5, label:"five"},
+            {v:6, label:"six"}];
+    layout.evaluate();
+    drawDemo($('test14'), layout, options);
+
+    layout.addDataset("reversed", dataset_rev);
+    layout.options.yTicks = null;
+    layout.options.xTicks = null;
+    layout.options.xNumberOfTicks = 10;
+    layout.options.yNumberOfTicks = 5;
+    layout.options.xTicks = null;
+    layout.options.yTicks = null;
+    layout.evaluate();
+    drawDemo($('test15'), layout, options);
+
+}
+
+function demo() {
+    demoWithStyle("pie");
+}
+
+addLoadEvent(demo);
diff --git a/plotkit_v091/tests/dynamic.html b/plotkit_v091/tests/dynamic.html
new file mode 100644 (file)
index 0000000..8a5ad0e
--- /dev/null
@@ -0,0 +1,161 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit : Basic Unit Tests</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+   <style type="text/css">
+   
+   body {
+       font-family: Lucida Grande, Verdana, Sans;
+       font-size: small;
+   }
+   
+    table#datatable td {
+        padding: 2px;        
+    }
+   
+    table#datatable thead td {
+        border-top: 1px solid #e0e0e0;
+        background-color: #d0d0d0;
+        border-bottom: 1px solid #c0c0c0;
+        padding-left: 10px;
+        padding-right: 10px;
+    }
+   
+    table#datatable tbody input {
+        border: 1px solid #eee;
+        padding: 2px;
+        width: 90px;
+    }
+   
+   </style>
+   
+   <script type="text/javascript">
+   
+   var dataTable = null;
+   var layout = null;
+   var renderer = null;
+   var options = null;
+   
+   function initDynamicTable() {
+       dataTable = $('datatable');
+       options = PlotKit.Base.officeBlue();
+       layout = new Layout("line", options);
+       renderer = new SweetCanvasRenderer($('canvasTest'), layout, options);
+   }
+   
+   function newRow() {
+       var tbody = dataTable.tBodies[0];
+       var blankRow = TR({}, [
+                TD({}, INPUT({"class":"xvalue", "size":"6", "type":"text", "value":"0"})),
+                TD({}, INPUT({"class":"yvalue", "size":"6", "type":"text", "value":"0"}))]);
+        tbody.appendChild(blankRow);
+   }
+   
+   function chartReload() {
+        var chartStyleSelected = document.forms["options"].chartStyle.selectedIndex;
+        var chartStyle = document.forms["options"].chartStyle[chartStyleSelected].value;
+
+        var colorSchemeSelected = document.forms["options"].colorScheme.selectedIndex;
+        var colorScheme = document.forms["options"].colorScheme[colorSchemeSelected].value;
+        // grab values
+        var getValue = function(row) {
+           var xElem = MochiKit.DOM.getElementsByTagAndClassName("input", "xvalue", row)[0];
+           var yElem = MochiKit.DOM.getElementsByTagAndClassName("input", "yvalue", row)[0];
+           var xVal = xElem.value;
+           var yVal = yElem.value;
+   
+           if (xVal.length > 0) {
+               xVal = parseFloat(xVal);
+           }
+           else {
+               xVal = 0;
+           }
+   
+           if (yVal.length > 0) {
+               yVal = parseFloat(yVal);
+           }
+           else {
+               yVal = 0;
+           }
+           return [xVal, yVal];
+        }
+       
+        var values = MochiKit.Base.map(getValue, dataTable.tBodies[0].rows);
+
+        // setup layout options
+        var themeName = "office" + colorScheme;
+        var theme = PlotKit.Base[themeName]();
+        MochiKit.Base.update(options, theme);
+                
+        layout.style = chartStyle;
+        MochiKit.Base.update(layout.options, options);
+        MochiKit.Base.update(renderer.options, options);
+                
+        layout.addDataset("data", values);        
+
+        // update
+        layout.evaluate();
+        renderer.clear();
+        renderer.render();
+       
+   }
+   
+   addLoadEvent(initDynamicTable);
+   
+   </script>
+</head>
+
+<body>
+    <div id="body">
+    <h2>PlotKit Dynamic Test</h2>
+    
+    <div style="padding: 20px;">
+        <form name="options">
+            Chart Style: 
+            <select id="chartStyle" name="chartStyle" onChange="chartReload();">
+                <option value="line">Line Chart</option>
+                <option value="bar">Bar Chart</option>
+                <option value="pie">Pie Chart</option>
+            </select>
+            
+            Colors:
+            <select id="colorScheme" name="colorScheme" onChange="chartReload();">
+                <option value="Blue">Blue</option>
+                <option value="Red">Red</option>
+                <option value="Green">Green</option>
+                <option value="Purple">Purple</option>
+                <option value="Cyan">Cyan</option>
+                <option value="Orange">Orange</option>
+            </select>
+            
+            
+        </form>
+    </div>
+    
+    <div style="float: left; width: 250px;">
+        <table id="datatable" cellspacing="0" cellpadding="0">
+            <thead>
+                <tr><td width="100">X</td><td width="100">Y</td></tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td><input class="xvalue" size="6" type="text" value="0"/></td>
+                    <td><input class="yvalue" size="6" type="text" value="0"/></td>                    
+                </tr>
+            </tbody>
+        </table>
+        <div><a href="#" onclick="newRow(); return false;">add new row</a> <a href="#" onclick="chartReload(); return false;">redraw</a></div>
+    </div>
+    <div style="float: left; width: 400px;">
+        <div><canvas id="canvasTest" width="400" height="400" style="border: 1px solid #eee;"></canvas></div>
+    </div>
+
+    <div style="clear: both;">&nbsp;</div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/img/firefox.png b/plotkit_v091/tests/img/firefox.png
new file mode 100644 (file)
index 0000000..d7cc603
Binary files /dev/null and b/plotkit_v091/tests/img/firefox.png differ
diff --git a/plotkit_v091/tests/img/konqueror.png b/plotkit_v091/tests/img/konqueror.png
new file mode 100644 (file)
index 0000000..637751f
Binary files /dev/null and b/plotkit_v091/tests/img/konqueror.png differ
diff --git a/plotkit_v091/tests/img/mozilla.ico b/plotkit_v091/tests/img/mozilla.ico
new file mode 100644 (file)
index 0000000..d444389
Binary files /dev/null and b/plotkit_v091/tests/img/mozilla.ico differ
diff --git a/plotkit_v091/tests/img/msie.gif b/plotkit_v091/tests/img/msie.gif
new file mode 100644 (file)
index 0000000..5101477
Binary files /dev/null and b/plotkit_v091/tests/img/msie.gif differ
diff --git a/plotkit_v091/tests/img/opera.ico b/plotkit_v091/tests/img/opera.ico
new file mode 100644 (file)
index 0000000..0e69e4c
Binary files /dev/null and b/plotkit_v091/tests/img/opera.ico differ
diff --git a/plotkit_v091/tests/img/safari.gif b/plotkit_v091/tests/img/safari.gif
new file mode 100644 (file)
index 0000000..677f423
Binary files /dev/null and b/plotkit_v091/tests/img/safari.gif differ
diff --git a/plotkit_v091/tests/labels-img.html b/plotkit_v091/tests/labels-img.html
new file mode 100644 (file)
index 0000000..3ca8c81
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: Image Labels Example</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Image Labels Example.</h2>
+    
+    <div id="example" style="margin: 0 auto 0 auto;" width="400" height="400"></div>
+    
+    <script type="text/javascript">
+        var data = [[0,0], [1,2], [2,3], [3, 7], [4, 8], [5, 6]];
+        var labels = [
+        {v:0, label:IMG({src:"img/konqueror.png", width:16, height:16})},
+        {v:1, label:IMG({src:"img/opera.ico", width:16, height:16})},
+        {v:2, label:IMG({src:"img/msie.gif", width:16, height:16})},
+        {v:3, label:IMG({src:"img/safari.gif", width:16, height:16})},
+        {v:4, label:IMG({src:"img/firefox.png", width:16,height:16})},
+        {v:5, label:IMG({src:"img/mozilla.ico", width:16, height:16})}
+        ];
+        var plotter = EasyPlot("bar", {"xTicks":labels}, $("example"), 
+        [data, "sample.txt"]);
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/labels.html b/plotkit_v091/tests/labels.html
new file mode 100644 (file)
index 0000000..fedaf6d
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: X Label Demo</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Base.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Layout.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Canvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/SweetCanvas.js" type="text/javascript"></script>
+   
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Label Demo</h2>
+
+    <div style="margin: 0 auto 0 auto; width: 500px;">
+    <div><canvas id="chart" width="500" height="300"></canvas></div>
+    
+    <script type="text/javascript">
+        var xTicks = [{label: "13:00", v: 0}, {label: "14:00", v: 1},
+                      {label: "14:00", v: 2}, {label: "15:00", v: 3},
+                      {label: "16:00", v: 4}];
+        var layout = new Layout("line", {"xTicks": xTicks} );
+        layout.addDataset("yay", [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16]]);
+        layout.addDataset("dataset2", [[0, 4], [1, 3], [2, 3], [3, 1], [4, 8]]);        
+        layout.evaluate();
+        
+        var chart = new SweetCanvasRenderer($("chart"), layout);
+        chart.render();
+
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/prototype_compat.html b/plotkit_v091/tests/prototype_compat.html
new file mode 100644 (file)
index 0000000..7ce3e5a
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: SweetCanvasRenderer Test</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="http://al.tse.id.au/gallery/lightbox/js/prototype.js" type="text/javascript"></script>
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Base.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Layout.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Canvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/SweetCanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-tests/sweet.js" type="text/javascript"></script>
+</head>
+
+<body>
+    <div id="body">
+    <h2>Sweet Canvas Renderer Tests</h2>
+    
+    <div id="tests">
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/quickstart-easy.html b/plotkit_v091/tests/quickstart-easy.html
new file mode 100644 (file)
index 0000000..d4eab21
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: Quickstart Demo</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Quickstart EasyPlot Demo</h2>
+    
+    <div id="example" style="margin: 0 auto 0 auto;" width="400" height="400"></div>
+    
+    <script type="text/javascript">
+        var data = [[0,0], [1,2], [2,3], [3, 7], [4, 8], [5, 6]];
+        var plotter = EasyPlot("line", {}, $("example"), [data, "sample.txt"]);
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/quickstart-horiz.html b/plotkit_v091/tests/quickstart-horiz.html
new file mode 100644 (file)
index 0000000..76d67b0
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: Quickstart Demo</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+  
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>   
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Quickstart Demo</h2>
+    
+    <div style="margin: 0 auto 0 auto; width: 500px;">
+    <div><canvas id="chart" width="500" height="300"></canvas></div>
+
+    <br/>
+    
+    <table id="values" class="data">
+        <thead>
+            <tr><td>x</td><td>y1</td><td>y2</td></tr>
+        </thead>
+        <tbody>
+            <tr><td>0</td><td>0</td><td>3</td></tr>
+            <tr><td>1</td><td>10</td><td>20</td></tr>
+            <tr><td>2</td><td>5</td><td>10</td></tr>
+            <tr><td>3</td><td>6</td><td>7</td></tr>
+            <tr><td>4</td><td>7</td><td>8</td></tr>
+            <tr><td>5</td><td>6</td><td>7</td></tr>
+            <tr><td>6</td><td>7</td><td>8</td></tr>            
+        </tbody>
+    </table>
+    
+    <script type="text/javascript">
+        var layout = new Layout("bar", {"barOrientation": "horizontal"});
+        layout.addDatasetFromTable("dataset2", $("values"), xcol = 0, ycol = 2);        
+        layout.addDatasetFromTable("dataset1", $("values"), xcol = 0, ycol = 1);
+        layout.evaluate();
+        
+        var chart = new SweetCanvasRenderer($("chart"), layout);
+        chart.render();
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/quickstart-neg.html b/plotkit_v091/tests/quickstart-neg.html
new file mode 100644 (file)
index 0000000..18b65b1
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: Quickstart Demo</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Quickstart EasyPlot Demo</h2>
+    
+    <div id="example" style="margin: 0 auto 0 auto;" width="400" height="400"></div>
+    
+    <script type="text/javascript">
+        var data = [[0,0], [1,-2], [2,3], [3, -7], [4, 8], [5, -6]];
+        var plotter = EasyPlot("line", {yOriginIsZero: false}, $("example"), [data]);
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/quickstart-svg.html b/plotkit_v091/tests/quickstart-svg.html
new file mode 100644 (file)
index 0000000..1d742a0
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html
+xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
+xmlns:svg="http://www.w3.org/2000/svg"
+xmlns:xlink="http://www.w3.org/1999/xlink">
+<head>        
+   <object id="AdobeSVG" width="1" height="1" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2"></object>
+   <?import namespace="svg" implementation="#AdobeSVG"?>
+   <title>PlotKit: Quickstart SVG Demo</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+</head>
+
+<body>
+    <div id="body">
+    <h2>Quickstart SVG Demo</h2>
+    
+    <div style="margin: 0 auto 0 auto; width: 500px;">
+    <div id="svgcontainer" style="width: 500px; height:300px;"></div>
+    <br/>
+    
+    <table id="values" class="data">
+        <thead>
+            <tr><td>x</td><td>y1</td><td>y2</td></tr>
+        </thead>
+        <tbody>
+            <tr><td>0</td><td>0</td><td>3</td></tr>
+            <tr><td>1</td><td>10</td><td>20</td></tr>
+            <tr><td>2</td><td>5</td><td>10</td></tr>
+            <tr><td>3</td><td>6</td><td>7</td></tr>
+            <tr><td>4</td><td>7</td><td>8</td></tr>
+            <tr><td>5</td><td>6</td><td>7</td></tr>
+            <tr><td>6</td><td>7</td><td>8</td></tr>            
+        </tbody>
+    </table>
+    
+    <p><em>Note: With SVG, the most compatible way is NOT to put in SVG tags, but create the SVG element with Javascript. Therefore, instead of adding &lt;svg&gt; tag, we just have a &lt;div&gt; container and create the SVG element using SVGRenderer.SVG().</em></p>
+    
+    <script type="text/javascript">
+        var layout = new Layout("line");
+        layout.addDatasetFromTable("dataset2", $("values"), xcol = 0, ycol = 2);        
+        layout.addDatasetFromTable("dataset1", $("values"), xcol = 0, ycol = 1);
+        layout.evaluate();
+        
+        var svg = SVGRenderer.SVG({"width": 500, "height": 300, "id":"chart"});
+        $('svgcontainer').appendChild(svg);
+        var chart = new SweetSVGRenderer(svg, layout);
+        chart.render();
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/quickstart.html b/plotkit_v091/tests/quickstart.html
new file mode 100644 (file)
index 0000000..f0e6176
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: Quickstart Demo</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Base.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Layout.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/Canvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/SweetCanvas.js" type="text/javascript"></script>
+   
+</head>
+
+
+<body>
+    <div id="body">
+    <h2>Quickstart Demo</h2>
+    
+    <div style="margin: 0 auto 0 auto; width: 500px;">
+    <div><canvas id="chart" width="500" height="300"></canvas></div>
+
+    <br/>
+    
+    <table id="values" class="data">
+        <thead>
+            <tr><td>x</td><td>y1</td><td>y2</td></tr>
+        </thead>
+        <tbody>
+            <tr><td>0</td><td>0</td><td>3</td></tr>
+            <tr><td>1</td><td>10</td><td>20</td></tr>
+            <tr><td>2</td><td>5</td><td>10</td></tr>
+            <tr><td>3</td><td>6</td><td>7</td></tr>
+            <tr><td>4</td><td>7</td><td>8</td></tr>
+            <tr><td>5</td><td>6</td><td>7</td></tr>
+            <tr><td>6</td><td>7</td><td>8</td></tr>            
+        </tbody>
+    </table>
+    
+    <script type="text/javascript">
+        var layout = new Layout("line");
+        layout.addDatasetFromTable("dataset2", $("values"), xcol = 0, ycol = 2);        
+        layout.addDatasetFromTable("dataset1", $("values"), xcol = 0, ycol = 1);
+        layout.evaluate();
+        
+        var chart = new SweetCanvasRenderer($("chart"), layout);
+        chart.render();
+
+    </script>
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/sample.txt b/plotkit_v091/tests/sample.txt
new file mode 100644 (file)
index 0000000..1703e81
--- /dev/null
@@ -0,0 +1,6 @@
+0,0
+1,1
+2,4
+3,8
+4,7
+5,8
diff --git a/plotkit_v091/tests/svg-sweet.html b/plotkit_v091/tests/svg-sweet.html
new file mode 100644 (file)
index 0000000..46faa75
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<head>
+<title>PlotKit: SVGRenderer Test</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link href="/css/page.css" media="screen" rel="Stylesheet" type="text/css" />
+<link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+<script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+<script src="/js/plotkit/Base.js" type="text/javascript"></script>
+<script src="/js/plotkit/Layout.js" type="text/javascript"></script>
+<script src="/js/plotkit/SVG.js" type="text/javascript"></script>
+<script src="/js/plotkit/SweetSVG.js" type="text/javascript"></script>
+<script src="/js/plotkit-tests/svg-sweet.js" type="text/javascript"></script>
+
+<!-- START Required for IE to support  inlined SVG -->
+<object id="AdobeSVG" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2" width="1" height="1"></object>
+<?import namespace="svg" implementation="#AdobeSVG"?>
+<!-- END   Required for IE to support inlined SVG -->
+
+</head>
+
+<body>
+    <div id="body">
+    <h2>SVG Renderer Tests</h2>
+    <div id="tests"></div>
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/svg-sweet.js b/plotkit_v091/tests/svg-sweet.js
new file mode 100644 (file)
index 0000000..f08f59e
--- /dev/null
@@ -0,0 +1,141 @@
+/* actual tests */
+
+var options = {
+    "axisLabelUseDiv": false
+};
+MochiKit.Base.update(options, PlotKit.Base.officeBlue());
+
+
+function genericTest(num, plotStyle) {
+    var l = new PlotKit.Layout(plotStyle, {});
+    var success = l.addDatasetFromTable("data" + num, $("test" + num));
+    l.evaluate();
+    var c = $("test" + num + "canvas");
+    var g = new PlotKit.SweetSVGRenderer(c, l, options);
+    g.render();
+}
+
+function genericTestAndClear(num, plotStyle) {
+    var l = new PlotKit.Layout(plotStyle, {});
+    l.addDatasetFromTable("data" + num, $("test" + num));   
+    l.evaluate();
+    var c = $("test" + num + "canvas");
+    var g = new PlotKit.SweetSVGRenderer(c, l, options);
+    g.render();
+    g.clear();
+}
+
+function dualDataSet(num, plotStyle) {
+    var l = new PlotKit.Layout(plotStyle, {});
+    l.addDatasetFromTable("data1." + num, $("test" + num), 0, 1);   
+    l.addDatasetFromTable("data2." + num, $("test" + num), 0, 2);   
+    l.evaluate();
+    var c = $("test" + num + "canvas");
+    var g = new PlotKit.SweetSVGRenderer(c, l, options);
+    g.render();
+}
+
+
+/* create HTML for tests */
+
+function makeTableRow(list) {
+    return TR({}, map(partial(TD, null), list));
+}
+
+function generateTestTable(num, data) {
+    var tableid = "test" + num;
+    var tablehead = THEAD(null, map(makeTableRow, [["x", "y"]]));
+    var tablebody = TBODY(null, map(makeTableRow, data));
+    
+    var table = TABLE({"class": "data", "id": tableid}, [tablehead, tablebody]);
+    return table;
+}
+
+function generateCanvas(num) {
+    var canvasid = "test" + num + "canvas";
+    var canvasopts = {
+        "id": canvasid,
+        "width": 400,
+        "height": 200,
+        "version": "1.1",
+        "baseProfile": "full"
+    };
+
+    var canvas = PlotKit.SVGRenderer.SVG(canvasopts, "");
+    return canvas
+}
+
+function generateUnitTest(num, func, data, type, desc) {
+    var table = DIV({"class": "data"}, generateTestTable(num, data));
+    var canvas = DIV({"class": "canvas"}, generateCanvas(num));
+    var ending = DIV({"class":"ending"}, desc);
+    
+    addLoadEvent(partial(func, num, type));
+    
+    return DIV({"class": "unit"}, [table, canvas, ending]);
+    return DIV({"class": "unit"}, [table, ending]);
+}
+
+function generateTests() {
+    var tests = $('tests');
+
+    // datasets 
+    var simpleData1 = [[0, 0], [1, 1], [2, 2], [3, 3]];
+    var simpleData2 = [[1, 2], [2, 3], [3, 4], [4, 5]];
+    var singleData = [[1, 1]];
+
+    var ninety = [[1, 9], [2, 1]];
+
+    var floatData1 = [[0, 0.5], [1, 0.4], [2, 0.3]];
+    var missingData = [[0, 1], [1, 4], [3, 16], [5, 17]];
+
+    var dualData = [[0,0,0], [1,2,1], [2,4,4], [3,8,9], [4,16,16], [5,32,25], [6, 64, 36], [7, 128, 49]];
+
+    tests.appendChild(H2(null, "Simple Tests"));
+
+    tests.appendChild(generateUnitTest(1, genericTest, simpleData1, "bar", ""));
+    tests.appendChild(generateUnitTest(2, genericTest, simpleData1, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(3, genericTest, simpleData2,
+    "pie", ""));
+
+    tests.appendChild(H2(null, "One Value Set"));
+
+    tests.appendChild(generateUnitTest(4, genericTest, singleData,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(5, genericTest, singleData, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(6, genericTest, singleData, 
+    "pie", ""));
+
+    tests.appendChild(H2(null, "Float Values Set"));
+    tests.appendChild(generateUnitTest(7, genericTest, floatData1,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(8, genericTest, floatData1, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(9, genericTest, floatData1, 
+    "pie", ""));    
+
+    tests.appendChild(H2(null, "Dual Value Set"));
+    tests.appendChild(generateUnitTest(10, dualDataSet, dualData,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(11, dualDataSet, dualData, 
+    "line", ""));
+
+    tests.appendChild(H2(null, "Drawing and Clearing"));
+    tests.appendChild(generateUnitTest(12, genericTest, floatData1,
+    "bar", ""));    
+    tests.appendChild(generateUnitTest(13, genericTestAndClear, floatData1,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(14, genericTest, floatData1,
+    "pie", ""));    
+    tests.appendChild(generateUnitTest(15, genericTestAndClear, floatData1,
+    "pie", ""));
+    
+    tests.appendChild(H2(null, "Testing Circle Drawing"));
+
+     tests.appendChild(generateUnitTest(16, genericTest, ninety,
+     "pie", ""));
+}
+
+addLoadEvent(generateTests);
diff --git a/plotkit_v091/tests/svg.html b/plotkit_v091/tests/svg.html
new file mode 100644 (file)
index 0000000..cc8ac7a
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<head>
+<title>PlotKit: SVGRenderer Test</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link href="/css/page.css" media="screen" rel="Stylesheet" type="text/css" />
+<link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+<script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+<script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+<script src="/js/plotkit-tests/svg.js" type="text/javascript"></script>
+
+<!-- START Required for IE to support  inlined SVG -->
+<object id="AdobeSVG" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2" width="1" height="1"></object>
+<?import namespace="svg" implementation="#AdobeSVG"?>
+<!-- END   Required for IE to support inlined SVG -->
+
+</head>
+
+<body>
+    <div id="body">
+    <h2>SVG Renderer Tests</h2>
+    <div id="tests"></div>
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/svg.js b/plotkit_v091/tests/svg.js
new file mode 100644 (file)
index 0000000..45dae8b
--- /dev/null
@@ -0,0 +1,147 @@
+/* actual tests */
+
+var options = {
+    "axisLineWidth": 2.0,
+    "axisLabelColor": Color.grayColor(),
+    "axisLineColor": Color.blackColor(),
+    "padding": {top: 5, bottom: 20, left: 40, right: 10},
+    "backgroundColor": Color.whiteColor(),
+    "strokeColor": null,
+    "axisLabelUseDiv": false
+};
+
+function genericTest(num, plotStyle) {
+    var l = new PlotKit.Layout(plotStyle, {});
+    var success = l.addDatasetFromTable("data" + num, $("test" + num));
+    l.evaluate();
+    var c = $("test" + num + "canvas");
+    var g = new PlotKit.SVGRenderer(c, l, options);
+    g.render();
+}
+
+function genericTestAndClear(num, plotStyle) {
+    var l = new PlotKit.Layout(plotStyle, {});
+    l.addDatasetFromTable("data" + num, $("test" + num));   
+    l.evaluate();
+    var c = $("test" + num + "canvas");
+    var g = new PlotKit.SVGRenderer(c, l, {});
+    g.render();
+    g.clear();
+}
+
+function dualDataSet(num, plotStyle) {
+    var l = new PlotKit.Layout(plotStyle, {});
+    l.addDatasetFromTable("data1." + num, $("test" + num), 0, 1);   
+    l.addDatasetFromTable("data2." + num, $("test" + num), 0, 2);   
+    l.evaluate();
+    var c = $("test" + num + "canvas");
+    var g = new PlotKit.SVGRenderer(c, l, options);
+    g.render();
+}
+
+
+/* create HTML for tests */
+
+function makeTableRow(list) {
+    return TR({}, map(partial(TD, null), list));
+}
+
+function generateTestTable(num, data) {
+    var tableid = "test" + num;
+    var tablehead = THEAD(null, map(makeTableRow, [["x", "y"]]));
+    var tablebody = TBODY(null, map(makeTableRow, data));
+    
+    var table = TABLE({"class": "data", "id": tableid}, [tablehead, tablebody]);
+    return table;
+}
+
+function generateCanvas(num) {
+    var canvasid = "test" + num + "canvas";
+    var canvasopts = {
+        "id": canvasid,
+        "width": 400,
+        "height": 200,
+        "version": "1.1",
+        "baseProfile": "full"
+    };
+
+    var canvas = PlotKit.SVGRenderer.SVG(canvasopts, "");
+    return canvas
+}
+
+function generateUnitTest(num, func, data, type, desc) {
+    var table = DIV({"class": "data"}, generateTestTable(num, data));
+    var canvas = DIV({"class": "canvas"}, generateCanvas(num));
+    var ending = DIV({"class":"ending"}, desc);
+    
+    addLoadEvent(partial(func, num, type));
+    
+    return DIV({"class": "unit"}, [table, canvas, ending]);
+    return DIV({"class": "unit"}, [table, ending]);
+}
+
+function generateTests() {
+    var tests = $('tests');
+
+    // datasets 
+    var simpleData1 = [[0, 0], [1, 1], [2, 2], [3, 3]];
+    var simpleData2 = [[1, 2], [2, 3], [3, 4], [4, 5]];
+    var singleData = [[1, 1]];
+
+    var ninety = [[1, 9], [2, 1]];
+
+    var floatData1 = [[0, 0.5], [1, 0.4], [2, 0.3]];
+    var missingData = [[0, 1], [1, 4], [3, 16], [5, 17]];
+
+    var dualData = [[0,0,0], [1,2,1], [2,4,4], [3,8,9], [4,16,16], [5,32,25], [6, 64, 36], [7, 128, 49]];
+
+    tests.appendChild(H2(null, "Simple Tests"));
+
+    tests.appendChild(generateUnitTest(1, genericTest, simpleData1, "bar", ""));
+
+    tests.appendChild(generateUnitTest(2, genericTest, simpleData1, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(3, genericTest, simpleData2,
+    "pie", ""));
+
+    tests.appendChild(H2(null, "One Value Set"));
+
+    tests.appendChild(generateUnitTest(4, genericTest, singleData,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(5, genericTest, singleData, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(6, genericTest, singleData, 
+    "pie", ""));
+
+    tests.appendChild(H2(null, "Float Values Set"));
+    tests.appendChild(generateUnitTest(7, genericTest, floatData1,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(8, genericTest, floatData1, 
+    "line", ""));
+    tests.appendChild(generateUnitTest(9, genericTest, floatData1, 
+    "pie", ""));    
+
+    tests.appendChild(H2(null, "Dual Value Set"));
+    tests.appendChild(generateUnitTest(10, dualDataSet, dualData,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(11, dualDataSet, dualData, 
+    "line", ""));
+
+    tests.appendChild(H2(null, "Drawing and Clearing"));
+    tests.appendChild(generateUnitTest(12, genericTest, floatData1,
+    "bar", ""));    
+    tests.appendChild(generateUnitTest(13, genericTestAndClear, floatData1,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(14, genericTest, floatData1,
+    "pie", ""));    
+    tests.appendChild(generateUnitTest(15, genericTestAndClear, floatData1,
+    "pie", ""));
+    
+    tests.appendChild(H2(null, "Testing Circle Drawing"));
+
+     tests.appendChild(generateUnitTest(16, genericTest, ninety,
+     "pie", ""));
+
+}
+
+addLoadEvent(generateTests);
diff --git a/plotkit_v091/tests/sweet.html b/plotkit_v091/tests/sweet.html
new file mode 100644 (file)
index 0000000..9e7685b
--- /dev/null
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <title>PlotKit: SweetCanvasRenderer Test</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet"
+   type="text/css" />
+   <link href="tests.css" media="screen" rel="Stylesheet" type="text/css" />
+   <script src="/js/mochi/MochiKit.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/excanvas.js" type="text/javascript"></script>
+   <script src="/js/plotkit-svn/PlotKit_Packed.js" type="text/javascript"></script>
+   <script src="/js/plotkit-tests/sweet.js" type="text/javascript"></script>
+</head>
+
+<body>
+    <div id="body">
+    <h2>Sweet Canvas Renderer Tests</h2>
+    
+    <div id="tests">
+    </div>
+    
+    <div class="footer"><a href="http://www.liquidx.net/plotkit/">PlotKit</a></div>    
+</div>
+</body></html>
diff --git a/plotkit_v091/tests/sweet.js b/plotkit_v091/tests/sweet.js
new file mode 100644 (file)
index 0000000..44e174c
--- /dev/null
@@ -0,0 +1,89 @@
+/* actual tests */
+
+var opts = {
+    "enableEvents": false
+};
+
+function genericTest(num, plotStyle) {
+       var l = new PlotKit.Layout(plotStyle, {});
+       var success = l.addDatasetFromTable("data" + num, $("test" + num));
+       l.evaluate();
+       var c = $("test" + num + "canvas");
+       var g = new PlotKit.SweetCanvasRenderer(c, l, opts);
+       g.render();
+}
+
+function dualDataSet(num, plotStyle) {
+       var l = new PlotKit.Layout(plotStyle, {});
+       l.addDatasetFromTable("data1." + num, $("test" + num), 0, 1);   
+       l.addDatasetFromTable("data2." + num, $("test" + num), 0, 2);   
+       l.evaluate();
+       var c = $("test" + num + "canvas");
+       var g = new PlotKit.SweetCanvasRenderer(c, l, opts);
+       g.render();
+}
+
+
+/* create HTML for tests */
+
+function makeTableRow(list) {
+    return TR({}, map(partial(TD, null), list));
+}
+
+function generateTestTable(num, data) {
+    var tableid = "test" + num;
+    var tablehead = THEAD(null, map(makeTableRow, [["x", "y"]]));
+    var tablebody = TBODY(null, map(makeTableRow, data));
+    
+    var table = TABLE({"class": "data", "id": tableid}, [tablehead, tablebody]);
+    return table;
+}
+
+function generateCanvas(num) {
+    var canvasid = "test" + num + "canvas";
+    var canvas = CANVAS({"id":canvasid, "width": "400", "height": "200"}, "");
+    return canvas
+}
+
+function generateUnitTest(num, func, data, type, desc) {
+    var table = DIV({"class": "data"}, generateTestTable(num, data));
+    var canvas = DIV({"class": "canvas"}, generateCanvas(num));
+    var ending = DIV({"class":"ending"}, desc);
+    
+    addLoadEvent(partial(func, num, type));
+    
+    return DIV({"class": "unit"}, [table, canvas, ending]);
+    
+}
+
+function generateTests() {
+    var tests = $('tests');
+    
+    // datasets 
+    var simpleData1 = [[0, 0], [1, 1], [2, 2], [3, 3]];
+    var simpleData2 = [[1, 2], [2, 3], [3, 4], [4, 5]];
+    var singleData = [[1, 1]];
+    
+    var floatData1 = [[0, 0.5], [1, 0.4], [2, 0.3]];
+    var missingData = [[0, 1], [1, 4], [3, 16], [5, 17]];
+    
+    var dualData = [[0,0,0], [1,2,1], [2,4,4], [3,8,9], [4,16,16], [5,32,25], [6, 64, 36], [7, 128, 49]];
+
+    tests.appendChild(H2(null, "Simple Tests"));
+
+    tests.appendChild(generateUnitTest(1, genericTest, simpleData1,
+    "bar", ""));
+    tests.appendChild(generateUnitTest(2, dualDataSet, dualData,
+    "bar", ""));
+
+    tests.appendChild(generateUnitTest(3, genericTest, simpleData1,
+    "line", ""));
+    tests.appendChild(generateUnitTest(4, dualDataSet, dualData,
+    "line", ""));
+    
+    tests.appendChild(generateUnitTest(5, genericTest, simpleData1,
+    "pie", ""));
+
+}
+
+addLoadEvent(generateTests);
diff --git a/plotkit_v091/tests/tests.css b/plotkit_v091/tests/tests.css
new file mode 100644 (file)
index 0000000..2816106
--- /dev/null
@@ -0,0 +1,66 @@
+table#dynamicTable {
+    margin: 10px auto 10px auto;
+}
+
+table.data td {
+    margin: 5px;
+    padding: 5px;
+    width: 50px;
+}
+
+table.data thead td {
+    background-color: #eee;
+}
+
+table.data thead th {
+    background-color: #eee;
+    border-bottom: 1px solid #ddd;
+    padding: 5px;
+    text-align: left;
+}
+
+table.data tbody td {
+    padding: 5px;
+    vertical-align: top;
+    text-align: left;
+    border-bottom: 1px solid #eee;
+}
+
+table.data {
+    width: 200px;
+}
+
+.center {
+    margin-left: auto;
+    margin-right: auto;
+}
+
+h3 {
+    font-size: large;
+    color: #666;
+    background-color: #eee;
+    border-bottom: 1px solid #ddd;
+    padding: 3px;
+}
+
+h4 {
+    font-size: medium;
+    margin: 5px;
+}
+
+div.data, div.canvas {
+    float: left;
+    margin: 5px;
+}
+
+div.ending {
+    clear: both;
+    margin: 10px;
+}
+
+div.unit {
+    border: 1px solid #eee;
+    margin: 10px;
+    padding: 10px;
+}
+
diff --git a/plotkit_v091/tests/testsvg.html b/plotkit_v091/tests/testsvg.html
new file mode 100644 (file)
index 0000000..008d669
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<head>
+       <object id="AdobeSVG" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2"></object>
+   <?import namespace="svg" implementation="#AdobeSVG"?>
+   <title>SVG Test</title>
+   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+   <link href="/css/page.css" media="screen" rel="Stylesheet" type="text/css" />
+
+   
+<script src="testsvg.js" type="text/javascript"></script>
+<script type="text/javascript">
+alert(testsvg());
+</script>
+</head>
+
+<body>
+</body>
+</html>
diff --git a/plotkit_v091/tests/testsvg.js b/plotkit_v091/tests/testsvg.js
new file mode 100644 (file)
index 0000000..3bcd3ef
--- /dev/null
@@ -0,0 +1,31 @@
+function testsvg() {
+    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/);
+    
+
+    if (ieVersion && (ieVersion[1] >= 6) && !isOpera) {
+        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;
+        }
+    }
+    
+    if (safariVersion && (safariVersion[1] > 419))
+        return true;
+
+    if (operaVersion && (operaVersion[1] > 8.9))
+        return true
+    
+    if (mozillaVersion && (mozillaVersion > 1.7))
+        return true;
+    
+    return false;
+}
\ No newline at end of file
diff --git a/test.html b/test.html
new file mode 100644 (file)
index 0000000..a7cfde1
--- /dev/null
+++ b/test.html
@@ -0,0 +1,152 @@
+<!-- This file serves as a test case for most of the dynamic graphs code -->
+<html>
+<head>
+
+<!-- The packed versions are fine, I just use these for more meaningful error messages -->
+<script type="text/javascript" src="mochikit_v14/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="plotkit_v091/PlotKit/PlotKit.js"></script>
+<script type="text/javascript" src="plotkit_v091/PlotKit/Base.js"></script>
+<script type="text/javascript" src="plotkit_v091/PlotKit/Layout.js"></script>
+<script type="text/javascript" src="plotkit_v091/PlotKit/Canvas.js"></script>
+
+<script type="text/javascript" src="dygraph-canvas.js"></script>
+<script type="text/javascript" src="dygraph.js"></script>
+
+<!--
+<script type="text/javascript" src="dygraph-combined.js"></script>
+-->
+<script type="text/javascript" src="data.js"></script>
+
+<!-- Test page load time -->
+<script type="text/javascript">
+var start_time = (new Date()).getTime();
+setTimeout("testLoadTime();", 0);
+function testLoadTime() {
+  var clock = new Date();
+  try {
+    document.getElementById('loadingtime').innerHTML =
+      "Loading time: " + (clock.getTime() - start_time) + "ms";
+  } catch(e) {
+    setTimeout("testLoadTime();", 100);
+  }
+}
+
+function addGraphs() {
+  g2 = new DateGraph(
+          document.getElementById("graphdiv2"),
+          function() {
+            var r = "date,parabola,line,another line,sine wave\n";
+            for (var i=1; i<=31; i++) {
+            r += "" + i;
+            r += "," + 10*(i*(31-i));
+            r += "," + 10*(8*i);
+            r += "," + 10*(250 - 8*i);
+            r += "," + 10*(125 + 125 * Math.sin(0.3*i));
+            r += "\n";
+            }
+            return r;
+          },
+          null,
+          {
+            labelsDiv: document.getElementById('status2'),
+            labelsSeparateLines: true,
+            labelsKMB: true,
+            colors: ["hsl(180,60,50)",
+                     "rgb(255,100,100)",
+                     "#00DD55",
+                     "rgba(50,50,200,0.4)"],
+            padding: {left: 40, right: 30, top: 5, bottom: 15},
+            xValueParser: function(x) { return parseFloat(x); },
+            xValueFormatter: function(x) { return x; },
+            xTicker: DateGraph.prototype.numericTicks
+          }
+      );
+
+  var end_time = (new Date('11/01/2006')).valueOf();
+  var sixmonths = 366 / 2 * 24 * 60 * 60 * 1000;
+
+  g = new DateGraph(
+      document.getElementById("graphdiv1"),
+      StubbedData,
+      null,  // Labels are taken from the series themselves.
+      { errorBars: true,
+        rollPeriod: 7,
+        minTickSize: 1,
+        dateWindow: [end_time - sixmonths, end_time]});
+
+  g3 = new DateGraph(
+      document.getElementById('fractiongraph'),
+      function() {
+      return "date,fraction1,fraction2\n" +
+             "20080701,2/18,41/1200\n" +
+             "20080702,1/13,43/1200\n" +
+             "20080703,2/18,48/1200\n" +
+             "20080704,3/21,42/1200\n" +
+             "20080705,5/29,57/1200\n" +
+             "20080706,0/20,42/1200\n" +
+             "20080707,4/14,43/1200\n" +
+             "20080708,1/20,37/1200\n" +
+             "20080709,1/19,53/1200\n" +
+             "20080710,4/22,42/1200\n" +
+             "20080711,3/24,57/1200\n" +
+             "20080712,8/27,58/1200\n" +
+             "20080713,0/14,43/1200\n" +
+             "20080714,0/17,39/1200\n" +
+             "20080715,2/11,49/1200\n" +
+             "20080716,1/17,48/1200\n" +
+             "20080717,6/25,43/1200\n" +
+             "20080718,2/21,43/1200\n" +
+             "20080719,3/24,58/1200\n" +
+             "20080720,4/25,50/1200\n" +
+             "20080721,1/5,3/166\n";
+      },
+      null,
+      {
+        errorBars: true,
+        rollPeriod: 7,
+        fractions: true,
+      });
+}
+</script>
+
+</head>
+<body>
+<p>Sample graph with multiple series/error bars. Mouse over to see specific
+points and change the "7" in the text to adjust the averaging period. Click and
+drag to zoom in on a region, or double-click to zoom out.</p>
+
+<div id="graphdiv1" style="width:800px; height:500px;">
+</div>
+
+<p>Another chart without error bars:</p>
+<table><tr><td>
+<div id="graphdiv2" style="width:480px;height:320px;"></div>
+</td><td valign=top>
+<div id="status2" style="width:200px; font-size:0.8em"></div>
+</td>
+</tr></table>
+
+<input type=button value="change"
+onClick="javascript:g2.updateOptions({
+  file: StubbedData,
+  errorBars: true,
+  labels: null
+});" />
+
+<input type=button value="zoom"
+onClick="javascript:g2.updateOptions({
+dateWindow: [(new Date('10/10/2006')).valueOf(),
+             (new Date('10/20/2006')).valueOf()],
+});" />
+
+<h3>Fraction graph</h3>
+<div id=fractiongraph style="width:480px; height:320px;"></div>
+
+<script defer>
+setTimeout("addGraphs();", 100);
+</script>
+
+<font size=-1><i><div id="loadingtime">loading time</div></i></font>
+
+</body>
+</html>