[Moksha-commits] 32 commits - AUTHORS docs/conf.py docs/_templates MANIFEST.in moksha/api moksha/apps moksha/controllers moksha/hub moksha/__init__.py moksha/lib moksha/middleware moksha.spec moksha/streams moksha/widgetbrowser moksha/widgets moksha/wsgiapp.py pavement.py production/apache setup.py

Luke Macken lmacken at fedoraproject.org
Sun Aug 9 06:00:28 UTC 2009


 AUTHORS                                                                                          |    2 
 MANIFEST.in                                                                                      |    2 
 dev/null                                                                                         |binary
 docs/_templates/indexcontent.html                                                                |    2 
 docs/conf.py                                                                                     |    8 
 moksha.spec                                                                                      |   11 
 moksha/__init__.py                                                                               |   15 
 moksha/api/menus/__init__.py                                                                     |   18 
 moksha/api/menus/controllers/__init__.py                                                         |   17 
 moksha/api/menus/controllers/menu.py                                                             |   43 
 moksha/api/menus/default.py                                                                      |  104 
 moksha/api/menus/static/GPL-LICENSE.txt                                                          |  279 
 moksha/api/menus/static/css/menu.css                                                             |  195 
 moksha/api/menus/static/css/menu1.css                                                            |  198 
 moksha/api/menus/static/mbMenu.js                                                                |  476 -
 moksha/api/menus/static/mbMenu.min.js                                                            |    1 
 moksha/api/menus/static/styleswitch.js                                                           |   55 
 moksha/api/menus/templates/mbmenu.mak                                                            |   19 
 moksha/api/menus/widgets.py                                                                      |  144 
 moksha/apps/chat/MANIFEST.in                                                                     |    1 
 moksha/apps/chat/moksha/__init__.py                                                              |    1 
 moksha/apps/chat/moksha/apps/chat/__init__.py                                                    |   17 
 moksha/apps/chat/moksha/apps/chat/chat.py                                                        |   50 
 moksha/apps/chat/moksha/apps/chat/controllers/__init__.py                                        |   17 
 moksha/apps/chat/moksha/apps/chat/controllers/chat.py                                            |  114 
 moksha/apps/chat/moksha/apps/chat/static/chat.css                                                |  119 
 moksha/apps/chat/moksha/apps/chat/static/chrome.js                                               |   83 
 moksha/apps/chat/moksha/apps/chat/static/gui.js                                                  |  215 
 moksha/apps/chat/moksha/apps/chat/static/index.html                                              |   48 
 moksha/apps/chat/moksha/apps/chat/static/irc2.js                                                 |  224 
 moksha/apps/chat/moksha/apps/chat/static/style.css                                               |  153 
 moksha/apps/chat/moksha/apps/chat/static/themes/dojo/chrome.js                                   |   83 
 moksha/apps/chat/moksha/apps/chat/static/themes/dojo/gui.js                                      |   19 
 moksha/apps/chat/moksha/apps/chat/static/themes/dojo/index.html                                  |  226 
 moksha/apps/chat/moksha/apps/chat/static/themes/dojo/style.css                                   |  151 
 moksha/apps/chat/moksha/apps/chat/static/themes/simple/chrome.js                                 |   83 
 moksha/apps/chat/moksha/apps/chat/static/themes/simple/gui.js                                    |  216 
 moksha/apps/chat/moksha/apps/chat/static/themes/simple/index.html                                |   58 
 moksha/apps/chat/moksha/apps/chat/static/themes/simple/style.css                                 |  151 
 moksha/apps/chat/moksha/apps/chat/static/willowchat.js                                           |  337 
 moksha/apps/chat/moksha/apps/chat/templates/bootstrap.mak                                        |  419 +
 moksha/apps/chat/moksha/apps/chat/templates/chat.mak                                             |   31 
 moksha/apps/chat/pavement.py                                                                     |   33 
 moksha/apps/demo/streams/__init__.py                                                             |   17 
 moksha/apps/demo/streams/demostream.py                                                           |  106 
 moksha/apps/docs/MANIFEST.in                                                                     |    1 
 moksha/apps/docs/moksha/__init__.py                                                              |    1 
 moksha/apps/docs/moksha/apps/docs.py                                                             |   52 
 moksha/apps/docs/moksha/apps/widgetbrowser/__init__.py                                           |    2 
 moksha/apps/docs/moksha/apps/widgetbrowser/command.py                                            |   54 
 moksha/apps/docs/moksha/apps/widgetbrowser/repl.py                                               |  305 
 moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py                                         |   43 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.css                                   |   78 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.js                                    |  432 +
 moksha/apps/docs/moksha/apps/widgetbrowser/static/jquery.js                                      | 3436 ++++++++++
 moksha/apps/docs/moksha/apps/widgetbrowser/static/loading.gif                                    |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/pygments.css                                   |   59 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/tab.png                                        |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.accordion.css               |   12 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.all.css                     |    9 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.calendar.css                |  167 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.css                         |    2 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.datepicker.css              |  179 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.dialog.css                  |   95 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.menu.css                    |    8 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.resizable.css               |   20 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.slider.css                  |   11 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tablesorter.css             |   40 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tabs.css                    |  105 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toasterLite.css             |  106 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toolbar.css                 |  241 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-act.png          |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-over.png         |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left.png              |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-act.png        |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-over.png       |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle.png            |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-act.png         |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-over.png        |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right.png             |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/asc.gif                         |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/bg.gif                          |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/desc.gif                        |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-e.gif                    |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-n.gif                    |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-ne.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-nw.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-s.gif                    |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-se.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-sw.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-title.gif                |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png       |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-w.gif                    |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/menu-submenu.gif                |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-e.gif                 |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-n.gif                 |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-ne.gif                |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-nw.gif                |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-s.gif                 |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-se.gif                |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-sw.gif                |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-w.gif                 |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/shadow.png                      |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-1.png                 |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-2.png                 |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-handle.gif               |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/tabs.png                        |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-e.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-n.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-ne.gif                  |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-nw.gif                  |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-s.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-se.gif                  |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-sw.gif                  |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-w.gif                   |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif             |binary
 moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.base.js                                     |  204 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.dialog.js                                   |  459 +
 moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.draggable.js                                |  572 +
 moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.resizable.js                                |  710 ++
 moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.css                                    |  114 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.js                                     |  616 +
 moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.css                              |    9 
 moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.js                               |   13 
 moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html                                   |   60 
 moksha/apps/docs/moksha/apps/widgetbrowser/templates/list_widgets.html                           |   15 
 moksha/apps/docs/moksha/apps/widgetbrowser/templates/show_widget.html                            |   11 
 moksha/apps/docs/moksha/apps/widgetbrowser/templates/validation_result.html                      |   13 
 moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_browser_tabs.html                    |   12 
 moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html                           |   18 
 moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_parameters.html                      |   21 
 moksha/apps/docs/moksha/apps/widgetbrowser/util.py                                               |  242 
 moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py                                            |   72 
 moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py                                            |  251 
 moksha/apps/docs/pavement.py                                                                     |   31 
 moksha/apps/feeds/streams/__init__.py                                                            |   17 
 moksha/apps/feeds/streams/feedstream.py                                                          |  289 
 moksha/apps/menus/MANIFEST.in                                                                    |    1 
 moksha/apps/menus/moksha/__init__.py                                                             |    1 
 moksha/apps/menus/moksha/apps/menus/__init__.py                                                  |   18 
 moksha/apps/menus/moksha/apps/menus/controllers/__init__.py                                      |   17 
 moksha/apps/menus/moksha/apps/menus/controllers/menu.py                                          |   43 
 moksha/apps/menus/moksha/apps/menus/default.py                                                   |  104 
 moksha/apps/menus/moksha/apps/menus/static/GPL-LICENSE.txt                                       |  279 
 moksha/apps/menus/moksha/apps/menus/static/css/menu.css                                          |  195 
 moksha/apps/menus/moksha/apps/menus/static/css/menu1.css                                         |  198 
 moksha/apps/menus/moksha/apps/menus/static/images/0682.gif                                       |binary
 moksha/apps/menus/moksha/apps/menus/static/images/16-member-remove.png                           |binary
 moksha/apps/menus/moksha/apps/menus/static/images/24-book-blue-check.png                         |binary
 moksha/apps/menus/moksha/apps/menus/static/images/24-image-add.png                               |binary
 moksha/apps/menus/moksha/apps/menus/static/images/24-tag-add.png                                 |binary
 moksha/apps/menus/moksha/apps/menus/static/images/Applet.gif                                     |binary
 moksha/apps/menus/moksha/apps/menus/static/images/DV_Tools.jpg                                   |binary
 moksha/apps/menus/moksha/apps/menus/static/images/bgColor.gif                                    |binary
 moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_1.jpg                                 |binary
 moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_2.jpg                                 |binary
 moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_3.jpg                                 |binary
 moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_4.png                                 |binary
 moksha/apps/menus/moksha/apps/menus/static/images/blank.gif                                      |binary
 moksha/apps/menus/moksha/apps/menus/static/images/browser.png                                    |binary
 moksha/apps/menus/moksha/apps/menus/static/images/buttonfind.gif                                 |binary
 moksha/apps/menus/moksha/apps/menus/static/images/header_bgnd.jpg                                |binary
 moksha/apps/menus/moksha/apps/menus/static/images/ico_view.gif                                   |binary
 moksha/apps/menus/moksha/apps/menus/static/images/iconDone.png                                   |binary
 moksha/apps/menus/moksha/apps/menus/static/images/icon_13.png                                    |binary
 moksha/apps/menus/moksha/apps/menus/static/images/icon_14.png                                    |binary
 moksha/apps/menus/moksha/apps/menus/static/images/menuArrow.gif                                  |binary
 moksha/apps/menus/moksha/apps/menus/static/images/menuArrow_w.gif                                |binary
 moksha/apps/menus/moksha/apps/menus/static/mbMenu.js                                             |  476 +
 moksha/apps/menus/moksha/apps/menus/static/mbMenu.min.js                                         |    1 
 moksha/apps/menus/moksha/apps/menus/static/styleswitch.js                                        |   55 
 moksha/apps/menus/moksha/apps/menus/templates/mbmenu.mak                                         |   19 
 moksha/apps/menus/moksha/apps/menus/widgets.py                                                   |  144 
 moksha/apps/menus/pavement.py                                                                    |   33 
 moksha/apps/metrics/moksha/__init__.py                                                           |    1 
 moksha/apps/metrics/moksha/apps/metrics/consumers/__init__.py                                    |    1 
 moksha/apps/metrics/moksha/apps/metrics/consumers/metrics_consumer.py                            |   36 
 moksha/apps/metrics/moksha/apps/metrics/streams/__init__.py                                      |    1 
 moksha/apps/metrics/moksha/apps/metrics/streams/metrics_stream.py                                |  295 
 moksha/apps/metrics/moksha/apps/metrics/widgets/__init__.py                                      |    1 
 moksha/apps/metrics/moksha/apps/metrics/widgets/metrics.py                                       |  154 
 moksha/apps/metrics/pavement.py                                                                  |   44 
 moksha/controllers/apps.py                                                                       |   11 
 moksha/controllers/root.py                                                                       |   43 
 moksha/hub/hub.py                                                                                |    7 
 moksha/lib/helpers.py                                                                            |    2 
 moksha/lib/paver_tasks.py                                                                        |   66 
 moksha/middleware/middleware.py                                                                  |   29 
 moksha/streams/demo/__init__.py                                                                  |   17 
 moksha/streams/demo/demostream.py                                                                |  100 
 moksha/streams/feed/__init__.py                                                                  |   17 
 moksha/streams/feed/feedstream.py                                                                |  289 
 moksha/widgetbrowser/paster.ini                                                                  |   21 
 moksha/widgetbrowser/setup.cfg                                                                   |   14 
 moksha/widgetbrowser/setup.py                                                                    |   39 
 moksha/widgetbrowser/widgetbrowser/__init__.py                                                   |    2 
 moksha/widgetbrowser/widgetbrowser/command.py                                                    |   54 
 moksha/widgetbrowser/widgetbrowser/repl.py                                                       |  305 
 moksha/widgetbrowser/widgetbrowser/sphinx_ext.py                                                 |   43 
 moksha/widgetbrowser/widgetbrowser/static/httprepl.css                                           |   78 
 moksha/widgetbrowser/widgetbrowser/static/httprepl.js                                            |  432 -
 moksha/widgetbrowser/widgetbrowser/static/jquery.js                                              | 3436 ----------
 moksha/widgetbrowser/widgetbrowser/static/pygments.css                                           |   59 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css                       |   12 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css                             |    9 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css                        |  167 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.css                                 |    2 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css                      |  179 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css                          |   95 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css                            |    8 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css                       |   20 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css                          |   11 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css                     |   40 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css                            |  105 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css                     |  106 
 moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css                         |  241 
 moksha/widgetbrowser/widgetbrowser/static/ui.base.js                                             |  204 
 moksha/widgetbrowser/widgetbrowser/static/ui.dialog.js                                           |  459 -
 moksha/widgetbrowser/widgetbrowser/static/ui.draggable.js                                        |  572 -
 moksha/widgetbrowser/widgetbrowser/static/ui.resizable.js                                        |  710 --
 moksha/widgetbrowser/widgetbrowser/static/ui.tabs.css                                            |  114 
 moksha/widgetbrowser/widgetbrowser/static/ui.tabs.js                                             |  616 -
 moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.css                                      |    9 
 moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.js                                       |   13 
 moksha/widgetbrowser/widgetbrowser/templates/home.html                                           |   60 
 moksha/widgetbrowser/widgetbrowser/templates/list_widgets.html                                   |   15 
 moksha/widgetbrowser/widgetbrowser/templates/show_widget.html                                    |   16 
 moksha/widgetbrowser/widgetbrowser/templates/validation_result.html                              |   13 
 moksha/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html                            |   12 
 moksha/widgetbrowser/widgetbrowser/templates/widget_index.html                                   |   18 
 moksha/widgetbrowser/widgetbrowser/templates/widget_parameters.html                              |   21 
 moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.html                                   |    1 
 moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak                                    |    1 
 moksha/widgetbrowser/widgetbrowser/tests/dummy_template.html                                     |    1 
 moksha/widgetbrowser/widgetbrowser/tests/test_app.txt                                            |   50 
 moksha/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py                                      |   26 
 moksha/widgetbrowser/widgetbrowser/tests/testdocs/conf.py                                        |  149 
 moksha/widgetbrowser/widgetbrowser/tests/testdocs/index.rst                                      |   12 
 moksha/widgetbrowser/widgetbrowser/tests/widgets.py                                              |   25 
 moksha/widgetbrowser/widgetbrowser/util.py                                                       |  242 
 moksha/widgetbrowser/widgetbrowser/widgets.py                                                    |   71 
 moksha/widgetbrowser/widgetbrowser/wsgiapp.py                                                    |  251 
 moksha/widgets/all.py                                                                            |   11 
 moksha/widgets/chat/__init__.py                                                                  |   17 
 moksha/widgets/chat/chat.py                                                                      |   50 
 moksha/widgets/chat/controllers/__init__.py                                                      |   17 
 moksha/widgets/chat/controllers/chat.py                                                          |  114 
 moksha/widgets/chat/static/chat.css                                                              |  119 
 moksha/widgets/chat/static/chrome.js                                                             |   83 
 moksha/widgets/chat/static/gui.js                                                                |  215 
 moksha/widgets/chat/static/index.html                                                            |   48 
 moksha/widgets/chat/static/irc2.js                                                               |  224 
 moksha/widgets/chat/static/style.css                                                             |  153 
 moksha/widgets/chat/static/themes/dojo/chrome.js                                                 |   83 
 moksha/widgets/chat/static/themes/dojo/gui.js                                                    |   19 
 moksha/widgets/chat/static/themes/dojo/index.html                                                |  226 
 moksha/widgets/chat/static/themes/dojo/style.css                                                 |  151 
 moksha/widgets/chat/static/themes/simple/chrome.js                                               |   83 
 moksha/widgets/chat/static/themes/simple/gui.js                                                  |  216 
 moksha/widgets/chat/static/themes/simple/index.html                                              |   58 
 moksha/widgets/chat/static/themes/simple/style.css                                               |  151 
 moksha/widgets/chat/static/willowchat.js                                                         |  337 
 moksha/widgets/chat/templates/bootstrap.mak                                                      |  419 -
 moksha/widgets/chat/templates/chat.mak                                                           |   31 
 moksha/widgets/feedtree/controllers/demo.py                                                      |    2 
 moksha/wsgiapp.py                                                                                |    1 
 pavement.py                                                                                      |   25 
 production/apache/moksha.wsgi                                                                    |    7 
 setup.py                                                                                         |   31 
 270 files changed, 14466 insertions(+), 14050 deletions(-)

New commits:
commit 04cf24d46fe3294ba09de6dd7fbe6d0fd5c86c6c
Merge: dafe569... 34191f8...
Author: Luke Macken <lmacken at redhat.com>
Date:   Sun Aug 9 00:58:03 2009 -0400

    Merge branch 'master' of git+ssh://git.fedorahosted.org/git/moksha



commit dafe569cc7433c4fade5733cb89ff6d668af814b
Author: Luke Macken <lmacken at redhat.com>
Date:   Sun Aug 9 00:42:48 2009 -0400

    Update our WSGI app

diff --git a/production/apache/moksha.wsgi b/production/apache/moksha.wsgi
index 5f2dc95..e4e5d25 100644
--- a/production/apache/moksha.wsgi
+++ b/production/apache/moksha.wsgi
@@ -1,9 +1,8 @@
 import os, sys
-sys.path.append('/srv/moksha')
-os.environ['PYTHON_EGG_CACHE'] = '/srv/moksha/.python-eggs'
+#sys.path.append('/srv/moksha')
+#os.environ['PYTHON_EGG_CACHE'] = '/srv/moksha/.python-eggs'
 
 #sys.stdout = sys.stderr
 
 from paste.deploy import loadapp
-
-application = loadapp('config:/srv/moksha/production.ini')
+application = loadapp('config:/etc/moksha/production.ini')


commit e5da265fa1d8df4e7dacde6098e396d4912e9735
Author: Luke Macken <lmacken at redhat.com>
Date:   Sun Aug 9 00:42:30 2009 -0400

    Update our setup.py

diff --git a/setup.py b/setup.py
index 128ffbc..d7f4ec6 100644
--- a/setup.py
+++ b/setup.py
@@ -15,20 +15,11 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from setuptools import setup, find_packages
-
-package_data = {'moksha': ['i18n/*/LC_MESSAGES/*.mo',
-                           'public/favicon',
-                           'public/css/*.css',
-                           'public/images/*.png',
-                           'public/images/*.gif',
-                           'public/images/*.jpg',
-                           'public/javascript/*.js',
-                           'public/javascript/ui/*.js']
-               }
+from paver.setuputils import find_package_data
 
 setup(
     name='moksha',
-    version='0.2',
+    version='0.3',
     description='',
     author='',
     author_email='',
@@ -54,15 +45,19 @@ setup(
     packages=find_packages(exclude=['ez_setup']),
     include_package_data=True,
     test_suite='nose.collector',
+    namespace_packages=['moksha'],
     tests_require=['WebTest', 'BeautifulSoup'],
-    package_data={'moksha': ['i18n/*/LC_MESSAGES/*.mo',
-                             'public/favicon',
-                             'public/css/*.css',
-                             'public/images/*.png',
-                             'public/images/*.gif',
-                             'public/images/*.jpg',
-                             'public/javascript/*.js',
-                             'public/javascript/ui/*.js']},
+    package_data=find_package_data(exclude=['ez_setup']),
+    #package_data={'moksha': ['i18n/*/LC_MESSAGES/*.mo',
+    #                         'public/favicon',
+    #                         'public/css/*.css',
+    #                         'public/images/*.png',
+    #                         'public/images/*.gif',
+    #                         'public/images/*.jpg',
+    #                         'public/javascript/*.js',
+    #                         'templates/*.html',
+    #                         'templates/*.mak',
+    #                         'public/javascript/ui/*.js']},
     message_extractors = {'moksha': [
             ('**.py', 'python', None),
             ('templates/**.mak', 'mako', None),


commit 9a1c9281e84acbdfb5abc651b241d25f596fa705
Author: Luke Macken <lmacken at redhat.com>
Date:   Sun Aug 9 00:32:26 2009 -0400

    Point to moksha.csh.rit.edu for our new demo dashboard
    Also, remove the old chat widgets

diff --git a/docs/_templates/indexcontent.html b/docs/_templates/indexcontent.html
index fa975a3..1e4fbad 100644
--- a/docs/_templates/indexcontent.html
+++ b/docs/_templates/indexcontent.html
@@ -24,7 +24,7 @@
          <span class="linkdescr">A handbook for hacking on and with Moksha</span></p>
       <p class="biglink"><a class="biglink" href="{{ pathto("main/Deployment") }}">Deployment</a><br/>
          <span class="linkdescr">Recipies for efficiently deploying and scaling Moksha</span></p>
-      <p class="biglink"><a class="biglink" href="http://bit.ly/RICf">Demo Dashboard</a><br/>
+      <p class="biglink"><a class="biglink" href="http://moksha.csh.rit.edu">Demo Dashboard</a><br/>
          <span class="linkdescr">A simple demo Moksha dashboard</span></p>
     </td></tr>
   </table>
diff --git a/moksha/widgets/chat/__init__.py b/moksha/widgets/chat/__init__.py
deleted file mode 100644
index 5447654..0000000
--- a/moksha/widgets/chat/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from chat import LiveChatWidget, LiveChatFrameWidget
diff --git a/moksha/widgets/chat/chat.py b/moksha/widgets/chat/chat.py
deleted file mode 100644
index 98ef860..0000000
--- a/moksha/widgets/chat/chat.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Authors: Luke Macken <lmacken at redhat.com>
-
-from tw.api import Widget, JSLink, CSSLink
-from tw.jquery import jquery_js
-
-from moksha.api.widgets.orbited import orbited_js
-
-irc2_js = JSLink(filename='static/irc2.js',
-                 javascript=[orbited_js],
-                 modname=__name__)
-
-willowchat_js = JSLink(filename='static/willowchat.js',
-                       javascript=[jquery_js, irc2_js],
-                       modname=__name__)
-
-gui_js = JSLink(filename='static/gui.js',
-                javascript=[willowchat_js],
-                modname=__name__)
-
-willowchat_css = CSSLink(filename='static/style.css', modname=__name__)
-
-
-class LiveChatWidget(Widget):
-    name = 'Chat'
-    params = ['bootstrap']
-    bootstrap = JSLink(link='/apps/chat/bootstrap')
-    template = '<div id="willowchat" reposition="true">${bootstrap}</div>'
-    visible = False
-
-
-class LiveChatFrameWidget(Widget):
-    template = 'mako:moksha.api.widgets.chat.templates.chat'
-    javascript = [orbited_js, willowchat_js, irc2_js, gui_js, jquery_js]
-    css = [willowchat_css]
diff --git a/moksha/widgets/chat/controllers/__init__.py b/moksha/widgets/chat/controllers/__init__.py
deleted file mode 100644
index 10fd377..0000000
--- a/moksha/widgets/chat/controllers/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from chat import ChatController
diff --git a/moksha/widgets/chat/controllers/chat.py b/moksha/widgets/chat/controllers/chat.py
deleted file mode 100644
index b413a00..0000000
--- a/moksha/widgets/chat/controllers/chat.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Authors: Luke Macken <lmacken at redhat.com>
-
-import logging
-log = logging.getLogger(__name__)
-
-import urlparse
-urlparse.uses_netloc.append('irc')
-
-from tg import expose, tmpl_context, config
-from pylons import request
-
-from moksha.lib.base import BaseController
-from moksha.api.widgets.chat import LiveChatFrameWidget
-
-chat_frame_widget = LiveChatFrameWidget('chat_frame')
-
-
-class ChatController(BaseController):
-
-    def __init__(self, *args, **kw):
-        super(ChatController, self).__init__(*args, **kw)
-        self.config = {}
-        backend = config.get('chat.backend')
-        if not backend:
-            log.info('No `chat.backend` defined; disabling chat functionality')
-            return
-        backend = urlparse.urlparse(backend)
-        if hasattr(backend, 'scheme'): # Python 2.5+
-            self.config['backendProtocol'] = backend.scheme
-            self.config['backendAddr'] = [backend.hostname, backend.port]
-        else: # Python 2.4
-            self.config['backendProtocol'] = backend[0]
-            host, port = backend[1].split(':')
-            self.config['backendAddr'] = [host, port]
-        self.config['startBuiltin'] = config.get('chat.builtin', False)
-        self.config['rooms'] = {}
-        display_opts = {
-                'floating': True, 'floatingToggle': False, 'width': 400 ,
-                'height': 300, 'theme': 'simple', 'resizable': True,
-                'greeting': 'Moksha Chat',
-                }
-        for room in config['chat.rooms'].replace(',', ' ').split():
-            self.config['rooms'][room] = {'display': {}}
-            for display_opt, default in display_opts.items():
-                self.config['rooms'][room]['display'][display_opt] = \
-                        config.get('chat.%s.display.%s' % (room, display_opt),
-                                   default)
-            self.config['rooms'][room]['roomAssignmentMode'] = \
-                    config.get('chat.%s.roomAssignmentMode' % room, 'static')
-            self.config['rooms'][room]['staticRoomName'] = \
-                    config.get('chat.%s.staticRoomName' % room, room)
-
-        log.debug('Chat config = %r' % self.config)
-
-    @expose('mako:moksha.templates.widget')
-    def index(self, *args, **kw):
-        tmpl_context.widget = chat_frame_widget
-        return dict(options={})
-
-    @expose('mako:moksha.api.widgets.chat.templates.bootstrap',
-            content_type='text/javascript')
-    def bootstrap(self, *args, **kw):
-        return dict(host=request.headers['host'])
-
-    @expose('json')
-    def rooms(self, roomClass='default', op=None, jsonp=None):
-        opts = None
-        if op:
-            opts = self.jsonp(getattr(self, 'op_%s' % op,
-                                      self.op_not_found)(roomClass), jsonp)
-        else:
-            opts = self.jsonp([False, ["op not specified"]], jsonp)
-        return opts
-
-    def jsonp(self, result, jsonp=None):
-        result = str(result).replace('True', 'true').replace('False', 'false')
-        if jsonp:
-            result = jsonp + '(' + result + ')'
-        return result
-
-    def op_info(self, roomClass):
-        if roomClass not in self.config['rooms']:
-            return [False, ['unknown room class: ' + roomClass]]
-        info = self.config['rooms'][roomClass]
-        displayInfo = info.get('display', {})
-        opts = {}
-        opts.update(displayInfo)
-        mode = info.get('roomAssignmentMode', 'static')
-        if mode == 'static':
-            opts['roomId'] = info.get('staticRoomName', 'default')
-        elif mode == 'referrer':
-            opts['roomId'] = request.headers.get('referer', 'default')
-        opts['protocol'] = self.config['backendProtocol']
-        opts['addr'] = self.config['backendAddr']
-        return [True, opts]
-
-    def op_not_found(self):
-        return [False, ['unrecognized op']]
diff --git a/moksha/widgets/chat/static/chat.css b/moksha/widgets/chat/static/chat.css
deleted file mode 100644
index fe0d13f..0000000
--- a/moksha/widgets/chat/static/chat.css
+++ /dev/null
@@ -1,119 +0,0 @@
-#signin_popup {
-  width:220pt;
-  padding:2em;
-  padding-bottom:3em;
-  text-align:center;
-  background-color: #A4C9D6;
-  color:#0E3541;
-  border: 5pt solid #195263;
-  position:absolute;
-  top:80pt;
-  left:100pt;
-  z-index:2;
-}
-#nickname {
-  width:90pt;
-}
-#absorb_clicks {
-  position:absolute;
-  top:0;
-  left:0;
-  width:300pt;
-  height:200pt;
-}
-
-.chatbox {
-  width:490pt;
-  font: 100% Verdana, sans-serif;
-  background-color:#24758E;
-  padding:5pt;
-  position:relative;
-}
-.chatbox .left_column {
-  width: 360pt;
-}
-.chatbox .chathistory {
-  width:100%;
-  height:217pt;
-  overflow: auto;
-  background-color: white;
-}
-.chatbox .chathistory div {
-  background-color:#ffffee;
-  padding:.2em;
-  padding-left:1.5em;
-  text-indent: -1em;
-  border-bottom: 1px dotted #ccc;
-}
-.chatbox .chathistory .message .user {
-  width:5em;
-  font-weight: bold;
-  color:#DD7200;
-  padding-right:.2em;
-  text-align:right;
-}
-.chatbox .chathistory .message.self .user{
-  color: #B42600;
-}
-.chatbox .chathistory .message.mentioned{
-  background-color: #d5c5ff;
-}
-.chatbox .chathistory .message.private{
-  background-color: #ccc;
-}
-.chatbox .chathistory .message.ctcp {
-  background-color: #f0f;
-}
-.chatbox .chathistory .action,
-.chatbox .chathistory .action .user {
-  color: #D68850;
-  font-style:italic;
-}
-.chatbox .chathistory .action.self,
-.chatbox .chathistory .action.self .user {
-  color: #A94C3B;
-  font-style:italic;
-}
-.chatbox .chathistory .informative {
-  font-size: 85%;
-  font-style: italic;
-  color:#999;
-  text-align:center;
-  padding:.3em;
-}
-
-.chatbox .chatbox_input {
-  width:100%;
-  height:30pt;
-  margin:0;
-  margin-top:3pt;
-  padding:0;
-  border:0;
-  font-family: Verdana, sans-serif;
-}
-
-.chatbox .user_list {
-  float:right;
-  position: absolute;
-  padding:0;
-  margin:0;
-  right:5pt;
-  top:5pt;
-  background-color:white;
-  width:127pt;
-  height:250pt;
-  overflow:auto;
-}
-.chatbox .user_list .user_entry{
-  padding:.2em;
-  padding-left:8pt;
-  border-bottom: 1px dotted #ccc;
-}
-
-#events {
-  visibility:hidden;
-  border:0;
-  width:0;
-  height:0;
-/*  display:none;*/
-}
diff --git a/moksha/widgets/chat/static/chrome.js b/moksha/widgets/chat/static/chrome.js
deleted file mode 100644
index 34caca5..0000000
--- a/moksha/widgets/chat/static/chrome.js
+++ /dev/null
@@ -1,83 +0,0 @@
-(function() {
-/* Boilerplate
- */
-if (!window.WillowChat) {
-    Willowchat = {}
-}
-
-if (!WillowChat.chrome) {
-    WillowChat.chrome = {}
-}
-
-if (!WillowChat.chrome.map) {
-    WillowChat.chrome.map = {}
-}
-
-
-WillowChat.chrome.map.simple = WillowChat.chrome.SimpleChrome = function(container, opts) {
-    /* Set configured height
-     */
-    container.style.width = opts.width + 'px'
-    container.style.height = opts.height + 'px'
-    container.style.background = "white";
-    var toggles = document.createElement('div')
-    toggles.setAttribute('id', 'willowchatToggles')
-    var floatToggle = document.createElement('div')
-    floatToggle.setAttribute('id', 'willowchatFloat')
-    floatToggle.innerHTML = "&uarr;"
-    var minToggle = document.createElement('div')
-    minToggle.setAttribute('id', 'willowchatMin')
-    minToggle.innerHTML = "-"
-    floatToggle.setAttribute('style', "float: left;")
-    minToggle.setAttribute('style', "float: left;")
-    var toggleElements = [ minToggle, floatToggle]
-    for (var i = 0; i < 2; ++i) {
-        var t = toggleElements[i]
-        t.style.width = "20px"
-        t.style.height = "20px"
-        t.style.textAlign = "center"
-        t.style.border = "1px solid black"
-        t.style.padding = "2px"
-        t.style.color = "white"
-        t.style.fontWeight = "bold"
-        t.style.background = "#005522"
-        t.style.cursor = "pointer"
-        t.style.cssFloat = "left"
-        t.style.styleFloat = "left"
-        t.style.display = "none"
-    }
-    container.appendChild(toggles)
-    toggles.appendChild(floatToggle)
-    toggles.appendChild(minToggle)
-
-    /* Should it be floating?
-     */
-    if (opts.floating) {
-        container.style.position = 'absolute';
-        container.style.bottom = '0';
-        container.style.right = '0';
-        minToggle.style.display = "block"
-        toggles.style.position = "absolute"
-        toggles.style.top = "1px"
-        toggles.style.left = "1px"
-        if (opts.reposition) {
-            container.parentNode.removeChild(container)
-            document.body.appendChild(container)
-
-        }
-    }
-    else {
-        var ifr = container.getElementsByTagName('iframe')[0]
-        toggles.style.marginBottom="-10px"
-        ifr.style.marginTop="10px"
-        container.removeChild(ifr)
-        container.appendChild(ifr)
-//        toggles.style.marginBottom = "-5px";
-    }
-    if (opts.floatingToggle) {
-        floatToggle.style.display = "block"
-    }
-    toggles.style.border = "1ps solid yellow"
-}
-
-})();
\ No newline at end of file
diff --git a/moksha/widgets/chat/static/gui.js b/moksha/widgets/chat/static/gui.js
deleted file mode 100644
index 2972753..0000000
--- a/moksha/widgets/chat/static/gui.js
+++ /dev/null
@@ -1,215 +0,0 @@
-(function() {
-
-if (!window.WillowChat) {
-    Willowchat = {}
-}
-
-if (!WillowChat.guis) {
-    WillowChat.guis = {}
-}
-
-if (!WillowChat.guis.map) {
-    WillowChat.guis.map = {}
-} 
-var ENTER_KEY = 13
-WillowChat.guis.map.simple = WillowChat.guis.SimpleGui = function(wc, opts) {
-    var self = this;
-    self.presenceShown = true;
-    var logger = Orbited.getLogger('WillowChatTest');
-//    logger.enabled = true;
-    var username = null;
-    var presence = {}
-    
-    $('#nickname').focus();    
-    $('#nickname').keypress( function(e) {
-        var key = e.charCode || e.keyCode || 0
-        if (key == ENTER_KEY) {
-            self.connect();
-        };
-    });
-    $('#chatboxInput').keypress(function(e) {
-        var key = e.charCode || e.keyCode || 0;
-        if (key == ENTER_KEY) {
-        self.sendMessage();
-        return false;
-        };
-    });
-    $("#popupContent p").html(opts.greeting)
-    $("#presenceToggle").click(function() {
-        if (self.presenceShown) {
-            self.presenceShown = false;
-            $("#presence").hide()
-            $("#presenceToggle").html('&larr;');
-        }
-        else {
-            self.presenceShown = true;
-            $("#presence").show();
-            $("#presenceToggle").html('&rarr;');
-        }
-        if (wc.readyState == wc.READY_STATE_CONNECTED) {
-            $('#chatboxInput').focus();
-        }
-        else {
-            $('#nickname').focus();
-        }
-    })
-    var scrollDown = function() {
-      var box = $('#history')[0]
-      box.scrollTop = box.scrollHeight;
-    }
-    var isSubstring = function (sub, str) {
-    // case insensitive substring test
-        return str.toLowerCase().indexOf(sub.toLowerCase()) >= 0;
-    };
-    var sanitize = (function(str) {
-    // See http://bigdingus.com/2007/12/29/html-escaping-in-javascript/
-        var MAP = {
-            '&': '&amp;',
-            '<': '&lt;',
-            '>': '&gt;',
-            '"': '&quot;',
-            "'": '&#39;'
-        };
-        var repl = function(c) { return MAP[c]; };
-        return function(s) {
-            return s.replace(/[&<>'"]/g, repl);
-        };
-    })();
-
-    // TODO: test this out
-    var userRenamed = function(oldname, newname) {
-        $("<div class='informative rename'></div>")
-            .html("<span class='user'>" + oldname + "</span> is now known as " +
-                "<span class='user'>" + newname + "</span>")
-            .appendTo("#history");
-        scrollDown();
-        $("#user_" + oldname)
-            .attr("id", "user_" + newname)
-            .html(newname);
-    }
-    
-    var addName = function (name) {
-        presence[name] = 1
-        $('<div class="user_entry" id="user_' + name + '">' + name + '</div>')
-            .appendTo("#presenceList");
-    };
-    
-    var removeName = function (name) {
-        delete presence[name];
-        $(".user_list #user_" + name).remove()
-    };
-
-    var sortNames = function () {
-        $('#presenceList').empty();
-        var list = [];
-        for (var user in presence) {
-            list.push(user);
-        };
-        list.sort()
-        for (var i=0; i < list.length; i++) {
-            var user = list[i];
-            $('<div class="user_entry" id="user_' + user + '">' + user + '</div>')
-                .appendTo("#presenceList");
-        };
-    };
-    self.connect = function() {
-        username = $("#nickname").val();
-        if (!username) {
-            logger.debug('please enter a username');
-            return
-        }
-        $('#popup, #absorbClicks').hide();
-        $('#chatboxInput').focus();
-        $('#chatboxInput').val('')
-
-        connected = true;
-        wc.connect( {
-            username: username
-        })
-        wc.onConnect = function(data) { 
-            /* This is somewhat important -- without this IE can run into some
-             * issues with reconnecting
-             */
-
-            window.onbeforeunload = function() {
-                if (wc.readyState == wc.READY_STATE_CONNECTED) {
-                return 'Are you sure you want to quit and lose the chat connection?';
-                }
-            };
-            window.onunload = function() {
-                if (wc.readyState == wc.READY_STATE_CONNECTED) {
-                    wc.disconnect();
-                }
-           }
-
-
-            $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history");
-            for (var i = 0; i < wc.presence.length; ++i) {
-                addName(wc.presence[i]);
-            }
-            sortNames();
-            logger.debug('connected', data, wc.presence) 
-        }
-        wc.onMessage = function(sender, message) { 
-            logger.debug('msg', sender, message); 
-            var messagediv = $('<div class="message"></div>');
-        
-            if (sender == username) {
-                messagediv.addClass("self");
-            }
-            if (isSubstring(username, message)) {
-                messagediv.addClass("mentioned");
-            }
-            messagediv.html('<span class="user">' + sender + ':</span> ' +
-                            sanitize(message))
-            .appendTo("#history");
-            scrollDown();
-        }
-        wc.onAction = function(s, m) { logger.debug('action', s, m); }
-
-        wc.onJoin = function(joiner) { 
-            logger.debug('join', joiner);
-            addName(joiner);
-            sortNames();
-            $("<div class='informative join'></div>")
-                .html("<span class='user'>" + joiner + '</span> has joined')
-                .appendTo("#history");
-            scrollDown();
-        }
-        wc.onLeave = function(leaver) { 
-            logger.debug('leave', leaver); 
-            removeName(leaver);
-            $("<div class='informative part'></div>")
-                .html("<span class='user'>" + leaver + '</span> left')
-                .appendTo("#history");
-            scrollDown();
-        }
-        wc.onDisconnect = function() { logger.debug('disconneted'); }
-        wc.onUsernameTaken = function() {
-            logger.debug('onUsernameTaken', username);
-            username += '_'
-            try {
-                wc.rename(username);
-                logger.debug('rename sent');
-            }
-            catch(e) {
-                logger.debug('rename failed:', e)
-            }
-        }
-    }
-    self.sendMessage = function() {
-        var msg = $('#chatboxInput').val();
-        wc.sendMessage(msg)
-        $('#chatboxInput').val('');
-        // the WillowChat server will not echo our message back, so simulate a send.
-        wc.onMessage(username, msg)
-    }
-    self.sendAction = function() {
-        var msg = getMessage()
-        wc.sendAction(msg);
-        logger.debug('action', username, msg)
-    }
-
-}
-})()
-
diff --git a/moksha/widgets/chat/static/index.html b/moksha/widgets/chat/static/index.html
deleted file mode 100644
index d4277bf..0000000
--- a/moksha/widgets/chat/static/index.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!-- @@ HACK -->
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/irc2.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/willowchat.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/gui.js"></script>
-<script src="/toscawidgets/resources/tw.jquery.base/static/javascript/jquery-1.2.6.pack.js"></script>
-<link rel="stylesheet" type="text/css" href="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/style.css"></link>
-  <script>
-    TCPSocket = Orbited.TCPSocket
-    document.domain = document.domain;
-/*    Orbited.system.enabled = true;
-    Orbited.loggers['Orbited.XSDR'].enabled = false
-    Orbited.loggers['Orbited.CometSession'].enabled = true
-    Orbited.loggers['Orbited.TCPSocket'].enabled = true
-    Orbited.loggers['XSDRBridge'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true.
-    Orbited.loggers['WC.c.IRCClient'].enabled = true
-*/
-  </script>
-
-<div id="popup">
-<div id="popupOuter">
-  <div id="popupMiddle">
-    <div id="popupContent">
-      <p>Greeting</p>
-      <label for="nickname">Nickname:</label>
-      <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" />
-    </div>
-  </div>
-</div>
-</div>
-
-  <div id="absorbClicks"></div>
-  <div id="presenceToggle">
-    &rarr;
-  </div>
-  <div id="presence">
-   <div id="presenceTitle">Presence</div>
-   <div id="presenceList">
-   </div>
-  </div>
-  <div id="history">
-  </div>
-  <div id="inputBar">
-   <textarea id="chatboxInput"></textarea>
-  </div>
diff --git a/moksha/widgets/chat/static/irc2.js b/moksha/widgets/chat/static/irc2.js
deleted file mode 100644
index 175be14..0000000
--- a/moksha/widgets/chat/static/irc2.js
+++ /dev/null
@@ -1,224 +0,0 @@
-/* irc.js
- *  This IRC client runs in a web browser using pure JavaScript
- *  Orbited 0.5+ required
- *
- *  Methods:
- *      connect(hostname, port)
- *      ident(nickname, modes, real_name)
- *      join(channel)
- *      names(channel)
- *      part(channel)
- *      quit(reason)
- *      privmsg(destination, message)
- *
- *  Callbacks:
- *      Built-in callbacks are onconnect(), onerror(), onresponse(), and onclose()
- *      onerror and onreply are passed numerical reponse codes, see:
- *      http://www.irchelp.org/irchelp/rfc/chapter6.html for a list of IRC response
- *      codes.
- *
- *      To add callbacks for IRC actions, for instance PRIVMSG,
- *          set onPRIVMSG = function(command) {...you code here...}
- *      See the included IRC demo (/static/demos/irc) for example usage
- *
- * Frank Salim (frank.salim at gmail.com)
- * ©2008 The Orbited Project
- */
-
-// TODO DRY this by creating a common logging infrastructure (this is also on stomp.js)
-IRC_DEBUG = false;
-
-if (IRC_DEBUG && typeof(Orbited)) {
-    var getIrcLogger = function(name) {
-        var logger = Orbited.getLogger(name);
-        if (!("dir" in logger)) {
-            logger.dir = function() {};
-        }
-        return logger;
-    }
-}
-else if (IRC_DEBUG && typeof(console)) {
-    var getIrcLogger = function(name) {
-        return {
-            debug: function() {
-                var args = Array.prototype.slice.call(arguments);
-                args.unshift(name, ": ");
-                console.debug.apply(console, args);
-            },
-            dir: function() {
-                console.debug(name, ":");
-                console.dir.apply(console, arguments);
-            }
-        };
-    };
-}
-else {
-    var getIrcLogger = function(name) {
-        return {
-            debug: function() {},
-            dir: function() {}
-        };
-    };
-}
-
-IRCClient = function() {
-    var log = getIrcLogger("IRCClient");
-    var self = this
-    var conn = null
-    var buffer = ""
-    var ENDL = "\r\n"
-
-    self.onopen = function() {};
-    self.onconnect = function() {}      // Do nothing in default callbacks
-    self.onclose = function() {}
-    self.onerror = function(command) {}
-    self.onresponse = function(command) {}     // used for numerical replies
-                            
-    self.connect = function(hostname, port) {
-        log.debug("connect");
-        conn = self._createTransport();
-        conn.onopen = conn_opened
-        conn.onclose = conn_closed
-        conn.onread = conn_read
-        conn.open(hostname, port)
-        // TODO set onerror.
-    }
-    self._createTransport = function() {
-        return new TCPSocket();
-    };
-    self.close = function() {
-        log.debug("close");
-        conn.close()
-        conn.onopen = null;
-        conn.onclose = null;
-        conn.onread = null;
-        self.onclose()
-    }
-    self.ident = function(nickname, modes, real_name) {
-        send("USER", nickname + " " + modes + " :" + real_name) 
-    }
-    self.nick = function(nickname) {
-        send("NICK", nickname)
-    }
-    self.join = function(channel) {
-        send("JOIN", channel)
-    }
-    self.names = function(channel) {
-        send("NAMES", channel)
-    }
-    self.part = function(channel, reason) {
-        send("PART", channel + " :" + reason)
-    }
-    self.quit = function(reason) {
-        var reason = reason || "leaving";
-        send("QUIT", ":" + reason)
-        conn.close()
-    }
-    self.reset = function() {
-        conn.reset();
-    }
-    self.action = function(destination, message) {
-        send('PRIVMSG', destination + ' :\01ACTION ' + message + '\01')
-    }
-
-    self.privmsg = function(destination, message) {
-        send('PRIVMSG', destination + ' :' + message)
-    }
-
-    // Socket Callbacks
-    var conn_opened = function() {
-        self.onopen()
-    }
-    var conn_closed = function() {
-        self.onclose()
-    }
-    var conn_read = function(data) {
-        log.debug("data:");
-        log.debug(data);
-        buffer += data
-        parse_buffer()
-    }
-
-    // Internal Functions
-    var send = function(type, payload) {
-        log.debug("send: " + payload);
-        conn.send(type + " " + payload + ENDL);
-    };
-    var parse_buffer= function() {
-        var commands = buffer.split(ENDL);
-        buffer = commands[commands.length-1];
-        for (var i = 0, l = commands.length - 1; i < l; ++i) {
-            var line = commands[i];
-            if (line.length > 0)
-                dispatch(line);
-        }
-    };
-    var parse_command = function(s) {
-        // See http://tools.ietf.org/html/rfc2812#section-2.3
-
-        // all the arguments are split by a single space character until
-        // the first ":" character.  the ":" marks the start of the last
-        // trailing argument which can contain embeded space characters.
-        var i = s.indexOf(" :");
-        if (i >= 0) {
-            var args = s.slice(0, i).split(' ');
-            args.push(s.slice(i + 2));
-        } else {
-            var args = s.split(' ');
-        }
-
-        // extract the prefix (if there is one).
-        if (args[0].charAt(0) == ":") {
-          var prefix = args.shift().slice(1);
-        } else {
-          var prefix = null;
-        }
-
-        var command = {
-            prefix: prefix,
-            type: args.shift(),
-            args: args
-        };
-        log.debug("command:");
-        log.dir(command);
-        return command;
-    };
-    var dispatch = function(line) {
-        command = parse_command(line);
-        if (command.type == "PING") {
-            send("PONG", ":" + command.args)
-        }
-        if (!isNaN(parseInt(command.type))) {
-            var error_code = parseInt(command.type)
-            if (error_code > 400)
-                return self.onerror(command)
-            else
-                return self.onresponse(command)
-        } 
-        if (command.type == "PRIVMSG") {
-            msg = command.args[1]
-            if (msg.charCodeAt(0) == 1 && msg.charCodeAt(msg.length-1) == 1) {
-                var args = [command.args[0]]
-                var newargs = msg.slice(1, msg.length - 1).split(' ')
-                if (newargs[0] == 'ACTION') {
-                    command.type = newargs.shift()
-                }
-                else {
-                    command.type = 'CTCP'
-                }
-
-                for (var i = 0; i < newargs.length; ++i) {
-                    args.push(newargs[i])
-                }
-                command.args = args
-            }
-        }
-        if (typeof(self["on" + command.type]) == "function") {
-            // XXX the user is able to define unknown command handlers,
-            //     but cannot send any arbitrary command
-            self["on" + command.type](command);
-        } else {
-            log.debug("unhandled command received: ", command.type);
-        }
-    };
-};
diff --git a/moksha/widgets/chat/static/style.css b/moksha/widgets/chat/static/style.css
deleted file mode 100644
index c92d64e..0000000
--- a/moksha/widgets/chat/static/style.css
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-html, body {
-    padding: 0px;
-    margin: 0px;
-    border: none;
-    _overflow: hidden;
- }
-     */
-#presenceToggle {
-    border: 1px solid black;
-    position: absolute;
-    right: 1px;
-    top: 1px;
-    padding: 2px;
-    background: #3f9824;
-    color: white;
-    font-weight: bold;
-    cursor: pointer;
-}
-#presenceToggle:hover {
-}
-#presence {
-    float: right;
-    border: 1px solid gray;
-    width: 130px;
-    height: 83%;
-    margin-left: 3px;
-    margin-bottom: 0px;
-    overflow: hidden;
-}
-#presenceTitle {
-    text-decoration: underline;
-}
-#presenceList {
-    overflow: auto;
-    height: 90%;
-}
-#history {
-    border: 1px solid gray;
-    height: 83%;
-    overflow: auto;
-    margin-bottom: 0px;
-}
-#historySpacer {
-    border: 1px solid red;    
-}
-#inputBar {
-    margin-top: 0px;
-    height: 15%;
-}
-#inputBar textarea {
-    width: 100%;
-    height: 100%;
-    border: 1px solid gray;
-}
-
-
-
-#popup {
-    position: absolute; 
-    height: 100%; 
-    width: 70%; 
-    left: 15%; 
-    z-index: 2;
-}
-
-#popupOuter { 
-    height: 100%;
-    width: 100%;
-    overflow: hidden;
-    position: relative;
-}
-#popupOuter[id] {display: table; position: static;}
-
-#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/
-#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;}
-
-#popupContent {position: relative; top: -50%} /* for explorer only */
-/* optional: #popupContent[id] {position: static;} */
-
-#popupContent {
-    font-size: 120%;
-    text-align:center;
-    background: #3f9824;
-    color: white;
-    border: 5pt solid #83cb22;
-    padding: 8px;
-    padding-bottom: 20px;
-    width: 100%;
-}
-#popupContent p {
-    font-size: 150%;
-}
-
-#absorbClicks {
-    position:absolute;
-    top:0;
-    left:0;
-    width:100%;
-    height:100%;
-}
-
-
-#history div {
-  background-color:#eeffee;
-  padding:.2em;
-  padding-left:1.5em;
-  text-indent: -1em;
-  border-bottom: 1px dotted #ccc;
-}
-#history .message .user {
-  width:5em;
-  font-weight: bold;
-  color:#DD7200;
-  padding-right:.2em;
-  text-align:right;
-}
-#history .message.self .user{
-  color: #B42600;
-}
-#history .message.mentioned{
-  background-color: #d5c5ff;
-}
-#history .message.private{
-  background-color: #ccc;
-}
-#history .message.ctcp {
-  background-color: #f0f;
-}
-#history .action {
-  color: #D68850;
-  font-style:italic;
-}
-#history .action {
-  color: #A94C3B;
-  font-style:italic;
-}
-#history .informative {
-  font-size: 85%;
-  font-style: italic;
-  color:#999;
-  text-align:center;
-  padding:.3em;
-}
-#presenceList .user_entry {
-  font-size: 90%;
-  padding:.2em;
-  padding-left:8pt;
-  border-bottom: 1px dotted #ccc;
-}
-
-
-
diff --git a/moksha/widgets/chat/static/themes/dojo/chrome.js b/moksha/widgets/chat/static/themes/dojo/chrome.js
deleted file mode 100644
index 770701f..0000000
--- a/moksha/widgets/chat/static/themes/dojo/chrome.js
+++ /dev/null
@@ -1,83 +0,0 @@
-(function() {
-/* Boilerplate
- */
-if (!window.WillowChat) {
-    Willowchat = {}
-}
-
-if (!WillowChat.chrome) {
-    WillowChat.chrome = {}
-}
-
-if (!WillowChat.chrome.map) {
-    WillowChat.chrome.map = {}
-}
-
-
-WillowChat.chrome.map.dojo = WillowChat.chrome.DojoChrome = function(container, opts) {
-    /* Set configured height
-     */
-    container.style.width = opts.width + 'px'
-    container.style.height = opts.height + 'px'
-    container.style.background = "white";
-    var toggles = document.createElement('div')
-    toggles.setAttribute('id', 'willowchatToggles')
-    var floatToggle = document.createElement('div')
-    floatToggle.setAttribute('id', 'willowchatFloat')
-    floatToggle.innerHTML = "&uarr;"
-    var minToggle = document.createElement('div')
-    minToggle.setAttribute('id', 'willowchatMin')
-    minToggle.innerHTML = "-"
-    floatToggle.setAttribute('style', "float: left;")
-    minToggle.setAttribute('style', "float: left;")
-    var toggleElements = [ minToggle, floatToggle]
-    for (var i = 0; i < 2; ++i) {
-        var t = toggleElements[i]
-        t.style.width = "20px"
-        t.style.height = "20px"
-        t.style.textAlign = "center"
-        t.style.border = "1px solid black"
-        t.style.padding = "2px"
-        t.style.color = "white"
-        t.style.fontWeight = "bold"
-        t.style.background = "#005522"
-        t.style.cursor = "pointer"
-        t.style.cssFloat = "left"
-        t.style.styleFloat = "left"
-        t.style.display = "none"
-    }
-    container.appendChild(toggles)
-    toggles.appendChild(floatToggle)
-    toggles.appendChild(minToggle)
-
-    /* Should it be floating?
-     */
-    if (opts.floating) {
-        container.style.position = 'absolute';
-        container.style.bottom = '0';
-        container.style.right = '0';
-        minToggle.style.display = "block"
-        toggles.style.position = "absolute"
-        toggles.style.top = "1px"
-        toggles.style.left = "1px"
-        if (opts.reposition) {
-            container.parentNode.removeChild(container)
-            document.body.appendChild(container)
-
-        }
-    }
-    else {
-        var ifr = container.getElementsByTagName('iframe')[0]
-        toggles.style.marginBottom="-10px"
-        ifr.style.marginTop="10px"
-        container.removeChild(ifr)
-        container.appendChild(ifr)
-//        toggles.style.marginBottom = "-5px";
-    }
-    if (opts.floatingToggle) {
-        floatToggle.style.display = "block"
-    }
-    toggles.style.border = "1ps solid yellow"
-}
-
-})();
\ No newline at end of file
diff --git a/moksha/widgets/chat/static/themes/dojo/gui.js b/moksha/widgets/chat/static/themes/dojo/gui.js
deleted file mode 100644
index b042620..0000000
--- a/moksha/widgets/chat/static/themes/dojo/gui.js
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-if (!window.WillowChat) {
-    Willowchat = {}
-}
-
-if (!WillowChat.guis) {
-    WillowChat.guis = {}
-}
-
-if (!WillowChat.guis.map) {
-    WillowChat.guis.map = {}
-} 
-
-var willowConnection = null;
-WillowChat.guis.map.dojo = WillowChat.guis.DojoGui = function(wc, opts) {
-  console.log("Neat? ", wc, opts);
- willowConnection = wc;
-}
diff --git a/moksha/widgets/chat/static/themes/dojo/index.html b/moksha/widgets/chat/static/themes/dojo/index.html
deleted file mode 100644
index fe50981..0000000
--- a/moksha/widgets/chat/static/themes/dojo/index.html
+++ /dev/null
@@ -1,226 +0,0 @@
-<html>
- <head>
-  <link rel="stylesheet" type="text/css" href="style.css">
-<script src="http://localhost:9000/static/Orbited.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/irc2.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/willowchat.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/gui.js"></script>
-<script src="gui.js"></script>
-  <script>
-    TCPSocket = Orbited.TCPSocket
-    document.domain = document.domain
-/*    Orbited.system.enabled = true;
-    Orbited.loggers['Orbited.XSDR'].enabled = false
-    Orbited.loggers['Orbited.CometSession'].enabled = true
-    Orbited.loggers['Orbited.TCPSocket'].enabled = true
-    Orbited.loggers['XSDRBridge'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true 
-    Orbited.loggers['WC.c.IRCClient'].enabled = true
-*/
-  </script>
-
-
-	<link rel="stylesheet" 
-			href="http://o.aolcdn.com/dojo/1.2/dijit/themes/soria/soria.css">
-		<!-- load Dojo, and all the required modules -->
-		
-		<script type="text/javascript">
-
-				djConfig = {
-					isDebug: true,
-					baseUrl: "./",
-					xdWaitSeconds: 10,
-					parseOnLoad: true
-				};
-			</script>
-		
-		<script src="http://o.aolcdn.com/dojo/1.2/dojo/dojo.xd.js" ></script>
-		
-		<script>
-		
-		dojo.require("dijit.layout.BorderContainer");
-		dojo.require("dijit.layout.AccordionContainer");
-		dojo.require("dijit.layout.ContentPane");
-		dojo.require("dijit.layout.TabContainer");
-		
-		dojo.require("dijit.form.TextBox");
-		dojo.require("dijit.form.Button");
-		dojo.require("dijit.Dialog");
-		
-		
-		var username = null;
-		var roomMembers = [];
-		
-		dojo.addOnLoad(function() {
-			dijit.byId("logindialog").show();
-			console.log("hi?", willowConnection);
-			
-			
-			var mssageBox = dojo.byId("messageBox");
-			dojo.connect(mssageBox, "keyup", function(e) {
-		        var key = e.charCode || e.keyCode || 0
-		        if (key == dojo.keys.ENTER) {
-					var msg = mssageBox.value;
-		           	willowConnection.sendMessage(msg)
-			        willowConnection.onMessage(username, msg);
-					mssageBox.value = "";
-		        };
-		    });
-	
-			
-		});
-		
-		function login(nickname) {
-			username = nickname;
-			 willowConnection.connect( {
-		            username: nickname
-		        });
-		
-		
-		
-		
-				    willowConnection.onConnect = function(data) { 
-			            /* This is somewhat important -- without this IE can run into some
-			             * issues with reconnecting
-			             */
-
-			            window.onbeforeunload = function() {
-			                if (willowConnection.readyState == willowConnection.READY_STATE_CONNECTED) {
-			                return 'Are you sure you want to quit and lose the chat connection?';
-			                }
-			            };
-			            window.onunload = function() {
-			                if (willowConnection.readyState == willowConnection.READY_STATE_CONNECTED) {
-			                    willowConnection.disconnect();
-			                }
-			           }
-
-
-			           // $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history");
-			            for (var i = 0; i < willowConnection.presence.length; ++i) {
-			              addName(willowConnection.presence[i]);
-			              console.log("who?", willowConnection.presence[i]);
-			            }
-						updateMembers();
- 						console.log('connected', data, willowConnection.presence) 
-			        }
-			        willowConnection.onMessage = function(sender, message) { 
-			            console.log('msg', sender, message); 
-						chatArea.domNode.innerHTML += "<div>" + sender + ": " + message + "</div>";
-						scrollDown();
-			          /*  var messagediv = $('<div class="message"></div>');
-
-			            if (sender == username) {
-			                messagediv.addClass("self");
-			            }
-			            if (isSubstring(username, message)) {
-			                messagediv.addClass("mentioned");
-			            }
-			            messagediv.html('<span class="user">' + sender + ':</span> ' +
-			                            sanitize(message))
-			            .appendTo("#history");
-			            scrollDown();*/
-			        }
-			        willowConnection.onAction = function(s, m) { console.log('action', s, m); }
-
-			        willowConnection.onJoin = function(joiner) { 
-			            console.log('join', joiner);
-			            addName(joiner);
-						updateMembers();
-						chatArea.domNode.innerHTML +=	"<span class='user'>" + joiner + "</span> has joined<br/>";
-						scrollDown();
-			        }
-			
-			        willowConnection.onLeave = function(leaver) { 
-			           console.log('leave', leaver); 
-						var idx = -1;
-					   for(var i = 0; idx > -1 && i < roomMembers.length; i++) {
-							if(leaver == roomMembers[i]) {
-								idx = i;
-							}
-						}
-						roomMembers.splice(i, 1);
-						_updateMemberDisplay();
-			        }
-			
-			        willowConnection.onDisconnect = function() { console.log('disconneted'); roomMembers = []; _updateMemberDisplay();	dijit.byId("logindialog").show();}
-			        willowConnection.onUsernameTaken = function() {
-			            console.log('onUsernameTaken', username);
-			         username += '_'
-			            try {
-			                willowConnection.rename(username);
-			                console.log('rename sent');
-			            }
-			            catch(e) {
-			                console.log('rename failed:', e)
-			            }
-			        }
-		
-		
-		
-		
-		
-		} 
-		
-		function addName(name) {
-			roomMembers.push(name);
-		//	presenceContainer.domNode.innerHTML += name + "<br/>";
-		} 
-		
-		
-		function updateMembers() {
-			roomMembers.sort();
-			_updateMemberDisplay();
-		}
-		
-		function _updateMemberDisplay() {
-				presenceContainer.domNode.innerHTML  =  "";
-				for(var i = 0; i < roomMembers.length; i++) {
-					var member = roomMembers[i];
-					presenceContainer.domNode.innerHTML += member + "<br/>";
-				}
-		}
-		
-		function scrollDown() {
-	      chatArea.domNode.scrollTop = chatArea.domNode.scrollHeight;
-	    }
-		
-		function logout() {
-			willowConnection.disconnect();
-		}
-		
-		
-		
-		
-		</script>
-
-
- </head>
- <body class="soria" >
-	<div dojoType="dijit.Dialog" id="logindialog" title="Chat"
-				execute="login(arguments[0]['name'] ? arguments[0]['name'] : 'guest');">
-		<label for="name">Nickname: </label>
-		<input dojoType=dijit.form.TextBox type="text"  maxlength="16"  name="name" id="name" value="">
-		<button dojoType=dijit.form.Button type="submit">OK</button>
-	</div>
-	
-	<div>
-		<div dojoType="dijit.layout.BorderContainer" style="width:100%; height:100%">
-				<div dojoType="dijit.layout.ContentPane" region="top" style="border:1px solid gray;  height: 20px; background: #eee;">
-					WillowChat now with Dojo 	<button dojoType=dijit.form.Button onClick="logout();" style="font-size:10px;" type="submit">Leave</button>
-				</div>
-				<div dojoType="dijit.layout.ContentPane" region="left" jsId="presenceContainer"  style="width: 100px; border:1px solid gray; background: #eee;" splitter="true" minSize="0" maxSize="250">
-					
-				</div>
-				<div dojoType="dijit.layout.ContentPane" region="center" jsId="chatArea"  style="border:1px solid gray;  background: #eee;" >
-				
-				</div>
-				<div dojoType="dijit.layout.ContentPane" region="bottom" style="height: 50px; border:1px solid gray;  background: #eee;" >
-					<textarea id="messageBox" style="width:90%"></textarea>
-				</div>
-			</div>
-	</div>
-</html>
diff --git a/moksha/widgets/chat/static/themes/dojo/style.css b/moksha/widgets/chat/static/themes/dojo/style.css
deleted file mode 100644
index 29f0a19..0000000
--- a/moksha/widgets/chat/static/themes/dojo/style.css
+++ /dev/null
@@ -1,151 +0,0 @@
-html, body {
-    padding: 0px;
-    margin: 0px;
-    border: none;
-    _overflow: hidden;
- }
-#presenceToggle {
-    border: 1px solid black;
-    position: absolute;
-    right: 1px;
-    top: 1px;
-    padding: 2px;
-    background: #005522;
-    color: white;
-    font-weight: bold;
-    cursor: pointer;
-}
-#presenceToggle:hover {
-}
-#presence {
-    float: right;
-    border: 1px solid gray;
-    width: 130px;
-    height: 83%;
-    margin-left: 3px;
-    margin-bottom: 0px;
-    overflow: hidden;
-}
-#presenceTitle {
-    text-decoration: underline;
-}
-#presenceList {
-    overflow: auto;
-    height: 90%;
-}
-#history {
-    border: 1px solid gray;
-    height: 83%;
-    overflow: auto;
-    margin-bottom: 0px;
-}
-#historySpacer {
-    border: 1px solid red;    
-}
-#inputBar {
-    margin-top: 0px;
-    height: 15%;
-}
-#inputBar textarea {
-    width: 100%;
-    height: 100%;
-    border: 1px solid gray;
-}
-
-
-
-#popup {
-    position: absolute; 
-    height: 100%; 
-    width: 70%; 
-    left: 15%; 
-    z-index: 2;
-}
-
-#popupOuter { 
-    height: 100%;
-    width: 100%;
-    overflow: hidden;
-    position: relative;
-}
-#popupOuter[id] {display: table; position: static;}
-
-#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/
-#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;}
-
-#popupContent {position: relative; top: -50%} /* for explorer only */
-/* optional: #popupContent[id] {position: static;} */
-
-#popupContent {
-    font-size: 120%;
-    text-align:center;
-    background: #005522;
-    color: white;
-    border: 5pt solid #50A572;
-    padding: 8px;
-    padding-bottom: 20px;
-    width: 100%;
-}
-#popupContent p {
-    font-size: 150%;
-}
-
-#absorbClicks {
-    position:absolute;
-    top:0;
-    left:0;
-    width:100%;
-    height:100%;
-}
-
-
-#history div {
-  background-color:#eeffee;
-  padding:.2em;
-  padding-left:1.5em;
-  text-indent: -1em;
-  border-bottom: 1px dotted #ccc;
-}
-#history .message .user {
-  width:5em;
-  font-weight: bold;
-  color:#DD7200;
-  padding-right:.2em;
-  text-align:right;
-}
-#history .message.self .user{
-  color: #B42600;
-}
-#history .message.mentioned{
-  background-color: #d5c5ff;
-}
-#history .message.private{
-  background-color: #ccc;
-}
-#history .message.ctcp {
-  background-color: #f0f;
-}
-#history .action {
-  color: #D68850;
-  font-style:italic;
-}
-#history .action {
-  color: #A94C3B;
-  font-style:italic;
-}
-#history .informative {
-  font-size: 85%;
-  font-style: italic;
-  color:#999;
-  text-align:center;
-  padding:.3em;
-}
-#presenceList .user_entry {
-  font-size: 90%;
-  padding:.2em;
-  padding-left:8pt;
-  border-bottom: 1px dotted #ccc;
-}
-
-
-
diff --git a/moksha/widgets/chat/static/themes/simple/chrome.js b/moksha/widgets/chat/static/themes/simple/chrome.js
deleted file mode 100644
index 4379ce6..0000000
--- a/moksha/widgets/chat/static/themes/simple/chrome.js
+++ /dev/null
@@ -1,83 +0,0 @@
-(function() {
-/* Boilerplate
- */
-if (!window.WillowChat) {
-    Willowchat = {}
-}
-
-if (!WillowChat.chrome) {
-    WillowChat.chrome = {}
-}
-
-if (!WillowChat.chrome.map) {
-    WillowChat.chrome.map = {}
-}
-
-
-WillowChat.chrome.map.simple = WillowChat.chrome.SimpleChrome = function(container, opts) {
-    /* Set configured height
-     */
-    container.style.width = opts.width + 'px'
-    container.style.height = opts.height + 'px'
-    container.style.background = "white";
-    var toggles = document.createElement('div')
-    toggles.setAttribute('id', 'willowchatToggles')
-    var floatToggle = document.createElement('div')
-    floatToggle.setAttribute('id', 'willowchatFloat')
-    floatToggle.innerHTML = "&uarr;"
-    var minToggle = document.createElement('div')
-    minToggle.setAttribute('id', 'willowchatMin')
-    minToggle.innerHTML = "-"
-    floatToggle.setAttribute('style', "float: left;")
-    minToggle.setAttribute('style', "float: left;")
-    var toggleElements = [ minToggle, floatToggle]
-    for (var i = 0; i < 2; ++i) {
-        var t = toggleElements[i]
-        t.style.width = "20px"
-        t.style.height = "20px"
-        t.style.textAlign = "center"
-        t.style.border = "1px solid black"
-        t.style.padding = "2px"
-        t.style.color = "white"
-        t.style.fontWeight = "bold"
-        t.style.background = "#005522"
-        t.style.cursor = "pointer"
-        t.style.cssFloat = "left"
-        t.style.styleFloat = "left"
-        t.style.display = "none"
-    }
-    container.appendChild(toggles)
-    toggles.appendChild(floatToggle)
-    toggles.appendChild(minToggle)
-
-    /* Should it be floating?
-     */
-    if (opts.floating) {
-        container.style.position = 'absolute';
-        container.style.bottom = '0';
-        container.style.right = '0';
-        minToggle.style.display = "block"
-        toggles.style.position = "absolute"
-        toggles.style.top = "1px"
-        toggles.style.left = "1px"
-        if (opts.reposition) {
-            container.parentNode.removeChild(container)
-            document.body.appendChild(container)
-
-        }
-    }
-    else {
-        var ifr = container.getElementsByTagName('iframe')[0]
-        toggles.style.marginBottom="-10px"
-        ifr.style.marginTop="10px"
-        container.removeChild(ifr)
-        container.appendChild(ifr)
-//        toggles.style.marginBottom = "-5px";
-    }
-    if (opts.floatingToggle) {
-        floatToggle.style.display = "block"
-    }
-    toggles.style.border = "1ps solid yellow"
-}
-
-})();
diff --git a/moksha/widgets/chat/static/themes/simple/gui.js b/moksha/widgets/chat/static/themes/simple/gui.js
deleted file mode 100644
index 2b5083f..0000000
--- a/moksha/widgets/chat/static/themes/simple/gui.js
+++ /dev/null
@@ -1,216 +0,0 @@
-(function() {
-
-if (!window.WillowChat) {
-    console.log('no willochat found in gui?');
-    Willowchat = {}
-}
-
-if (!WillowChat.guis) {
-    WillowChat.guis = {}
-}
-
-if (!WillowChat.guis.map) {
-    WillowChat.guis.map = {}
-} 
-var ENTER_KEY = 13
-WillowChat.guis.map.simple = WillowChat.guis.SimpleGui = function(wc, opts) {
-    var self = this;
-    self.presenceShown = true;
-    var logger = Orbited.getLogger('WillowChatTest');
-//    logger.enabled = true;
-    var username = null;
-    var presence = {}
-    
-    $('#nickname').focus();    
-    $('#nickname').keypress( function(e) {
-        var key = e.charCode || e.keyCode || 0
-        if (key == ENTER_KEY) {
-            self.connect();
-        };
-    });
-    $('#chatboxInput').keypress(function(e) {
-        var key = e.charCode || e.keyCode || 0;
-        if (key == ENTER_KEY) {
-        self.sendMessage();
-        return false;
-        };
-    });
-    $("#popupContent p").html(opts.greeting)
-    $("#presenceToggle").click(function() {
-        if (self.presenceShown) {
-            self.presenceShown = false;
-            $("#presence").hide()
-            $("#presenceToggle").html('&larr;');
-        }
-        else {
-            self.presenceShown = true;
-            $("#presence").show();
-            $("#presenceToggle").html('&rarr;');
-        }
-        if (wc.readyState == wc.READY_STATE_CONNECTED) {
-            $('#chatboxInput').focus();
-        }
-        else {
-            $('#nickname').focus();
-        }
-    })
-    var scrollDown = function() {
-      var box = $('#history')[0]
-      box.scrollTop = box.scrollHeight;
-    }
-    var isSubstring = function (sub, str) {
-    // case insensitive substring test
-        return str.toLowerCase().indexOf(sub.toLowerCase()) >= 0;
-    };
-    var sanitize = (function(str) {
-    // See http://bigdingus.com/2007/12/29/html-escaping-in-javascript/
-        var MAP = {
-            '&': '&amp;',
-            '<': '&lt;',
-            '>': '&gt;',
-            '"': '&quot;',
-            "'": '&#39;'
-        };
-        var repl = function(c) { return MAP[c]; };
-        return function(s) {
-            return s.replace(/[&<>'"]/g, repl);
-        };
-    })();
-
-    // TODO: test this out
-    var userRenamed = function(oldname, newname) {
-        $("<div class='informative rename'></div>")
-            .html("<span class='user'>" + oldname + "</span> is now known as " +
-                "<span class='user'>" + newname + "</span>")
-            .appendTo("#history");
-        scrollDown();
-        $("#user_" + oldname)
-            .attr("id", "user_" + newname)
-            .html(newname);
-    }
-    
-    var addName = function (name) {
-        presence[name] = 1
-        $('<div class="user_entry" id="user_' + name + '">' + name + '</div>')
-            .appendTo("#presenceList");
-    };
-    
-    var removeName = function (name) {
-        delete presence[name];
-        $(".user_list #user_" + name).remove()
-    };
-
-    var sortNames = function () {
-        $('#presenceList').empty();
-        var list = [];
-        for (var user in presence) {
-            list.push(user);
-        };
-        list.sort()
-        for (var i=0; i < list.length; i++) {
-            var user = list[i];
-            $('<div class="user_entry" id="user_' + user + '">' + user + '</div>')
-                .appendTo("#presenceList");
-        };
-    };
-    self.connect = function() {
-        username = $("#nickname").val();
-        if (!username) {
-            logger.debug('please enter a username');
-            return
-        }
-        $('#popup, #absorbClicks').hide();
-        $('#chatboxInput').focus();
-        $('#chatboxInput').val('')
-
-        connected = true;
-        wc.connect( {
-            username: username
-        })
-        wc.onConnect = function(data) { 
-            /* This is somewhat important -- without this IE can run into some
-             * issues with reconnecting
-             */
-
-            window.onbeforeunload = function() {
-                if (wc.readyState == wc.READY_STATE_CONNECTED) {
-                return 'Are you sure you want to quit and lose the chat connection?';
-                }
-            };
-            window.onunload = function() {
-                if (wc.readyState == wc.READY_STATE_CONNECTED) {
-                    wc.disconnect();
-                }
-           }
-
-
-            $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history");
-            for (var i = 0; i < wc.presence.length; ++i) {
-                addName(wc.presence[i]);
-            }
-            sortNames();
-            logger.debug('connected', data, wc.presence) 
-        }
-        wc.onMessage = function(sender, message) { 
-            logger.debug('msg', sender, message); 
-            var messagediv = $('<div class="message"></div>');
-        
-            if (sender == username) {
-                messagediv.addClass("self");
-            }
-            if (isSubstring(username, message)) {
-                messagediv.addClass("mentioned");
-            }
-            messagediv.html('<span class="user">' + sender + ':</span> ' +
-                            sanitize(message))
-            .appendTo("#history");
-            scrollDown();
-        }
-        wc.onAction = function(s, m) { logger.debug('action', s, m); }
-
-        wc.onJoin = function(joiner) { 
-            logger.debug('join', joiner);
-            addName(joiner);
-            sortNames();
-            $("<div class='informative join'></div>")
-                .html("<span class='user'>" + joiner + '</span> has joined')
-                .appendTo("#history");
-            scrollDown();
-        }
-        wc.onLeave = function(leaver) { 
-            logger.debug('leave', leaver); 
-            removeName(leaver);
-            $("<div class='informative part'></div>")
-                .html("<span class='user'>" + leaver + '</span> left')
-                .appendTo("#history");
-            scrollDown();
-        }
-        wc.onDisconnect = function() { logger.debug('disconneted'); }
-        wc.onUsernameTaken = function() {
-            logger.debug('onUsernameTaken', username);
-            username += '_'
-            try {
-                wc.rename(username);
-                logger.debug('rename sent');
-            }
-            catch(e) {
-                logger.debug('rename failed:', e)
-            }
-        }
-    }
-    self.sendMessage = function() {
-        var msg = $('#chatboxInput').val();
-        wc.sendMessage(msg)
-        $('#chatboxInput').val('');
-        // the WillowChat server will not echo our message back, so simulate a send.
-        wc.onMessage(username, msg)
-    }
-    self.sendAction = function() {
-        var msg = getMessage()
-        wc.sendAction(msg);
-        logger.debug('action', username, msg)
-    }
-
-}
-})()
-
diff --git a/moksha/widgets/chat/static/themes/simple/index.html b/moksha/widgets/chat/static/themes/simple/index.html
deleted file mode 100644
index ee659cf..0000000
--- a/moksha/widgets/chat/static/themes/simple/index.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<html>
- <head>
-  <link rel="stylesheet" type="text/css" href="style.css">
-<!-- @@ HACK -->
-<script src="http://localhost:9000/static/Orbited.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/irc2.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/willowchat.js"></script>
-<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/gui.js"></script>
-<script src="/toscawidgets/resources/tw.jquery.base/static/javascript/jquery-1.2.6.pack.js"></script>
-  <script src="gui.js"></script>
-  <script>
-    TCPSocket = Orbited.TCPSocket
-    document.domain = document.domain
-
-/*    Orbited.system.enabled = true;
-    Orbited.loggers['Orbited.XSDR'].enabled = false
-    Orbited.loggers['Orbited.CometSession'].enabled = true
-    Orbited.loggers['Orbited.TCPSocket'].enabled = true
-    Orbited.loggers['XSDRBridge'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true
-    Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true 
-    Orbited.loggers['WC.c.IRCClient'].enabled = true
-*/
-  </script>
-
- </head>
- <body> 
-<div id="popup">
-<div id="popupOuter">
-  <div id="popupMiddle">
-    <div id="popupContent">
-      <p>Greeting</p>
-      <label for="nickname">Nickname:</label>
-      <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" />
-    </div>
-  </div>
-</div>
-</div>
-
-
-  <div id="absorbClicks"></div>
-  <div id="presenceToggle">
-    &rarr;
-  </div>
-  <div id="presence">
-   <div id="presenceTitle">Presence</div>
-   <div id="presenceList">
-   </div>
-  </div>
-  <div id="history">
-  </div>
-  <div id="inputBar">
-   <textarea id="chatboxInput"></textarea>
-  </div>
- </body>
-</html>
diff --git a/moksha/widgets/chat/static/themes/simple/style.css b/moksha/widgets/chat/static/themes/simple/style.css
deleted file mode 100644
index 29f0a19..0000000
--- a/moksha/widgets/chat/static/themes/simple/style.css
+++ /dev/null
@@ -1,151 +0,0 @@
-html, body {
-    padding: 0px;
-    margin: 0px;
-    border: none;
-    _overflow: hidden;
- }
-#presenceToggle {
-    border: 1px solid black;
-    position: absolute;
-    right: 1px;
-    top: 1px;
-    padding: 2px;
-    background: #005522;
-    color: white;
-    font-weight: bold;
-    cursor: pointer;
-}
-#presenceToggle:hover {
-}
-#presence {
-    float: right;
-    border: 1px solid gray;
-    width: 130px;
-    height: 83%;
-    margin-left: 3px;
-    margin-bottom: 0px;
-    overflow: hidden;
-}
-#presenceTitle {
-    text-decoration: underline;
-}
-#presenceList {
-    overflow: auto;
-    height: 90%;
-}
-#history {
-    border: 1px solid gray;
-    height: 83%;
-    overflow: auto;
-    margin-bottom: 0px;
-}
-#historySpacer {
-    border: 1px solid red;    
-}
-#inputBar {
-    margin-top: 0px;
-    height: 15%;
-}
-#inputBar textarea {
-    width: 100%;
-    height: 100%;
-    border: 1px solid gray;
-}
-
-
-
-#popup {
-    position: absolute; 
-    height: 100%; 
-    width: 70%; 
-    left: 15%; 
-    z-index: 2;
-}
-
-#popupOuter { 
-    height: 100%;
-    width: 100%;
-    overflow: hidden;
-    position: relative;
-}
-#popupOuter[id] {display: table; position: static;}
-
-#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/
-#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;}
-
-#popupContent {position: relative; top: -50%} /* for explorer only */
-/* optional: #popupContent[id] {position: static;} */
-
-#popupContent {
-    font-size: 120%;
-    text-align:center;
-    background: #005522;
-    color: white;
-    border: 5pt solid #50A572;
-    padding: 8px;
-    padding-bottom: 20px;
-    width: 100%;
-}
-#popupContent p {
-    font-size: 150%;
-}
-
-#absorbClicks {
-    position:absolute;
-    top:0;
-    left:0;
-    width:100%;
-    height:100%;
-}
-
-
-#history div {
-  background-color:#eeffee;
-  padding:.2em;
-  padding-left:1.5em;
-  text-indent: -1em;
-  border-bottom: 1px dotted #ccc;
-}
-#history .message .user {
-  width:5em;
-  font-weight: bold;
-  color:#DD7200;
-  padding-right:.2em;
-  text-align:right;
-}
-#history .message.self .user{
-  color: #B42600;
-}
-#history .message.mentioned{
-  background-color: #d5c5ff;
-}
-#history .message.private{
-  background-color: #ccc;
-}
-#history .message.ctcp {
-  background-color: #f0f;
-}
-#history .action {
-  color: #D68850;
-  font-style:italic;
-}
-#history .action {
-  color: #A94C3B;
-  font-style:italic;
-}
-#history .informative {
-  font-size: 85%;
-  font-style: italic;
-  color:#999;
-  text-align:center;
-  padding:.3em;
-}
-#presenceList .user_entry {
-  font-size: 90%;
-  padding:.2em;
-  padding-left:8pt;
-  border-bottom: 1px dotted #ccc;
-}
-
-
-
diff --git a/moksha/widgets/chat/static/willowchat.js b/moksha/widgets/chat/static/willowchat.js
deleted file mode 100644
index 0561630..0000000
--- a/moksha/widgets/chat/static/willowchat.js
+++ /dev/null
@@ -1,337 +0,0 @@
-(function() {
-
-Orbited.settings.streaming = true
-
-if (window.addEventListener) {
-    window.addEventListener('load', function() { WillowChat.util.setup(); }, false);
-}
-else if (window.attachEvent) {
-    window.attachEvent('onload', function() { WillowChat.util.setup(); });
-}
-
-
-if (!window.WillowChat) {
-    WillowChat = {}
-}
-WillowChat.settings = {}
-WillowChat.settings.hostname = document.domain
-WillowChat.settings.port = (location.port.length > 0) ? location.port : 80
-WillowChat.settings.defaultTheme = 'simple'
-WillowChat.settings.client = 'irc'
-WillowChat.clients = {}
-WillowChat.clients.map = {}
-WillowChat.util = {}
-
-
-if (!WillowChat.guis) {
-    WillowChat.guis = {}
-}
-if (!WillowChat.guis.map) {
-    WillowChat.guis.map = {}
-}
-
-if (!Array.prototype.indexOf) {
-    Array.prototype.indexOf = function(n) {
-        for (var i = 0; i < this.length; ++i) {
-            if (this[i] === n) {
-                return i
-            }
-        }
-        return -1
-    }
-}
-
-
-
-
-WillowChat.util.setup = function() {
-    // TODO: first setup from remote and url
-    // TODO: this is a *really* ugly way to do this... Fix it
-
-    try {
-        var i = location.href.indexOf('&opts=')
-        var opts = JSON.parse(unescape(location.href.slice(i+6)))
-    }
-    catch(e) {
-        // If the options aren't there, then someone must be trying to use this
-        // library manually, which we want to allow.
-        return
-    }
-    // TODO: we actually need to get the "backend" hostname value
-    WillowChat.settings.hostname = 'localhost'
-    var client = new WillowChat.clients.map[WillowChat.settings.client](opts)
-    var gui = new WillowChat.guis.map[opts.theme ? opts.theme : WillowChat.settings.defaultTheme](client, opts)
-
-    return gui
-}
-
-
-
-
-
-WillowChat.BaseClient = function() { 
-    var self = this;
-    self.readyState = self.READY_STATE_INITIALIZED;
-    self.onUsernameTaken = function() { };
-    self.onConnect = function() { };
-    self.onPresence= function() { };
-    self.onDisconnect = function() { };
-    self.onMessage = function() { };
-    self.onJoin = function() { };
-    self.onLeave = function() { };
-    self.onAction = function() { };
-    self.onRename = function() { };
-} 
- 
-WillowChat.BaseClient.prototype.connect = function(options) {
-    var self = this;
-    if (!this.doConnect) {
-        throw new Error("NotImplemented");
-    }
-    var username = options.username
-    if (!username) {
-        throw new Error("Missing username")
-    }
-    var roomId = options.roomId ? options.roomId : self.opts.roomId
-    if (!roomId) {
-        throw new Error("Missing roomId")
-    }
-    var hostname = options.hostname
-    var port = options.port
-    if (!port) {
-        port = 6667
-    }    
-    if (!hostname) {
-        if (!self.opts.addr) {
-            throw new Error("missing connection information");
-        }
-        hostname = self.opts.addr[0]
-        port = self.opts.addr[1]
-    }
-    return self.doConnect(username, roomId, hostname, port);
-};
-WillowChat.BaseClient.prototype.rename = function(newName) {
-    throw new Error("NotImplemented");
-};
-WillowChat.BaseClient.prototype.sendMessage = function(msg) {
-    throw new Error("NotImplemented");
-};
-WillowChat.BaseClient.prototype.sendAction = function(action) {
-    throw new Error("NotImplemented");
-};
-WillowChat.BaseClient.prototype.disconnect = function() {
-    throw new Error("NotImplemented");
-};
-WillowChat.BaseClient.prototype.READY_STATE_INITIALIZED = 0;
-WillowChat.BaseClient.prototype.READY_STATE_CONNECTING = 1;
-WillowChat.BaseClient.prototype.READY_STATE_CONNECTED = 2;
-WillowChat.BaseClient.prototype.READY_STATE_DISCONNECTED = 3;
-
-
-WillowChat.clients.IRCClient = function(opts) {
-    var self = this;
-    self._conn = null;
-    self.opts = opts
-};
-
-WillowChat.clients.IRCClient.prototype = new WillowChat.BaseClient();
-
-WillowChat.clients.IRCClient.prototype.logger = Orbited.getLogger('WC.c.IRCClient');
-WillowChat.clients.map.irc = WillowChat.clients.IRCClient
-
-WillowChat.clients.IRCClient.prototype.disconnect = function() {
-    var self = this;
-    if (self.readyState == self.READY_STATE_DISCONNECTED) {
-        return
-    }
-    self.readyState = self.READY_STATE_DISCONNECTED;
-    // TODO: would be nice to have a quit message or something
-    self._conn.reset()
-    self._conn = null;
-    self.onDisconnect()
-}
-
-
-WillowChat.clients.IRCClient.prototype.doConnect = function(username, roomId, hostname, port) {
-    var self = this;
-    self.username = username
-    self.roomId = roomId;
-    if (self.roomId[0] != '#') {
-        self.roomId = '#' + self.roomId
-    }
-    self._conn = new IRCClient()
-    self.presence = []
-    var irc = self._conn
-    // By default, assume the irc server is on the same host as the willowchat
-    // server
-    
-    function parseName(identity) {
-        // TODO remove privileges from name head.
-        return identity.split("!", 1)[0];
-    }
-    irc.onclose = function() {
-        self.disconnect();
-    }
-    irc.onopen = function() {
-        irc.ident(self.username, '8 *', self.username);
-        irc.nick(self.username);
-    }
-;;; self.logger.debug('do irc.connect', hostname, port)
-    irc.connect(hostname, port)
-    self.readyState = self.READY_STATE_CONNECTING
-
-    irc.onJOIN = function(command) {
-;;;     self.logger.debug('irc.onJOIN', command)
-        // Ignore initial onJoin (before names)
-        var joiner = parseName(command.prefix)
-;;;     self.logger.debug('irc.onJoin.a')
-        self.logger.debug('self.presence', self.presence, Orbited.JSON.stringify(self.presence))
-        if (self.presence.indexOf(joiner) == -1) {
-;;;     self.logger.debug('irc.onJoin.b')
-            self.presence.push(joiner)
-        }
-;;;     self.logger.debug('irc.onJoin.c')
-        if (self.readyState == self.READY_STATE_CONNECTED) {
-;;;     self.logger.debug('irc.onJoin.d')
-            self.onJoin(joiner);
-        }
-;;;     self.logger.debug('irc.onJoin.e')
-    }
-    irc.onPART = irc.onQUIT = function(command) {
-        var leaver = parseName(command.prefix);
-        var message = command.args.join(" ");
-        var i = self.presence.indexOf(leaver)
-        if (i != -1) {
-            self.presence.splice(i,1)
-        }
-        self.onLeave(leaver);
-    }
-    irc.onNICK = function(command) {
-        // See http://tools.ietf.org/html/rfc2812#section-3.1.2
-        var previousNick = parseName(command.prefix);
-        var i = self.presence.indexOf(previousNick)
-        if (i != -1) {
-            self.presence.splice(i,1)
-        }
-        var newNick = command.args[0];
-        if (self.presence.indexOf(newNick) == -1) {
-            self.presence.push(newNick)
-        }
-        self.onPresence()
-    };
-    
-    irc.onPRIVMSG = function(command) {
-        var sender = parseName(command.prefix);
-        var target = command.args[0];
-        var message = command.args[1];
-        self.onMessage(sender, message);
-    }
-    irc.onACTION = function(command) {
-;;;     self.logger.debug('irc.onACTION', command)
-        var sender = parseName(command.prefix);
-        var message = command.args.slice(1).join(" ")
-        self.onAction(sender, message);
-    }
-
-    irc.onresponse = function(command) {
-        self.logger.debug('onresponse', command)
-        var responseCode = parseInt(command.type);
-        if (responseCode == 353) {
-            // 353 is the code for RPL_NAMEREPLY.
-        
-            // The args are:
-            //
-            // """
-            //   <target> ( "=" / "*" / "@" ) <channel>
-            //    :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
-            //
-            //   - "@" is used for secret channels, "*" for private
-            //     channels, and "=" for others (public channels).
-            // """ -- rfc2812    
-            var channel = command.args[2];
-            if (channel != self.roomId)
-                return;
-            var partialUserList = command.args[3].split(' ');
-            for (var i = 0, l = partialUserList.length; i < l; ++i) {
-                // trim the name
-                var name = partialUserList[i].replace(/^\s+|\s+$/g,"");
-                if (name[0] == '@' || name[0] == '+') {
-                    name = name.slice(1);
-                }
-                if (name == "" || self.presence.indexOf(name) != -1) {
-                    continue;
-                }
-                self.presence.push(name)
-            }
-        }
-        else if (responseCode == 366) {
-        // 366 is the code for RPL_ENDOFNAMES.
-            self.readyState = self.READY_STATE_CONNECTED
-            self.onConnect();
-        }
-        else if (responseCode == 376) {
-        //  376     RPL_ENDOFMOTD
-        //  :End of /MOTD command"
-            irc.join(self.roomId);
-        }
-    }
-    irc.onerror = function(command) {
-        self.logger.debug('onerror', command)
-        var responseCode = parseInt(command.type);
-        if (responseCode == 431 || responseCode == 432 || responseCode == 433) {
-        // 431     ERR_NONICKNAMEGIVEN
-        // 432     ERR_ERRONEUSNICKNAME
-        // 433     ERR_NICKNAMEINUSE
-            self.onUsernameTaken();
-        }
-/*        else if (responseCode == 451) {
-        // 451 is the code for ERR_NOTREGISTERED
-        // Probably means the nick we chose was taken
-        }
-*/
-    }
-}
-WillowChat.clients.IRCClient.prototype.rename = function(newUserName) {
-    var self = this;
-    var irc = self._conn;
-    switch(self.readyState) {
-        case self.READY_STATE_CONNECTING:
-        case self.READY_STATE_CONNECTED:
-            irc.nick(newUserName);
-            self.userName = newUserName;
-            break;
-        default:
-            throw new Error("invalid readyState")
-    }    
-}
-
-WillowChat.clients.IRCClient.prototype.sendMessage = function(msg) {
-    var self = this;
-    if (self.readyState != self.READY_STATE_CONNECTED) {
-        throw new Error('invalid readyState: ' + self.readyState);
-    }
-    var irc = self._conn;
-    irc.privmsg(self.roomId, msg);
-}
-
-WillowChat.clients.IRCClient.prototype.sendAction = function(action) {
-    var self = this;
-    if (self.readyState != self.READY_STATE_CONNECTED) {
-        throw new Error('invalid readyState: ' + self.readyState);
-    }
-    var irc = self._conn;
-    irc.action(self.roomId, action);
-}
-
-
-var createXHR = function () {
-    try { return new XMLHttpRequest(); } catch(e) {}
-    try { return new ActiveXObject('MSXML3.XMLHTTP'); } catch(e) {}
-    try { return new ActiveXObject('MSXML2.XMLHTTP.3.0'); } catch(e) {}
-    try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
-    try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
-    throw new Error('Could not find XMLHttpRequest or an alternative.');
-}
-
-
-})()
diff --git a/moksha/widgets/chat/templates/__init__.py b/moksha/widgets/chat/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/moksha/widgets/chat/templates/bootstrap.mak b/moksha/widgets/chat/templates/bootstrap.mak
deleted file mode 100644
index 65ab577..0000000
--- a/moksha/widgets/chat/templates/bootstrap.mak
+++ /dev/null
@@ -1,419 +0,0 @@
-(function() {
-var gatherOptions = function(roomOptions, container) {
-    var opts = {}
-    var containerOptions = [ 'width', 'height', 'roomClass', 'reposition', 'theme' ]
-    for (var key in roomOptions) {
-        opts[key] = roomOptions[key]
-    }
-    for (var i = 0; i < containerOptions.length; ++i) {
-        var key = containerOptions[i]
-        var option = container.getAttribute(key)
-        if (option) {
-            opts[key] = option
-        }
-    }
-    if (!opts.roomId) {
-        var roomId = container.getAttribute('roomId')
-        opts.roomId = roomId ? roomId : 'default'
-    }
-    if (!opts.width) {
-        opts.width = 350;
-    }
-    if (!opts.height) {
-        opts.height = 240;
-    }
-    if (!opts.theme) {
-        opts.theme = 'simple'
-    }
-    if (!opts.greeting) {
-        opts.greeting = "Willow Chat"
-    }
-    return opts
-}
-
-var loaded = function() {
-    if (!window.WillowChat) {
-        WillowChat = {}
-    }
-    if (!WillowChat.util) {
-        WillowChat.util = {}
-    }
-    var container = document.getElementById('willowchat');
-    if (!container) {
-        container = document.createElement('div');
-        container.setAttribute('id', 'willowchat');
-    }
-
-
-    var roomClass = container.getAttribute('roomClass');
-    var roomClass= roomClass ? roomClass : 'default'
-    s = document.createElement('script')
-    var baseurl = 'http://' + WillowChat.hostHeader
-    s.src = baseurl + '/apps/chat/rooms?jsonp=WillowChat.util.optionsCallback&op=info&roomClass=' + roomClass
-
-    WillowChat.util.optionsCallback = function(result) {
-        success = result[0]
-        if (!success) {
-            throw new Error("Failed: " + result[1])
-        }
-        room = result[1]
-        var opts = gatherOptions(room, container);
-        ifr = document.createElement('iframe')
-        var staticurl = baseurl + '/toscawidgets/resources/moksha.api.widgets.chat.chat/static'
-        ifr.src = '/apps/chat/index?json=1&opts=' +  escape(JSON.stringify(opts))
-        ifr.style.border = "0px";
-        ifr.style.width = "100%";
-        ifr.style.height = "100%";
-       var chromeCallback = function() {
-            container.appendChild(ifr)
-            chrome = new WillowChat.chrome.map[opts.theme](container, opts)
-        }
-        var s = document.createElement('script')
-        // TODO: whats the deal with this? Can't we do any better?
-        s.src = staticurl + '/themes/' + opts.theme + '/chrome.js?ienocache=' + Math.floor(Math.random()*10000)
-        if (s.addEventListener) {
-            s.addEventListener('load', chromeCallback, false)
-        }
-        else if (s.attachEvent) {
-            s.attachEvent('onreadystatechange', function() {
-                if (s.readyState == "loaded") {
-                    chromeCallback()
-                }
-            })
-        }
-        if (true) {
-            var k = 3 + 3
-        }
-//        var d = document.createElement('div')
-//        d.innerHTML = 'go'
-//        document.body.appendChild(d)
-        document.getElementsByTagName('head')[0].appendChild(s)
-    }
-    document.getElementsByTagName('head')[0].appendChild(s)
-
-}
-
-$(document).ready(function(){
-    if (!window.WillowChat) { WillowChat = {} }; WillowChat.hostHeader = "${host}";
-    loaded();
-});
-
-})();
-if (!this.JSON) {
-
-// Create a JSON object only if one does not already exist. We create the
-// object in a closure to avoid creating global variables.
-
-    JSON = function () {
-
-        function f(n) {
-            // Format integers to have at least two digits.
-            return n < 10 ? '0' + n : n;
-        }
-
-        Date.prototype.toJSON = function (key) {
-
-            return this.getUTCFullYear()   + '-' +
-                 f(this.getUTCMonth() + 1) + '-' +
-                 f(this.getUTCDate())      + 'T' +
-                 f(this.getUTCHours())     + ':' +
-                 f(this.getUTCMinutes())   + ':' +
-                 f(this.getUTCSeconds())   + 'Z';
-        };
-
-        String.prototype.toJSON =
-        Number.prototype.toJSON =
-        Boolean.prototype.toJSON = function (key) {
-            return this.valueOf();
-        };
-
-        var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-            escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-            gap,
-            indent,
-            meta = {    // table of character substitutions
-                '\b': '\\b',
-                '\t': '\\t',
-                '\n': '\\n',
-                '\f': '\\f',
-                '\r': '\\r',
-                '"' : '\\"',
-                '\\': '\\\\'
-            },
-            rep;
-
-
-        function quote(string) {
-
-// If the string contains no control characters, no quote characters, and no
-// backslash characters, then we can safely slap some quotes around it.
-// Otherwise we must also replace the offending characters with safe escape
-// sequences.
-
-            escapeable.lastIndex = 0;
-            return escapeable.test(string) ?
-                '"' + string.replace(escapeable, function (a) {
-                    var c = meta[a];
-                    if (typeof c === 'string') {
-                        return c;
-                    }
-                    return '\\u' + ('0000' +
-                            (+(a.charCodeAt(0))).toString(16)).slice(-4);
-                }) + '"' :
-                '"' + string + '"';
-        }
-
-
-        function str(key, holder) {
-
-// Produce a string from holder[key].
-
-            var i,          // The loop counter.
-                k,          // The member key.
-                v,          // The member value.
-                length,
-                mind = gap,
-                partial,
-                value = holder[key];
-
-// If the value has a toJSON method, call it to obtain a replacement value.
-
-            if (value && typeof value === 'object' &&
-                    typeof value.toJSON === 'function') {
-                value = value.toJSON(key);
-            }
-
-// If we were called with a replacer function, then call the replacer to
-// obtain a replacement value.
-
-            if (typeof rep === 'function') {
-                value = rep.call(holder, key, value);
-            }
-
-// What happens next depends on the value's type.
-
-            switch (typeof value) {
-            case 'string':
-                return quote(value);
-
-            case 'number':
-
-// JSON numbers must be finite. Encode non-finite numbers as null.
-
-                return isFinite(value) ? String(value) : 'null';
-
-            case 'boolean':
-            case 'null':
-
-// If the value is a boolean or null, convert it to a string. Note:
-// typeof null does not produce 'null'. The case is included here in
-// the remote chance that this gets fixed someday.
-
-                return String(value);
-
-// If the type is 'object', we might be dealing with an object or an array or
-// null.
-
-            case 'object':
-
-// Due to a specification blunder in ECMAScript, typeof null is 'object',
-// so watch out for that case.
-
-                if (!value) {
-                    return 'null';
-                }
-
-// Make an array to hold the partial results of stringifying this object value.
-
-                gap += indent;
-                partial = [];
-
-// If the object has a dontEnum length property, we'll treat it as an array.
-
-                if (typeof value.length === 'number' &&
-                        !(value.propertyIsEnumerable('length'))) {
-
-// The object is an array. Stringify every element. Use null as a placeholder
-// for non-JSON values.
-
-                    length = value.length;
-                    for (i = 0; i < length; i += 1) {
-                        partial[i] = str(i, value) || 'null';
-                    }
-
-// Join all of the elements together, separated with commas, and wrap them in
-// brackets.
-
-                    v = partial.length === 0 ? '[]' :
-                        gap ? '[\n' + gap +
-                                partial.join(',\n' + gap) + '\n' +
-                                    mind + ']' :
-                              '[' + partial.join(',') + ']';
-                    gap = mind;
-                    return v;
-                }
-
-// If the replacer is an array, use it to select the members to be stringified.
-
-                if (rep && typeof rep === 'object') {
-                    length = rep.length;
-                    for (i = 0; i < length; i += 1) {
-                        k = rep[i];
-                        if (typeof k === 'string') {
-                            v = str(k, value);
-                            if (v) {
-                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                            }
-                        }
-                    }
-                } else {
-
-// Otherwise, iterate through all of the keys in the object.
-
-                    for (k in value) {
-                        if (Object.hasOwnProperty.call(value, k)) {
-                            v = str(k, value);
-                            if (v) {
-                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                            }
-                        }
-                    }
-                }
-
-// Join all of the member texts together, separated with commas,
-// and wrap them in braces.
-
-                v = partial.length === 0 ? '{}' :
-                    gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
-                            mind + '}' : '{' + partial.join(',') + '}';
-                gap = mind;
-                return v;
-            }
-        }
-
-// Return the JSON object containing the stringify and parse methods.
-
-        return {
-            stringify: function (value, replacer, space) {
-
-// The stringify method takes a value and an optional replacer, and an optional
-// space parameter, and returns a JSON text. The replacer can be a function
-// that can replace values, or an array of strings that will select the keys.
-// A default replacer method can be provided. Use of the space parameter can
-// produce text that is more easily readable.
-
-                var i;
-                gap = '';
-                indent = '';
-
-// If the space parameter is a number, make an indent string containing that
-// many spaces.
-
-                if (typeof space === 'number') {
-                    for (i = 0; i < space; i += 1) {
-                        indent += ' ';
-                    }
-
-// If the space parameter is a string, it will be used as the indent string.
-
-                } else if (typeof space === 'string') {
-                    indent = space;
-                }
-
-// If there is a replacer, it must be a function or an array.
-// Otherwise, throw an error.
-
-                rep = replacer;
-                if (replacer && typeof replacer !== 'function' &&
-                        (typeof replacer !== 'object' ||
-                         typeof replacer.length !== 'number')) {
-                    throw new Error('JSON.stringify');
-                }
-
-// Make a fake root object containing our value under the key of ''.
-// Return the result of stringifying the value.
-
-                return str('', {'': value});
-            },
-
-
-            parse: function (text, reviver) {
-
-// The parse method takes a text and an optional reviver function, and returns
-// a JavaScript value if the text is a valid JSON text.
-
-                var j;
-
-                function walk(holder, key) {
-
-// The walk method is used to recursively walk the resulting structure so
-// that modifications can be made.
-
-                    var k, v, value = holder[key];
-                    if (value && typeof value === 'object') {
-                        for (k in value) {
-                            if (Object.hasOwnProperty.call(value, k)) {
-                                v = walk(value, k);
-                                if (v !== undefined) {
-                                    value[k] = v;
-                                } else {
-                                    delete value[k];
-                                }
-                            }
-                        }
-                    }
-                    return reviver.call(holder, key, value);
-                }
-
-
-// Parsing happens in four stages. In the first stage, we replace certain
-// Unicode characters with escape sequences. JavaScript handles many characters
-// incorrectly, either silently deleting them, or treating them as line endings.
-
-                cx.lastIndex = 0;
-                if (cx.test(text)) {
-                    text = text.replace(cx, function (a) {
-                        return '\\u' + ('0000' +
-                                (+(a.charCodeAt(0))).toString(16)).slice(-4);
-                    });
-                }
-
-// In the second stage, we run the text against regular expressions that look
-// for non-JSON patterns. We are especially concerned with '()' and 'new'
-// because they can cause invocation, and '=' because it can cause mutation.
-// But just to be safe, we want to reject all unexpected forms.
-
-// We split the second stage into 4 regexp operations in order to work around
-// crippling inefficiencies in IE's and Safari's regexp engines. First we
-// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
-// replace all simple value tokens with ']' characters. Third, we delete all
-// open brackets that follow a colon or comma or that begin the text. Finally,
-// we look to see that the remaining characters are only whitespace or ']' or
-// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
-                if (/^[\],:{}\s]*$/.
-test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
-replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
-replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
-// In the third stage we use the eval function to compile the text into a
-// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-// in JavaScript: it can begin a block or an object literal. We wrap the text
-// in parens to eliminate the ambiguity.
-
-                    j = eval('(' + text + ')');
-
-// In the optional fourth stage, we recursively walk the new structure, passing
-// each name/value pair to a reviver function for possible transformation.
-
-                    return typeof reviver === 'function' ?
-                        walk({'': j}, '') : j;
-                }
-
-// If the text is not JSON parseable, then a SyntaxError is thrown.
-
-                throw new SyntaxError('JSON.parse');
-            }
-        };
-    }();
-}
diff --git a/moksha/widgets/chat/templates/chat.mak b/moksha/widgets/chat/templates/chat.mak
deleted file mode 100644
index a3ab679..0000000
--- a/moksha/widgets/chat/templates/chat.mak
+++ /dev/null
@@ -1,31 +0,0 @@
-<script>
-  TCPSocket = Orbited.TCPSocket
-  document.domain = document.domain;
-</script>
-
-<div id="popup">
-<div id="popupOuter">
-  <div id="popupMiddle">
-    <div id="popupContent">
-      <p>Greeting</p>
-      <label for="nickname">Nickname:</label>
-      <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" />
-    </div>
-  </div>
-</div>
-</div>
-
-  <div id="absorbClicks"></div>
-  <div id="presenceToggle">
-    &rarr;
-  </div>
-  <div id="presence">
-   <div id="presenceTitle">Presence</div>
-   <div id="presenceList">
-   </div>
-  </div>
-  <div id="history">
-  </div>
-  <div id="inputBar">
-   <textarea id="chatboxInput"></textarea>
-  </div>


commit c08444613bcf0504aa2527b44299f66f466f95d6
Author: Luke Macken <lmacken at redhat.com>
Date:   Sun Aug 9 00:25:47 2009 -0400

    Add a moksha.chat app

diff --git a/moksha/apps/chat/MANIFEST.in b/moksha/apps/chat/MANIFEST.in
new file mode 100644
index 0000000..5121d7c
--- /dev/null
+++ b/moksha/apps/chat/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include moksha *.mak *.html *.js *.png *.gif *.css *.jpg *.jpeg
diff --git a/moksha/apps/chat/moksha/__init__.py b/moksha/apps/chat/moksha/__init__.py
new file mode 100644
index 0000000..de40ea7
--- /dev/null
+++ b/moksha/apps/chat/moksha/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/moksha/apps/chat/moksha/apps/__init__.py b/moksha/apps/chat/moksha/apps/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/chat/moksha/apps/chat/__init__.py b/moksha/apps/chat/moksha/apps/chat/__init__.py
new file mode 100644
index 0000000..5447654
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/__init__.py
@@ -0,0 +1,17 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from chat import LiveChatWidget, LiveChatFrameWidget
diff --git a/moksha/apps/chat/moksha/apps/chat/chat.py b/moksha/apps/chat/moksha/apps/chat/chat.py
new file mode 100644
index 0000000..ad53922
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/chat.py
@@ -0,0 +1,50 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors: Luke Macken <lmacken at redhat.com>
+
+from tw.api import Widget, JSLink, CSSLink
+from tw.jquery import jquery_js
+
+from moksha.api.widgets.orbited import orbited_js
+
+irc2_js = JSLink(filename='static/irc2.js',
+                 javascript=[orbited_js],
+                 modname=__name__)
+
+willowchat_js = JSLink(filename='static/willowchat.js',
+                       javascript=[jquery_js, irc2_js],
+                       modname=__name__)
+
+gui_js = JSLink(filename='static/gui.js',
+                javascript=[willowchat_js],
+                modname=__name__)
+
+willowchat_css = CSSLink(filename='static/style.css', modname=__name__)
+
+
+class LiveChatWidget(Widget):
+    name = 'Chat'
+    params = ['bootstrap']
+    bootstrap = JSLink(link='/apps/chat/bootstrap')
+    template = '<div id="willowchat" reposition="true">${bootstrap}</div>'
+    visible = False
+
+
+class LiveChatFrameWidget(Widget):
+    template = 'mako:moksha.apps.chat.templates.chat'
+    javascript = [orbited_js, willowchat_js, irc2_js, gui_js, jquery_js]
+    css = [willowchat_css]
diff --git a/moksha/apps/chat/moksha/apps/chat/controllers/__init__.py b/moksha/apps/chat/moksha/apps/chat/controllers/__init__.py
new file mode 100644
index 0000000..10fd377
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/controllers/__init__.py
@@ -0,0 +1,17 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from chat import ChatController
diff --git a/moksha/apps/chat/moksha/apps/chat/controllers/chat.py b/moksha/apps/chat/moksha/apps/chat/controllers/chat.py
new file mode 100644
index 0000000..6987d9e
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/controllers/chat.py
@@ -0,0 +1,114 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors: Luke Macken <lmacken at redhat.com>
+
+import logging
+log = logging.getLogger(__name__)
+
+import urlparse
+urlparse.uses_netloc.append('irc')
+
+from tg import expose, tmpl_context, config
+from pylons import request
+
+from moksha.lib.base import BaseController
+from moksha.apps.chat import LiveChatFrameWidget
+
+chat_frame_widget = LiveChatFrameWidget('chat_frame')
+
+
+class ChatController(BaseController):
+
+    def __init__(self, *args, **kw):
+        super(ChatController, self).__init__(*args, **kw)
+        self.config = {}
+        backend = config.get('chat.backend')
+        if not backend:
+            log.info('No `chat.backend` defined; disabling chat functionality')
+            return
+        backend = urlparse.urlparse(backend)
+        if hasattr(backend, 'scheme'): # Python 2.5+
+            self.config['backendProtocol'] = backend.scheme
+            self.config['backendAddr'] = [backend.hostname, backend.port]
+        else: # Python 2.4
+            self.config['backendProtocol'] = backend[0]
+            host, port = backend[1].split(':')
+            self.config['backendAddr'] = [host, port]
+        self.config['startBuiltin'] = config.get('chat.builtin', False)
+        self.config['rooms'] = {}
+        display_opts = {
+                'floating': True, 'floatingToggle': False, 'width': 400 ,
+                'height': 300, 'theme': 'simple', 'resizable': True,
+                'greeting': 'Moksha Chat',
+                }
+        for room in config['chat.rooms'].replace(',', ' ').split():
+            self.config['rooms'][room] = {'display': {}}
+            for display_opt, default in display_opts.items():
+                self.config['rooms'][room]['display'][display_opt] = \
+                        config.get('chat.%s.display.%s' % (room, display_opt),
+                                   default)
+            self.config['rooms'][room]['roomAssignmentMode'] = \
+                    config.get('chat.%s.roomAssignmentMode' % room, 'static')
+            self.config['rooms'][room]['staticRoomName'] = \
+                    config.get('chat.%s.staticRoomName' % room, room)
+
+        log.debug('Chat config = %r' % self.config)
+
+    @expose('mako:moksha.templates.widget')
+    def index(self, *args, **kw):
+        tmpl_context.widget = chat_frame_widget
+        return dict(options={})
+
+    @expose('mako:moksha.apps.chat.templates.bootstrap',
+            content_type='text/javascript')
+    def bootstrap(self, *args, **kw):
+        return dict(host=request.headers['host'])
+
+    @expose('json')
+    def rooms(self, roomClass='default', op=None, jsonp=None):
+        opts = None
+        if op:
+            opts = self.jsonp(getattr(self, 'op_%s' % op,
+                                      self.op_not_found)(roomClass), jsonp)
+        else:
+            opts = self.jsonp([False, ["op not specified"]], jsonp)
+        return opts
+
+    def jsonp(self, result, jsonp=None):
+        result = str(result).replace('True', 'true').replace('False', 'false')
+        if jsonp:
+            result = jsonp + '(' + result + ')'
+        return result
+
+    def op_info(self, roomClass):
+        if roomClass not in self.config['rooms']:
+            return [False, ['unknown room class: ' + roomClass]]
+        info = self.config['rooms'][roomClass]
+        displayInfo = info.get('display', {})
+        opts = {}
+        opts.update(displayInfo)
+        mode = info.get('roomAssignmentMode', 'static')
+        if mode == 'static':
+            opts['roomId'] = info.get('staticRoomName', 'default')
+        elif mode == 'referrer':
+            opts['roomId'] = request.headers.get('referer', 'default')
+        opts['protocol'] = self.config['backendProtocol']
+        opts['addr'] = self.config['backendAddr']
+        return [True, opts]
+
+    def op_not_found(self):
+        return [False, ['unrecognized op']]
diff --git a/moksha/apps/chat/moksha/apps/chat/static/chat.css b/moksha/apps/chat/moksha/apps/chat/static/chat.css
new file mode 100644
index 0000000..fe0d13f
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/chat.css
@@ -0,0 +1,119 @@
+#signin_popup {
+  width:220pt;
+  padding:2em;
+  padding-bottom:3em;
+  text-align:center;
+  background-color: #A4C9D6;
+  color:#0E3541;
+  border: 5pt solid #195263;
+  position:absolute;
+  top:80pt;
+  left:100pt;
+  z-index:2;
+}
+#nickname {
+  width:90pt;
+}
+#absorb_clicks {
+  position:absolute;
+  top:0;
+  left:0;
+  width:300pt;
+  height:200pt;
+}
+
+.chatbox {
+  width:490pt;
+  font: 100% Verdana, sans-serif;
+  background-color:#24758E;
+  padding:5pt;
+  position:relative;
+}
+.chatbox .left_column {
+  width: 360pt;
+}
+.chatbox .chathistory {
+  width:100%;
+  height:217pt;
+  overflow: auto;
+  background-color: white;
+}
+.chatbox .chathistory div {
+  background-color:#ffffee;
+  padding:.2em;
+  padding-left:1.5em;
+  text-indent: -1em;
+  border-bottom: 1px dotted #ccc;
+}
+.chatbox .chathistory .message .user {
+  width:5em;
+  font-weight: bold;
+  color:#DD7200;
+  padding-right:.2em;
+  text-align:right;
+}
+.chatbox .chathistory .message.self .user{
+  color: #B42600;
+}
+.chatbox .chathistory .message.mentioned{
+  background-color: #d5c5ff;
+}
+.chatbox .chathistory .message.private{
+  background-color: #ccc;
+}
+.chatbox .chathistory .message.ctcp {
+  background-color: #f0f;
+}
+.chatbox .chathistory .action,
+.chatbox .chathistory .action .user {
+  color: #D68850;
+  font-style:italic;
+}
+.chatbox .chathistory .action.self,
+.chatbox .chathistory .action.self .user {
+  color: #A94C3B;
+  font-style:italic;
+}
+.chatbox .chathistory .informative {
+  font-size: 85%;
+  font-style: italic;
+  color:#999;
+  text-align:center;
+  padding:.3em;
+}
+
+.chatbox .chatbox_input {
+  width:100%;
+  height:30pt;
+  margin:0;
+  margin-top:3pt;
+  padding:0;
+  border:0;
+  font-family: Verdana, sans-serif;
+}
+
+.chatbox .user_list {
+  float:right;
+  position: absolute;
+  padding:0;
+  margin:0;
+  right:5pt;
+  top:5pt;
+  background-color:white;
+  width:127pt;
+  height:250pt;
+  overflow:auto;
+}
+.chatbox .user_list .user_entry{
+  padding:.2em;
+  padding-left:8pt;
+  border-bottom: 1px dotted #ccc;
+}
+
+#events {
+  visibility:hidden;
+  border:0;
+  width:0;
+  height:0;
+/*  display:none;*/
+}
diff --git a/moksha/apps/chat/moksha/apps/chat/static/chrome.js b/moksha/apps/chat/moksha/apps/chat/static/chrome.js
new file mode 100644
index 0000000..34caca5
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/chrome.js
@@ -0,0 +1,83 @@
+(function() {
+/* Boilerplate
+ */
+if (!window.WillowChat) {
+    Willowchat = {}
+}
+
+if (!WillowChat.chrome) {
+    WillowChat.chrome = {}
+}
+
+if (!WillowChat.chrome.map) {
+    WillowChat.chrome.map = {}
+}
+
+
+WillowChat.chrome.map.simple = WillowChat.chrome.SimpleChrome = function(container, opts) {
+    /* Set configured height
+     */
+    container.style.width = opts.width + 'px'
+    container.style.height = opts.height + 'px'
+    container.style.background = "white";
+    var toggles = document.createElement('div')
+    toggles.setAttribute('id', 'willowchatToggles')
+    var floatToggle = document.createElement('div')
+    floatToggle.setAttribute('id', 'willowchatFloat')
+    floatToggle.innerHTML = "&uarr;"
+    var minToggle = document.createElement('div')
+    minToggle.setAttribute('id', 'willowchatMin')
+    minToggle.innerHTML = "-"
+    floatToggle.setAttribute('style', "float: left;")
+    minToggle.setAttribute('style', "float: left;")
+    var toggleElements = [ minToggle, floatToggle]
+    for (var i = 0; i < 2; ++i) {
+        var t = toggleElements[i]
+        t.style.width = "20px"
+        t.style.height = "20px"
+        t.style.textAlign = "center"
+        t.style.border = "1px solid black"
+        t.style.padding = "2px"
+        t.style.color = "white"
+        t.style.fontWeight = "bold"
+        t.style.background = "#005522"
+        t.style.cursor = "pointer"
+        t.style.cssFloat = "left"
+        t.style.styleFloat = "left"
+        t.style.display = "none"
+    }
+    container.appendChild(toggles)
+    toggles.appendChild(floatToggle)
+    toggles.appendChild(minToggle)
+
+    /* Should it be floating?
+     */
+    if (opts.floating) {
+        container.style.position = 'absolute';
+        container.style.bottom = '0';
+        container.style.right = '0';
+        minToggle.style.display = "block"
+        toggles.style.position = "absolute"
+        toggles.style.top = "1px"
+        toggles.style.left = "1px"
+        if (opts.reposition) {
+            container.parentNode.removeChild(container)
+            document.body.appendChild(container)
+
+        }
+    }
+    else {
+        var ifr = container.getElementsByTagName('iframe')[0]
+        toggles.style.marginBottom="-10px"
+        ifr.style.marginTop="10px"
+        container.removeChild(ifr)
+        container.appendChild(ifr)
+//        toggles.style.marginBottom = "-5px";
+    }
+    if (opts.floatingToggle) {
+        floatToggle.style.display = "block"
+    }
+    toggles.style.border = "1ps solid yellow"
+}
+
+})();
\ No newline at end of file
diff --git a/moksha/apps/chat/moksha/apps/chat/static/gui.js b/moksha/apps/chat/moksha/apps/chat/static/gui.js
new file mode 100644
index 0000000..2972753
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/gui.js
@@ -0,0 +1,215 @@
+(function() {
+
+if (!window.WillowChat) {
+    Willowchat = {}
+}
+
+if (!WillowChat.guis) {
+    WillowChat.guis = {}
+}
+
+if (!WillowChat.guis.map) {
+    WillowChat.guis.map = {}
+} 
+var ENTER_KEY = 13
+WillowChat.guis.map.simple = WillowChat.guis.SimpleGui = function(wc, opts) {
+    var self = this;
+    self.presenceShown = true;
+    var logger = Orbited.getLogger('WillowChatTest');
+//    logger.enabled = true;
+    var username = null;
+    var presence = {}
+    
+    $('#nickname').focus();    
+    $('#nickname').keypress( function(e) {
+        var key = e.charCode || e.keyCode || 0
+        if (key == ENTER_KEY) {
+            self.connect();
+        };
+    });
+    $('#chatboxInput').keypress(function(e) {
+        var key = e.charCode || e.keyCode || 0;
+        if (key == ENTER_KEY) {
+        self.sendMessage();
+        return false;
+        };
+    });
+    $("#popupContent p").html(opts.greeting)
+    $("#presenceToggle").click(function() {
+        if (self.presenceShown) {
+            self.presenceShown = false;
+            $("#presence").hide()
+            $("#presenceToggle").html('&larr;');
+        }
+        else {
+            self.presenceShown = true;
+            $("#presence").show();
+            $("#presenceToggle").html('&rarr;');
+        }
+        if (wc.readyState == wc.READY_STATE_CONNECTED) {
+            $('#chatboxInput').focus();
+        }
+        else {
+            $('#nickname').focus();
+        }
+    })
+    var scrollDown = function() {
+      var box = $('#history')[0]
+      box.scrollTop = box.scrollHeight;
+    }
+    var isSubstring = function (sub, str) {
+    // case insensitive substring test
+        return str.toLowerCase().indexOf(sub.toLowerCase()) >= 0;
+    };
+    var sanitize = (function(str) {
+    // See http://bigdingus.com/2007/12/29/html-escaping-in-javascript/
+        var MAP = {
+            '&': '&amp;',
+            '<': '&lt;',
+            '>': '&gt;',
+            '"': '&quot;',
+            "'": '&#39;'
+        };
+        var repl = function(c) { return MAP[c]; };
+        return function(s) {
+            return s.replace(/[&<>'"]/g, repl);
+        };
+    })();
+
+    // TODO: test this out
+    var userRenamed = function(oldname, newname) {
+        $("<div class='informative rename'></div>")
+            .html("<span class='user'>" + oldname + "</span> is now known as " +
+                "<span class='user'>" + newname + "</span>")
+            .appendTo("#history");
+        scrollDown();
+        $("#user_" + oldname)
+            .attr("id", "user_" + newname)
+            .html(newname);
+    }
+    
+    var addName = function (name) {
+        presence[name] = 1
+        $('<div class="user_entry" id="user_' + name + '">' + name + '</div>')
+            .appendTo("#presenceList");
+    };
+    
+    var removeName = function (name) {
+        delete presence[name];
+        $(".user_list #user_" + name).remove()
+    };
+
+    var sortNames = function () {
+        $('#presenceList').empty();
+        var list = [];
+        for (var user in presence) {
+            list.push(user);
+        };
+        list.sort()
+        for (var i=0; i < list.length; i++) {
+            var user = list[i];
+            $('<div class="user_entry" id="user_' + user + '">' + user + '</div>')
+                .appendTo("#presenceList");
+        };
+    };
+    self.connect = function() {
+        username = $("#nickname").val();
+        if (!username) {
+            logger.debug('please enter a username');
+            return
+        }
+        $('#popup, #absorbClicks').hide();
+        $('#chatboxInput').focus();
+        $('#chatboxInput').val('')
+
+        connected = true;
+        wc.connect( {
+            username: username
+        })
+        wc.onConnect = function(data) { 
+            /* This is somewhat important -- without this IE can run into some
+             * issues with reconnecting
+             */
+
+            window.onbeforeunload = function() {
+                if (wc.readyState == wc.READY_STATE_CONNECTED) {
+                return 'Are you sure you want to quit and lose the chat connection?';
+                }
+            };
+            window.onunload = function() {
+                if (wc.readyState == wc.READY_STATE_CONNECTED) {
+                    wc.disconnect();
+                }
+           }
+
+
+            $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history");
+            for (var i = 0; i < wc.presence.length; ++i) {
+                addName(wc.presence[i]);
+            }
+            sortNames();
+            logger.debug('connected', data, wc.presence) 
+        }
+        wc.onMessage = function(sender, message) { 
+            logger.debug('msg', sender, message); 
+            var messagediv = $('<div class="message"></div>');
+        
+            if (sender == username) {
+                messagediv.addClass("self");
+            }
+            if (isSubstring(username, message)) {
+                messagediv.addClass("mentioned");
+            }
+            messagediv.html('<span class="user">' + sender + ':</span> ' +
+                            sanitize(message))
+            .appendTo("#history");
+            scrollDown();
+        }
+        wc.onAction = function(s, m) { logger.debug('action', s, m); }
+
+        wc.onJoin = function(joiner) { 
+            logger.debug('join', joiner);
+            addName(joiner);
+            sortNames();
+            $("<div class='informative join'></div>")
+                .html("<span class='user'>" + joiner + '</span> has joined')
+                .appendTo("#history");
+            scrollDown();
+        }
+        wc.onLeave = function(leaver) { 
+            logger.debug('leave', leaver); 
+            removeName(leaver);
+            $("<div class='informative part'></div>")
+                .html("<span class='user'>" + leaver + '</span> left')
+                .appendTo("#history");
+            scrollDown();
+        }
+        wc.onDisconnect = function() { logger.debug('disconneted'); }
+        wc.onUsernameTaken = function() {
+            logger.debug('onUsernameTaken', username);
+            username += '_'
+            try {
+                wc.rename(username);
+                logger.debug('rename sent');
+            }
+            catch(e) {
+                logger.debug('rename failed:', e)
+            }
+        }
+    }
+    self.sendMessage = function() {
+        var msg = $('#chatboxInput').val();
+        wc.sendMessage(msg)
+        $('#chatboxInput').val('');
+        // the WillowChat server will not echo our message back, so simulate a send.
+        wc.onMessage(username, msg)
+    }
+    self.sendAction = function() {
+        var msg = getMessage()
+        wc.sendAction(msg);
+        logger.debug('action', username, msg)
+    }
+
+}
+})()
+
diff --git a/moksha/apps/chat/moksha/apps/chat/static/index.html b/moksha/apps/chat/moksha/apps/chat/static/index.html
new file mode 100644
index 0000000..470b999
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/index.html
@@ -0,0 +1,48 @@
+<!-- @@ HACK -->
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/irc2.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/willowchat.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/gui.js"></script>
+<script src="/toscawidgets/resources/tw.jquery.base/static/javascript/jquery-1.2.6.pack.js"></script>
+<link rel="stylesheet" type="text/css" href="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/style.css"></link>
+  <script>
+    TCPSocket = Orbited.TCPSocket
+    document.domain = document.domain;
+/*    Orbited.system.enabled = true;
+    Orbited.loggers['Orbited.XSDR'].enabled = false
+    Orbited.loggers['Orbited.CometSession'].enabled = true
+    Orbited.loggers['Orbited.TCPSocket'].enabled = true
+    Orbited.loggers['XSDRBridge'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true.
+    Orbited.loggers['WC.c.IRCClient'].enabled = true
+*/
+  </script>
+
+<div id="popup">
+<div id="popupOuter">
+  <div id="popupMiddle">
+    <div id="popupContent">
+      <p>Greeting</p>
+      <label for="nickname">Nickname:</label>
+      <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" />
+    </div>
+  </div>
+</div>
+</div>
+
+  <div id="absorbClicks"></div>
+  <div id="presenceToggle">
+    &rarr;
+  </div>
+  <div id="presence">
+   <div id="presenceTitle">Presence</div>
+   <div id="presenceList">
+   </div>
+  </div>
+  <div id="history">
+  </div>
+  <div id="inputBar">
+   <textarea id="chatboxInput"></textarea>
+  </div>
diff --git a/moksha/apps/chat/moksha/apps/chat/static/irc2.js b/moksha/apps/chat/moksha/apps/chat/static/irc2.js
new file mode 100644
index 0000000..175be14
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/irc2.js
@@ -0,0 +1,224 @@
+/* irc.js
+ *  This IRC client runs in a web browser using pure JavaScript
+ *  Orbited 0.5+ required
+ *
+ *  Methods:
+ *      connect(hostname, port)
+ *      ident(nickname, modes, real_name)
+ *      join(channel)
+ *      names(channel)
+ *      part(channel)
+ *      quit(reason)
+ *      privmsg(destination, message)
+ *
+ *  Callbacks:
+ *      Built-in callbacks are onconnect(), onerror(), onresponse(), and onclose()
+ *      onerror and onreply are passed numerical reponse codes, see:
+ *      http://www.irchelp.org/irchelp/rfc/chapter6.html for a list of IRC response
+ *      codes.
+ *
+ *      To add callbacks for IRC actions, for instance PRIVMSG,
+ *          set onPRIVMSG = function(command) {...you code here...}
+ *      See the included IRC demo (/static/demos/irc) for example usage
+ *
+ * Frank Salim (frank.salim at gmail.com)
+ * ©2008 The Orbited Project
+ */
+
+// TODO DRY this by creating a common logging infrastructure (this is also on stomp.js)
+IRC_DEBUG = false;
+
+if (IRC_DEBUG && typeof(Orbited)) {
+    var getIrcLogger = function(name) {
+        var logger = Orbited.getLogger(name);
+        if (!("dir" in logger)) {
+            logger.dir = function() {};
+        }
+        return logger;
+    }
+}
+else if (IRC_DEBUG && typeof(console)) {
+    var getIrcLogger = function(name) {
+        return {
+            debug: function() {
+                var args = Array.prototype.slice.call(arguments);
+                args.unshift(name, ": ");
+                console.debug.apply(console, args);
+            },
+            dir: function() {
+                console.debug(name, ":");
+                console.dir.apply(console, arguments);
+            }
+        };
+    };
+}
+else {
+    var getIrcLogger = function(name) {
+        return {
+            debug: function() {},
+            dir: function() {}
+        };
+    };
+}
+
+IRCClient = function() {
+    var log = getIrcLogger("IRCClient");
+    var self = this
+    var conn = null
+    var buffer = ""
+    var ENDL = "\r\n"
+
+    self.onopen = function() {};
+    self.onconnect = function() {}      // Do nothing in default callbacks
+    self.onclose = function() {}
+    self.onerror = function(command) {}
+    self.onresponse = function(command) {}     // used for numerical replies
+                            
+    self.connect = function(hostname, port) {
+        log.debug("connect");
+        conn = self._createTransport();
+        conn.onopen = conn_opened
+        conn.onclose = conn_closed
+        conn.onread = conn_read
+        conn.open(hostname, port)
+        // TODO set onerror.
+    }
+    self._createTransport = function() {
+        return new TCPSocket();
+    };
+    self.close = function() {
+        log.debug("close");
+        conn.close()
+        conn.onopen = null;
+        conn.onclose = null;
+        conn.onread = null;
+        self.onclose()
+    }
+    self.ident = function(nickname, modes, real_name) {
+        send("USER", nickname + " " + modes + " :" + real_name) 
+    }
+    self.nick = function(nickname) {
+        send("NICK", nickname)
+    }
+    self.join = function(channel) {
+        send("JOIN", channel)
+    }
+    self.names = function(channel) {
+        send("NAMES", channel)
+    }
+    self.part = function(channel, reason) {
+        send("PART", channel + " :" + reason)
+    }
+    self.quit = function(reason) {
+        var reason = reason || "leaving";
+        send("QUIT", ":" + reason)
+        conn.close()
+    }
+    self.reset = function() {
+        conn.reset();
+    }
+    self.action = function(destination, message) {
+        send('PRIVMSG', destination + ' :\01ACTION ' + message + '\01')
+    }
+
+    self.privmsg = function(destination, message) {
+        send('PRIVMSG', destination + ' :' + message)
+    }
+
+    // Socket Callbacks
+    var conn_opened = function() {
+        self.onopen()
+    }
+    var conn_closed = function() {
+        self.onclose()
+    }
+    var conn_read = function(data) {
+        log.debug("data:");
+        log.debug(data);
+        buffer += data
+        parse_buffer()
+    }
+
+    // Internal Functions
+    var send = function(type, payload) {
+        log.debug("send: " + payload);
+        conn.send(type + " " + payload + ENDL);
+    };
+    var parse_buffer= function() {
+        var commands = buffer.split(ENDL);
+        buffer = commands[commands.length-1];
+        for (var i = 0, l = commands.length - 1; i < l; ++i) {
+            var line = commands[i];
+            if (line.length > 0)
+                dispatch(line);
+        }
+    };
+    var parse_command = function(s) {
+        // See http://tools.ietf.org/html/rfc2812#section-2.3
+
+        // all the arguments are split by a single space character until
+        // the first ":" character.  the ":" marks the start of the last
+        // trailing argument which can contain embeded space characters.
+        var i = s.indexOf(" :");
+        if (i >= 0) {
+            var args = s.slice(0, i).split(' ');
+            args.push(s.slice(i + 2));
+        } else {
+            var args = s.split(' ');
+        }
+
+        // extract the prefix (if there is one).
+        if (args[0].charAt(0) == ":") {
+          var prefix = args.shift().slice(1);
+        } else {
+          var prefix = null;
+        }
+
+        var command = {
+            prefix: prefix,
+            type: args.shift(),
+            args: args
+        };
+        log.debug("command:");
+        log.dir(command);
+        return command;
+    };
+    var dispatch = function(line) {
+        command = parse_command(line);
+        if (command.type == "PING") {
+            send("PONG", ":" + command.args)
+        }
+        if (!isNaN(parseInt(command.type))) {
+            var error_code = parseInt(command.type)
+            if (error_code > 400)
+                return self.onerror(command)
+            else
+                return self.onresponse(command)
+        } 
+        if (command.type == "PRIVMSG") {
+            msg = command.args[1]
+            if (msg.charCodeAt(0) == 1 && msg.charCodeAt(msg.length-1) == 1) {
+                var args = [command.args[0]]
+                var newargs = msg.slice(1, msg.length - 1).split(' ')
+                if (newargs[0] == 'ACTION') {
+                    command.type = newargs.shift()
+                }
+                else {
+                    command.type = 'CTCP'
+                }
+
+                for (var i = 0; i < newargs.length; ++i) {
+                    args.push(newargs[i])
+                }
+                command.args = args
+            }
+        }
+        if (typeof(self["on" + command.type]) == "function") {
+            // XXX the user is able to define unknown command handlers,
+            //     but cannot send any arbitrary command
+            self["on" + command.type](command);
+        } else {
+            log.debug("unhandled command received: ", command.type);
+        }
+    };
+};
diff --git a/moksha/apps/chat/moksha/apps/chat/static/style.css b/moksha/apps/chat/moksha/apps/chat/static/style.css
new file mode 100644
index 0000000..c92d64e
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/style.css
@@ -0,0 +1,153 @@
+/*
+html, body {
+    padding: 0px;
+    margin: 0px;
+    border: none;
+    _overflow: hidden;
+ }
+     */
+#presenceToggle {
+    border: 1px solid black;
+    position: absolute;
+    right: 1px;
+    top: 1px;
+    padding: 2px;
+    background: #3f9824;
+    color: white;
+    font-weight: bold;
+    cursor: pointer;
+}
+#presenceToggle:hover {
+}
+#presence {
+    float: right;
+    border: 1px solid gray;
+    width: 130px;
+    height: 83%;
+    margin-left: 3px;
+    margin-bottom: 0px;
+    overflow: hidden;
+}
+#presenceTitle {
+    text-decoration: underline;
+}
+#presenceList {
+    overflow: auto;
+    height: 90%;
+}
+#history {
+    border: 1px solid gray;
+    height: 83%;
+    overflow: auto;
+    margin-bottom: 0px;
+}
+#historySpacer {
+    border: 1px solid red;    
+}
+#inputBar {
+    margin-top: 0px;
+    height: 15%;
+}
+#inputBar textarea {
+    width: 100%;
+    height: 100%;
+    border: 1px solid gray;
+}
+
+
+
+#popup {
+    position: absolute; 
+    height: 100%; 
+    width: 70%; 
+    left: 15%; 
+    z-index: 2;
+}
+
+#popupOuter { 
+    height: 100%;
+    width: 100%;
+    overflow: hidden;
+    position: relative;
+}
+#popupOuter[id] {display: table; position: static;}
+
+#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/
+#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;}
+
+#popupContent {position: relative; top: -50%} /* for explorer only */
+/* optional: #popupContent[id] {position: static;} */
+
+#popupContent {
+    font-size: 120%;
+    text-align:center;
+    background: #3f9824;
+    color: white;
+    border: 5pt solid #83cb22;
+    padding: 8px;
+    padding-bottom: 20px;
+    width: 100%;
+}
+#popupContent p {
+    font-size: 150%;
+}
+
+#absorbClicks {
+    position:absolute;
+    top:0;
+    left:0;
+    width:100%;
+    height:100%;
+}
+
+
+#history div {
+  background-color:#eeffee;
+  padding:.2em;
+  padding-left:1.5em;
+  text-indent: -1em;
+  border-bottom: 1px dotted #ccc;
+}
+#history .message .user {
+  width:5em;
+  font-weight: bold;
+  color:#DD7200;
+  padding-right:.2em;
+  text-align:right;
+}
+#history .message.self .user{
+  color: #B42600;
+}
+#history .message.mentioned{
+  background-color: #d5c5ff;
+}
+#history .message.private{
+  background-color: #ccc;
+}
+#history .message.ctcp {
+  background-color: #f0f;
+}
+#history .action {
+  color: #D68850;
+  font-style:italic;
+}
+#history .action {
+  color: #A94C3B;
+  font-style:italic;
+}
+#history .informative {
+  font-size: 85%;
+  font-style: italic;
+  color:#999;
+  text-align:center;
+  padding:.3em;
+}
+#presenceList .user_entry {
+  font-size: 90%;
+  padding:.2em;
+  padding-left:8pt;
+  border-bottom: 1px dotted #ccc;
+}
+
+
+
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/chrome.js b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/chrome.js
new file mode 100644
index 0000000..770701f
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/chrome.js
@@ -0,0 +1,83 @@
+(function() {
+/* Boilerplate
+ */
+if (!window.WillowChat) {
+    Willowchat = {}
+}
+
+if (!WillowChat.chrome) {
+    WillowChat.chrome = {}
+}
+
+if (!WillowChat.chrome.map) {
+    WillowChat.chrome.map = {}
+}
+
+
+WillowChat.chrome.map.dojo = WillowChat.chrome.DojoChrome = function(container, opts) {
+    /* Set configured height
+     */
+    container.style.width = opts.width + 'px'
+    container.style.height = opts.height + 'px'
+    container.style.background = "white";
+    var toggles = document.createElement('div')
+    toggles.setAttribute('id', 'willowchatToggles')
+    var floatToggle = document.createElement('div')
+    floatToggle.setAttribute('id', 'willowchatFloat')
+    floatToggle.innerHTML = "&uarr;"
+    var minToggle = document.createElement('div')
+    minToggle.setAttribute('id', 'willowchatMin')
+    minToggle.innerHTML = "-"
+    floatToggle.setAttribute('style', "float: left;")
+    minToggle.setAttribute('style', "float: left;")
+    var toggleElements = [ minToggle, floatToggle]
+    for (var i = 0; i < 2; ++i) {
+        var t = toggleElements[i]
+        t.style.width = "20px"
+        t.style.height = "20px"
+        t.style.textAlign = "center"
+        t.style.border = "1px solid black"
+        t.style.padding = "2px"
+        t.style.color = "white"
+        t.style.fontWeight = "bold"
+        t.style.background = "#005522"
+        t.style.cursor = "pointer"
+        t.style.cssFloat = "left"
+        t.style.styleFloat = "left"
+        t.style.display = "none"
+    }
+    container.appendChild(toggles)
+    toggles.appendChild(floatToggle)
+    toggles.appendChild(minToggle)
+
+    /* Should it be floating?
+     */
+    if (opts.floating) {
+        container.style.position = 'absolute';
+        container.style.bottom = '0';
+        container.style.right = '0';
+        minToggle.style.display = "block"
+        toggles.style.position = "absolute"
+        toggles.style.top = "1px"
+        toggles.style.left = "1px"
+        if (opts.reposition) {
+            container.parentNode.removeChild(container)
+            document.body.appendChild(container)
+
+        }
+    }
+    else {
+        var ifr = container.getElementsByTagName('iframe')[0]
+        toggles.style.marginBottom="-10px"
+        ifr.style.marginTop="10px"
+        container.removeChild(ifr)
+        container.appendChild(ifr)
+//        toggles.style.marginBottom = "-5px";
+    }
+    if (opts.floatingToggle) {
+        floatToggle.style.display = "block"
+    }
+    toggles.style.border = "1ps solid yellow"
+}
+
+})();
\ No newline at end of file
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/gui.js b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/gui.js
new file mode 100644
index 0000000..b042620
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/gui.js
@@ -0,0 +1,19 @@
+
+
+if (!window.WillowChat) {
+    Willowchat = {}
+}
+
+if (!WillowChat.guis) {
+    WillowChat.guis = {}
+}
+
+if (!WillowChat.guis.map) {
+    WillowChat.guis.map = {}
+} 
+
+var willowConnection = null;
+WillowChat.guis.map.dojo = WillowChat.guis.DojoGui = function(wc, opts) {
+  console.log("Neat? ", wc, opts);
+ willowConnection = wc;
+}
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/index.html b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/index.html
new file mode 100644
index 0000000..8205a22
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/index.html
@@ -0,0 +1,226 @@
+<html>
+ <head>
+  <link rel="stylesheet" type="text/css" href="style.css">
+<script src="http://localhost:9000/static/Orbited.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/irc2.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/willowchat.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/gui.js"></script>
+<script src="gui.js"></script>
+  <script>
+    TCPSocket = Orbited.TCPSocket
+    document.domain = document.domain
+/*    Orbited.system.enabled = true;
+    Orbited.loggers['Orbited.XSDR'].enabled = false
+    Orbited.loggers['Orbited.CometSession'].enabled = true
+    Orbited.loggers['Orbited.TCPSocket'].enabled = true
+    Orbited.loggers['XSDRBridge'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true 
+    Orbited.loggers['WC.c.IRCClient'].enabled = true
+*/
+  </script>
+
+
+	<link rel="stylesheet" 
+			href="http://o.aolcdn.com/dojo/1.2/dijit/themes/soria/soria.css">
+		<!-- load Dojo, and all the required modules -->
+		
+		<script type="text/javascript">
+
+				djConfig = {
+					isDebug: true,
+					baseUrl: "./",
+					xdWaitSeconds: 10,
+					parseOnLoad: true
+				};
+			</script>
+		
+		<script src="http://o.aolcdn.com/dojo/1.2/dojo/dojo.xd.js" ></script>
+		
+		<script>
+		
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.Dialog");
+		
+		
+		var username = null;
+		var roomMembers = [];
+		
+		dojo.addOnLoad(function() {
+			dijit.byId("logindialog").show();
+			console.log("hi?", willowConnection);
+			
+			
+			var mssageBox = dojo.byId("messageBox");
+			dojo.connect(mssageBox, "keyup", function(e) {
+		        var key = e.charCode || e.keyCode || 0
+		        if (key == dojo.keys.ENTER) {
+					var msg = mssageBox.value;
+		           	willowConnection.sendMessage(msg)
+			        willowConnection.onMessage(username, msg);
+					mssageBox.value = "";
+		        };
+		    });
+	
+			
+		});
+		
+		function login(nickname) {
+			username = nickname;
+			 willowConnection.connect( {
+		            username: nickname
+		        });
+		
+		
+		
+		
+				    willowConnection.onConnect = function(data) { 
+			            /* This is somewhat important -- without this IE can run into some
+			             * issues with reconnecting
+			             */
+
+			            window.onbeforeunload = function() {
+			                if (willowConnection.readyState == willowConnection.READY_STATE_CONNECTED) {
+			                return 'Are you sure you want to quit and lose the chat connection?';
+			                }
+			            };
+			            window.onunload = function() {
+			                if (willowConnection.readyState == willowConnection.READY_STATE_CONNECTED) {
+			                    willowConnection.disconnect();
+			                }
+			           }
+
+
+			           // $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history");
+			            for (var i = 0; i < willowConnection.presence.length; ++i) {
+			              addName(willowConnection.presence[i]);
+			              console.log("who?", willowConnection.presence[i]);
+			            }
+						updateMembers();
+ 						console.log('connected', data, willowConnection.presence) 
+			        }
+			        willowConnection.onMessage = function(sender, message) { 
+			            console.log('msg', sender, message); 
+						chatArea.domNode.innerHTML += "<div>" + sender + ": " + message + "</div>";
+						scrollDown();
+			          /*  var messagediv = $('<div class="message"></div>');
+
+			            if (sender == username) {
+			                messagediv.addClass("self");
+			            }
+			            if (isSubstring(username, message)) {
+			                messagediv.addClass("mentioned");
+			            }
+			            messagediv.html('<span class="user">' + sender + ':</span> ' +
+			                            sanitize(message))
+			            .appendTo("#history");
+			            scrollDown();*/
+			        }
+			        willowConnection.onAction = function(s, m) { console.log('action', s, m); }
+
+			        willowConnection.onJoin = function(joiner) { 
+			            console.log('join', joiner);
+			            addName(joiner);
+						updateMembers();
+						chatArea.domNode.innerHTML +=	"<span class='user'>" + joiner + "</span> has joined<br/>";
+						scrollDown();
+			        }
+			
+			        willowConnection.onLeave = function(leaver) { 
+			           console.log('leave', leaver); 
+						var idx = -1;
+					   for(var i = 0; idx > -1 && i < roomMembers.length; i++) {
+							if(leaver == roomMembers[i]) {
+								idx = i;
+							}
+						}
+						roomMembers.splice(i, 1);
+						_updateMemberDisplay();
+			        }
+			
+			        willowConnection.onDisconnect = function() { console.log('disconneted'); roomMembers = []; _updateMemberDisplay();	dijit.byId("logindialog").show();}
+			        willowConnection.onUsernameTaken = function() {
+			            console.log('onUsernameTaken', username);
+			         username += '_'
+			            try {
+			                willowConnection.rename(username);
+			                console.log('rename sent');
+			            }
+			            catch(e) {
+			                console.log('rename failed:', e)
+			            }
+			        }
+		
+		
+		
+		
+		
+		} 
+		
+		function addName(name) {
+			roomMembers.push(name);
+		//	presenceContainer.domNode.innerHTML += name + "<br/>";
+		} 
+		
+		
+		function updateMembers() {
+			roomMembers.sort();
+			_updateMemberDisplay();
+		}
+		
+		function _updateMemberDisplay() {
+				presenceContainer.domNode.innerHTML  =  "";
+				for(var i = 0; i < roomMembers.length; i++) {
+					var member = roomMembers[i];
+					presenceContainer.domNode.innerHTML += member + "<br/>";
+				}
+		}
+		
+		function scrollDown() {
+	      chatArea.domNode.scrollTop = chatArea.domNode.scrollHeight;
+	    }
+		
+		function logout() {
+			willowConnection.disconnect();
+		}
+		
+		
+		
+		
+		</script>
+
+
+ </head>
+ <body class="soria" >
+	<div dojoType="dijit.Dialog" id="logindialog" title="Chat"
+				execute="login(arguments[0]['name'] ? arguments[0]['name'] : 'guest');">
+		<label for="name">Nickname: </label>
+		<input dojoType=dijit.form.TextBox type="text"  maxlength="16"  name="name" id="name" value="">
+		<button dojoType=dijit.form.Button type="submit">OK</button>
+	</div>
+	
+	<div>
+		<div dojoType="dijit.layout.BorderContainer" style="width:100%; height:100%">
+				<div dojoType="dijit.layout.ContentPane" region="top" style="border:1px solid gray;  height: 20px; background: #eee;">
+					WillowChat now with Dojo 	<button dojoType=dijit.form.Button onClick="logout();" style="font-size:10px;" type="submit">Leave</button>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="left" jsId="presenceContainer"  style="width: 100px; border:1px solid gray; background: #eee;" splitter="true" minSize="0" maxSize="250">
+					
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center" jsId="chatArea"  style="border:1px solid gray;  background: #eee;" >
+				
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="bottom" style="height: 50px; border:1px solid gray;  background: #eee;" >
+					<textarea id="messageBox" style="width:90%"></textarea>
+				</div>
+			</div>
+	</div>
+</html>
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/style.css b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/style.css
new file mode 100644
index 0000000..29f0a19
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/dojo/style.css
@@ -0,0 +1,151 @@
+html, body {
+    padding: 0px;
+    margin: 0px;
+    border: none;
+    _overflow: hidden;
+ }
+#presenceToggle {
+    border: 1px solid black;
+    position: absolute;
+    right: 1px;
+    top: 1px;
+    padding: 2px;
+    background: #005522;
+    color: white;
+    font-weight: bold;
+    cursor: pointer;
+}
+#presenceToggle:hover {
+}
+#presence {
+    float: right;
+    border: 1px solid gray;
+    width: 130px;
+    height: 83%;
+    margin-left: 3px;
+    margin-bottom: 0px;
+    overflow: hidden;
+}
+#presenceTitle {
+    text-decoration: underline;
+}
+#presenceList {
+    overflow: auto;
+    height: 90%;
+}
+#history {
+    border: 1px solid gray;
+    height: 83%;
+    overflow: auto;
+    margin-bottom: 0px;
+}
+#historySpacer {
+    border: 1px solid red;    
+}
+#inputBar {
+    margin-top: 0px;
+    height: 15%;
+}
+#inputBar textarea {
+    width: 100%;
+    height: 100%;
+    border: 1px solid gray;
+}
+
+
+
+#popup {
+    position: absolute; 
+    height: 100%; 
+    width: 70%; 
+    left: 15%; 
+    z-index: 2;
+}
+
+#popupOuter { 
+    height: 100%;
+    width: 100%;
+    overflow: hidden;
+    position: relative;
+}
+#popupOuter[id] {display: table; position: static;}
+
+#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/
+#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;}
+
+#popupContent {position: relative; top: -50%} /* for explorer only */
+/* optional: #popupContent[id] {position: static;} */
+
+#popupContent {
+    font-size: 120%;
+    text-align:center;
+    background: #005522;
+    color: white;
+    border: 5pt solid #50A572;
+    padding: 8px;
+    padding-bottom: 20px;
+    width: 100%;
+}
+#popupContent p {
+    font-size: 150%;
+}
+
+#absorbClicks {
+    position:absolute;
+    top:0;
+    left:0;
+    width:100%;
+    height:100%;
+}
+
+
+#history div {
+  background-color:#eeffee;
+  padding:.2em;
+  padding-left:1.5em;
+  text-indent: -1em;
+  border-bottom: 1px dotted #ccc;
+}
+#history .message .user {
+  width:5em;
+  font-weight: bold;
+  color:#DD7200;
+  padding-right:.2em;
+  text-align:right;
+}
+#history .message.self .user{
+  color: #B42600;
+}
+#history .message.mentioned{
+  background-color: #d5c5ff;
+}
+#history .message.private{
+  background-color: #ccc;
+}
+#history .message.ctcp {
+  background-color: #f0f;
+}
+#history .action {
+  color: #D68850;
+  font-style:italic;
+}
+#history .action {
+  color: #A94C3B;
+  font-style:italic;
+}
+#history .informative {
+  font-size: 85%;
+  font-style: italic;
+  color:#999;
+  text-align:center;
+  padding:.3em;
+}
+#presenceList .user_entry {
+  font-size: 90%;
+  padding:.2em;
+  padding-left:8pt;
+  border-bottom: 1px dotted #ccc;
+}
+
+
+
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/simple/chrome.js b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/chrome.js
new file mode 100644
index 0000000..4379ce6
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/chrome.js
@@ -0,0 +1,83 @@
+(function() {
+/* Boilerplate
+ */
+if (!window.WillowChat) {
+    Willowchat = {}
+}
+
+if (!WillowChat.chrome) {
+    WillowChat.chrome = {}
+}
+
+if (!WillowChat.chrome.map) {
+    WillowChat.chrome.map = {}
+}
+
+
+WillowChat.chrome.map.simple = WillowChat.chrome.SimpleChrome = function(container, opts) {
+    /* Set configured height
+     */
+    container.style.width = opts.width + 'px'
+    container.style.height = opts.height + 'px'
+    container.style.background = "white";
+    var toggles = document.createElement('div')
+    toggles.setAttribute('id', 'willowchatToggles')
+    var floatToggle = document.createElement('div')
+    floatToggle.setAttribute('id', 'willowchatFloat')
+    floatToggle.innerHTML = "&uarr;"
+    var minToggle = document.createElement('div')
+    minToggle.setAttribute('id', 'willowchatMin')
+    minToggle.innerHTML = "-"
+    floatToggle.setAttribute('style', "float: left;")
+    minToggle.setAttribute('style', "float: left;")
+    var toggleElements = [ minToggle, floatToggle]
+    for (var i = 0; i < 2; ++i) {
+        var t = toggleElements[i]
+        t.style.width = "20px"
+        t.style.height = "20px"
+        t.style.textAlign = "center"
+        t.style.border = "1px solid black"
+        t.style.padding = "2px"
+        t.style.color = "white"
+        t.style.fontWeight = "bold"
+        t.style.background = "#005522"
+        t.style.cursor = "pointer"
+        t.style.cssFloat = "left"
+        t.style.styleFloat = "left"
+        t.style.display = "none"
+    }
+    container.appendChild(toggles)
+    toggles.appendChild(floatToggle)
+    toggles.appendChild(minToggle)
+
+    /* Should it be floating?
+     */
+    if (opts.floating) {
+        container.style.position = 'absolute';
+        container.style.bottom = '0';
+        container.style.right = '0';
+        minToggle.style.display = "block"
+        toggles.style.position = "absolute"
+        toggles.style.top = "1px"
+        toggles.style.left = "1px"
+        if (opts.reposition) {
+            container.parentNode.removeChild(container)
+            document.body.appendChild(container)
+
+        }
+    }
+    else {
+        var ifr = container.getElementsByTagName('iframe')[0]
+        toggles.style.marginBottom="-10px"
+        ifr.style.marginTop="10px"
+        container.removeChild(ifr)
+        container.appendChild(ifr)
+//        toggles.style.marginBottom = "-5px";
+    }
+    if (opts.floatingToggle) {
+        floatToggle.style.display = "block"
+    }
+    toggles.style.border = "1ps solid yellow"
+}
+
+})();
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/simple/gui.js b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/gui.js
new file mode 100644
index 0000000..2b5083f
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/gui.js
@@ -0,0 +1,216 @@
+(function() {
+
+if (!window.WillowChat) {
+    console.log('no willochat found in gui?');
+    Willowchat = {}
+}
+
+if (!WillowChat.guis) {
+    WillowChat.guis = {}
+}
+
+if (!WillowChat.guis.map) {
+    WillowChat.guis.map = {}
+} 
+var ENTER_KEY = 13
+WillowChat.guis.map.simple = WillowChat.guis.SimpleGui = function(wc, opts) {
+    var self = this;
+    self.presenceShown = true;
+    var logger = Orbited.getLogger('WillowChatTest');
+//    logger.enabled = true;
+    var username = null;
+    var presence = {}
+    
+    $('#nickname').focus();    
+    $('#nickname').keypress( function(e) {
+        var key = e.charCode || e.keyCode || 0
+        if (key == ENTER_KEY) {
+            self.connect();
+        };
+    });
+    $('#chatboxInput').keypress(function(e) {
+        var key = e.charCode || e.keyCode || 0;
+        if (key == ENTER_KEY) {
+        self.sendMessage();
+        return false;
+        };
+    });
+    $("#popupContent p").html(opts.greeting)
+    $("#presenceToggle").click(function() {
+        if (self.presenceShown) {
+            self.presenceShown = false;
+            $("#presence").hide()
+            $("#presenceToggle").html('&larr;');
+        }
+        else {
+            self.presenceShown = true;
+            $("#presence").show();
+            $("#presenceToggle").html('&rarr;');
+        }
+        if (wc.readyState == wc.READY_STATE_CONNECTED) {
+            $('#chatboxInput').focus();
+        }
+        else {
+            $('#nickname').focus();
+        }
+    })
+    var scrollDown = function() {
+      var box = $('#history')[0]
+      box.scrollTop = box.scrollHeight;
+    }
+    var isSubstring = function (sub, str) {
+    // case insensitive substring test
+        return str.toLowerCase().indexOf(sub.toLowerCase()) >= 0;
+    };
+    var sanitize = (function(str) {
+    // See http://bigdingus.com/2007/12/29/html-escaping-in-javascript/
+        var MAP = {
+            '&': '&amp;',
+            '<': '&lt;',
+            '>': '&gt;',
+            '"': '&quot;',
+            "'": '&#39;'
+        };
+        var repl = function(c) { return MAP[c]; };
+        return function(s) {
+            return s.replace(/[&<>'"]/g, repl);
+        };
+    })();
+
+    // TODO: test this out
+    var userRenamed = function(oldname, newname) {
+        $("<div class='informative rename'></div>")
+            .html("<span class='user'>" + oldname + "</span> is now known as " +
+                "<span class='user'>" + newname + "</span>")
+            .appendTo("#history");
+        scrollDown();
+        $("#user_" + oldname)
+            .attr("id", "user_" + newname)
+            .html(newname);
+    }
+    
+    var addName = function (name) {
+        presence[name] = 1
+        $('<div class="user_entry" id="user_' + name + '">' + name + '</div>')
+            .appendTo("#presenceList");
+    };
+    
+    var removeName = function (name) {
+        delete presence[name];
+        $(".user_list #user_" + name).remove()
+    };
+
+    var sortNames = function () {
+        $('#presenceList').empty();
+        var list = [];
+        for (var user in presence) {
+            list.push(user);
+        };
+        list.sort()
+        for (var i=0; i < list.length; i++) {
+            var user = list[i];
+            $('<div class="user_entry" id="user_' + user + '">' + user + '</div>')
+                .appendTo("#presenceList");
+        };
+    };
+    self.connect = function() {
+        username = $("#nickname").val();
+        if (!username) {
+            logger.debug('please enter a username');
+            return
+        }
+        $('#popup, #absorbClicks').hide();
+        $('#chatboxInput').focus();
+        $('#chatboxInput').val('')
+
+        connected = true;
+        wc.connect( {
+            username: username
+        })
+        wc.onConnect = function(data) { 
+            /* This is somewhat important -- without this IE can run into some
+             * issues with reconnecting
+             */
+
+            window.onbeforeunload = function() {
+                if (wc.readyState == wc.READY_STATE_CONNECTED) {
+                return 'Are you sure you want to quit and lose the chat connection?';
+                }
+            };
+            window.onunload = function() {
+                if (wc.readyState == wc.READY_STATE_CONNECTED) {
+                    wc.disconnect();
+                }
+           }
+
+
+            $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history");
+            for (var i = 0; i < wc.presence.length; ++i) {
+                addName(wc.presence[i]);
+            }
+            sortNames();
+            logger.debug('connected', data, wc.presence) 
+        }
+        wc.onMessage = function(sender, message) { 
+            logger.debug('msg', sender, message); 
+            var messagediv = $('<div class="message"></div>');
+        
+            if (sender == username) {
+                messagediv.addClass("self");
+            }
+            if (isSubstring(username, message)) {
+                messagediv.addClass("mentioned");
+            }
+            messagediv.html('<span class="user">' + sender + ':</span> ' +
+                            sanitize(message))
+            .appendTo("#history");
+            scrollDown();
+        }
+        wc.onAction = function(s, m) { logger.debug('action', s, m); }
+
+        wc.onJoin = function(joiner) { 
+            logger.debug('join', joiner);
+            addName(joiner);
+            sortNames();
+            $("<div class='informative join'></div>")
+                .html("<span class='user'>" + joiner + '</span> has joined')
+                .appendTo("#history");
+            scrollDown();
+        }
+        wc.onLeave = function(leaver) { 
+            logger.debug('leave', leaver); 
+            removeName(leaver);
+            $("<div class='informative part'></div>")
+                .html("<span class='user'>" + leaver + '</span> left')
+                .appendTo("#history");
+            scrollDown();
+        }
+        wc.onDisconnect = function() { logger.debug('disconneted'); }
+        wc.onUsernameTaken = function() {
+            logger.debug('onUsernameTaken', username);
+            username += '_'
+            try {
+                wc.rename(username);
+                logger.debug('rename sent');
+            }
+            catch(e) {
+                logger.debug('rename failed:', e)
+            }
+        }
+    }
+    self.sendMessage = function() {
+        var msg = $('#chatboxInput').val();
+        wc.sendMessage(msg)
+        $('#chatboxInput').val('');
+        // the WillowChat server will not echo our message back, so simulate a send.
+        wc.onMessage(username, msg)
+    }
+    self.sendAction = function() {
+        var msg = getMessage()
+        wc.sendAction(msg);
+        logger.debug('action', username, msg)
+    }
+
+}
+})()
+
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/simple/index.html b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/index.html
new file mode 100644
index 0000000..1246e2e
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/index.html
@@ -0,0 +1,58 @@
+<html>
+ <head>
+  <link rel="stylesheet" type="text/css" href="style.css">
+<!-- @@ HACK -->
+<script src="http://localhost:9000/static/Orbited.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/irc2.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/willowchat.js"></script>
+<script src="/toscawidgets/resources/moksha.apps.chat.widgets.chat.chat/static/gui.js"></script>
+<script src="/toscawidgets/resources/tw.jquery.base/static/javascript/jquery-1.2.6.pack.js"></script>
+  <script src="gui.js"></script>
+  <script>
+    TCPSocket = Orbited.TCPSocket
+    document.domain = document.domain
+
+/*    Orbited.system.enabled = true;
+    Orbited.loggers['Orbited.XSDR'].enabled = false
+    Orbited.loggers['Orbited.CometSession'].enabled = true
+    Orbited.loggers['Orbited.TCPSocket'].enabled = true
+    Orbited.loggers['XSDRBridge'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true
+    Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true 
+    Orbited.loggers['WC.c.IRCClient'].enabled = true
+*/
+  </script>
+
+ </head>
+ <body> 
+<div id="popup">
+<div id="popupOuter">
+  <div id="popupMiddle">
+    <div id="popupContent">
+      <p>Greeting</p>
+      <label for="nickname">Nickname:</label>
+      <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" />
+    </div>
+  </div>
+</div>
+</div>
+
+
+  <div id="absorbClicks"></div>
+  <div id="presenceToggle">
+    &rarr;
+  </div>
+  <div id="presence">
+   <div id="presenceTitle">Presence</div>
+   <div id="presenceList">
+   </div>
+  </div>
+  <div id="history">
+  </div>
+  <div id="inputBar">
+   <textarea id="chatboxInput"></textarea>
+  </div>
+ </body>
+</html>
diff --git a/moksha/apps/chat/moksha/apps/chat/static/themes/simple/style.css b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/style.css
new file mode 100644
index 0000000..29f0a19
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/themes/simple/style.css
@@ -0,0 +1,151 @@
+html, body {
+    padding: 0px;
+    margin: 0px;
+    border: none;
+    _overflow: hidden;
+ }
+#presenceToggle {
+    border: 1px solid black;
+    position: absolute;
+    right: 1px;
+    top: 1px;
+    padding: 2px;
+    background: #005522;
+    color: white;
+    font-weight: bold;
+    cursor: pointer;
+}
+#presenceToggle:hover {
+}
+#presence {
+    float: right;
+    border: 1px solid gray;
+    width: 130px;
+    height: 83%;
+    margin-left: 3px;
+    margin-bottom: 0px;
+    overflow: hidden;
+}
+#presenceTitle {
+    text-decoration: underline;
+}
+#presenceList {
+    overflow: auto;
+    height: 90%;
+}
+#history {
+    border: 1px solid gray;
+    height: 83%;
+    overflow: auto;
+    margin-bottom: 0px;
+}
+#historySpacer {
+    border: 1px solid red;    
+}
+#inputBar {
+    margin-top: 0px;
+    height: 15%;
+}
+#inputBar textarea {
+    width: 100%;
+    height: 100%;
+    border: 1px solid gray;
+}
+
+
+
+#popup {
+    position: absolute; 
+    height: 100%; 
+    width: 70%; 
+    left: 15%; 
+    z-index: 2;
+}
+
+#popupOuter { 
+    height: 100%;
+    width: 100%;
+    overflow: hidden;
+    position: relative;
+}
+#popupOuter[id] {display: table; position: static;}
+
+#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/
+#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;}
+
+#popupContent {position: relative; top: -50%} /* for explorer only */
+/* optional: #popupContent[id] {position: static;} */
+
+#popupContent {
+    font-size: 120%;
+    text-align:center;
+    background: #005522;
+    color: white;
+    border: 5pt solid #50A572;
+    padding: 8px;
+    padding-bottom: 20px;
+    width: 100%;
+}
+#popupContent p {
+    font-size: 150%;
+}
+
+#absorbClicks {
+    position:absolute;
+    top:0;
+    left:0;
+    width:100%;
+    height:100%;
+}
+
+
+#history div {
+  background-color:#eeffee;
+  padding:.2em;
+  padding-left:1.5em;
+  text-indent: -1em;
+  border-bottom: 1px dotted #ccc;
+}
+#history .message .user {
+  width:5em;
+  font-weight: bold;
+  color:#DD7200;
+  padding-right:.2em;
+  text-align:right;
+}
+#history .message.self .user{
+  color: #B42600;
+}
+#history .message.mentioned{
+  background-color: #d5c5ff;
+}
+#history .message.private{
+  background-color: #ccc;
+}
+#history .message.ctcp {
+  background-color: #f0f;
+}
+#history .action {
+  color: #D68850;
+  font-style:italic;
+}
+#history .action {
+  color: #A94C3B;
+  font-style:italic;
+}
+#history .informative {
+  font-size: 85%;
+  font-style: italic;
+  color:#999;
+  text-align:center;
+  padding:.3em;
+}
+#presenceList .user_entry {
+  font-size: 90%;
+  padding:.2em;
+  padding-left:8pt;
+  border-bottom: 1px dotted #ccc;
+}
+
+
+
diff --git a/moksha/apps/chat/moksha/apps/chat/static/willowchat.js b/moksha/apps/chat/moksha/apps/chat/static/willowchat.js
new file mode 100644
index 0000000..0561630
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/static/willowchat.js
@@ -0,0 +1,337 @@
+(function() {
+
+Orbited.settings.streaming = true
+
+if (window.addEventListener) {
+    window.addEventListener('load', function() { WillowChat.util.setup(); }, false);
+}
+else if (window.attachEvent) {
+    window.attachEvent('onload', function() { WillowChat.util.setup(); });
+}
+
+
+if (!window.WillowChat) {
+    WillowChat = {}
+}
+WillowChat.settings = {}
+WillowChat.settings.hostname = document.domain
+WillowChat.settings.port = (location.port.length > 0) ? location.port : 80
+WillowChat.settings.defaultTheme = 'simple'
+WillowChat.settings.client = 'irc'
+WillowChat.clients = {}
+WillowChat.clients.map = {}
+WillowChat.util = {}
+
+
+if (!WillowChat.guis) {
+    WillowChat.guis = {}
+}
+if (!WillowChat.guis.map) {
+    WillowChat.guis.map = {}
+}
+
+if (!Array.prototype.indexOf) {
+    Array.prototype.indexOf = function(n) {
+        for (var i = 0; i < this.length; ++i) {
+            if (this[i] === n) {
+                return i
+            }
+        }
+        return -1
+    }
+}
+
+
+
+
+WillowChat.util.setup = function() {
+    // TODO: first setup from remote and url
+    // TODO: this is a *really* ugly way to do this... Fix it
+
+    try {
+        var i = location.href.indexOf('&opts=')
+        var opts = JSON.parse(unescape(location.href.slice(i+6)))
+    }
+    catch(e) {
+        // If the options aren't there, then someone must be trying to use this
+        // library manually, which we want to allow.
+        return
+    }
+    // TODO: we actually need to get the "backend" hostname value
+    WillowChat.settings.hostname = 'localhost'
+    var client = new WillowChat.clients.map[WillowChat.settings.client](opts)
+    var gui = new WillowChat.guis.map[opts.theme ? opts.theme : WillowChat.settings.defaultTheme](client, opts)
+
+    return gui
+}
+
+
+
+
+
+WillowChat.BaseClient = function() { 
+    var self = this;
+    self.readyState = self.READY_STATE_INITIALIZED;
+    self.onUsernameTaken = function() { };
+    self.onConnect = function() { };
+    self.onPresence= function() { };
+    self.onDisconnect = function() { };
+    self.onMessage = function() { };
+    self.onJoin = function() { };
+    self.onLeave = function() { };
+    self.onAction = function() { };
+    self.onRename = function() { };
+} 
+ 
+WillowChat.BaseClient.prototype.connect = function(options) {
+    var self = this;
+    if (!this.doConnect) {
+        throw new Error("NotImplemented");
+    }
+    var username = options.username
+    if (!username) {
+        throw new Error("Missing username")
+    }
+    var roomId = options.roomId ? options.roomId : self.opts.roomId
+    if (!roomId) {
+        throw new Error("Missing roomId")
+    }
+    var hostname = options.hostname
+    var port = options.port
+    if (!port) {
+        port = 6667
+    }    
+    if (!hostname) {
+        if (!self.opts.addr) {
+            throw new Error("missing connection information");
+        }
+        hostname = self.opts.addr[0]
+        port = self.opts.addr[1]
+    }
+    return self.doConnect(username, roomId, hostname, port);
+};
+WillowChat.BaseClient.prototype.rename = function(newName) {
+    throw new Error("NotImplemented");
+};
+WillowChat.BaseClient.prototype.sendMessage = function(msg) {
+    throw new Error("NotImplemented");
+};
+WillowChat.BaseClient.prototype.sendAction = function(action) {
+    throw new Error("NotImplemented");
+};
+WillowChat.BaseClient.prototype.disconnect = function() {
+    throw new Error("NotImplemented");
+};
+WillowChat.BaseClient.prototype.READY_STATE_INITIALIZED = 0;
+WillowChat.BaseClient.prototype.READY_STATE_CONNECTING = 1;
+WillowChat.BaseClient.prototype.READY_STATE_CONNECTED = 2;
+WillowChat.BaseClient.prototype.READY_STATE_DISCONNECTED = 3;
+
+
+WillowChat.clients.IRCClient = function(opts) {
+    var self = this;
+    self._conn = null;
+    self.opts = opts
+};
+
+WillowChat.clients.IRCClient.prototype = new WillowChat.BaseClient();
+
+WillowChat.clients.IRCClient.prototype.logger = Orbited.getLogger('WC.c.IRCClient');
+WillowChat.clients.map.irc = WillowChat.clients.IRCClient
+
+WillowChat.clients.IRCClient.prototype.disconnect = function() {
+    var self = this;
+    if (self.readyState == self.READY_STATE_DISCONNECTED) {
+        return
+    }
+    self.readyState = self.READY_STATE_DISCONNECTED;
+    // TODO: would be nice to have a quit message or something
+    self._conn.reset()
+    self._conn = null;
+    self.onDisconnect()
+}
+
+
+WillowChat.clients.IRCClient.prototype.doConnect = function(username, roomId, hostname, port) {
+    var self = this;
+    self.username = username
+    self.roomId = roomId;
+    if (self.roomId[0] != '#') {
+        self.roomId = '#' + self.roomId
+    }
+    self._conn = new IRCClient()
+    self.presence = []
+    var irc = self._conn
+    // By default, assume the irc server is on the same host as the willowchat
+    // server
+    
+    function parseName(identity) {
+        // TODO remove privileges from name head.
+        return identity.split("!", 1)[0];
+    }
+    irc.onclose = function() {
+        self.disconnect();
+    }
+    irc.onopen = function() {
+        irc.ident(self.username, '8 *', self.username);
+        irc.nick(self.username);
+    }
+;;; self.logger.debug('do irc.connect', hostname, port)
+    irc.connect(hostname, port)
+    self.readyState = self.READY_STATE_CONNECTING
+
+    irc.onJOIN = function(command) {
+;;;     self.logger.debug('irc.onJOIN', command)
+        // Ignore initial onJoin (before names)
+        var joiner = parseName(command.prefix)
+;;;     self.logger.debug('irc.onJoin.a')
+        self.logger.debug('self.presence', self.presence, Orbited.JSON.stringify(self.presence))
+        if (self.presence.indexOf(joiner) == -1) {
+;;;     self.logger.debug('irc.onJoin.b')
+            self.presence.push(joiner)
+        }
+;;;     self.logger.debug('irc.onJoin.c')
+        if (self.readyState == self.READY_STATE_CONNECTED) {
+;;;     self.logger.debug('irc.onJoin.d')
+            self.onJoin(joiner);
+        }
+;;;     self.logger.debug('irc.onJoin.e')
+    }
+    irc.onPART = irc.onQUIT = function(command) {
+        var leaver = parseName(command.prefix);
+        var message = command.args.join(" ");
+        var i = self.presence.indexOf(leaver)
+        if (i != -1) {
+            self.presence.splice(i,1)
+        }
+        self.onLeave(leaver);
+    }
+    irc.onNICK = function(command) {
+        // See http://tools.ietf.org/html/rfc2812#section-3.1.2
+        var previousNick = parseName(command.prefix);
+        var i = self.presence.indexOf(previousNick)
+        if (i != -1) {
+            self.presence.splice(i,1)
+        }
+        var newNick = command.args[0];
+        if (self.presence.indexOf(newNick) == -1) {
+            self.presence.push(newNick)
+        }
+        self.onPresence()
+    };
+    
+    irc.onPRIVMSG = function(command) {
+        var sender = parseName(command.prefix);
+        var target = command.args[0];
+        var message = command.args[1];
+        self.onMessage(sender, message);
+    }
+    irc.onACTION = function(command) {
+;;;     self.logger.debug('irc.onACTION', command)
+        var sender = parseName(command.prefix);
+        var message = command.args.slice(1).join(" ")
+        self.onAction(sender, message);
+    }
+
+    irc.onresponse = function(command) {
+        self.logger.debug('onresponse', command)
+        var responseCode = parseInt(command.type);
+        if (responseCode == 353) {
+            // 353 is the code for RPL_NAMEREPLY.
+        
+            // The args are:
+            //
+            // """
+            //   <target> ( "=" / "*" / "@" ) <channel>
+            //    :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
+            //
+            //   - "@" is used for secret channels, "*" for private
+            //     channels, and "=" for others (public channels).
+            // """ -- rfc2812    
+            var channel = command.args[2];
+            if (channel != self.roomId)
+                return;
+            var partialUserList = command.args[3].split(' ');
+            for (var i = 0, l = partialUserList.length; i < l; ++i) {
+                // trim the name
+                var name = partialUserList[i].replace(/^\s+|\s+$/g,"");
+                if (name[0] == '@' || name[0] == '+') {
+                    name = name.slice(1);
+                }
+                if (name == "" || self.presence.indexOf(name) != -1) {
+                    continue;
+                }
+                self.presence.push(name)
+            }
+        }
+        else if (responseCode == 366) {
+        // 366 is the code for RPL_ENDOFNAMES.
+            self.readyState = self.READY_STATE_CONNECTED
+            self.onConnect();
+        }
+        else if (responseCode == 376) {
+        //  376     RPL_ENDOFMOTD
+        //  :End of /MOTD command"
+            irc.join(self.roomId);
+        }
+    }
+    irc.onerror = function(command) {
+        self.logger.debug('onerror', command)
+        var responseCode = parseInt(command.type);
+        if (responseCode == 431 || responseCode == 432 || responseCode == 433) {
+        // 431     ERR_NONICKNAMEGIVEN
+        // 432     ERR_ERRONEUSNICKNAME
+        // 433     ERR_NICKNAMEINUSE
+            self.onUsernameTaken();
+        }
+/*        else if (responseCode == 451) {
+        // 451 is the code for ERR_NOTREGISTERED
+        // Probably means the nick we chose was taken
+        }
+*/
+    }
+}
+WillowChat.clients.IRCClient.prototype.rename = function(newUserName) {
+    var self = this;
+    var irc = self._conn;
+    switch(self.readyState) {
+        case self.READY_STATE_CONNECTING:
+        case self.READY_STATE_CONNECTED:
+            irc.nick(newUserName);
+            self.userName = newUserName;
+            break;
+        default:
+            throw new Error("invalid readyState")
+    }    
+}
+
+WillowChat.clients.IRCClient.prototype.sendMessage = function(msg) {
+    var self = this;
+    if (self.readyState != self.READY_STATE_CONNECTED) {
+        throw new Error('invalid readyState: ' + self.readyState);
+    }
+    var irc = self._conn;
+    irc.privmsg(self.roomId, msg);
+}
+
+WillowChat.clients.IRCClient.prototype.sendAction = function(action) {
+    var self = this;
+    if (self.readyState != self.READY_STATE_CONNECTED) {
+        throw new Error('invalid readyState: ' + self.readyState);
+    }
+    var irc = self._conn;
+    irc.action(self.roomId, action);
+}
+
+
+var createXHR = function () {
+    try { return new XMLHttpRequest(); } catch(e) {}
+    try { return new ActiveXObject('MSXML3.XMLHTTP'); } catch(e) {}
+    try { return new ActiveXObject('MSXML2.XMLHTTP.3.0'); } catch(e) {}
+    try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
+    try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
+    throw new Error('Could not find XMLHttpRequest or an alternative.');
+}
+
+
+})()
diff --git a/moksha/apps/chat/moksha/apps/chat/templates/__init__.py b/moksha/apps/chat/moksha/apps/chat/templates/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/chat/moksha/apps/chat/templates/bootstrap.mak b/moksha/apps/chat/moksha/apps/chat/templates/bootstrap.mak
new file mode 100644
index 0000000..3aeafeb
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/templates/bootstrap.mak
@@ -0,0 +1,419 @@
+(function() {
+var gatherOptions = function(roomOptions, container) {
+    var opts = {}
+    var containerOptions = [ 'width', 'height', 'roomClass', 'reposition', 'theme' ]
+    for (var key in roomOptions) {
+        opts[key] = roomOptions[key]
+    }
+    for (var i = 0; i < containerOptions.length; ++i) {
+        var key = containerOptions[i]
+        var option = container.getAttribute(key)
+        if (option) {
+            opts[key] = option
+        }
+    }
+    if (!opts.roomId) {
+        var roomId = container.getAttribute('roomId')
+        opts.roomId = roomId ? roomId : 'default'
+    }
+    if (!opts.width) {
+        opts.width = 350;
+    }
+    if (!opts.height) {
+        opts.height = 240;
+    }
+    if (!opts.theme) {
+        opts.theme = 'simple'
+    }
+    if (!opts.greeting) {
+        opts.greeting = "Willow Chat"
+    }
+    return opts
+}
+
+var loaded = function() {
+    if (!window.WillowChat) {
+        WillowChat = {}
+    }
+    if (!WillowChat.util) {
+        WillowChat.util = {}
+    }
+    var container = document.getElementById('willowchat');
+    if (!container) {
+        container = document.createElement('div');
+        container.setAttribute('id', 'willowchat');
+    }
+
+
+    var roomClass = container.getAttribute('roomClass');
+    var roomClass= roomClass ? roomClass : 'default'
+    s = document.createElement('script')
+    var baseurl = 'http://' + WillowChat.hostHeader
+    s.src = baseurl + '/apps/chat/rooms?jsonp=WillowChat.util.optionsCallback&op=info&roomClass=' + roomClass
+
+    WillowChat.util.optionsCallback = function(result) {
+        success = result[0]
+        if (!success) {
+            throw new Error("Failed: " + result[1])
+        }
+        room = result[1]
+        var opts = gatherOptions(room, container);
+        ifr = document.createElement('iframe')
+        var staticurl = baseurl + '/toscawidgets/resources/moksha.apps.chat.chat/static'
+        ifr.src = '/apps/chat/index?json=1&opts=' +  escape(JSON.stringify(opts))
+        ifr.style.border = "0px";
+        ifr.style.width = "100%";
+        ifr.style.height = "100%";
+       var chromeCallback = function() {
+            container.appendChild(ifr)
+            chrome = new WillowChat.chrome.map[opts.theme](container, opts)
+        }
+        var s = document.createElement('script')
+        // TODO: whats the deal with this? Can't we do any better?
+        s.src = staticurl + '/themes/' + opts.theme + '/chrome.js?ienocache=' + Math.floor(Math.random()*10000)
+        if (s.addEventListener) {
+            s.addEventListener('load', chromeCallback, false)
+        }
+        else if (s.attachEvent) {
+            s.attachEvent('onreadystatechange', function() {
+                if (s.readyState == "loaded") {
+                    chromeCallback()
+                }
+            })
+        }
+        if (true) {
+            var k = 3 + 3
+        }
+//        var d = document.createElement('div')
+//        d.innerHTML = 'go'
+//        document.body.appendChild(d)
+        document.getElementsByTagName('head')[0].appendChild(s)
+    }
+    document.getElementsByTagName('head')[0].appendChild(s)
+
+}
+
+$(document).ready(function(){
+    if (!window.WillowChat) { WillowChat = {} }; WillowChat.hostHeader = "${host}";
+    loaded();
+});
+
+})();
+if (!this.JSON) {
+
+// Create a JSON object only if one does not already exist. We create the
+// object in a closure to avoid creating global variables.
+
+    JSON = function () {
+
+        function f(n) {
+            // Format integers to have at least two digits.
+            return n < 10 ? '0' + n : n;
+        }
+
+        Date.prototype.toJSON = function (key) {
+
+            return this.getUTCFullYear()   + '-' +
+                 f(this.getUTCMonth() + 1) + '-' +
+                 f(this.getUTCDate())      + 'T' +
+                 f(this.getUTCHours())     + ':' +
+                 f(this.getUTCMinutes())   + ':' +
+                 f(this.getUTCSeconds())   + 'Z';
+        };
+
+        String.prototype.toJSON =
+        Number.prototype.toJSON =
+        Boolean.prototype.toJSON = function (key) {
+            return this.valueOf();
+        };
+
+        var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+            escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+            gap,
+            indent,
+            meta = {    // table of character substitutions
+                '\b': '\\b',
+                '\t': '\\t',
+                '\n': '\\n',
+                '\f': '\\f',
+                '\r': '\\r',
+                '"' : '\\"',
+                '\\': '\\\\'
+            },
+            rep;
+
+
+        function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+            escapeable.lastIndex = 0;
+            return escapeable.test(string) ?
+                '"' + string.replace(escapeable, function (a) {
+                    var c = meta[a];
+                    if (typeof c === 'string') {
+                        return c;
+                    }
+                    return '\\u' + ('0000' +
+                            (+(a.charCodeAt(0))).toString(16)).slice(-4);
+                }) + '"' :
+                '"' + string + '"';
+        }
+
+
+        function str(key, holder) {
+
+// Produce a string from holder[key].
+
+            var i,          // The loop counter.
+                k,          // The member key.
+                v,          // The member value.
+                length,
+                mind = gap,
+                partial,
+                value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+            if (value && typeof value === 'object' &&
+                    typeof value.toJSON === 'function') {
+                value = value.toJSON(key);
+            }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+            if (typeof rep === 'function') {
+                value = rep.call(holder, key, value);
+            }
+
+// What happens next depends on the value's type.
+
+            switch (typeof value) {
+            case 'string':
+                return quote(value);
+
+            case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+                return isFinite(value) ? String(value) : 'null';
+
+            case 'boolean':
+            case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+                return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+            case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+                if (!value) {
+                    return 'null';
+                }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+                gap += indent;
+                partial = [];
+
+// If the object has a dontEnum length property, we'll treat it as an array.
+
+                if (typeof value.length === 'number' &&
+                        !(value.propertyIsEnumerable('length'))) {
+
+// The object is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+                    length = value.length;
+                    for (i = 0; i < length; i += 1) {
+                        partial[i] = str(i, value) || 'null';
+                    }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+                    v = partial.length === 0 ? '[]' :
+                        gap ? '[\n' + gap +
+                                partial.join(',\n' + gap) + '\n' +
+                                    mind + ']' :
+                              '[' + partial.join(',') + ']';
+                    gap = mind;
+                    return v;
+                }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+                if (rep && typeof rep === 'object') {
+                    length = rep.length;
+                    for (i = 0; i < length; i += 1) {
+                        k = rep[i];
+                        if (typeof k === 'string') {
+                            v = str(k, value);
+                            if (v) {
+                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                            }
+                        }
+                    }
+                } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+                    for (k in value) {
+                        if (Object.hasOwnProperty.call(value, k)) {
+                            v = str(k, value);
+                            if (v) {
+                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                            }
+                        }
+                    }
+                }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+                v = partial.length === 0 ? '{}' :
+                    gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+                            mind + '}' : '{' + partial.join(',') + '}';
+                gap = mind;
+                return v;
+            }
+        }
+
+// Return the JSON object containing the stringify and parse methods.
+
+        return {
+            stringify: function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+                var i;
+                gap = '';
+                indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+                if (typeof space === 'number') {
+                    for (i = 0; i < space; i += 1) {
+                        indent += ' ';
+                    }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+                } else if (typeof space === 'string') {
+                    indent = space;
+                }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+                rep = replacer;
+                if (replacer && typeof replacer !== 'function' &&
+                        (typeof replacer !== 'object' ||
+                         typeof replacer.length !== 'number')) {
+                    throw new Error('JSON.stringify');
+                }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+                return str('', {'': value});
+            },
+
+
+            parse: function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+                var j;
+
+                function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+                    var k, v, value = holder[key];
+                    if (value && typeof value === 'object') {
+                        for (k in value) {
+                            if (Object.hasOwnProperty.call(value, k)) {
+                                v = walk(value, k);
+                                if (v !== undefined) {
+                                    value[k] = v;
+                                } else {
+                                    delete value[k];
+                                }
+                            }
+                        }
+                    }
+                    return reviver.call(holder, key, value);
+                }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+                cx.lastIndex = 0;
+                if (cx.test(text)) {
+                    text = text.replace(cx, function (a) {
+                        return '\\u' + ('0000' +
+                                (+(a.charCodeAt(0))).toString(16)).slice(-4);
+                    });
+                }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+                if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+                    j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+                    return typeof reviver === 'function' ?
+                        walk({'': j}, '') : j;
+                }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+                throw new SyntaxError('JSON.parse');
+            }
+        };
+    }();
+}
diff --git a/moksha/apps/chat/moksha/apps/chat/templates/chat.mak b/moksha/apps/chat/moksha/apps/chat/templates/chat.mak
new file mode 100644
index 0000000..a3ab679
--- /dev/null
+++ b/moksha/apps/chat/moksha/apps/chat/templates/chat.mak
@@ -0,0 +1,31 @@
+<script>
+  TCPSocket = Orbited.TCPSocket
+  document.domain = document.domain;
+</script>
+
+<div id="popup">
+<div id="popupOuter">
+  <div id="popupMiddle">
+    <div id="popupContent">
+      <p>Greeting</p>
+      <label for="nickname">Nickname:</label>
+      <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" />
+    </div>
+  </div>
+</div>
+</div>
+
+  <div id="absorbClicks"></div>
+  <div id="presenceToggle">
+    &rarr;
+  </div>
+  <div id="presence">
+   <div id="presenceTitle">Presence</div>
+   <div id="presenceList">
+   </div>
+  </div>
+  <div id="history">
+  </div>
+  <div id="inputBar">
+   <textarea id="chatboxInput"></textarea>
+  </div>
diff --git a/moksha/apps/chat/pavement.py b/moksha/apps/chat/pavement.py
new file mode 100644
index 0000000..17df19b
--- /dev/null
+++ b/moksha/apps/chat/pavement.py
@@ -0,0 +1,33 @@
+from paver.easy import *
+from paver.setuputils import (setup, find_package_data, find_packages,
+                              install_distutils_tasks)
+from moksha.lib.paver_tasks import *
+
+install_distutils_tasks()
+
+options(
+    setup=Bunch(
+        name="moksha.chat",
+        version="0.1",
+        release="1",
+        url="http://moksha.fedorahosted.org",
+        description="Moksha Chat App",
+        long_description="",
+        author="Luke Macken",
+        author_email="lmacken at redhat.com",
+        license="AGPLv3",
+        rpm_name='moksha-apps-chat',
+        packages=find_packages(),
+        package_data=find_package_data(),
+        namespace_packages=['moksha'],
+        install_requires=["Moksha"],
+        entry_points={
+            'moksha.application': (
+                'chat = moksha.apps.chat.controllers:ChatController',
+            ),
+            'moksha.widget': (
+                'chat = moksha.apps.chat:LiveChatWidget',
+            ),
+        }
+    ),
+)


commit e4fe8771be6da60469b0488f67d1bc6bab6c1ca8
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:41:57 2009 -0400

    More widgetbrowser modifications

diff --git a/moksha/widgets/feedtree/controllers/demo.py b/moksha/widgets/feedtree/controllers/demo.py
index d3cbc64..a41c786 100644
--- a/moksha/widgets/feedtree/controllers/demo.py
+++ b/moksha/widgets/feedtree/controllers/demo.py
@@ -18,7 +18,7 @@
 
 from tg.controllers import WSGIAppController
 from pylons import cache
-from widgetbrowser import WidgetBrowser
+from moksha.apps.widgetbrowser import WidgetBrowser
 
 from moksha.widgets.feedtree import moksha_feedreader
 from moksha.controllers.apps import AppController


commit 24604c0aa521c1f3c830b66a1b7aaf8eaded8a75
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:41:37 2009 -0400

    Update moksha.widgets.all for the new widgetbrowser app

diff --git a/moksha/widgets/all.py b/moksha/widgets/all.py
index d662763..d55b054 100644
--- a/moksha/widgets/all.py
+++ b/moksha/widgets/all.py
@@ -41,7 +41,10 @@ for entry_point in ('moksha.widget', 'moksha.menu', 'moksha.global'):
 from moksha.widgets.container import MokshaContainer
 __all__.append(MokshaContainer)
 
-from widgetbrowser import widgets
-for obj in dir(widgets):
-    if isinstance(getattr(widgets, obj), Widget):
-        __all__.append(obj)
+try:
+    from moksha.apps.widgetbrowser import widgets
+    for obj in dir(widgets):
+        if isinstance(getattr(widgets, obj), Widget):
+            __all__.append(obj)
+except ImportError:
+    pass


commit 7575c12398ad0cd775a4c231e3b3e567b7d0d66d
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:41:17 2009 -0400

    Have our hub.py acquire the proper config file

diff --git a/moksha/hub/hub.py b/moksha/hub/hub.py
index 8a8ebf5..862ed0e 100644
--- a/moksha/hub/hub.py
+++ b/moksha/hub/hub.py
@@ -29,7 +29,7 @@ from orbited import json
 from threading import Thread
 from paste.deploy import appconfig
 
-from moksha.lib.helpers import trace, defaultdict
+from moksha.lib.helpers import trace, defaultdict, get_moksha_config_path
 from moksha.hub.amqp import AMQPHub
 from moksha.hub.stomp import StompHub
 
@@ -219,10 +219,7 @@ def setup_logger(verbose):
 def main():
     """ The main MokshaHub method """
     setup_logger('-v' in sys.argv or '--verbose' in sys.argv)
-    cfgfile = 'development.ini'
-    if os.path.isfile('production.ini'):
-        cfgfile= 'production.ini'
-    cfg = appconfig('config:' + os.path.abspath(cfgfile))
+    cfg = appconfig('config:' + get_moksha_config_path())
     config.update(cfg)
 
     hub = CentralMokshaHub()


commit 62ceb23bd94bcd55500e2982138d6f9f1d8818a7
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:40:56 2009 -0400

    Include the namespace pth file in our spec

diff --git a/moksha.spec b/moksha.spec
index 3131488..931f25c 100644
--- a/moksha.spec
+++ b/moksha.spec
@@ -94,6 +94,7 @@ make -C docs html
 %defattr(-,root,root,-)
 %doc README AUTHORS LICENSE COPYING
 %{python_sitelib}/%{name}/
+%{python_sitelib}/%{name}-%{version}-py%{pyver}-nspkg.pth
 %attr(-,apache,root) %{_datadir}/%{name}
 %attr(-,apache,root) %{_localstatedir}/log/%{name}
 %{python_sitelib}/%{name}-%{version}-py%{pyver}.egg-info/


commit eebf87d47e93f6014ae2811e9d6fc369ca75a743
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:40:10 2009 -0400

    Remove the moksha/apps/widgetbrowser, as it's now in the docs app

diff --git a/moksha/apps/widgetbrowser/paster.ini b/moksha/apps/widgetbrowser/paster.ini
deleted file mode 100644
index c1b4d92..0000000
--- a/moksha/apps/widgetbrowser/paster.ini
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Sample PasteDeploy ini file to launch the WidgetBrowser.
-# 
-# This is most useful while developing and debugging widgets since paster can autoreload the WidgetBrowser
-# whenever any imported module's source is modified. To enable reloading do:
-#
-#   $ paster serve --reload paster.ini
-#
-# The %(here)s variable will be replaced with the parent directory of this file
-#
-
-[server:main]
-use = egg:Paste#http
-# Bind only to the loopback interface since we're starting in intercative mode.
-host = 127.0.0.1
-port = 8000
-
-[app:main]
-use = egg:WidgetBrowser
-# Enable interactive mode so WebError (needs to be easy_installed first) and the Terminal are available
-interactive = true
diff --git a/moksha/apps/widgetbrowser/setup.cfg b/moksha/apps/widgetbrowser/setup.cfg
deleted file mode 100644
index e00908b..0000000
--- a/moksha/apps/widgetbrowser/setup.cfg
+++ /dev/null
@@ -1,14 +0,0 @@
-[aliases]
-release = egg_info -RDb "" sdist bdist_egg register upload
-test = nosetests
-cover = nosetests --with-coverage
-
-#[egg_info]
-#tag_build = dev
-#tag_date = true
-
-[nosetests]
-with-coverage = false
-cover-package = widgetbrowser
-doctest-extension = .txt
-with-doctest = true
diff --git a/moksha/apps/widgetbrowser/setup.py b/moksha/apps/widgetbrowser/setup.py
deleted file mode 100644
index 967a1f9..0000000
--- a/moksha/apps/widgetbrowser/setup.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from setuptools import setup, find_packages
-import sys, os
-
-version = '0.1'
-
-setup(name='WidgetBrowser',
-      version=version,
-      description="ToscaWidgets browser",
-      long_description="""\
-""",
-      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
-      keywords='toscawidgets',
-      author='Alberto Valverde Gonzalez',
-      author_email='alberto at toscat.net',
-      url='http://toscawidgets.org/',
-      license='MIT',
-      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
-      include_package_data=True,
-      zip_safe=True,
-      install_requires=[
-          "ToscaWidgets>=0.9.2dev-20080602",
-          "Genshi",
-          "WebOb",
-          "docutils",
-      ],
-      tests_require = ['nose', 'formencode', 'sphinx'],
-      extras_require = {
-          'full': ['Sphinx', 'Pygments', 'docutils', 'nose', 'WebTest',
-                   'WebError', 'coverage', 'FormEncode'],
-      },
-      entry_points="""
-      [console_scripts]
-      twbrowser = widgetbrowser.command:browser_command
-      [paste.app_factory]
-      main = widgetbrowser.wsgiapp:WidgetBrowser
-      [toscawidgets.widgets]
-      widgets = widgetbrowser.widgets
-      """,
-      )
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/__init__.py b/moksha/apps/widgetbrowser/widgetbrowser/__init__.py
deleted file mode 100644
index c037ed3..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from wsgiapp import WidgetBrowser
-from util import widget_url
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/command.py b/moksha/apps/widgetbrowser/widgetbrowser/command.py
deleted file mode 100644
index 4b15fbe..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/command.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from wsgiref.simple_server import make_server
-from optparse import OptionParser
-
-from widgetbrowser.wsgiapp import WidgetBrowser
-
-
-_parser = OptionParser(usage = "%prog [OPTIONS] [widget_url]")
-_parser.add_option("-i", "--interactive",
-                   dest="interactive",
-                   action="store_true",
-                   default=False)
-_parser.add_option("-b", "--browser",
-                   dest="browser",
-                   action="store_true",
-                   default=False)
-_parser.add_option("-d", "--docs",
-                   dest="docs",
-                   default=None)
-_parser.add_option("-p", "--port",
-                   dest="port",
-                   default=8000)
-
-def browser_command(argv=None):
-    """Command line interface to launch the widgetbrowser"""
-    opts, args = _parser.parse_args(argv)
-
-    # Only allow passing display arguments in debug mode 
-    if args:
-        widget_url = args[0] + '/'
-    else:
-        widget_url = ''
-    app = WidgetBrowser(interactive=opts.interactive, docs_dir=opts.docs)
-    if opts.interactive:
-        try:
-            from weberror.evalexception import EvalException
-            app = EvalException(app)
-        except ImportError:
-            raise ImportError("You need to install WebError for interactive "
-                              "debugging")
-    url = "http://127.0.0.1:%s/" % opts.port
-    if opts.browser:
-        import webbrowser
-        webbrowser.open(url + widget_url)
-    server = make_server('127.0.0.1', int(opts.port), app)
-    print "Server started at " + url
-    try:
-        server.serve_forever()
-    except (KeyboardInterrupt, SystemExit):
-        pass
-
-if __name__ == '__main__':
-    import sys
-    sys.exit(browser_command(sys.argv))
-
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/repl.py b/moksha/apps/widgetbrowser/widgetbrowser/repl.py
deleted file mode 100644
index 5855068..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/repl.py
+++ /dev/null
@@ -1,305 +0,0 @@
-"""
-Robert Brewer was the original author of the module this module has heavily
-inspired from.  http://www.aminus.net/wiki/HTTPREPL
-"""
-import warnings
-from itertools import count
-import codeop
-import inspect
-import os
-import re
-
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
-
-import sys
-import traceback
-
-from webob import Request, Response, exc
-
-try:
-    from formencode import Invalid
-    have_formencode = True
-except ImportError:
-    have_formencode = False
-
-from genshi.util import LRUCache
-import tw
-from tw.api import make_middleware, Widget
-
-from widgetbrowser import util, widgets
-
-class HTTPREPL:
-    
-    def __init__(self, locals=None):
-        self.locals = {}
-        if locals:
-            self.locals.update(locals)
-        self.buffer = []
-    
-    def push(self, line):
-        """Push 'line' and return exec results (None if more input needed)."""
-        if line == "help":
-            return "Type help(object) for help about object."
-        if line == "help()":
-            return "You cannot call help() without an argument."
-        
-        self.buffer.append(line)
-        source = "\n".join(self.buffer)
-        
-        try:
-            code = codeop.compile_command(source, "<HTTP input>", 'single')
-        except (OverflowError, SyntaxError, ValueError):
-            self.buffer = []
-            return traceback.format_exc()
-        
-        if code is None:
-            # More lines needed.
-            return None
-        
-        self.buffer = []
-        return self.execute(code)
-    
-    def execute(self, code):
-        """Execute the given code in self.locals and return any stdout/sterr."""
-        out = StringIO()
-        oldout = sys.stdout
-        olderr = sys.stderr
-        sys.stdout = sys.stderr = out
-        try:
-            try:
-                exec code in self.locals
-            except:
-                result = traceback.format_exc()
-            else:
-                result = out.getvalue()
-        finally:
-            # FormEncode will break if _ is left in __builtins__ and it tries
-            # to use it as a translator
-            __builtins__.pop('_', None)
-            sys.stdout = oldout
-            sys.stderr = olderr
-        out.close()
-        return result
-    
-    def dir(self, line):
-        """Examine a partial line and provide attr list of final expr."""
-        line = re.split(r"\s", line)[-1].strip()
-        # Support lines like "thing.attr" as "thing.", because the browser
-        # may not finish calculating the partial line until after the user
-        # has clicked on a few more keys.
-        line = ".".join(line.split(".")[:-1])
-        try:
-            result = eval("dir(%s)" % line, {}, self.locals)
-        except:
-            return []
-        return result
-    
-    def doc(self, line):
-        """Examine a partial line and provide sig+doc of final expr."""
-        line = re.split(r"\s", line)[-1].strip()
-        # Support lines like "func(text" as "func(", because the browser
-        # may not finish calculating the partial line until after the user
-        # has clicked on a few more keys.
-        line = "(".join(line.split("(")[:-1])
-        try:
-            result = eval(line, {}, self.locals)
-            try:
-                if isinstance(result, type):
-                    func = result.__init__
-                else:
-                    func = result
-                args, varargs, varkw, defaults = inspect.getargspec(func)
-            except TypeError:
-                if callable(result):
-                    doc = getattr(result, "__doc__", "") or ""
-                    return "%s\n\n%s" % (line, doc)
-                return None
-        except:
-            return None
-        
-        if args and args[0] == 'self':
-            args.pop(0)
-        missing = object()
-        defaults = defaults or []
-        defaults = ([missing] * (len(args) - len(defaults))) + list(defaults)
-        arglist = []
-        for a, d in zip(args, defaults):
-            if d is missing:
-                arglist.append(a)
-            else:
-                arglist.append("%s=%s" % (a, d))
-        if varargs:
-            arglist.append("*%s" % varargs)
-        if varkw:
-            arglist.append("**%s" % varkw)
-        doc = getattr(result, "__doc__", "") or ""
-        return "%s(%s)\n%s" % (line, ", ".join(arglist), doc)
-
-
-class DeferredDisplay(object):
-    """Wraps a widget and the args passed to display/render so we can defer
-    its display to another request.
-    
-    .. note::
-        The JS code is dependent on the output of __repr__ since it parses it
-        to know a widget is being displayed so it can open an overlay.
-    """
-    _counter = count(0)
-    def __init__(self, widget, value, **kw):
-        self.id = self._counter.next()
-        self.value = value
-        self.widget = widget
-        self.kw = kw
-
-    def display(self):
-        """
-        Displays the widget as it was intended to be displayed when it was
-        wrapped.
-        """
-        return self.widget.display(self.value, **self.kw)
-
-    __call__ = display
-
-    def __repr__(self):
-        data = (self.id, self.widget.__class__)
-        return self.__class__.__name__ + repr(data)
-
-
-class WidgetReplApp(object):
-    def __init__(self, locals=None, widget_browser=None, max_dialogs=10):
-        self.repl = HTTPREPL(locals)
-        warnings.warn("\n"*2 + "*"*79 + "\n"
-                      "DISCLAIMER:\n"
-                      "Running this app poses a significant security threat "
-                      "if accessible to an \nattacker. Make sure the server is "
-                      "bound to the loopback interface or behind\na firewall "
-                      "and that there are no local untrusted users.\n" + "*"*79)
-        if widget_browser:
-            self.widget_browser = widget_browser
-            self.displayed_widgets = LRUCache(max_dialogs)
-            self.setup_tw()
-
-    def setup_tw(repl_app):
-        # Stack TW's middleware configured with dummy default_view to signal
-        # that a widget is being displayed so we can wrap and register its
-        # output.
-        conf = {'toscawidgets.framework.default_view' : 'tw_repl',
-                'toscawidgets.middleware.inject_resources' : True}
-        repl_app.app = make_middleware(repl_app.app, conf)
-        # monkey-patch display and render to hijack output
-        def wrap(f):
-            if f.func_name == 'wrapper':
-                return f
-            def wrapper(self, value=None, **kw):
-                if self.displays_on == 'tw_repl':
-                    o = DeferredDisplay(self, value, **kw)
-                    repl_app.displayed_widgets[o.id] = o
-                else:
-                    o = f(self, value, **kw)
-                return o
-            return wrapper
-        Widget.display = wrap(Widget.display)
-        Widget.render = wrap(Widget.render)
-
-    def __call__(self, environ, start_response):
-        assert not environ['wsgi.multiprocess'], "Cannot run in a multiprocess"\
-                                                 " environment"
-        return self.app(environ, start_response)
-
-    def app(self, environ, start_response):
-        """Main dispatcher. pops PATH_INFO and delegates to exposed methods."""
-        req = Request(environ.copy())
-        resp = Response(request=req, content_type='text/html; charset=UTF8')
-        first_part = req.path_info_pop() or 'index'
-        method = getattr(self, first_part, None)
-        if getattr(method, 'exposed', False):
-            output = method(req, resp)
-            if isinstance(output, unicode):
-                resp.body = output.encode('utf-8')
-            elif isinstance(output, str):
-                resp.body = output
-            elif output:
-                resp = output
-        else:
-            resp = exc.HTTPNotImplemented()
-        return resp(environ, start_response)
-        
-    def index(self, req, resp):
-        """Return an HTTP-based Read-Eval-Print-Loop terminal."""
-        # Override default_view so resources display properly
-        tw.framework.default_view = 'toscawidgets'
-        tpl = '<html><head><title>"%(title)s</title></head>' \
-              '<body class="flora">%(repl)s</body></html>'
-        prefix = req.script_name + '/'
-        return tpl % {'title': 'WidgetBrowser Terminal',
-                      'repl': widgets.repl(prefix=req.script_name + '/')}
-    index.exposed = True
-    
-    def push(self, req, resp):
-        """Push 'line' and return exec results as a bare response."""
-        line = req.params['line']
-        result = self.repl.push(line)
-        if result is None:
-            # More input lines needed.
-            resp.status_int = 204
-        return result
-    push.exposed = True
-    
-    def dir(self, req, resp):
-        """Push 'line' and return result of eval on the final expr."""
-        line = req.params['line']
-        result = self.repl.dir(line)
-        if not result:
-            resp.status_int = 204
-            return
-        return repr(result)
-    dir.exposed = True
-    
-    def doc(self, req, resp):
-        """Push 'line' and return result of getargspec on the final expr."""
-        line = req.params['line']
-        result = self.repl.doc(line)
-        if not result:
-            resp.status_int = 204
-        return result
-    doc.exposed = True
-    
-    def enrich_namespace(self, ns, request):
-        
-        _disp = request.GET.get('_disp', '')
-        
-        if not "_disp" in ns:
-            ns["_disp"]=_disp
-        if not "interactive" in ns:
-            ns["interactive"]=True
-        return ns
-    
-    def widget_output(self, req, resp):
-        try:
-            key = int(req.path_info.strip('/'))
-            dd = self.displayed_widgets[key]
-        except KeyError:
-            resp.status_int = 404
-            return "There's now widget output at this URL. Maybe it has "\
-                   "expired? Try increasing the 'max_dialogs' parameter"
-
-        widget = dd.widget
-        widget_name = widget.__class__.__name__
-        render = self.widget_browser.render
-        if have_formencode and req.method.upper() == "POST":
-            # A widget submission, try to validate.
-            try:
-                value = widget.validate(req.POST)
-                value = util.pretty_print(value)
-                return render('validation_result.html', locals())
-            except Invalid, error:
-                pass
-        # Override default_view because WidgetBrowser renders on Genshi, not
-        # 'tw_repl', this is needed so widget and resources display properly
-        tw.framework.default_view = 'genshi'
-        widget_output = dd.display()
-        return render('show_widget.html', self.enrich_namespace(locals(),request=req))
-    widget_output.exposed = True
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/sphinx_ext.py b/moksha/apps/widgetbrowser/widgetbrowser/sphinx_ext.py
deleted file mode 100644
index f0c9bea..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/sphinx_ext.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import os
-from docutils import nodes, utils
-from docutils.parsers.rst import directives
-
-from widgetbrowser import util, widgets
-
-widget_tabs = widgets.WidgetBrowserTabs(in_sphinx=True)
-
-def widgetbrowser_directive(dirname, arguments, options, content, lineno,
-                            content_offset, block_text, state, state_machine):
-    """Processes the `widgetbrowser` reStructuredText directive.
-    
-    When generating the URL for the widget it peeks into os.environ for the
-    'TW_BROWSER_PREFIX' environment variable.
-    """
-    widget_path = arguments[0]
-    widget = util.import_widget(widget_path)
-    if not widget:
-        reporter = state.document.reporter
-        msg = reporter.warning(
-            'No widget found at %r' % widget_path, line=lineno)
-        prb = nodes.problematic(block_text, block_text, msg)
-        return [msg, prb]
-    tabs = options.get('tabs') or widget_tabs.tabs
-    prefix = os.environ.get('TW_BROWSER_PREFIX')
-    size = options.get('size')
-    html = widget_tabs(widget, tabs=tabs, prefix=prefix, size=size)
-    node = nodes.raw('', html, format='html')
-    return [node]
-
-
-def _get_tabs(arg):
-    if arg is None:
-        return []
-    return [s.strip() for s in arg.split(',')]
-    
-def _get_size(arg):
-    return arg or "small"
-
-def setup(app):
-    browser_options = {'tabs': _get_tabs, 'size':_get_size}
-    app.add_directive('widgetbrowser', widgetbrowser_directive, 1, (1, 0, 1),
-                      **browser_options)
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.css b/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.css
deleted file mode 100644
index 6eda851..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.css
+++ /dev/null
@@ -1,78 +0,0 @@
-.httprepl .output pre {
-    font: 10pt monospace;
-    margin: 0;
-    padding: 1px;
-    border: 1px solid #E0E0FF;
-    background-color: #F8F8FF;
-    
-    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
-    white-space: -pre-wrap; /* Opera 4 - 6 */
-    white-space: -o-pre-wrap; /* Opera 7 */
-    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
-                            http://www.w3.org/TR/css3-text/#white-space */
-    word-wrap: break-word; /* IE 5.5+ */
-}
-
-.httprepl .output pre.stdin {
-    border: none;
-    background-color: transparent;
-}
-
-form {
-    font: 10pt monospace;
-    margin: 0;
-}
-
-.httprepl .input {
-    font: 10pt monospace;
-    width: 95%;
-    border-top: none;
-    border-right: 1px dotted #E0E0FF;
-    border-bottom: none;
-    border-left: 1px dotted #E0E0FF;
-}
-
-.httprepl .tipbar {
-    position: fixed;
-    top: 10px;
-    
-    /* See http://annevankesteren.nl/test/examples/ie/position-fixed.html */
-    _position:absolute;
-    _top:expression(eval(document.body.scrollTop) + 10);
-    
-    right: 10px;
-    
-    max-width: 50%;
-    max-height: 80%;
-    /* See http://www.svendtofte.com/code/max_width_in_ie/ */
-    width: expression(document.body.clientWidth / 2);
-    height: expression(document.body.clientHeight * 0.8);
-    
-    border: 2px outset #DDCCBB;
-    background-color: #FFEEDD;
-    font: 9pt monospace;
-    
-    margin: 0;
-    padding: 4px;
-    
-    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
-    white-space: -pre-wrap; /* Opera 4 - 6 */
-    white-space: -o-pre-wrap; /* Opera 7 */
-    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
-                            http://www.w3.org/TR/css3-text/#white-space */
-    word-wrap: break-word; /* IE 5.5+ */
-    
-    display: none;
-    overflow: auto;
-}
-
-.httprepl .tipbar a {
-    padding: 4px;
-    text-decoration: none;
-    color: #666666;
-}
-
-.widget-dialog  {
-    background: #fff;
-    z-index: 9999;
-}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.js b/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.js
deleted file mode 100644
index a85f1ef..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.js
+++ /dev/null
@@ -1,432 +0,0 @@
-var HTTPRepl = (function ($) {
-    function http() {
-        var h;
-        if (typeof(XMLHttpRequest) != "undefined") {
-            h = new XMLHttpRequest();
-        } else {
-            try { h = new ActiveXObject("Msxml2.XMLHTTP"); }
-            catch (e) {
-                try { h = new ActiveXObject("Microsoft.XMLHTTP"); }
-                catch (E) { alert("Your browser is not supported."); }
-            }
-        }
-        return h
-    }
-
-
-    //                           HISTORY NAVIGATION                           //
-
-    function use_history(elem) {
-        var content = get_text(elem);
-        // Strip the leading prompt
-        if (elem.className == 'stdin') content = content.substr(4);
-        input.value = content;
-        input.focus();
-    }
-
-    function history_hook() {
-        use_history(this);
-    }
-
-    var current_history = undefined;
-
-    function prev_history() {
-        if (current_history == undefined) {
-            var prev = output.lastChild;
-        } else {
-            var prev = current_history.previousSibling;
-        }
-        while (prev != null && prev.className != 'stdin') {
-            prev = prev.previousSibling;
-        }
-        if (prev != null) {
-            current_history = prev;
-            use_history(prev);
-        }
-    }
-
-    function next_history() {
-        if (current_history == undefined) return;
-        
-        var next = current_history.nextSibling;
-        while (next != null && next.className != 'stdin') {
-            next = next.nextSibling;
-        }
-        if (next != null) {
-            current_history = next;
-            use_history(next);
-        }
-    }
-
-
-    //                            CODE COMPLETION                            //
-
-    current_range = undefined;
-
-    function partial_line() {
-        if (document.selection) {
-            // Internet Explorer
-            current_range = document.selection.createRange();
-            var end = current_range.getBookmark().charCodeAt(2) - 2;
-        } else {
-            var end = input.selectionEnd;
-        }
-        return input.value.substring(0, end);
-    }
-
-    function insert_text(newtext) {
-        if (document.selection) {
-            // Internet Explorer
-            current_range.text = newtext;
-            current_range.select();
-        } else {
-            var start = input.selectionStart;
-            input.value = input.value.substring(0, start) + newtext + input.value.substr(input.selectionEnd);
-            var end = start + newtext.length;
-            input.setSelectionRange(end, end);
-        }
-    }
-
-    function clear_tips() {
-        tipbar.style.display = '';
-        while (tipbar.hasChildNodes()) {
-            tipbar.removeChild(tipbar.lastChild);
-        }
-    }
-
-    function show_tips() {
-        tipbar.style.display = 'block';
-    }
-
-    var intip = false;
-
-    function use_tip() {
-        insert_text(get_text(this));
-        clear_tips();
-        intip = true;
-        input.focus();
-    }
-
-    function dir() {
-        var data = partial_line();
-        
-        clear_tips();
-        
-        var h = http();
-        h.onreadystatechange = function() {
-            if (h.readyState == 4) {
-                try {
-                    var status = h.status;
-                } catch(e) {
-                    var status = "NO HTTP RESPONSE";
-                }
-                switch (status) {
-                    case 200:
-                        var tips = eval(h.responseText);
-                        for (var i=0; i < tips.length; i++) {
-                            var tiplink = document.createElement("a");
-                            tiplink.onclick = use_tip;
-                            tiplink.href = "javascript:void(0)";
-                            set_text(tiplink, tips[i]);
-                            tipbar.appendChild(tiplink);
-                            tipbar.appendChild(document.createElement("br"));
-                        }
-                        show_tips()
-                        input.focus();
-                        break;
-                    // Internet Explorer might return 1223 for 204
-                    case 1223:
-                    case 204:
-                        // No tips available
-                        break;
-                    case 12029:
-                        // Internet Explorer client could not connect to server
-                        status = "NO HTTP RESPONSE";
-                    case 403:
-                        stdout_write("Interactive mode is disabled", false);
-                        break;
-                    default:
-                        stdout_write(status + "\n" + h.responseText, false);
-                }
-            }
-        }
-        h.open("GET", prefix + "dir?line=" + escape(data), true);
-        h.send(null);
-    }
-
-    function doc() {
-        var data = partial_line();
-        
-        clear_tips();
-        
-        var h = http();
-        h.onreadystatechange = function() {
-            if (h.readyState == 4) {
-                try {
-                    var status = h.status;
-                } catch(e) {
-                    var status = "NO HTTP RESPONSE";
-                }
-                switch (status) {
-                    case 200:
-                        tipbar.appendChild(document.createTextNode(h.responseText));
-                        show_tips();
-                        input.focus();
-                        break;
-                    // Internet Explorer might return 1223 for 204
-                    case 1223:
-                    case 403:
-                        stdout_write("Interactive mode is disabled", false);
-                        break;
-                    case 204:
-                        // No tips available
-                        break;
-                    case 12029:
-                        // Internet Explorer client could not connect to server
-                        status = "NO HTTP RESPONSE";
-                    default:
-                        stdout_write(status + "\n" + h.responseText, false);
-                }
-            }
-        }
-        h.open("GET", prefix + "doc?line=" + escape(data), true);
-        h.send(null);
-    }
-
-    //                           COMMAND EXECUTION                           //
-
-    function get_text(elem) {
-        if (elem.innerText != undefined) {
-            // Internet Explorer
-            return elem.innerText;
-        } else {
-            // Mozilla
-            return elem.textContent;
-        }
-    }
-
-    function set_text(elem, newvalue) {
-        if (elem.innerText != undefined) {
-            // Internet Explorer
-            elem.innerText = newvalue;
-        } else {
-            // Mozilla
-            elem.textContent = newvalue;
-        }
-    }
-
-    function get_prompt() {
-        return get_text(prompt_);
-    }
-
-    function set_prompt(newvalue) {
-        set_text(prompt_, newvalue);
-    }
-
-    function stdout_write(content, stdin) {
-        current_history = undefined;
-        if (content == "") return;
-        
-        var block = document.createElement("pre");
-        block.ondblclick = history_hook;
-        if (stdin) {
-            content = get_prompt() + content;
-            block.className = 'stdin';
-        }
-        if (block.innerText != undefined) {
-            // Internet Explorer quirkiness
-            block.innerText = content;
-        } else {
-            block.appendChild(document.createTextNode(content));
-        }
-        output.appendChild(block);
-    }
-
-    whitespace = /^\s+$/;
-
-    function push() {
-        var data = input.value;
-        // Uncomment to treat a line with only whitespace like a blank line
-        // if (whitespace.test(data)) data = "";
-        
-        input.value = "";
-        
-        var h = http();
-        h.onreadystatechange = function() {
-            if (h.readyState == 4) {
-                stdout_write(data, true);
-                try {
-                    var status = h.status;
-                } catch(e) {
-                    var status = "NO HTTP RESPONSE";
-                }
-                switch (status) {
-                    case 200:
-                        set_prompt(">>> ");
-                        var response = h.responseText;
-                        if (!handle_widget_output(response)) {
-                            stdout_write(response, false);
-                        }
-                        break;
-                    // Internet Explorer might return 1223 for 204
-                    case 1223:
-                    case 204:
-                        set_prompt("... ");
-                        // input.value *should* be blank, but just in case...
-                        input.value = "    " + input.value;
-                        break;
-                    case 403:
-                        stdout_write("Interactive mode is disabled", false);
-                        break;
-                    case 12029:
-                        // Internet Explorer client could not connect to server
-                        status = "NO HTTP RESPONSE";
-                    default:
-                        stdout_write(status + "\n" + h.responseText, false);
-                }
-                input.focus();
-            }
-        }
-        h.open("POST", prefix + "push", true);
-        h.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
-        h.send("line=" + escape(data));
-    }
-
-
-    function escape(data) {
-        data = data.replace(/%/gi, "%25");
-        data = data.replace(/&/gi, "%26");
-        data = data.replace(/[+]/gi, "%2B");
-        data = data.replace(/;/gi, "%3B");
-        return data;
-    }
-
-
-    //                                 SETUP                                 //
-
-    function mapKeys(key_code) {
-        if (intip) {
-            intip = false;
-            // Trap the bubbling keyup event from a tiplink. This means that,
-            // if you actually click a tiplink instead of tab and hit 'enter',
-            // you have to hit 'enter' twice to push the line. :(
-            if (key_code == 13) return;
-        }
-        switch(key_code) {
-            case 8:    // backspace
-                clear_tips();
-                break;
-            case 13:   // enter
-                clear_tips();
-                push();
-                break;
-            case 38:   // up arrow
-                prev_history();
-                break;
-            case 40:   // down arrow
-                next_history();
-                break;
-            case 48:  // close paren "("
-                clear_tips();
-                break;
-            case 57:  // open paren "("
-                doc();
-                break;
-            case 190:  // period "."
-                dir();
-                break;
-        }
-    }
-
-    function trapKeys(e) {
-        if (!e) var e = window.event;
-        mapKeys(e.keyCode);
-    }
-
-    //                   WIDGET DIALOGS                                      //
-
-    var new_id = (function make_counter(value) {
-        var state = {value: value || 0};
-        function next() {
-            state.value ++;
-            return 'widget-dialog-' + state.value;
-        }
-        return next;
-    })();
-
-    function open_dialog(config) {
-        var c = $.extend({}, {height:450, width:600}, config);
-        var iframe = $('<iframe><iframe>');
-        iframe.attr({id: new_id(), 'class': 'widget-dialog'});
-        function setSize(size) {
-            var attr = {
-                height: Math.max(0, Math.round(size.height-60)),
-                width: Math.max(0, Math.round(size.width-40))
-            }
-            iframe.attr(attr);
-        }
-        function onResizeStart(event, data) {
-            // Hide the iframe so it doesn't captute mouse events while dragging
-            // the resize handlers
-            iframe.hide();
-        }
-        function onResizeStop(event, data) {
-            setSize(data.instance.size);
-            iframe.show();
-        }
-        function onClose() {
-            iframe.remove();
-            input.focus();
-        }
-        iframe.appendTo(httprepl).dialog(config)
-              .bind('dialogclose', onClose)
-              .trigger('setData.dialog', ['resizeStart', onResizeStart])
-              .trigger('setData.dialog', ['resizeStop', onResizeStop])
-              .attr('src', config.url)
-              .dialog('open');
-        setSize(c);
-    }
-
-    var displayed_widget = /DeferredDisplay\((\d+)[^']*'([^']+)'/;
-
-    function handle_widget_output(response) {
-        var match = displayed_widget(response);
-        if (match) {
-            var config = {
-                url: prefix + 'widget_output/' + match[1],
-                height: 500,
-                width: 750,
-                title: match[2]
-            }
-            open_dialog(config);
-            return true;
-        }
-        return false;
-    }
-    var httprepl = $(''
-        +'<div class="httprepl">' 
-        +  '<div class="output"></div>'
-        +  '<form action="" class="terminal">'
-        +    '<div class="tipbar"></div>'
-        +    '<nobr>'
-        +      '<span class="prompt">&gt;&gt;&gt; </span>'
-        +      '<input type="text" class="input" size=60" />'
-        +    '</nobr>'
-        +  '</form>'
-        +'</div>'
-    );
-    var prefix = '';
-    var input = $('.input', httprepl)[0];
-    input.onkeyup = trapKeys;
-    var output = $('.output', httprepl)[0];
-    var tipbar = $('.tipbar', httprepl)[0];
-    var prompt_ = $('.prompt', httprepl)[0];
-    $('form', httprepl).submit(function() { return false });
-
-    return {
-        render: function(el, config) {
-            prefix = config.prefix || '';
-            httprepl.appendTo($(el));
-        }
-    }
-})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/jquery.js b/moksha/apps/widgetbrowser/widgetbrowser/static/jquery.js
deleted file mode 100644
index ea64073..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/jquery.js
+++ /dev/null
@@ -1,3436 +0,0 @@
-(function(){
-/*
- * jQuery 1.2.4a - New Wave Javascript
- *
- * Copyright (c) 2008 John Resig (jquery.com)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * $Date: 2008-04-08 13:40:03 -0300 (ter, 08 abr 2008) $
- * $Rev: 5214 $
- */
-
-// Map over jQuery in case of overwrite
-if ( window.jQuery )
-	var _jQuery = window.jQuery;
-
-var jQuery = window.jQuery = function( selector, context ) {
-	// The jQuery object is actually just the init constructor 'enhanced'
-	return new jQuery.prototype.init( selector, context );
-};
-
-// Map over the $ in case of overwrite
-if ( window.$ )
-	var _$ = window.$;
-	
-// Map the jQuery namespace to the '$' one
-window.$ = jQuery;
-
-// A simple way to check for HTML strings or ID strings
-// (both of which we optimize for)
-var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
-
-// Is it a simple selector
-var isSimple = /^.[^:#\[\.]*$/;
-
-jQuery.fn = jQuery.prototype = {
-	init: function( selector, context ) {
-		// Make sure that a selection was provided
-		selector = selector || document;
-
-		// Handle $(DOMElement)
-		if ( selector.nodeType ) {
-			this[0] = selector;
-			this.length = 1;
-			return this;
-
-		// Handle HTML strings
-		} else if ( typeof selector == "string" ) {
-			// Are we dealing with HTML string or an ID?
-			var match = quickExpr.exec( selector );
-
-			// Verify a match, and that no context was specified for #id
-			if ( match && (match[1] || !context) ) {
-
-				// HANDLE: $(html) -> $(array)
-				if ( match[1] )
-					selector = jQuery.clean( [ match[1] ], context );
-
-				// HANDLE: $("#id")
-				else {
-					var elem = document.getElementById( match[3] );
-
-					// Make sure an element was located
-					if ( elem )
-						// Handle the case where IE and Opera return items
-						// by name instead of ID
-						if ( elem.id != match[3] )
-							return jQuery().find( selector );
-
-						// Otherwise, we inject the element directly into the jQuery object
-						else {
-							this[0] = elem;
-							this.length = 1;
-							return this;
-						}
-
-					else
-						selector = [];
-				}
-
-			// HANDLE: $(expr, [context])
-			// (which is just equivalent to: $(content).find(expr)
-			} else
-				return new jQuery( context ).find( selector );
-
-		// HANDLE: $(function)
-		// Shortcut for document ready
-		} else if ( jQuery.isFunction( selector ) )
-			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
-
-		return this.setArray(
-			// HANDLE: $(array)
-			selector.constructor == Array && selector ||
-
-			// HANDLE: $(arraylike)
-			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
-			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
-
-			// HANDLE: $(*)
-			[ selector ] );
-	},
-	
-	// The current version of jQuery being used
-	jquery: "1.2.4a",
-
-	// The number of elements contained in the matched element set
-	size: function() {
-		return this.length;
-	},
-	
-	// The number of elements contained in the matched element set
-	length: 0,
-
-	// Get the Nth element in the matched element set OR
-	// Get the whole matched element set as a clean array
-	get: function( num ) {
-		return num == undefined ?
-
-			// Return a 'clean' array
-			jQuery.makeArray( this ) :
-
-			// Return just the object
-			this[ num ];
-	},
-	
-	// Take an array of elements and push it onto the stack
-	// (returning the new matched element set)
-	pushStack: function( elems ) {
-		// Build a new jQuery matched element set
-		var ret = jQuery( elems );
-
-		// Add the old object onto the stack (as a reference)
-		ret.prevObject = this;
-
-		// Return the newly-formed element set
-		return ret;
-	},
-	
-	// Force the current matched set of elements to become
-	// the specified array of elements (destroying the stack in the process)
-	// You should use pushStack() in order to do this, but maintain the stack
-	setArray: function( elems ) {
-		// Resetting the length to 0, then using the native Array push
-		// is a super-fast way to populate an object with array-like properties
-		this.length = 0;
-		Array.prototype.push.apply( this, elems );
-		
-		return this;
-	},
-
-	// Execute a callback for every element in the matched set.
-	// (You can seed the arguments with an array of args, but this is
-	// only used internally.)
-	each: function( callback, args ) {
-		return jQuery.each( this, callback, args );
-	},
-
-	// Determine the position of an element within 
-	// the matched set of elements
-	index: function( elem ) {
-		var ret = -1;
-
-		// Locate the position of the desired element
-		this.each(function(i){
-			if ( this == elem )
-				ret = i;
-		});
-
-		return ret;
-	},
-
-	attr: function( name, value, type ) {
-		var options = name;
-		
-		// Look for the case where we're accessing a style value
-		if ( name.constructor == String )
-			if ( value == undefined )
-				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
-
-			else {
-				options = {};
-				options[ name ] = value;
-			}
-		
-		// Check to see if we're setting style values
-		return this.each(function(i){
-			// Set all the styles
-			for ( name in options )
-				jQuery.attr(
-					type ?
-						this.style :
-						this,
-					name, jQuery.prop( this, options[ name ], type, i, name )
-				);
-		});
-	},
-
-	css: function( key, value ) {
-		// ignore negative width and height values
-		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
-			value = undefined;
-		return this.attr( key, value, "curCSS" );
-	},
-
-	text: function( text ) {
-		if ( typeof text != "object" && text != null )
-			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
-
-		var ret = "";
-
-		jQuery.each( text || this, function(){
-			jQuery.each( this.childNodes, function(){
-				if ( this.nodeType != 8 )
-					ret += this.nodeType != 1 ?
-						this.nodeValue :
-						jQuery.fn.text( [ this ] );
-			});
-		});
-
-		return ret;
-	},
-
-	wrapAll: function( html ) {
-		if ( this[0] )
-			// The elements to wrap the target around
-			jQuery( html, this[0].ownerDocument )
-				.clone()
-				.insertBefore( this[0] )
-				.map(function(){
-					var elem = this;
-
-					while ( elem.firstChild )
-						elem = elem.firstChild;
-
-					return elem;
-				})
-				.append(this);
-
-		return this;
-	},
-
-	wrapInner: function( html ) {
-		return this.each(function(){
-			jQuery( this ).contents().wrapAll( html );
-		});
-	},
-
-	wrap: function( html ) {
-		return this.each(function(){
-			jQuery( this ).wrapAll( html );
-		});
-	},
-
-	append: function() {
-		return this.domManip(arguments, true, false, function(elem){
-			if (this.nodeType == 1)
-				this.appendChild( elem );
-		});
-	},
-
-	prepend: function() {
-		return this.domManip(arguments, true, true, function(elem){
-			if (this.nodeType == 1)
-				this.insertBefore( elem, this.firstChild );
-		});
-	},
-	
-	before: function() {
-		return this.domManip(arguments, false, false, function(elem){
-			this.parentNode.insertBefore( elem, this );
-		});
-	},
-
-	after: function() {
-		return this.domManip(arguments, false, true, function(elem){
-			this.parentNode.insertBefore( elem, this.nextSibling );
-		});
-	},
-
-	end: function() {
-		return this.prevObject || jQuery( [] );
-	},
-
-	find: function( selector ) {
-		var elems = jQuery.map(this, function(elem){
-			return jQuery.find( selector, elem );
-		});
-
-		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
-			jQuery.unique( elems ) :
-			elems );
-	},
-
-	clone: function( events ) {
-		// Do the clone
-		var ret = this.map(function(){
-			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
-				// IE copies events bound via attachEvent when
-				// using cloneNode. Calling detachEvent on the
-				// clone will also remove the events from the orignal
-				// In order to get around this, we use innerHTML.
-				// Unfortunately, this means some modifications to 
-				// attributes in IE that are actually only stored 
-				// as properties will not be copied (such as the
-				// the name attribute on an input).
-				var clone = this.cloneNode(true),
-					container = document.createElement("div");
-				container.appendChild(clone);
-				return jQuery.clean([container.innerHTML])[0];
-			} else
-				return this.cloneNode(true);
-		});
-
-		// Need to set the expando to null on the cloned set if it exists
-		// removeData doesn't work here, IE removes it from the original as well
-		// this is primarily for IE but the data expando shouldn't be copied over in any browser
-		var clone = ret.find("*").andSelf().each(function(){
-			if ( this[ expando ] != undefined )
-				this[ expando ] = null;
-		});
-		
-		// Copy the events from the original to the clone
-		if ( events === true )
-			this.find("*").andSelf().each(function(i){
-				if (this.nodeType == 3)
-					return;
-				var events = jQuery.data( this, "events" );
-
-				for ( var type in events )
-					for ( var handler in events[ type ] )
-						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
-			});
-
-		// Return the cloned set
-		return ret;
-	},
-
-	filter: function( selector ) {
-		return this.pushStack(
-			jQuery.isFunction( selector ) &&
-			jQuery.grep(this, function(elem, i){
-				return selector.call( elem, i );
-			}) ||
-
-			jQuery.multiFilter( selector, this ) );
-	},
-
-	not: function( selector ) {
-		if ( selector.constructor == String )
-			// test special case where just one selector is passed in
-			if ( isSimple.test( selector ) )
-				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
-			else
-				selector = jQuery.multiFilter( selector, this );
-
-		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
-		return this.filter(function() {
-			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
-		});
-	},
-
-	add: function( selector ) {
-		return !selector ? this : this.pushStack( jQuery.merge( 
-			this.get(),
-			selector.constructor == String ? 
-				jQuery( selector ).get() :
-				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
-					selector : [selector] ) );
-	},
-
-	is: function( selector ) {
-		return selector ?
-			jQuery.multiFilter( selector, this ).length > 0 :
-			false;
-	},
-
-	hasClass: function( selector ) {
-		return this.is( "." + selector );
-	},
-	
-	val: function( value ) {
-		if ( value == undefined ) {
-
-			if ( this.length ) {
-				var elem = this[0];
-
-				// We need to handle select boxes special
-				if ( jQuery.nodeName( elem, "select" ) ) {
-					var index = elem.selectedIndex,
-						values = [],
-						options = elem.options,
-						one = elem.type == "select-one";
-					
-					// Nothing was selected
-					if ( index < 0 )
-						return null;
-
-					// Loop through all the selected options
-					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
-						var option = options[ i ];
-
-						if ( option.selected ) {
-							// Get the specifc value for the option
-							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
-							
-							// We don't need an array for one selects
-							if ( one )
-								return value;
-							
-							// Multi-Selects return an array
-							values.push( value );
-						}
-					}
-					
-					return values;
-					
-				// Everything else, we just grab the value
-				} else
-					return (this[0].value || "").replace(/\r/g, "");
-
-			}
-
-			return undefined;
-		}
-
-		return this.each(function(){
-			if ( this.nodeType != 1 )
-				return;
-
-			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
-				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
-					jQuery.inArray(this.name, value) >= 0);
-
-			else if ( jQuery.nodeName( this, "select" ) ) {
-				var values = value.constructor == Array ?
-					value :
-					[ value ];
-
-				jQuery( "option", this ).each(function(){
-					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
-						jQuery.inArray( this.text, values ) >= 0);
-				});
-
-				if ( !values.length )
-					this.selectedIndex = -1;
-
-			} else
-				this.value = value;
-		});
-	},
-	
-	html: function( value ) {
-		return value == undefined ?
-			(this.length ?
-				this[0].innerHTML :
-				null) :
-			this.empty().append( value );
-	},
-
-	replaceWith: function( value ) {
-		return this.after( value ).remove();
-	},
-
-	eq: function( i ) {
-		return this.slice( i, i + 1 );
-	},
-
-	slice: function() {
-		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
-	},
-
-	map: function( callback ) {
-		return this.pushStack( jQuery.map(this, function(elem, i){
-			return callback.call( elem, i, elem );
-		}));
-	},
-
-	andSelf: function() {
-		return this.add( this.prevObject );
-	},
-
-	data: function( key, value ){
-		var parts = key.split(".");
-		parts[1] = parts[1] ? "." + parts[1] : "";
-
-		if ( value == null ) {
-			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-			
-			if ( data == undefined && this.length )
-				data = jQuery.data( this[0], key );
-
-			return data == null && parts[1] ?
-				this.data( parts[0] ) :
-				data;
-		} else
-			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
-				jQuery.data( this, key, value );
-			});
-	},
-
-	removeData: function( key ){
-		return this.each(function(){
-			jQuery.removeData( this, key );
-		});
-	},
-	
-	domManip: function( args, table, reverse, callback ) {
-		var clone = this.length > 1, elems; 
-
-		return this.each(function(){
-			if ( !elems ) {
-				elems = jQuery.clean( args, this.ownerDocument );
-
-				if ( reverse )
-					elems.reverse();
-			}
-
-			var obj = this;
-
-			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
-				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
-
-			var scripts = jQuery( [] );
-
-			jQuery.each(elems, function(){
-				var elem = clone ?
-					jQuery( this ).clone( true )[0] :
-					this;
-
-				// execute all scripts after the elements have been injected
-				if ( jQuery.nodeName( elem, "script" ) ) {
-					scripts = scripts.add( elem );
-				} else {
-					// Remove any inner scripts for later evaluation
-					if ( elem.nodeType == 1 )
-						scripts = scripts.add( jQuery( "script", elem ).remove() );
-
-					// Inject the elements into the document
-					callback.call( obj, elem );
-				}
-			});
-
-			scripts.each( evalScript );
-		});
-	}
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.prototype.init.prototype = jQuery.prototype;
-
-function evalScript( i, elem ) {
-	if ( elem.src )
-		jQuery.ajax({
-			url: elem.src,
-			async: false,
-			dataType: "script"
-		});
-
-	else
-		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
-
-	if ( elem.parentNode )
-		elem.parentNode.removeChild( elem );
-}
-
-jQuery.extend = jQuery.fn.extend = function() {
-	// copy reference to target object
-	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
-
-	// Handle a deep copy situation
-	if ( target.constructor == Boolean ) {
-		deep = target;
-		target = arguments[1] || {};
-		// skip the boolean and the target
-		i = 2;
-	}
-
-	// Handle case when target is a string or something (possible in deep copy)
-	if ( typeof target != "object" && typeof target != "function" )
-		target = {};
-
-	// extend jQuery itself if only one argument is passed
-	if ( length == 1 ) {
-		target = this;
-		i = 0;
-	}
-
-	for ( ; i < length; i++ )
-		// Only deal with non-null/undefined values
-		if ( (options = arguments[ i ]) != null )
-			// Extend the base object
-			for ( var name in options ) {
-				// Prevent never-ending loop
-				if ( target === options[ name ] )
-					continue;
-
-				// Recurse if we're merging object values
-				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
-					target[ name ] = jQuery.extend( deep, target[ name ], options[ name ] );
-
-				// Don't bring in undefined values
-				else if ( options[ name ] != undefined )
-					target[ name ] = options[ name ];
-
-			}
-
-	// Return the modified object
-	return target;
-};
-
-var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
-
-// exclude the following css properties to add px
-var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
-
-jQuery.extend({
-	noConflict: function( deep ) {
-		window.$ = _$;
-
-		if ( deep )
-			window.jQuery = _jQuery;
-
-		return jQuery;
-	},
-
-	// See test/unit/core.js for details concerning this function.
-	isFunction: function( fn ) {
-		return !!fn && typeof fn != "string" && !fn.nodeName && 
-			fn.constructor != Array && /function/i.test( fn + "" );
-	},
-	
-	// check if an element is in a (or is an) XML document
-	isXMLDoc: function( elem ) {
-		return elem.documentElement && !elem.body ||
-			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
-	},
-
-	// Evalulates a script in a global context
-	globalEval: function( data ) {
-		data = jQuery.trim( data );
-
-		if ( data ) {
-			// Inspired by code by Andrea Giammarchi
-			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
-			var head = document.getElementsByTagName("head")[0] || document.documentElement,
-				script = document.createElement("script");
-
-			script.type = "text/javascript";
-			if ( jQuery.browser.msie )
-				script.text = data;
-			else
-				script.appendChild( document.createTextNode( data ) );
-
-			head.appendChild( script );
-			head.removeChild( script );
-		}
-	},
-
-	nodeName: function( elem, name ) {
-		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
-	},
-	
-	cache: {},
-	
-	data: function( elem, name, data ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// Compute a unique ID for the element
-		if ( !id ) 
-			id = elem[ expando ] = ++uuid;
-
-		// Only generate the data cache if we're
-		// trying to access or manipulate it
-		if ( name && !jQuery.cache[ id ] )
-			jQuery.cache[ id ] = {};
-		
-		// Prevent overriding the named cache with undefined values
-		if ( data != undefined )
-			jQuery.cache[ id ][ name ] = data;
-		
-		// Return the named cache data, or the ID for the element	
-		return name ?
-			jQuery.cache[ id ][ name ] :
-			id;
-	},
-	
-	removeData: function( elem, name ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// If we want to remove a specific section of the element's data
-		if ( name ) {
-			if ( jQuery.cache[ id ] ) {
-				// Remove the section of cache data
-				delete jQuery.cache[ id ][ name ];
-
-				// If we've removed all the data, remove the element's cache
-				name = "";
-
-				for ( name in jQuery.cache[ id ] )
-					break;
-
-				if ( !name )
-					jQuery.removeData( elem );
-			}
-
-		// Otherwise, we want to remove all of the element's data
-		} else {
-			// Clean up the element expando
-			try {
-				delete elem[ expando ];
-			} catch(e){
-				// IE has trouble directly removing the expando
-				// but it's ok with using removeAttribute
-				if ( elem.removeAttribute )
-					elem.removeAttribute( expando );
-			}
-
-			// Completely remove the data cache
-			delete jQuery.cache[ id ];
-		}
-	},
-
-	// args is for internal usage only
-	each: function( object, callback, args ) {
-		if ( args ) {
-			if ( object.length == undefined ) {
-				for ( var name in object )
-					if ( callback.apply( object[ name ], args ) === false )
-						break;
-			} else
-				for ( var i = 0, length = object.length; i < length; i++ )
-					if ( callback.apply( object[ i ], args ) === false )
-						break;
-
-		// A special, fast, case for the most common use of each
-		} else {
-			if ( object.length == undefined ) {
-				for ( var name in object )
-					if ( callback.call( object[ name ], name, object[ name ] ) === false )
-						break;
-			} else
-				for ( var i = 0, length = object.length, value = object[0]; 
-					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
-		}
-
-		return object;
-	},
-	
-	prop: function( elem, value, type, i, name ) {
-			// Handle executable functions
-			if ( jQuery.isFunction( value ) )
-				value = value.call( elem, i );
-				
-			// Handle passing in a number to a CSS property
-			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
-				value + "px" :
-				value;
-	},
-
-	className: {
-		// internal only, use addClass("class")
-		add: function( elem, classNames ) {
-			jQuery.each((classNames || "").split(/\s+/), function(i, className){
-				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
-					elem.className += (elem.className ? " " : "") + className;
-			});
-		},
-
-		// internal only, use removeClass("class")
-		remove: function( elem, classNames ) {
-			if (elem.nodeType == 1)
-				elem.className = classNames != undefined ?
-					jQuery.grep(elem.className.split(/\s+/), function(className){
-						return !jQuery.className.has( classNames, className );	
-					}).join(" ") :
-					"";
-		},
-
-		// internal only, use is(".class")
-		has: function( elem, className ) {
-			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
-		}
-	},
-
-	// A method for quickly swapping in/out CSS properties to get correct calculations
-	swap: function( elem, options, callback ) {
-		var old = {};
-		// Remember the old values, and insert the new ones
-		for ( var name in options ) {
-			old[ name ] = elem.style[ name ];
-			elem.style[ name ] = options[ name ];
-		}
-
-		callback.call( elem );
-
-		// Revert the old values
-		for ( var name in options )
-			elem.style[ name ] = old[ name ];
-	},
-
-	css: function( elem, name, force ) {
-		if ( name == "width" || name == "height" ) {
-			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
-		
-			function getWH() {
-				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
-				var padding = 0, border = 0;
-				jQuery.each( which, function() {
-					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
-					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
-				});
-				val -= Math.round(padding + border);
-			}
-		
-			if ( jQuery(elem).is(":visible") )
-				getWH();
-			else
-				jQuery.swap( elem, props, getWH );
-			
-			return Math.max(0, val);
-		}
-		
-		return jQuery.curCSS( elem, name, force );
-	},
-
-	curCSS: function( elem, name, force ) {
-		var ret;
-
-		// A helper method for determining if an element's values are broken
-		function color( elem ) {
-			if ( !jQuery.browser.safari )
-				return false;
-
-			var ret = document.defaultView.getComputedStyle( elem, null );
-			return !ret || ret.getPropertyValue("color") == "";
-		}
-
-		// We need to handle opacity special in IE
-		if ( name == "opacity" && jQuery.browser.msie ) {
-			ret = jQuery.attr( elem.style, "opacity" );
-
-			return ret == "" ?
-				"1" :
-				ret;
-		}
-		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
-		if ( jQuery.browser.opera && name == "display" ) {
-			var save = elem.style.outline;
-			elem.style.outline = "0 solid black";
-			elem.style.outline = save;
-		}
-		
-		// Make sure we're using the right name for getting the float value
-		if ( name.match( /float/i ) )
-			name = styleFloat;
-
-		if ( !force && elem.style && elem.style[ name ] )
-			ret = elem.style[ name ];
-
-		else if ( document.defaultView && document.defaultView.getComputedStyle ) {
-
-			// Only "float" is needed here
-			if ( name.match( /float/i ) )
-				name = "float";
-
-			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
-
-			var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
-
-			if ( getComputedStyle && !color( elem ) )
-				ret = getComputedStyle.getPropertyValue( name );
-
-			// If the element isn't reporting its values properly in Safari
-			// then some display: none elements are involved
-			else {
-				var swap = [], stack = [];
-
-				// Locate all of the parent display: none elements
-				for ( var a = elem; a && color(a); a = a.parentNode )
-					stack.unshift(a);
-
-				// Go through and make them visible, but in reverse
-				// (It would be better if we knew the exact display type that they had)
-				for ( var i = 0; i < stack.length; i++ )
-					if ( color( stack[ i ] ) ) {
-						swap[ i ] = stack[ i ].style.display;
-						stack[ i ].style.display = "block";
-					}
-
-				// Since we flip the display style, we have to handle that
-				// one special, otherwise get the value
-				ret = name == "display" && swap[ stack.length - 1 ] != null ?
-					"none" :
-					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
-
-				// Finally, revert the display styles back
-				for ( var i = 0; i < swap.length; i++ )
-					if ( swap[ i ] != null )
-						stack[ i ].style.display = swap[ i ];
-			}
-
-			// We should always get a number back from opacity
-			if ( name == "opacity" && ret == "" )
-				ret = "1";
-
-		} else if ( elem.currentStyle ) {
-			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
-				return letter.toUpperCase();
-			});
-
-			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
-
-			// From the awesome hack by Dean Edwards
-			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
-			// If we're not dealing with a regular pixel number
-			// but a number that has a weird ending, we need to convert it to pixels
-			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
-				// Remember the original values
-				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
-
-				// Put in the new values to get a computed value out
-				elem.runtimeStyle.left = elem.currentStyle.left;
-				elem.style.left = ret || 0;
-				ret = elem.style.pixelLeft + "px";
-
-				// Revert the changed values
-				elem.style.left = style;
-				elem.runtimeStyle.left = runtimeStyle;
-			}
-		}
-
-		return ret;
-	},
-	
-	clean: function( elems, context ) {
-		var ret = [];
-		context = context || document;
-		// !context.createElement fails in IE with an error but returns typeof 'object'
-		if (typeof context.createElement == 'undefined') 
-			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
-
-		jQuery.each(elems, function(i, elem){
-			if ( !elem )
-				return;
-
-			if ( elem.constructor == Number )
-				elem = elem.toString();
-			
-			// Convert html string into DOM nodes
-			if ( typeof elem == "string" ) {
-				// Fix "XHTML"-style tags in all browsers
-				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
-					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
-						all :
-						front + "></" + tag + ">";
-				});
-
-				// Trim whitespace, otherwise indexOf won't work as expected
-				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
-
-				var wrap =
-					// option or optgroup
-					!tags.indexOf("<opt") &&
-					[ 1, "<select multiple='multiple'>", "</select>" ] ||
-					
-					!tags.indexOf("<leg") &&
-					[ 1, "<fieldset>", "</fieldset>" ] ||
-					
-					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
-					[ 1, "<table>", "</table>" ] ||
-					
-					!tags.indexOf("<tr") &&
-					[ 2, "<table><tbody>", "</tbody></table>" ] ||
-					
-				 	// <thead> matched above
-					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
-					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
-					
-					!tags.indexOf("<col") &&
-					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
-
-					// IE can't serialize <link> and <script> tags normally
-					jQuery.browser.msie &&
-					[ 1, "div<div>", "</div>" ] ||
-					
-					[ 0, "", "" ];
-
-				// Go to html and back, then peel off extra wrappers
-				div.innerHTML = wrap[1] + elem + wrap[2];
-				
-				// Move to the right depth
-				while ( wrap[0]-- )
-					div = div.lastChild;
-				
-				// Remove IE's autoinserted <tbody> from table fragments
-				if ( jQuery.browser.msie ) {
-					
-					// String was a <table>, *may* have spurious <tbody>
-					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
-						div.firstChild && div.firstChild.childNodes :
-						
-						// String was a bare <thead> or <tfoot>
-						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
-							div.childNodes :
-							[];
-				
-					for ( var j = tbody.length - 1; j >= 0 ; --j )
-						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
-							tbody[ j ].parentNode.removeChild( tbody[ j ] );
-					
-					// IE completely kills leading whitespace when innerHTML is used	
-					if ( /^\s/.test( elem ) )	
-						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
-				
-				}
-				
-				elem = jQuery.makeArray( div.childNodes );
-			}
-
-			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
-				return;
-
-			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
-				ret.push( elem );
-
-			else
-				ret = jQuery.merge( ret, elem );
-
-		});
-
-		return ret;
-	},
-	
-	attr: function( elem, name, value ) {
-		// don't set attributes on text and comment nodes
-		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
-			return undefined;
-
-		var fix = jQuery.isXMLDoc( elem ) ?
-			{} :
-			jQuery.props;
-
-		// Safari mis-reports the default selected property of a hidden option
-		// Accessing the parent's selectedIndex property fixes it
-		if ( name == "selected" && jQuery.browser.safari )
-			elem.parentNode.selectedIndex;
-		
-		// Certain attributes only work when accessed via the old DOM 0 way
-		if ( fix[ name ] ) {
-			if ( value != undefined )
-				elem[ fix[ name ] ] = value;
-
-			return elem[ fix[ name ] ];
-
-		} else if ( jQuery.browser.msie && name == "style" )
-			return jQuery.attr( elem.style, "cssText", value );
-
-		else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
-			return elem.getAttributeNode( name ).nodeValue;
-
-		// IE elem.getAttribute passes even for style
-		else if ( elem.tagName ) {
-
-			if ( value != undefined ) {
-				// We can't allow the type property to be changed (since it causes problems in IE)
-				if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
-					throw "type property can't be changed";
-
-				// convert the value to a string (all browsers do this but IE) see #1070
-				elem.setAttribute( name, "" + value );
-			}
-
-			if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) ) 
-				return elem.getAttribute( name, 2 );
-
-			return elem.getAttribute( name );
-
-		// elem is actually elem.style ... set the style
-		} else {
-			// IE actually uses filters for opacity
-			if ( name == "opacity" && jQuery.browser.msie ) {
-				if ( value != undefined ) {
-					// IE has trouble with opacity if it does not have layout
-					// Force it by setting the zoom level
-					elem.zoom = 1; 
-	
-					// Set the alpha filter to set the opacity
-					elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
-						(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
-				}
-	
-				return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
-					(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
-					"";
-			}
-
-			name = name.replace(/-([a-z])/ig, function(all, letter){
-				return letter.toUpperCase();
-			});
-
-			if ( value != undefined )
-				elem[ name ] = value;
-
-			return elem[ name ];
-		}
-	},
-	
-	trim: function( text ) {
-		return (text || "").replace( /^\s+|\s+$/g, "" );
-	},
-
-	makeArray: function( array ) {
-		var ret = [];
-
-		// Need to use typeof to fight Safari childNodes crashes
-		if ( array.constructor != Array )
-			for ( var i = 0, length = array.length; i < length; i++ )
-				ret.push( array[ i ] );
-		else
-			ret = array.slice( 0 );
-
-		return ret;
-	},
-
-	inArray: function( elem, array ) {
-		for ( var i = 0, length = array.length; i < length; i++ )
-			if ( array[ i ] == elem )
-				return i;
-
-		return -1;
-	},
-
-	merge: function( first, second ) {
-		// We have to loop this way because IE & Opera overwrite the length
-		// expando of getElementsByTagName
-
-		// Also, we need to make sure that the correct elements are being returned
-		// (IE returns comment nodes in a '*' query)
-		if ( jQuery.browser.msie ) {
-			for ( var i = 0; second[ i ]; i++ )
-				if ( second[ i ].nodeType != 8 )
-					first.push( second[ i ] );
-
-		} else
-			for ( var i = 0; second[ i ]; i++ )
-				first.push( second[ i ] );
-
-		return first;
-	},
-
-	unique: function( array ) {
-		var ret = [], done = {};
-
-		try {
-
-			for ( var i = 0, length = array.length; i < length; i++ ) {
-				var id = jQuery.data( array[ i ] );
-
-				if ( !done[ id ] ) {
-					done[ id ] = true;
-					ret.push( array[ i ] );
-				}
-			}
-
-		} catch( e ) {
-			ret = array;
-		}
-
-		return ret;
-	},
-
-	grep: function( elems, callback, inv ) {
-		var ret = [];
-
-		// Go through the array, only saving the items
-		// that pass the validator function
-		for ( var i = 0, length = elems.length; i < length; i++ )
-			if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
-				ret.push( elems[ i ] );
-
-		return ret;
-	},
-
-	map: function( elems, callback ) {
-		var ret = [];
-
-		// Go through the array, translating each of the items to their
-		// new value (or values).
-		for ( var i = 0, length = elems.length; i < length; i++ ) {
-			var value = callback( elems[ i ], i );
-
-			if ( value !== null && value != undefined ) {
-				if ( value.constructor != Array )
-					value = [ value ];
-
-				ret = ret.concat( value );
-			}
-		}
-
-		return ret;
-	}
-});
-
-var userAgent = navigator.userAgent.toLowerCase();
-
-// Figure out what browser is being used
-jQuery.browser = {
-	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
-	safari: /webkit/.test( userAgent ),
-	opera: /opera/.test( userAgent ),
-	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
-	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
-};
-
-var styleFloat = jQuery.browser.msie ?
-	"styleFloat" :
-	"cssFloat";
-	
-jQuery.extend({
-	// Check to see if the W3C box model is being used
-	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
-	
-	props: {
-		"for": "htmlFor",
-		"class": "className",
-		"float": styleFloat,
-		cssFloat: styleFloat,
-		styleFloat: styleFloat,
-		innerHTML: "innerHTML",
-		className: "className",
-		value: "value",
-		disabled: "disabled",
-		checked: "checked",
-		readonly: "readOnly",
-		selected: "selected",
-		maxlength: "maxLength",
-		selectedIndex: "selectedIndex",
-		defaultValue: "defaultValue",
-		tagName: "tagName",
-		nodeName: "nodeName"
-	}
-});
-
-jQuery.each({
-	parent: function(elem){return elem.parentNode;},
-	parents: function(elem){return jQuery.dir(elem,"parentNode");},
-	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
-	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
-	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
-	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
-	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
-	children: function(elem){return jQuery.sibling(elem.firstChild);},
-	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
-}, function(name, fn){
-	jQuery.fn[ name ] = function( selector ) {
-		var ret = jQuery.map( this, fn );
-
-		if ( selector && typeof selector == "string" )
-			ret = jQuery.multiFilter( selector, ret );
-
-		return this.pushStack( jQuery.unique( ret ) );
-	};
-});
-
-jQuery.each({
-	appendTo: "append",
-	prependTo: "prepend",
-	insertBefore: "before",
-	insertAfter: "after",
-	replaceAll: "replaceWith"
-}, function(name, original){
-	jQuery.fn[ name ] = function() {
-		var args = arguments;
-
-		return this.each(function(){
-			for ( var i = 0, length = args.length; i < length; i++ )
-				jQuery( args[ i ] )[ original ]( this );
-		});
-	};
-});
-
-jQuery.each({
-	removeAttr: function( name ) {
-		jQuery.attr( this, name, "" );
-		if (this.nodeType == 1) 
-			this.removeAttribute( name );
-	},
-
-	addClass: function( classNames ) {
-		jQuery.className.add( this, classNames );
-	},
-
-	removeClass: function( classNames ) {
-		jQuery.className.remove( this, classNames );
-	},
-
-	toggleClass: function( classNames ) {
-		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
-	},
-
-	remove: function( selector ) {
-		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
-			// Prevent memory leaks
-			jQuery( "*", this ).add(this).each(function(){
-				jQuery.event.remove(this);
-				jQuery.removeData(this);
-			});
-			if (this.parentNode)
-				this.parentNode.removeChild( this );
-		}
-	},
-
-	empty: function() {
-		// Remove element nodes and prevent memory leaks
-		jQuery( ">*", this ).remove();
-		
-		// Remove any remaining nodes
-		while ( this.firstChild )
-			this.removeChild( this.firstChild );
-	}
-}, function(name, fn){
-	jQuery.fn[ name ] = function(){
-		return this.each( fn, arguments );
-	};
-});
-
-jQuery.each([ "Height", "Width" ], function(i, name){
-	var type = name.toLowerCase();
-	
-	jQuery.fn[ type ] = function( size ) {
-		// Get window width or height
-		return this[0] == window ?
-			// Opera reports document.body.client[Width/Height] properly in both quirks and standards
-			jQuery.browser.opera && document.body[ "client" + name ] || 
-			
-			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
-			jQuery.browser.safari && window[ "inner" + name ] ||
-			
-			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
-			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
-		
-			// Get document width or height
-			this[0] == document ?
-				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
-				Math.max( 
-					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), 
-					Math.max(document.body["offset" + name], document.documentElement["offset" + name]) 
-				) :
-
-				// Get or set width or height on the element
-				size == undefined ?
-					// Get width or height on the element
-					(this.length ? jQuery.css( this[0], type ) : null) :
-
-					// Set the width or height on the element (default to pixels if value is unitless)
-					this.css( type, size.constructor == String ? size : size + "px" );
-	};
-});
-
-var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
-		"(?:[\\w*_-]|\\\\.)" :
-		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
-	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
-	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
-	quickClass = new RegExp("^([#.]?)(" + chars + "*)");
-
-jQuery.extend({
-	expr: {
-		"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
-		"#": function(a,i,m){return a.getAttribute("id")==m[2];},
-		":": {
-			// Position Checks
-			lt: function(a,i,m){return i<m[3]-0;},
-			gt: function(a,i,m){return i>m[3]-0;},
-			nth: function(a,i,m){return m[3]-0==i;},
-			eq: function(a,i,m){return m[3]-0==i;},
-			first: function(a,i){return i==0;},
-			last: function(a,i,m,r){return i==r.length-1;},
-			even: function(a,i){return i%2==0;},
-			odd: function(a,i){return i%2;},
-
-			// Child Checks
-			"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
-			"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
-			"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
-
-			// Parent Checks
-			parent: function(a){return a.firstChild;},
-			empty: function(a){return !a.firstChild;},
-
-			// Text Check
-			contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
-
-			// Visibility
-			visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
-			hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
-
-			// Form attributes
-			enabled: function(a){return !a.disabled;},
-			disabled: function(a){return a.disabled;},
-			checked: function(a){return a.checked;},
-			selected: function(a){return a.selected||jQuery.attr(a,"selected");},
-
-			// Form elements
-			text: function(a){return "text"==a.type;},
-			radio: function(a){return "radio"==a.type;},
-			checkbox: function(a){return "checkbox"==a.type;},
-			file: function(a){return "file"==a.type;},
-			password: function(a){return "password"==a.type;},
-			submit: function(a){return "submit"==a.type;},
-			image: function(a){return "image"==a.type;},
-			reset: function(a){return "reset"==a.type;},
-			button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
-			input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
-
-			// :has()
-			has: function(a,i,m){return jQuery.find(m[3],a).length;},
-
-			// :header
-			header: function(a){return /h\d/i.test(a.nodeName);},
-
-			// :animated
-			animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
-		}
-	},
-	
-	// The regular expressions that power the parsing engine
-	parse: [
-		// Match: [@value='test'], [@foo]
-		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
-
-		// Match: :contains('foo')
-		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
-
-		// Match: :even, :last-chlid, #id, .class
-		new RegExp("^([:.#]*)(" + chars + "+)")
-	],
-
-	multiFilter: function( expr, elems, not ) {
-		var old, cur = [];
-
-		while ( expr && expr != old ) {
-			old = expr;
-			var f = jQuery.filter( expr, elems, not );
-			expr = f.t.replace(/^\s*,\s*/, "" );
-			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
-		}
-
-		return cur;
-	},
-
-	find: function( t, context ) {
-		// Quickly handle non-string expressions
-		if ( typeof t != "string" )
-			return [ t ];
-
-		// check to make sure context is a DOM element or a document
-		if ( context && context.nodeType != 1 && context.nodeType != 9)
-			return [ ];
-
-		// Set the correct context (if none is provided)
-		context = context || document;
-
-		// Initialize the search
-		var ret = [context], done = [], last, nodeName;
-
-		// Continue while a selector expression exists, and while
-		// we're no longer looping upon ourselves
-		while ( t && last != t ) {
-			var r = [];
-			last = t;
-
-			t = jQuery.trim(t);
-
-			var foundToken = false;
-
-			// An attempt at speeding up child selectors that
-			// point to a specific element tag
-			var re = quickChild;
-			var m = re.exec(t);
-
-			if ( m ) {
-				nodeName = m[1].toUpperCase();
-
-				// Perform our own iteration and filter
-				for ( var i = 0; ret[i]; i++ )
-					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
-						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
-							r.push( c );
-
-				ret = r;
-				t = t.replace( re, "" );
-				if ( t.indexOf(" ") == 0 ) continue;
-				foundToken = true;
-			} else {
-				re = /^([>+~])\s*(\w*)/i;
-
-				if ( (m = re.exec(t)) != null ) {
-					r = [];
-
-					var merge = {};
-					nodeName = m[2].toUpperCase();
-					m = m[1];
-
-					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
-						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
-						for ( ; n; n = n.nextSibling )
-							if ( n.nodeType == 1 ) {
-								var id = jQuery.data(n);
-
-								if ( m == "~" && merge[id] ) break;
-								
-								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
-									if ( m == "~" ) merge[id] = true;
-									r.push( n );
-								}
-								
-								if ( m == "+" ) break;
-							}
-					}
-
-					ret = r;
-
-					// And remove the token
-					t = jQuery.trim( t.replace( re, "" ) );
-					foundToken = true;
-				}
-			}
-
-			// See if there's still an expression, and that we haven't already
-			// matched a token
-			if ( t && !foundToken ) {
-				// Handle multiple expressions
-				if ( !t.indexOf(",") ) {
-					// Clean the result set
-					if ( context == ret[0] ) ret.shift();
-
-					// Merge the result sets
-					done = jQuery.merge( done, ret );
-
-					// Reset the context
-					r = ret = [context];
-
-					// Touch up the selector string
-					t = " " + t.substr(1,t.length);
-
-				} else {
-					// Optimize for the case nodeName#idName
-					var re2 = quickID;
-					var m = re2.exec(t);
-					
-					// Re-organize the results, so that they're consistent
-					if ( m ) {
-						m = [ 0, m[2], m[3], m[1] ];
-
-					} else {
-						// Otherwise, do a traditional filter check for
-						// ID, class, and element selectors
-						re2 = quickClass;
-						m = re2.exec(t);
-					}
-
-					m[2] = m[2].replace(/\\/g, "");
-
-					var elem = ret[ret.length-1];
-
-					// Try to do a global search by ID, where we can
-					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
-						// Optimization for HTML document case
-						var oid = elem.getElementById(m[2]);
-						
-						// Do a quick check for the existence of the actual ID attribute
-						// to avoid selecting by the name attribute in IE
-						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
-						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
-							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
-
-						// Do a quick check for node name (where applicable) so
-						// that div#foo searches will be really fast
-						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
-					} else {
-						// We need to find all descendant elements
-						for ( var i = 0; ret[i]; i++ ) {
-							// Grab the tag name being searched for
-							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
-
-							// Handle IE7 being really dumb about <object>s
-							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
-								tag = "param";
-
-							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
-						}
-
-						// It's faster to filter by class and be done with it
-						if ( m[1] == "." )
-							r = jQuery.classFilter( r, m[2] );
-
-						// Same with ID filtering
-						if ( m[1] == "#" ) {
-							var tmp = [];
-
-							// Try to find the element with the ID
-							for ( var i = 0; r[i]; i++ )
-								if ( r[i].getAttribute("id") == m[2] ) {
-									tmp = [ r[i] ];
-									break;
-								}
-
-							r = tmp;
-						}
-
-						ret = r;
-					}
-
-					t = t.replace( re2, "" );
-				}
-
-			}
-
-			// If a selector string still exists
-			if ( t ) {
-				// Attempt to filter it
-				var val = jQuery.filter(t,r);
-				ret = r = val.r;
-				t = jQuery.trim(val.t);
-			}
-		}
-
-		// An error occurred with the selector;
-		// just return an empty set instead
-		if ( t )
-			ret = [];
-
-		// Remove the root context
-		if ( ret && context == ret[0] )
-			ret.shift();
-
-		// And combine the results
-		done = jQuery.merge( done, ret );
-
-		return done;
-	},
-
-	classFilter: function(r,m,not){
-		m = " " + m + " ";
-		var tmp = [];
-		for ( var i = 0; r[i]; i++ ) {
-			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
-			if ( !not && pass || not && !pass )
-				tmp.push( r[i] );
-		}
-		return tmp;
-	},
-
-	filter: function(t,r,not) {
-		var last;
-
-		// Look for common filter expressions
-		while ( t && t != last ) {
-			last = t;
-
-			var p = jQuery.parse, m;
-
-			for ( var i = 0; p[i]; i++ ) {
-				m = p[i].exec( t );
-
-				if ( m ) {
-					// Remove what we just matched
-					t = t.substring( m[0].length );
-
-					m[2] = m[2].replace(/\\/g, "");
-					break;
-				}
-			}
-
-			if ( !m )
-				break;
-
-			// :not() is a special case that can be optimized by
-			// keeping it out of the expression list
-			if ( m[1] == ":" && m[2] == "not" )
-				// optimize if only one selector found (most common case)
-				r = isSimple.test( m[3] ) ?
-					jQuery.filter(m[3], r, true).r :
-					jQuery( r ).not( m[3] );
-
-			// We can get a big speed boost by filtering by class here
-			else if ( m[1] == "." )
-				r = jQuery.classFilter(r, m[2], not);
-
-			else if ( m[1] == "[" ) {
-				var tmp = [], type = m[3];
-				
-				for ( var i = 0, rl = r.length; i < rl; i++ ) {
-					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
-					
-					if ( z == null || /href|src|selected/.test(m[2]) )
-						z = jQuery.attr(a,m[2]) || '';
-
-					if ( (type == "" && !!z ||
-						 type == "=" && z == m[5] ||
-						 type == "!=" && z != m[5] ||
-						 type == "^=" && z && !z.indexOf(m[5]) ||
-						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
-						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
-							tmp.push( a );
-				}
-				
-				r = tmp;
-
-			// We can get a speed boost by handling nth-child here
-			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
-				var merge = {}, tmp = [],
-					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
-					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
-						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
-						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
-					// calculate the numbers (first)n+(last) including if they are negative
-					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
- 
-				// loop through all the elements left in the jQuery object
-				for ( var i = 0, rl = r.length; i < rl; i++ ) {
-					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
-
-					if ( !merge[id] ) {
-						var c = 1;
-
-						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
-							if ( n.nodeType == 1 )
-								n.nodeIndex = c++;
-
-						merge[id] = true;
-					}
-
-					var add = false;
-
-					if ( first == 0 ) {
-						if ( node.nodeIndex == last )
-							add = true;
-					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
-						add = true;
-
-					if ( add ^ not )
-						tmp.push( node );
-				}
-
-				r = tmp;
-
-			// Otherwise, find the expression to execute
-			} else {
-				var fn = jQuery.expr[ m[1] ];
-				if ( typeof fn == "object" )
-					fn = fn[ m[2] ];
-
-				if ( typeof fn == "string" )
-					fn = eval("false||function(a,i){return " + fn + ";}");
-
-				// Execute it against the current filter
-				r = jQuery.grep( r, function(elem, i){
-					return fn(elem, i, m, r);
-				}, not );
-			}
-		}
-
-		// Return an array of filtered elements (r)
-		// and the modified expression string (t)
-		return { r: r, t: t };
-	},
-
-	dir: function( elem, dir ){
-		var matched = [];
-		var cur = elem[dir];
-		while ( cur && cur != document ) {
-			if ( cur.nodeType == 1 )
-				matched.push( cur );
-			cur = cur[dir];
-		}
-		return matched;
-	},
-	
-	nth: function(cur,result,dir,elem){
-		result = result || 1;
-		var num = 0;
-
-		for ( ; cur; cur = cur[dir] )
-			if ( cur.nodeType == 1 && ++num == result )
-				break;
-
-		return cur;
-	},
-	
-	sibling: function( n, elem ) {
-		var r = [];
-
-		for ( ; n; n = n.nextSibling ) {
-			if ( n.nodeType == 1 && (!elem || n != elem) )
-				r.push( n );
-		}
-
-		return r;
-	}
-});
-
-/*
- * A number of helper functions used for managing events.
- * Many of the ideas behind this code orignated from 
- * Dean Edwards' addEvent library.
- */
-jQuery.event = {
-
-	// Bind an event to an element
-	// Original by Dean Edwards
-	add: function(elem, types, handler, data) {
-		if ( elem.nodeType == 3 || elem.nodeType == 8 )
-			return;
-
-		// For whatever reason, IE has trouble passing the window object
-		// around, causing it to be cloned in the process
-		if ( jQuery.browser.msie && elem.setInterval != undefined )
-			elem = window;
-
-		// Make sure that the function being executed has a unique ID
-		if ( !handler.guid )
-			handler.guid = this.guid++;
-			
-		// if data is passed, bind to handler 
-		if( data != undefined ) { 
-			// Create temporary function pointer to original handler 
-			var fn = handler; 
-
-			// Create unique handler function, wrapped around original handler 
-			handler = function() { 
-				// Pass arguments and context to original handler 
-				return fn.apply(this, arguments); 
-			};
-
-			// Store data in unique handler 
-			handler.data = data;
-
-			// Set the guid of unique handler to the same of original handler, so it can be removed 
-			handler.guid = fn.guid;
-		}
-
-		// Init the element's event structure
-		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
-			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
-				// returned undefined or false
-				var val;
-
-				// Handle the second event of a trigger and when
-				// an event is called after a page has unloaded
-				if ( typeof jQuery == "undefined" || jQuery.event.triggered )
-					return val;
-		
-				val = jQuery.event.handle.apply(arguments.callee.elem, arguments);
-		
-				return val;
-			});
-		// Add elem as a property of the handle function
-		// This is to prevent a memory leak with non-native
-		// event in IE.
-		handle.elem = elem;
-			
-			// Handle multiple events seperated by a space
-			// jQuery(...).bind("mouseover mouseout", fn);
-			jQuery.each(types.split(/\s+/), function(index, type) {
-				// Namespaced event handlers
-				var parts = type.split(".");
-				type = parts[0];
-				handler.type = parts[1];
-
-				// Get the current list of functions bound to this event
-				var handlers = events[type];
-
-				// Init the event handler queue
-				if (!handlers) {
-					handlers = events[type] = {};
-		
-					// Check for a special event handler
-					// Only use addEventListener/attachEvent if the special
-					// events handler returns false
-					if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
-						// Bind the global event handler to the element
-						if (elem.addEventListener)
-							elem.addEventListener(type, handle, false);
-						else if (elem.attachEvent)
-							elem.attachEvent("on" + type, handle);
-					}
-				}
-
-				// Add the function to the element's handler list
-				handlers[handler.guid] = handler;
-
-				// Keep track of which events have been used, for global triggering
-				jQuery.event.global[type] = true;
-			});
-		
-		// Nullify elem to prevent memory leaks in IE
-		elem = null;
-	},
-
-	guid: 1,
-	global: {},
-
-	// Detach an event or set of events from an element
-	remove: function(elem, types, handler) {
-		// don't do events on text and comment nodes
-		if ( elem.nodeType == 3 || elem.nodeType == 8 )
-			return;
-
-		var events = jQuery.data(elem, "events"), ret, index;
-
-		if ( events ) {
-			// Unbind all events for the element
-			if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
-				for ( var type in events )
-					this.remove( elem, type + (types || "") );
-			else {
-				// types is actually an event object here
-				if ( types.type ) {
-					handler = types.handler;
-					types = types.type;
-				}
-				
-				// Handle multiple events seperated by a space
-				// jQuery(...).unbind("mouseover mouseout", fn);
-				jQuery.each(types.split(/\s+/), function(index, type){
-					// Namespaced event handlers
-					var parts = type.split(".");
-					type = parts[0];
-					
-					if ( events[type] ) {
-						// remove the given handler for the given type
-						if ( handler )
-							delete events[type][handler.guid];
-			
-						// remove all handlers for the given type
-						else
-							for ( handler in events[type] )
-								// Handle the removal of namespaced events
-								if ( !parts[1] || events[type][handler].type == parts[1] )
-									delete events[type][handler];
-
-						// remove generic event handler if no more handlers exist
-						for ( ret in events[type] ) break;
-						if ( !ret ) {
-							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
-								if (elem.removeEventListener)
-									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
-								else if (elem.detachEvent)
-									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
-							}
-							ret = null;
-							delete events[type];
-						}
-					}
-				});
-			}
-
-			// Remove the expando if it's no longer used
-			for ( ret in events ) break;
-			if ( !ret ) {
-				var handle = jQuery.data( elem, "handle" );
-				if ( handle ) handle.elem = null;
-				jQuery.removeData( elem, "events" );
-				jQuery.removeData( elem, "handle" );
-			}
-		}
-	},
-
-	trigger: function(type, data, elem, donative, extra) {
-		// Clone the incoming data, if any
-		data = jQuery.makeArray(data || []);
-
-		if ( type.indexOf("!") >= 0 ) {
-			type = type.slice(0, -1);
-			var exclusive = true;
-		}
-
-		// Handle a global trigger
-		if ( !elem ) {
-			// Only trigger if we've ever bound an event for it
-			if ( this.global[type] )
-				jQuery("*").add([window, document]).trigger(type, data);
-
-		// Handle triggering a single element
-		} else {
-			// don't do events on text and comment nodes
-			if ( elem.nodeType == 3 || elem.nodeType == 8 )
-				return undefined;
-
-			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
-				// Check to see if we need to provide a fake event, or not
-				event = !data[0] || !data[0].preventDefault;
-			
-			// Pass along a fake event
-			if ( event )
-				data.unshift( this.fix({ type: type, target: elem }) );
-
-			// Enforce the right trigger type
-			data[0].type = type;
-			if ( exclusive )
-				data[0].exclusive = true;
-
-			// Trigger the event
-			if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
-				val = jQuery.data(elem, "handle").apply( elem, data );
-
-			// Handle triggering native .onfoo handlers
-			if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
-				val = false;
-
-			// Extra functions don't get the custom event object
-			if ( event )
-				data.shift();
-
-			// Handle triggering of extra function
-			if ( extra && jQuery.isFunction( extra ) ) {
-				// call the extra function and tack the current return value on the end for possible inspection
-				ret = extra.apply( elem, val == null ? data : data.concat( val ) );
-				// if anything is returned, give it precedence and have it overwrite the previous value
-				if (ret !== undefined)
-					val = ret;
-			}
-
-			// Trigger the native events (except for clicks on links)
-			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
-				this.triggered = true;
-				try {
-					elem[ type ]();
-				// prevent IE from throwing an error for some hidden elements
-				} catch (e) {}
-			}
-
-			this.triggered = false;
-		}
-
-		return val;
-	},
-
-	handle: function(event) {
-		// returned undefined or false
-		var val;
-
-		// Empty object is for triggered events with no data
-		event = jQuery.event.fix( event || window.event || {} ); 
-
-		// Namespaced event handlers
-		var parts = event.type.split(".");
-		event.type = parts[0];
-
-		var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
-		args.unshift( event );
-
-		for ( var j in handlers ) {
-			var handler = handlers[j];
-			// Pass in a reference to the handler function itself
-			// So that we can later remove it
-			args[0].handler = handler;
-			args[0].data = handler.data;
-
-			// Filter the functions by class
-			if ( !parts[1] && !event.exclusive || handler.type == parts[1] ) {
-				var ret = handler.apply( this, args );
-
-				if ( val !== false )
-					val = ret;
-
-				if ( ret === false ) {
-					event.preventDefault();
-					event.stopPropagation();
-				}
-			}
-		}
-
-		// Clean up added properties in IE to prevent memory leak
-		if (jQuery.browser.msie)
-			event.target = event.preventDefault = event.stopPropagation =
-				event.handler = event.data = null;
-
-		return val;
-	},
-
-	fix: function(event) {
-		// store a copy of the original event object 
-		// and clone to set read-only properties
-		var originalEvent = event;
-		event = jQuery.extend({}, originalEvent);
-		
-		// add preventDefault and stopPropagation since 
-		// they will not work on the clone
-		event.preventDefault = function() {
-			// if preventDefault exists run it on the original event
-			if (originalEvent.preventDefault)
-				originalEvent.preventDefault();
-			// otherwise set the returnValue property of the original event to false (IE)
-			originalEvent.returnValue = false;
-		};
-		event.stopPropagation = function() {
-			// if stopPropagation exists run it on the original event
-			if (originalEvent.stopPropagation)
-				originalEvent.stopPropagation();
-			// otherwise set the cancelBubble property of the original event to true (IE)
-			originalEvent.cancelBubble = true;
-		};
-		
-		// Fix target property, if necessary
-		if ( !event.target )
-			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
-				
-		// check if target is a textnode (safari)
-		if ( event.target.nodeType == 3 )
-			event.target = originalEvent.target.parentNode;
-
-		// Add relatedTarget, if necessary
-		if ( !event.relatedTarget && event.fromElement )
-			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
-
-		// Calculate pageX/Y if missing and clientX/Y available
-		if ( event.pageX == null && event.clientX != null ) {
-			var doc = document.documentElement, body = document.body;
-			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
-			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
-		}
-			
-		// Add which for key events
-		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
-			event.which = event.charCode || event.keyCode;
-		
-		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
-		if ( !event.metaKey && event.ctrlKey )
-			event.metaKey = event.ctrlKey;
-
-		// Add which for click: 1 == left; 2 == middle; 3 == right
-		// Note: button is not normalized, so don't use it
-		if ( !event.which && event.button )
-			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
-			
-		return event;
-	},
-	
-	special: {
-		ready: {
-			setup: function() {
-				// Make sure the ready event is setup
-				bindReady();
-				return;
-			},
-			
-			teardown: function() { return; }
-		},
-		
-		mouseenter: {
-			setup: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
-				return true;
-			},
-		
-			teardown: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
-				return true;
-			},
-			
-			handler: function(event) {
-				// If we actually just moused on to a sub-element, ignore it
-				if ( withinElement(event, this) ) return true;
-				// Execute the right handlers by setting the event type to mouseenter
-				arguments[0].type = "mouseenter";
-				return jQuery.event.handle.apply(this, arguments);
-			}
-		},
-	
-		mouseleave: {
-			setup: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
-				return true;
-			},
-		
-			teardown: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
-				return true;
-			},
-			
-			handler: function(event) {
-				// If we actually just moused on to a sub-element, ignore it
-				if ( withinElement(event, this) ) return true;
-				// Execute the right handlers by setting the event type to mouseleave
-				arguments[0].type = "mouseleave";
-				return jQuery.event.handle.apply(this, arguments);
-			}
-		}
-	}
-};
-
-jQuery.fn.extend({
-	bind: function( type, data, fn ) {
-		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
-			jQuery.event.add( this, type, fn || data, fn && data );
-		});
-	},
-	
-	one: function( type, data, fn ) {
-		return this.each(function(){
-			jQuery.event.add( this, type, function(event) {
-				jQuery(this).unbind(event);
-				return (fn || data).apply( this, arguments);
-			}, fn && data);
-		});
-	},
-
-	unbind: function( type, fn ) {
-		return this.each(function(){
-			jQuery.event.remove( this, type, fn );
-		});
-	},
-
-	trigger: function( type, data, fn ) {
-		return this.each(function(){
-			jQuery.event.trigger( type, data, this, true, fn );
-		});
-	},
-
-	triggerHandler: function( type, data, fn ) {
-		if ( this[0] )
-			return jQuery.event.trigger( type, data, this[0], false, fn );
-		return undefined;
-	},
-
-	toggle: function() {
-		// Save reference to arguments for access in closure
-		var args = arguments;
-
-		return this.click(function(event) {
-			// Figure out which function to execute
-			this.lastToggle = 0 == this.lastToggle ? 1 : 0;
-			
-			// Make sure that clicks stop
-			event.preventDefault();
-			
-			// and execute the function
-			return args[this.lastToggle].apply( this, arguments ) || false;
-		});
-	},
-
-	hover: function(fnOver, fnOut) {
-		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
-	},
-	
-	ready: function(fn) {
-		// Attach the listeners
-		bindReady();
-
-		// If the DOM is already ready
-		if ( jQuery.isReady )
-			// Execute the function immediately
-			fn.call( document, jQuery );
-			
-		// Otherwise, remember the function for later
-		else
-			// Add the function to the wait list
-			jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
-	
-		return this;
-	}
-});
-
-jQuery.extend({
-	isReady: false,
-	readyList: [],
-	// Handle when the DOM is ready
-	ready: function() {
-		// Make sure that the DOM is not already loaded
-		if ( !jQuery.isReady ) {
-			// Remember that the DOM is ready
-			jQuery.isReady = true;
-			
-			// If there are functions bound, to execute
-			if ( jQuery.readyList ) {
-				// Execute all of them
-				jQuery.each( jQuery.readyList, function(){
-					this.apply( document );
-				});
-				
-				// Reset the list of functions
-				jQuery.readyList = null;
-			}
-		
-			// Trigger any bound ready events
-			jQuery(document).triggerHandler("ready");
-		}
-	}
-});
-
-var readyBound = false;
-
-function bindReady(){
-	if ( readyBound ) return;
-	readyBound = true;
-
-	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
-	if ( document.addEventListener && !jQuery.browser.opera)
-		// Use the handy event callback
-		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
-	
-	// If IE is used and is not in a frame
-	// Continually check to see if the document is ready
-	if ( jQuery.browser.msie && window == top ) (function(){
-		if (jQuery.isReady) return;
-		try {
-			// If IE is used, use the trick by Diego Perini
-			// http://javascript.nwbox.com/IEContentLoaded/
-			document.documentElement.doScroll("left");
-		} catch( error ) {
-			setTimeout( arguments.callee, 0 );
-			return;
-		}
-		// and execute any waiting functions
-		jQuery.ready();
-	})();
-
-	if ( jQuery.browser.opera )
-		document.addEventListener( "DOMContentLoaded", function () {
-			if (jQuery.isReady) return;
-			for (var i = 0; i < document.styleSheets.length; i++)
-				if (document.styleSheets[i].disabled) {
-					setTimeout( arguments.callee, 0 );
-					return;
-				}
-			// and execute any waiting functions
-			jQuery.ready();
-		}, false);
-
-	if ( jQuery.browser.safari ) {
-		var numStyles;
-		(function(){
-			if (jQuery.isReady) return;
-			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
-				setTimeout( arguments.callee, 0 );
-				return;
-			}
-			if ( numStyles === undefined )
-				numStyles = jQuery("style, link[rel=stylesheet]").length;
-			if ( document.styleSheets.length != numStyles ) {
-				setTimeout( arguments.callee, 0 );
-				return;
-			}
-			// and execute any waiting functions
-			jQuery.ready();
-		})();
-	}
-
-	// A fallback to window.onload, that will always work
-	jQuery.event.add( window, "load", jQuery.ready );
-}
-
-jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
-	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
-	"submit,keydown,keypress,keyup,error").split(","), function(i, name){
-	
-	// Handle event binding
-	jQuery.fn[name] = function(fn){
-		return fn ? this.bind(name, fn) : this.trigger(name);
-	};
-});
-
-// Checks if an event happened on an element within another element
-// Used in jQuery.event.special.mouseenter and mouseleave handlers
-var withinElement = function(event, elem) {
-	// Check if mouse(over|out) are still within the same parent element
-	var parent = event.relatedTarget;
-	// Traverse up the tree
-	while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
-	// Return true if we actually just moused on to a sub-element
-	return parent == elem;
-};
-
-// Prevent memory leaks in IE
-// And prevent errors on refresh with events like mouseover in other browsers
-// Window isn't included so as not to unbind existing unload events
-jQuery(window).bind("unload", function() {
-	jQuery("*").add(document).unbind();
-});
-jQuery.fn.extend({
-	load: function( url, params, callback ) {
-		if ( jQuery.isFunction( url ) )
-			return this.bind("load", url);
-
-		var off = url.indexOf(" ");
-		if ( off >= 0 ) {
-			var selector = url.slice(off, url.length);
-			url = url.slice(0, off);
-		}
-
-		callback = callback || function(){};
-
-		// Default to a GET request
-		var type = "GET";
-
-		// If the second parameter was provided
-		if ( params )
-			// If it's a function
-			if ( jQuery.isFunction( params ) ) {
-				// We assume that it's the callback
-				callback = params;
-				params = null;
-
-			// Otherwise, build a param string
-			} else {
-				params = jQuery.param( params );
-				type = "POST";
-			}
-
-		var self = this;
-
-		// Request the remote document
-		jQuery.ajax({
-			url: url,
-			type: type,
-			dataType: "html",
-			data: params,
-			complete: function(res, status){
-				// If successful, inject the HTML into all the matched elements
-				if ( status == "success" || status == "notmodified" )
-					// See if a selector was specified
-					self.html( selector ?
-						// Create a dummy div to hold the results
-						jQuery("<div/>")
-							// inject the contents of the document in, removing the scripts
-							// to avoid any 'Permission Denied' errors in IE
-							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
-
-							// Locate the specified elements
-							.find(selector) :
-
-						// If not, just inject the full result
-						res.responseText );
-
-				self.each( callback, [res.responseText, status, res] );
-			}
-		});
-		return this;
-	},
-
-	serialize: function() {
-		return jQuery.param(this.serializeArray());
-	},
-	serializeArray: function() {
-		return this.map(function(){
-			return jQuery.nodeName(this, "form") ?
-				jQuery.makeArray(this.elements) : this;
-		})
-		.filter(function(){
-			return this.name && !this.disabled && 
-				(this.checked || /select|textarea/i.test(this.nodeName) || 
-					/text|hidden|password/i.test(this.type));
-		})
-		.map(function(i, elem){
-			var val = jQuery(this).val();
-			return val == null ? null :
-				val.constructor == Array ?
-					jQuery.map( val, function(val, i){
-						return {name: elem.name, value: val};
-					}) :
-					{name: elem.name, value: val};
-		}).get();
-	}
-});
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
-	jQuery.fn[o] = function(f){
-		return this.bind(o, f);
-	};
-});
-
-var jsc = (new Date).getTime();
-
-jQuery.extend({
-	get: function( url, data, callback, type ) {
-		// shift arguments if data argument was ommited
-		if ( jQuery.isFunction( data ) ) {
-			callback = data;
-			data = null;
-		}
-		
-		return jQuery.ajax({
-			type: "GET",
-			url: url,
-			data: data,
-			success: callback,
-			dataType: type
-		});
-	},
-
-	getScript: function( url, callback ) {
-		return jQuery.get(url, null, callback, "script");
-	},
-
-	getJSON: function( url, data, callback ) {
-		return jQuery.get(url, data, callback, "json");
-	},
-
-	post: function( url, data, callback, type ) {
-		if ( jQuery.isFunction( data ) ) {
-			callback = data;
-			data = {};
-		}
-
-		return jQuery.ajax({
-			type: "POST",
-			url: url,
-			data: data,
-			success: callback,
-			dataType: type
-		});
-	},
-
-	ajaxSetup: function( settings ) {
-		jQuery.extend( jQuery.ajaxSettings, settings );
-	},
-
-	ajaxSettings: {
-		global: true,
-		type: "GET",
-		timeout: 0,
-		contentType: "application/x-www-form-urlencoded",
-		processData: true,
-		async: true,
-		data: null,
-		username: null,
-		password: null,
-		accepts: {
-			xml: "application/xml, text/xml",
-			html: "text/html",
-			script: "text/javascript, application/javascript",
-			json: "application/json, text/javascript",
-			text: "text/plain",
-			_default: "*/*"
-		}
-	},
-	
-	// Last-Modified header cache for next request
-	lastModified: {},
-
-	ajax: function( s ) {
-		var jsonp, jsre = /=\?(&|$)/g, status, data;
-
-		// Extend the settings, but re-extend 's' so that it can be
-		// checked again later (in the test suite, specifically)
-		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
-
-		// convert data if not already a string
-		if ( s.data && s.processData && typeof s.data != "string" )
-			s.data = jQuery.param(s.data);
-
-		// Handle JSONP Parameter Callbacks
-		if ( s.dataType == "jsonp" ) {
-			if ( s.type.toLowerCase() == "get" ) {
-				if ( !s.url.match(jsre) )
-					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
-			} else if ( !s.data || !s.data.match(jsre) )
-				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
-			s.dataType = "json";
-		}
-
-		// Build temporary JSONP function
-		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
-			jsonp = "jsonp" + jsc++;
-
-			// Replace the =? sequence both in the query string and the data
-			if ( s.data )
-				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
-			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
-
-			// We need to make sure
-			// that a JSONP style response is executed properly
-			s.dataType = "script";
-
-			// Handle JSONP-style loading
-			window[ jsonp ] = function(tmp){
-				data = tmp;
-				success();
-				complete();
-				// Garbage collect
-				window[ jsonp ] = undefined;
-				try{ delete window[ jsonp ]; } catch(e){}
-				if ( head )
-					head.removeChild( script );
-			};
-		}
-
-		if ( s.dataType == "script" && s.cache == null )
-			s.cache = false;
-
-		if ( s.cache === false && s.type.toLowerCase() == "get" ) {
-			var ts = (new Date()).getTime();
-			// try replacing _= if it is there
-			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
-			// if nothing was replaced, add timestamp to the end
-			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
-		}
-
-		// If data is available, append data to url for get requests
-		if ( s.data && s.type.toLowerCase() == "get" ) {
-			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
-
-			// IE likes to send both get and post data, prevent this
-			s.data = null;
-		}
-
-		// Watch for a new set of requests
-		if ( s.global && ! jQuery.active++ )
-			jQuery.event.trigger( "ajaxStart" );
-
-		// If we're requesting a remote document
-		// and trying to load JSON or Script with a GET
-		if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get" ) {
-			var head = document.getElementsByTagName("head")[0];
-			var script = document.createElement("script");
-			script.src = s.url;
-			if (s.scriptCharset)
-				script.charset = s.scriptCharset;
-
-			// Handle Script loading
-			if ( !jsonp ) {
-				var done = false;
-
-				// Attach handlers for all browsers
-				script.onload = script.onreadystatechange = function(){
-					if ( !done && (!this.readyState || 
-							this.readyState == "loaded" || this.readyState == "complete") ) {
-						done = true;
-						success();
-						complete();
-						head.removeChild( script );
-					}
-				};
-			}
-
-			head.appendChild(script);
-
-			// We handle everything using the script element injection
-			return undefined;
-		}
-
-		var requestDone = false;
-
-		// Create the request object; Microsoft failed to properly
-		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
-		var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
-
-		// Open the socket
-		xml.open(s.type, s.url, s.async, s.username, s.password);
-
-		// Need an extra try/catch for cross domain requests in Firefox 3
-		try {
-			// Set the correct header, if data is being sent
-			if ( s.data )
-				xml.setRequestHeader("Content-Type", s.contentType);
-
-			// Set the If-Modified-Since header, if ifModified mode.
-			if ( s.ifModified )
-				xml.setRequestHeader("If-Modified-Since",
-					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
-
-			// Set header so the called script knows that it's an XMLHttpRequest
-			xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-
-			// Set the Accepts header for the server, depending on the dataType
-			xml.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
-				s.accepts[ s.dataType ] + ", */*" :
-				s.accepts._default );
-		} catch(e){}
-
-		// Allow custom headers/mimetypes
-		if ( s.beforeSend )
-			s.beforeSend(xml);
-			
-		if ( s.global )
-			jQuery.event.trigger("ajaxSend", [xml, s]);
-
-		// Wait for a response to come back
-		var onreadystatechange = function(isTimeout){
-			// The transfer is complete and the data is available, or the request timed out
-			if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
-				requestDone = true;
-				
-				// clear poll interval
-				if (ival) {
-					clearInterval(ival);
-					ival = null;
-				}
-				
-				status = isTimeout == "timeout" && "timeout" ||
-					!jQuery.httpSuccess( xml ) && "error" ||
-					s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
-					"success";
-
-				if ( status == "success" ) {
-					// Watch for, and catch, XML document parse errors
-					try {
-						// process the data (runs the xml through httpData regardless of callback)
-						data = jQuery.httpData( xml, s.dataType );
-					} catch(e) {
-						status = "parsererror";
-					}
-				}
-
-				// Make sure that the request was successful or notmodified
-				if ( status == "success" ) {
-					// Cache Last-Modified header, if ifModified mode.
-					var modRes;
-					try {
-						modRes = xml.getResponseHeader("Last-Modified");
-					} catch(e) {} // swallow exception thrown by FF if header is not available
-	
-					if ( s.ifModified && modRes )
-						jQuery.lastModified[s.url] = modRes;
-
-					// JSONP handles its own success callback
-					if ( !jsonp )
-						success();	
-				} else
-					jQuery.handleError(s, xml, status);
-
-				// Fire the complete handlers
-				complete();
-
-				// Stop memory leaks
-				if ( s.async )
-					xml = null;
-			}
-		};
-		
-		if ( s.async ) {
-			// don't attach the handler to the request, just poll it instead
-			var ival = setInterval(onreadystatechange, 13); 
-
-			// Timeout checker
-			if ( s.timeout > 0 )
-				setTimeout(function(){
-					// Check to see if the request is still happening
-					if ( xml ) {
-						// Cancel the request
-						xml.abort();
-	
-						if( !requestDone )
-							onreadystatechange( "timeout" );
-					}
-				}, s.timeout);
-		}
-			
-		// Send the data
-		try {
-			xml.send(s.data);
-		} catch(e) {
-			jQuery.handleError(s, xml, null, e);
-		}
-		
-		// firefox 1.5 doesn't fire statechange for sync requests
-		if ( !s.async )
-			onreadystatechange();
-
-		function success(){
-			// If a local callback was specified, fire it and pass it the data
-			if ( s.success )
-				s.success( data, status );
-
-			// Fire the global callback
-			if ( s.global )
-				jQuery.event.trigger( "ajaxSuccess", [xml, s] );
-		}
-
-		function complete(){
-			// Process result
-			if ( s.complete )
-				s.complete(xml, status);
-
-			// The request was completed
-			if ( s.global )
-				jQuery.event.trigger( "ajaxComplete", [xml, s] );
-
-			// Handle the global AJAX counter
-			if ( s.global && ! --jQuery.active )
-				jQuery.event.trigger( "ajaxStop" );
-		}
-		
-		// return XMLHttpRequest to allow aborting the request etc.
-		return xml;
-	},
-
-	handleError: function( s, xml, status, e ) {
-		// If a local callback was specified, fire it
-		if ( s.error ) s.error( xml, status, e );
-
-		// Fire the global callback
-		if ( s.global )
-			jQuery.event.trigger( "ajaxError", [xml, s, e] );
-	},
-
-	// Counter for holding the number of active queries
-	active: 0,
-
-	// Determines if an XMLHttpRequest was successful or not
-	httpSuccess: function( r ) {
-		try {
-			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
-			return !r.status && location.protocol == "file:" ||
-				( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
-				jQuery.browser.safari && r.status == undefined;
-		} catch(e){}
-		return false;
-	},
-
-	// Determines if an XMLHttpRequest returns NotModified
-	httpNotModified: function( xml, url ) {
-		try {
-			var xmlRes = xml.getResponseHeader("Last-Modified");
-
-			// Firefox always returns 200. check Last-Modified date
-			return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
-				jQuery.browser.safari && xml.status == undefined;
-		} catch(e){}
-		return false;
-	},
-
-	httpData: function( r, type ) {
-		var ct = r.getResponseHeader("content-type");
-		var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
-		var data = xml ? r.responseXML : r.responseText;
-
-		if ( xml && data.documentElement.tagName == "parsererror" )
-			throw "parsererror";
-
-		// If the type is "script", eval it in global context
-		if ( type == "script" )
-			jQuery.globalEval( data );
-
-		// Get the JavaScript object, if JSON is used.
-		if ( type == "json" )
-			data = eval("(" + data + ")");
-
-		return data;
-	},
-
-	// Serialize an array of form elements or a set of
-	// key/values into a query string
-	param: function( a ) {
-		var s = [];
-
-		// If an array was passed in, assume that it is an array
-		// of form elements
-		if ( a.constructor == Array || a.jquery )
-			// Serialize the form elements
-			jQuery.each( a, function(){
-				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
-			});
-
-		// Otherwise, assume that it's an object of key/value pairs
-		else
-			// Serialize the key/values
-			for ( var j in a )
-				// If the value is an array then the key names need to be repeated
-				if ( a[j] && a[j].constructor == Array )
-					jQuery.each( a[j], function(){
-						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
-					});
-				else
-					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
-
-		// Return the resulting serialization
-		return s.join("&").replace(/%20/g, "+");
-	}
-
-});
-jQuery.fn.extend({
-	show: function(speed,callback){
-		return speed ?
-			this.animate({
-				height: "show", width: "show", opacity: "show"
-			}, speed, callback) :
-			
-			this.filter(":hidden").each(function(){
-				this.style.display = this.oldblock || "";
-				if ( jQuery.css(this,"display") == "none" ) {
-					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
-					this.style.display = elem.css("display");
-					// handle an edge condition where css is - div { display:none; } or similar
-					if (this.style.display == "none")
-						this.style.display = "block";
-					elem.remove();
-				}
-			}).end();
-	},
-	
-	hide: function(speed,callback){
-		return speed ?
-			this.animate({
-				height: "hide", width: "hide", opacity: "hide"
-			}, speed, callback) :
-			
-			this.filter(":visible").each(function(){
-				this.oldblock = this.oldblock || jQuery.css(this,"display");
-				this.style.display = "none";
-			}).end();
-	},
-
-	// Save the old toggle function
-	_toggle: jQuery.fn.toggle,
-	
-	toggle: function( fn, fn2 ){
-		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
-			this._toggle( fn, fn2 ) :
-			fn ?
-				this.animate({
-					height: "toggle", width: "toggle", opacity: "toggle"
-				}, fn, fn2) :
-				this.each(function(){
-					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
-				});
-	},
-	
-	slideDown: function(speed,callback){
-		return this.animate({height: "show"}, speed, callback);
-	},
-	
-	slideUp: function(speed,callback){
-		return this.animate({height: "hide"}, speed, callback);
-	},
-
-	slideToggle: function(speed, callback){
-		return this.animate({height: "toggle"}, speed, callback);
-	},
-	
-	fadeIn: function(speed, callback){
-		return this.animate({opacity: "show"}, speed, callback);
-	},
-	
-	fadeOut: function(speed, callback){
-		return this.animate({opacity: "hide"}, speed, callback);
-	},
-	
-	fadeTo: function(speed,to,callback){
-		return this.animate({opacity: to}, speed, callback);
-	},
-	
-	animate: function( prop, speed, easing, callback ) {
-		var optall = jQuery.speed(speed, easing, callback);
-
-		return this[ optall.queue === false ? "each" : "queue" ](function(){
-			if ( this.nodeType != 1)
-				return false;
-
-			var opt = jQuery.extend({}, optall);
-			var hidden = jQuery(this).is(":hidden"), self = this;
-			
-			for ( var p in prop ) {
-				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
-					return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
-
-				if ( p == "height" || p == "width" ) {
-					// Store display property
-					opt.display = jQuery.css(this, "display");
-
-					// Make sure that nothing sneaks out
-					opt.overflow = this.style.overflow;
-				}
-			}
-
-			if ( opt.overflow != null )
-				this.style.overflow = "hidden";
-
-			opt.curAnim = jQuery.extend({}, prop);
-			
-			jQuery.each( prop, function(name, val){
-				var e = new jQuery.fx( self, opt, name );
-
-				if ( /toggle|show|hide/.test(val) )
-					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
-				else {
-					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
-						start = e.cur(true) || 0;
-
-					if ( parts ) {
-						var end = parseFloat(parts[2]),
-							unit = parts[3] || "px";
-
-						// We need to compute starting value
-						if ( unit != "px" ) {
-							self.style[ name ] = (end || 1) + unit;
-							start = ((end || 1) / e.cur(true)) * start;
-							self.style[ name ] = start + unit;
-						}
-
-						// If a +=/-= token was provided, we're doing a relative animation
-						if ( parts[1] )
-							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
-
-						e.custom( start, end, unit );
-					} else
-						e.custom( start, val, "" );
-				}
-			});
-
-			// For JS strict compliance
-			return true;
-		});
-	},
-	
-	queue: function(type, fn){
-		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
-			fn = type;
-			type = "fx";
-		}
-
-		if ( !type || (typeof type == "string" && !fn) )
-			return queue( this[0], type );
-
-		return this.each(function(){
-			if ( fn.constructor == Array )
-				queue(this, type, fn);
-			else {
-				queue(this, type).push( fn );
-			
-				if ( queue(this, type).length == 1 )
-					fn.apply(this);
-			}
-		});
-	},
-
-	stop: function(clearQueue, gotoEnd){
-		var timers = jQuery.timers;
-
-		if (clearQueue)
-			this.queue([]);
-
-		this.each(function(){
-			// go in reverse order so anything added to the queue during the loop is ignored
-			for ( var i = timers.length - 1; i >= 0; i-- )
-				if ( timers[i].elem == this ) {
-					if (gotoEnd)
-						// force the next step to be the last
-						timers[i](true);
-					timers.splice(i, 1);
-				}
-		});
-
-		// start the next in the queue if the last step wasn't forced
-		if (!gotoEnd)
-			this.dequeue();
-
-		return this;
-	}
-
-});
-
-var queue = function( elem, type, array ) {
-	if ( !elem )
-		return undefined;
-
-	type = type || "fx";
-
-	var q = jQuery.data( elem, type + "queue" );
-
-	if ( !q || array )
-		q = jQuery.data( elem, type + "queue", 
-			array ? jQuery.makeArray(array) : [] );
-
-	return q;
-};
-
-jQuery.fn.dequeue = function(type){
-	type = type || "fx";
-
-	return this.each(function(){
-		var q = queue(this, type);
-
-		q.shift();
-
-		if ( q.length )
-			q[0].apply( this );
-	});
-};
-
-jQuery.extend({
-	
-	speed: function(speed, easing, fn) {
-		var opt = speed && speed.constructor == Object ? speed : {
-			complete: fn || !fn && easing || 
-				jQuery.isFunction( speed ) && speed,
-			duration: speed,
-			easing: fn && easing || easing && easing.constructor != Function && easing
-		};
-
-		opt.duration = (opt.duration && opt.duration.constructor == Number ? 
-			opt.duration : 
-			{ slow: 600, fast: 200 }[opt.duration]) || 400;
-	
-		// Queueing
-		opt.old = opt.complete;
-		opt.complete = function(){
-			if ( opt.queue !== false )
-				jQuery(this).dequeue();
-			if ( jQuery.isFunction( opt.old ) )
-				opt.old.apply( this );
-		};
-	
-		return opt;
-	},
-	
-	easing: {
-		linear: function( p, n, firstNum, diff ) {
-			return firstNum + diff * p;
-		},
-		swing: function( p, n, firstNum, diff ) {
-			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
-		}
-	},
-	
-	timers: [],
-	timerId: null,
-
-	fx: function( elem, options, prop ){
-		this.options = options;
-		this.elem = elem;
-		this.prop = prop;
-
-		if ( !options.orig )
-			options.orig = {};
-	}
-
-});
-
-jQuery.fx.prototype = {
-
-	// Simple function for setting a style value
-	update: function(){
-		if ( this.options.step )
-			this.options.step.apply( this.elem, [ this.now, this ] );
-
-		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
-
-		// Set display property to block for height/width animations
-		if ( this.prop == "height" || this.prop == "width" )
-			this.elem.style.display = "block";
-	},
-
-	// Get the current size
-	cur: function(force){
-		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
-			return this.elem[ this.prop ];
-
-		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
-		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
-	},
-
-	// Start an animation from one number to another
-	custom: function(from, to, unit){
-		this.startTime = (new Date()).getTime();
-		this.start = from;
-		this.end = to;
-		this.unit = unit || this.unit || "px";
-		this.now = this.start;
-		this.pos = this.state = 0;
-		this.update();
-
-		var self = this;
-		function t(gotoEnd){
-			return self.step(gotoEnd);
-		}
-
-		t.elem = this.elem;
-
-		jQuery.timers.push(t);
-
-		if ( jQuery.timerId == null ) {
-			jQuery.timerId = setInterval(function(){
-				var timers = jQuery.timers;
-				
-				for ( var i = 0; i < timers.length; i++ )
-					if ( !timers[i]() )
-						timers.splice(i--, 1);
-
-				if ( !timers.length ) {
-					clearInterval( jQuery.timerId );
-					jQuery.timerId = null;
-				}
-			}, 13);
-		}
-	},
-
-	// Simple 'show' function
-	show: function(){
-		// Remember where we started, so that we can go back to it later
-		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
-		this.options.show = true;
-
-		// Begin the animation
-		this.custom(0, this.cur());
-
-		// Make sure that we start at a small width/height to avoid any
-		// flash of content
-		if ( this.prop == "width" || this.prop == "height" )
-			this.elem.style[this.prop] = "1px";
-		
-		// Start by showing the element
-		jQuery(this.elem).show();
-	},
-
-	// Simple 'hide' function
-	hide: function(){
-		// Remember where we started, so that we can go back to it later
-		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
-		this.options.hide = true;
-
-		// Begin the animation
-		this.custom(this.cur(), 0);
-	},
-
-	// Each step of an animation
-	step: function(gotoEnd){
-		var t = (new Date()).getTime();
-
-		if ( gotoEnd || t > this.options.duration + this.startTime ) {
-			this.now = this.end;
-			this.pos = this.state = 1;
-			this.update();
-
-			this.options.curAnim[ this.prop ] = true;
-
-			var done = true;
-			for ( var i in this.options.curAnim )
-				if ( this.options.curAnim[i] !== true )
-					done = false;
-
-			if ( done ) {
-				if ( this.options.display != null ) {
-					// Reset the overflow
-					this.elem.style.overflow = this.options.overflow;
-				
-					// Reset the display
-					this.elem.style.display = this.options.display;
-					if ( jQuery.css(this.elem, "display") == "none" )
-						this.elem.style.display = "block";
-				}
-
-				// Hide the element if the "hide" operation was done
-				if ( this.options.hide )
-					this.elem.style.display = "none";
-
-				// Reset the properties, if the item has been hidden or shown
-				if ( this.options.hide || this.options.show )
-					for ( var p in this.options.curAnim )
-						jQuery.attr(this.elem.style, p, this.options.orig[p]);
-			}
-
-			// If a callback was provided, execute it
-			if ( done && jQuery.isFunction( this.options.complete ) )
-				// Execute the complete function
-				this.options.complete.apply( this.elem );
-
-			return false;
-		} else {
-			var n = t - this.startTime;
-			this.state = n / this.options.duration;
-
-			// Perform the easing function, defaults to swing
-			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
-			this.now = this.start + ((this.end - this.start) * this.pos);
-
-			// Perform the next step of the animation
-			this.update();
-		}
-
-		return true;
-	}
-
-};
-
-jQuery.fx.step = {
-	scrollLeft: function(fx){
-		fx.elem.scrollLeft = fx.now;
-	},
-
-	scrollTop: function(fx){
-		fx.elem.scrollTop = fx.now;
-	},
-
-	opacity: function(fx){
-		jQuery.attr(fx.elem.style, "opacity", fx.now);
-	},
-
-	_default: function(fx){
-		fx.elem.style[ fx.prop ] = fx.now + fx.unit;
-	}
-};
-// The Offset Method
-// Originally By Brandon Aaron, part of the Dimension Plugin
-// http://jquery.com/plugins/project/dimensions
-jQuery.fn.offset = function() {
-	var left = 0, top = 0, elem = this[0], results;
-	
-	if ( elem ) with ( jQuery.browser ) {
-		var parent       = elem.parentNode, 
-		    offsetChild  = elem,
-		    offsetParent = elem.offsetParent, 
-		    doc          = elem.ownerDocument,
-		    safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
-		    fixed        = jQuery.css(elem, "position") == "fixed";
-	
-		// Use getBoundingClientRect if available
-		if ( elem.getBoundingClientRect ) {
-			var box = elem.getBoundingClientRect();
-		
-			// Add the document scroll offsets
-			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
-				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
-		
-			// IE adds the HTML element's border, by default it is medium which is 2px
-			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
-			// IE 7 standards mode, the border is always 2px
-			// This border/offset is typically represented by the clientLeft and clientTop properties
-			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
-			// Therefore this method will be off by 2px in IE while in quirksmode
-			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
-	
-		// Otherwise loop through the offsetParents and parentNodes
-		} else {
-		
-			// Initial element offsets
-			add( elem.offsetLeft, elem.offsetTop );
-			
-			// Get parent offsets
-			while ( offsetParent ) {
-				// Add offsetParent offsets
-				add( offsetParent.offsetLeft, offsetParent.offsetTop );
-			
-				// Mozilla and Safari > 2 does not include the border on offset parents
-				// However Mozilla adds the border for table or table cells
-				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
-					border( offsetParent );
-					
-				// Add the document scroll offsets if position is fixed on any offsetParent
-				if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
-					fixed = true;
-			
-				// Set offsetChild to previous offsetParent unless it is the body element
-				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
-				// Get next offsetParent
-				offsetParent = offsetParent.offsetParent;
-			}
-		
-			// Get parent scroll offsets
-			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
-				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
-				if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
-					// Subtract parent scroll offsets
-					add( -parent.scrollLeft, -parent.scrollTop );
-			
-				// Mozilla does not add the border for a parent that has overflow != visible
-				if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
-					border( parent );
-			
-				// Get next parent
-				parent = parent.parentNode;
-			}
-		
-			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
-			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
-			if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) || 
-				(mozilla && jQuery.css(offsetChild, "position") != "absolute") )
-					add( -doc.body.offsetLeft, -doc.body.offsetTop );
-			
-			// Add the document scroll offsets if position is fixed
-			if ( fixed )
-				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
-					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
-		}
-
-		// Return an object with top and left properties
-		results = { top: top, left: left };
-	}
-
-	function border(elem) {
-		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
-	}
-
-	function add(l, t) {
-		left += parseInt(l) || 0;
-		top += parseInt(t) || 0;
-	}
-
-	return results;
-};
-
-// Create innerHeight, innerWidth, outerHeight and outerWidth methods
-jQuery.each(["Height", "Width"], function(i, name){
-
-	var tl = name == "Height" ? "Top"    : "Left",  // top or left
-		br = name == "Height" ? "Bottom" : "Right"; // bottom or right
-	
-	// innerHeight and innerWidth
-	jQuery.fn["inner" + name] = function(){
-		return this[ name.toLowerCase() ]() + 
-			num(this, "padding" + tl) + 
-			num(this, "padding" + br);
-	};
-	
-	// outerHeight and outerWidth
-	jQuery.fn["outer" + name] = function(margin) {
-		return this["inner" + name]() + 
-			num(this, "border" + tl + "Width") +
-			num(this, "border" + br + "Width") +
-			(!!margin ? 
-				num(this, "margin" + tl) + num(this, "margin" + br) : 0);
-	};
-	
-});
-
-function num(elem, prop) {
-	elem = elem.jquery ? elem[0] : elem;
-	return elem && parseInt( jQuery.curCSS(elem, prop, true) ) || 0;
-}})();
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/loading.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/loading.gif
deleted file mode 100644
index 85b99d4..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/loading.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/pygments.css b/moksha/apps/widgetbrowser/widgetbrowser/static/pygments.css
deleted file mode 100644
index a55a324..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/pygments.css
+++ /dev/null
@@ -1,59 +0,0 @@
-.c { color: #408090; font-style: italic } /* Comment */
-.err { border: 1px solid #FF0000 } /* Error */
-.k { color: #007020; font-weight: bold } /* Keyword */
-.o { color: #666666 } /* Operator */
-.cm { color: #408090; font-style: italic } /* Comment.Multiline */
-.cp { color: #007020 } /* Comment.Preproc */
-.c1 { color: #408090; font-style: italic } /* Comment.Single */
-.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
-.gd { color: #A00000 } /* Generic.Deleted */
-.ge { font-style: italic } /* Generic.Emph */
-.gr { color: #FF0000 } /* Generic.Error */
-.gh { color: #000080; font-weight: bold } /* Generic.Heading */
-.gi { color: #00A000 } /* Generic.Inserted */
-.go { color: #303030 } /* Generic.Output */
-.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
-.gs { font-weight: bold } /* Generic.Strong */
-.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
-.gt { color: #0040D0 } /* Generic.Traceback */
-.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
-.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
-.kp { color: #007020 } /* Keyword.Pseudo */
-.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
-.kt { color: #902000 } /* Keyword.Type */
-.m { color: #208050 } /* Literal.Number */
-.s { color: #4070a0 } /* Literal.String */
-.na { color: #4070a0 } /* Name.Attribute */
-.nb { color: #007020 } /* Name.Builtin */
-.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
-.no { color: #60add5 } /* Name.Constant */
-.nd { color: #555555; font-weight: bold } /* Name.Decorator */
-.ni { color: #d55537; font-weight: bold } /* Name.Entity */
-.ne { color: #007020 } /* Name.Exception */
-.nf { color: #06287e } /* Name.Function */
-.nl { color: #002070; font-weight: bold } /* Name.Label */
-.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
-.nt { color: #062873; font-weight: bold } /* Name.Tag */
-.nv { color: #bb60d5 } /* Name.Variable */
-.ow { color: #007020; font-weight: bold } /* Operator.Word */
-.w { color: #bbbbbb } /* Text.Whitespace */
-.mf { color: #208050 } /* Literal.Number.Float */
-.mh { color: #208050 } /* Literal.Number.Hex */
-.mi { color: #208050 } /* Literal.Number.Integer */
-.mo { color: #208050 } /* Literal.Number.Oct */
-.sb { color: #4070a0 } /* Literal.String.Backtick */
-.sc { color: #4070a0 } /* Literal.String.Char */
-.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
-.s2 { color: #4070a0 } /* Literal.String.Double */
-.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
-.sh { color: #4070a0 } /* Literal.String.Heredoc */
-.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
-.sx { color: #c65d09 } /* Literal.String.Other */
-.sr { color: #235388 } /* Literal.String.Regex */
-.s1 { color: #4070a0 } /* Literal.String.Single */
-.ss { color: #517918 } /* Literal.String.Symbol */
-.bp { color: #007020 } /* Name.Builtin.Pseudo */
-.vc { color: #bb60d5 } /* Name.Variable.Class */
-.vg { color: #bb60d5 } /* Name.Variable.Global */
-.vi { color: #bb60d5 } /* Name.Variable.Instance */
-.il { color: #208050 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/tab.png b/moksha/apps/widgetbrowser/widgetbrowser/static/tab.png
deleted file mode 100644
index 413c755..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/tab.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css
deleted file mode 100644
index f45ed75..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css
+++ /dev/null
@@ -1,12 +0,0 @@
-ul.ui-accordion { margin: 0; padding: 0; list-style-type: none; }
-ul.ui-accordion li { margin: 0; margin-bottom: 2px; padding: 0; background-image: url(i/accordion-left.png); background-repeat: no-repeat; }
-ul.ui-accordion li a.ui-accordion-header { display: block; padding-left: 5px; margin-right: 3px; height: 28px; background-image: url(i/accordion-middle.png); color: #000; text-decoration: none; line-height: 28px; }
-ul.ui-accordion li .ui-accordion-right { display: block; background-image: url(i/accordion-right.png); position: absolute; top: 0px; right: 0px; height: 28px; width: 3px;  }
-
-ul.ui-accordion li:hover { background-image: url(i/accordion-left-over.png); }
-ul.ui-accordion li:hover a.ui-accordion-header { background-image: url(i/accordion-middle-over.png); }
-ul.ui-accordion li:hover .ui-accordion-right { background-image: url(i/accordion-right-over.png); }
-
-ul.ui-accordion li.active { background-image: url(i/accordion-left-act.png); }
-ul.ui-accordion li.active a.ui-accordion-header { background-image: url(i/accordion-middle-act.png); }
-ul.ui-accordion li.active .ui-accordion-right { background-image: url(i/accordion-right-act.png); }
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css
deleted file mode 100644
index 3de5386..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css
+++ /dev/null
@@ -1,9 +0,0 @@
- at import "flora.css";
- at import "flora.shadow.css";
- at import "flora.resizable.css";
- at import "flora.slider.css";
- at import "flora.accordion.css";
- at import "flora.tabs.css";
- at import "flora.dialog.css";
- at import "flora.tablesorter.css";
- at import "flora.datepicker.css";
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css
deleted file mode 100644
index dedcf0c..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Main Style Sheet for jQuery Calendar */
-#calendar_div, .calendar_inline {
-	font-family: Arial, Helvetica, sans-serif;
-	font-size: 14px;
-	padding: 0;
-	margin: 0;
-	background: #ddd;
-}
-#calendar_div {
-	display: none;
-	border: 1px solid #FF9900;
-	z-index: 10; /*must have*/ 
-}
-#calendar_div, .calendar_control, .calendar_links, .calendar_header, .calendar {
-	width: 185px;
-}
-.calendar_inline {
-	float: left;
-	display: block;
-	border: 0;
-}
-.calendar_dialog {
-	padding: 5px !important;
-	border: 4px ridge #ddd !important;
-}
-button.calendar_trigger {
-	width: 25px;
-}
-img.calendar_trigger {
-	margin: 2px;
-	vertical-align: middle;
-}
-.calendar_prompt {
-	float: left;
-	width: 181px;
-	padding: 2px;
-	background: #ddd;
-	color: #000;
-}
-* html .calendar_prompt {
-	width: 185px;
-}
-.calendar_control, .calendar_links, .calendar_header, .calendar {
-	clear: both;
-	float: left;
-	color: #fff;
-}
-.calendar_control {
-	background: #FF9900;
-}
-.calendar_links {
-	background: #E0F4D7;
-}
-.calendar_control, .calendar_links {
-	font-weight: bold;
-	font-size: 80%;
-	letter-spacing: 1px;
-}
-.calendar_links label { /* disabled links */
-	padding: 2px 5px;
-	color: #888;
-}
-.calendar_clear, .calendar_prev {
-	float: left;
-}
-.calendar_current {
-	float: left;
-	width: 35%;
-	text-align: center;
-}
-.calendar_close, .calendar_next {
-	float: right;
-}
-.calendar_header {
-	background: #83C948;
-	text-align: center;
-	font-weight: bold;
-}
-.calendar_header select {
-	background: #83C948;
-	color: #000;
-	border: 0px;
-	font-weight: bold;
-}
-.calendar {
-	background: #ccc;
-	text-align: center;
-	font-size: 100%;
-}
-.calendar a {
-	display: block;
-	width: 100%;
-}
-.calendar .calendar_titleRow {
-	background: #B1DB87;
-	color: #000 !important;
-}
-.calendar .calendar_daysRow {
-	background: #FFF;
-	color: #666;
-}
-.calendar .calendar_daysCell {
-	color: #000;
-	border: 1px solid #ddd;
-}
-#calendar .calendar_daysCell a{
-	display: block;
-}
-.calendar .calendar_weekEndCell {
-	background: #E0F4D7;
-}
-.calendar .calendar_daysCellOver {
-	background: #fff;
-	border: 1px solid #777;
-}
-.calendar .calendar_unselectable {
-	color: #888;
-}
-.calendar_today {
-	background: #ccc !important;
-}
-.calendar_currentDay {
-	background: #999 !important;
-}
-
-/* ________ CALENDAR LINKS _______
-
-** Reset link properties and then override them with !important */
-#calendar_div a, .calendar_inline a {
-	cursor: pointer;
-	margin: 0;
-	padding: 0;
-	background: none;
-	color: #000;
-}
-.calendar_inline .calendar_links a {
-	padding: 0 5px !important;
-}
-.calendar_control a, .calendar_links a {
-	padding: 2px 5px !important;
-	color: #000 !important;
-}
-.calendar_titleRow a {
-	color: #000 !important;
-}
-.calendar_control a:hover {
-	/*background: #fdd !important;*/
-	color: #333 !important;
-}
-.calendar_links a:hover, .calendar_titleRow a:hover {
-	background: #FFF !important;
-	color: #333 !important;
-}
-
-/* ___________ IE6 IFRAME FIX ________ */
-
-.calendar_cover {
-    display: none; /*sorry for IE5*/
-    display/**/: block; /*sorry for IE5*/
-    position: absolute; /*must have*/
-    z-index: -1; /*must have*/
-    filter: mask(); /*must have*/
-    top: -4px; /*must have*/
-    left: -4px; /*must have*/
-    width: 193px; /*must have to match width and borders*/
-    height: 200px; /*must have to match maximum height*/ 
-}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.css
deleted file mode 100644
index 761217d..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.css
+++ /dev/null
@@ -1,2 +0,0 @@
-.ui-wrapper { border: 1px solid #50A029; }
-.ui-wrapper input, .ui-wrapper textarea { border: 0; }
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css
deleted file mode 100644
index 34ea650..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Main Flora Style Sheet for jQuery UI Datepicker */
-#datepicker_div, .datepicker_inline {
-	font-family: Arial,Helvetica,sans-serif;
-	font-size: 14px;
-	padding: 0;
-	margin: 0;
-	background: #DDD;
-	width: 185px;
-}
-#datepicker_div {
-	display: none;
-	border: 1px solid #FF9900;
-	z-index: 10;
-}
-.datepicker_inline {
-	float: left;
-	display: block;
-	border: 0;
-}
-.datepicker_dialog {
-	padding: 5px !important;
-	border: 4px ridge #DDD !important;
-}
-button.datepicker_trigger {
-	width: 25px;
-}
-img.datepicker_trigger {
-	margin: 2px;
-	vertical-align: middle;
-}
-.datepicker_prompt {
-	float: left;
-	padding: 2px;
-	background: #DDD;
-	color: #000;
-}
-*html .datepicker_prompt {
-	width: 185px;
-}
-.datepicker_control, .datepicker_links, .datepicker_header, .datepicker {
-	clear: both;
-	float: left;
-	width: 100%;
-	color: #FFF;
-}
-.datepicker_control {
-	background: #FF9900;
-	padding: 2px 0px;
-}
-.datepicker_links {
-	background: #E0F4D7;
-	padding: 2px 0px;
-}
-.datepicker_control, .datepicker_links {
-	font-weight: bold;
-	font-size: 80%;
-	letter-spacing: 1px;
-}
-.datepicker_links label {
-	padding: 2px 5px;
-	color: #888;
-}
-.datepicker_clear, .datepicker_prev {
-	float: left;
-	width: 34%;
-}
-.datepicker_current {
-	float: left;
-	width: 30%;
-	text-align: center;
-}
-.datepicker_close, .datepicker_next {
-	float: right;
-	width: 34%;
-	text-align: right;
-}
-.datepicker_header {
-	padding: 1px 0 3px;
-	background: #83C948;
-	text-align: center;
-	font-weight: bold;
-	height: 1.3em;
-}
-.datepicker_header select {
-	background: #83C948;
-	color: #000;
-	border: 0px;
-	font-weight: bold;
-}
-.datepicker {
-	background: #CCC;
-	text-align: center;
-	font-size: 100%;
-}
-.datepicker a {
-	display: block;
-	width: 100%;
-}
-.datepicker .datepicker_titleRow {
-	background: #B1DB87;
-	color: #000;
-}
-.datepicker .datepicker_daysRow {
-	background: #FFF;
-	color: #666;
-}
-.datepicker_weekCol {
-	background: #B1DB87;
-	color: #000;
-}
-.datepicker .datepicker_daysCell {
-	color: #000;
-	border: 1px solid #DDD;
-}
-#datepicker .datepicker_daysCell a {
-	display: block;
-}
-.datepicker .datepicker_weekEndCell {
-	background: #E0F4D7;
-}
-.datepicker .datepicker_daysCellOver {
-	background: #FFF;
-	border: 1px solid #777;
-}
-.datepicker .datepicker_unselectable {
-	color: #888;
-}
-.datepicker_today {
-	background: #B1DB87 !important;
-}
-.datepicker_currentDay {
-	background: #83C948 !important;
-}
-#datepicker_div a, .datepicker_inline a {
-	cursor: pointer;
-	margin: 0;
-	padding: 0;
-	background: none;
-	color: #000;
-}
-.datepicker_inline .datepicker_links a {
-	padding: 0 5px !important;
-}
-.datepicker_control a, .datepicker_links a {
-	padding: 2px 5px !important;
-	color: #000 !important;
-}
-.datepicker_titleRow a {
-	color: #000 !important;
-}
-.datepicker_control a:hover {
-	background: #FDD !important;
-	color: #333 !important;
-}
-.datepicker_links a:hover, .datepicker_titleRow a:hover {
-	background: #FFF !important;
-	color: #333 !important;
-}
-.datepicker_multi .datepicker {
-	border: 1px solid #83C948;
-}
-.datepicker_oneMonth {
-	float: left;
-	width: 185px;
-}
-.datepicker_newRow {
-	clear: left;
-}
-.datepicker_cover {
-	display: none;
-	display/**/: block;
-	position: absolute;
-	z-index: -1;
-	filter: mask();
-	top: -4px;
-	left: -4px;
-	width: 193px;
-	height: 200px;
-}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css
deleted file mode 100644
index efef1c4..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css
+++ /dev/null
@@ -1,95 +0,0 @@
-/* This file skins dialog */
-
-.flora .ui-dialog,
-.flora.ui-dialog {
-	background-color: #e6f7d4;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar,
-.flora.ui-dialog .ui-dialog-titlebar {
-	border-bottom: 1px solid #d8d2aa;
-	background: #ff9900 url(i/dialog-title.gif) repeat-x;
-	padding: 0px;
-	height: 28px;
-	_height: 29px;
-}
-
-.flora .ui-dialog.ui-draggable .ui-dialog-titlebar,
-.flora.ui-dialog.ui-draggable .ui-dialog-titlebar {
-	cursor: move;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar-close,
-.flora.ui-dialog .ui-dialog-titlebar-close {
-	width: 16px;
-	height: 16px;
-	background: url(i/dialog-titlebar-close.png) no-repeat;
-	position:absolute;
-	top: 6px;
-	right: 7px;
-	cursor: default;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar-close span,
-.flora.ui-dialog .ui-dialog-titlebar-close span {
-	display: none;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar-close-hover,
-.flora.ui-dialog .ui-dialog-titlebar-close-hover {
-	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
-}
-
-.flora .ui-dialog .ui-dialog-title,
-.flora.ui-dialog .ui-dialog-title {
-	margin-left: 5px;
-	color: white;
-	font-weight: bold;
-	position: relative;
-	top: 7px;
-	left: 4px;
-}
-
-.flora .ui-dialog .ui-dialog-content,
-.flora.ui-dialog .ui-dialog-content {
-	margin: 1.2em;
-}
-
-.flora .ui-dialog .ui-dialog-buttonpane,
-.flora.ui-dialog .ui-dialog-buttonpane {
-	position: absolute;
-	bottom: 8px;
-	right: 12px;
-	width: 100%;
-	text-align: right;
-}
-
-.flora .ui-dialog .ui-dialog-buttonpane button,
-.flora.ui-dialog .ui-dialog-buttonpane button {
-	margin: 6px;
-}
-
-/* Dialog handle styles */
-.flora .ui-dialog .ui-resizable-n,
-.flora.ui-dialog .ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/dialog-n.gif) repeat scroll center top; }
-
-.flora .ui-dialog .ui-resizable-s,
-.flora.ui-dialog .ui-resizable-s { cursor: s-resize; height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/dialog-s.gif) repeat scroll center top; }
-
-.flora .ui-dialog .ui-resizable-e,
-.flora.ui-dialog .ui-resizable-e { cursor: e-resize; width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-e.gif) repeat scroll right center; }
-
-.flora .ui-dialog .ui-resizable-w,
-.flora.ui-dialog .ui-resizable-w { cursor: w-resize; width: 7px; left: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-w.gif) repeat scroll right center; }
-
-.flora .ui-dialog .ui-resizable-se,
-.flora.ui-dialog .ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/dialog-se.gif); }
-
-.flora .ui-dialog .ui-resizable-sw,
-.flora.ui-dialog .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/dialog-sw.gif); }
-
-.flora .ui-dialog .ui-resizable-nw,
-.flora.ui-dialog .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/dialog-nw.gif); }
-
-.flora .ui-dialog .ui-resizable-ne,
-.flora.ui-dialog .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/dialog-ne.gif); }
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css
deleted file mode 100644
index 6d2dd21..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css
+++ /dev/null
@@ -1,8 +0,0 @@
-.ui-menu-toolbar {z-index:500; list-style:none;}
-.ui-menu-toolbar-button {float:left; padding:4px 20px; cursor:pointer;}
-.ui-menu-toolbar-button:hover {}
-.ui-menu-toolbar-button a {text-decoration:none;}
-.ui-menu-items {display:none; padding:0; z-index:500; list-style:none; padding:1px 4px; min-width:80px; *width:80px;}
-.ui-menu-item a { text-decoration:none;}
-.ui-menu-item-parent { background: url('i/menu-submenu.gif') no-repeat center right; }
-.ui-menu-item-disabled {}
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css
deleted file mode 100644
index 5e30c0c..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This file skins resizables */
-
-.ui-resizable { position: relative; }
-
-/* Global handle styles */
-.ui-resizable-handle { position: absolute; display: none; font-size: 0.1px; }
-.ui-resizable .ui-resizable-handle { display: block; }
-body .ui-resizable-disabled .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
-body .ui-resizable-autohide .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
-
-.ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/resizable-n.gif) repeat scroll center top; }
-.ui-resizable-s { cursor: s-resize; height: 6px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/resizable-s.gif) repeat scroll center top; }
-
-.ui-resizable-e { cursor: e-resize; width: 6px; right: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-e.gif) repeat scroll right center; }
-.ui-resizable-w { cursor: w-resize; width: 6px; left: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-w.gif) repeat scroll right center; }
-
-.ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/resizable-se.gif); }
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/resizable-sw.gif); }
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: 0px; top: 0px; background: transparent url(i/resizable-nw.gif); }
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: 0px; top: 0px; background: transparent url(i/resizable-ne.gif); }
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css
deleted file mode 100644
index 94827b3..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This file skins sliders */
-
-.ui-slider { width: 200px; height: 23px; position: relative; background-repeat: no-repeat; background-position: center center; }
-.ui-slider-handle { position: absolute; z-index: 1; height: 23px; width: 12px; top: 0px; left: 0px; background-image: url(i/slider-handle.gif);  }
-.ui-slider-handle-active { border: 1px dotted black;  }
-.ui-slider-disabled .ui-slider-handle { opacity: 0.5; filter: alpha(opacity=50); }
-.ui-slider-range { position: absolute; background: #50A029; opacity: 0.3; filter: alpha(opacity=30); width: 100%; height: 100%; }
-
-/* Default slider backgrounds */
-.ui-slider, .ui-slider-1 { background-image: url(i/slider-bg-1.png); }
-.ui-slider-2 { background-image: url(i/slider-bg-2.png); }
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css
deleted file mode 100644
index 7d805a7..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This file skins tableSorter */
-
-table.tablesorter {
-	font-family:arial;
-	background-color: #CDCDCD;
-	margin:10px 0pt 15px;
-	font-size: 8pt;
-	width: 100%;
-	text-align: left;
-}
-table.tablesorter thead tr th, table.tablesorter tfoot tr th {
-	background-color: #B1DB87;
-	border: 1px solid #FFF;
-	font-size: 8pt;
-	padding: 4px;
-}
-table.tablesorter thead tr .header {
-	background-image: url(i/bg.gif);
-	background-repeat: no-repeat;
-	background-position: center right;
-	cursor: pointer;
-}
-table.tablesorter tbody td {
-	color: #3D3D3D;
-	padding: 4px;
-	background-color: #FFF;
-	vertical-align: top;
-}
-table.tablesorter tbody tr.odd td {
-	background-color:#E0F4D7;
-}
-table.tablesorter thead tr .headerSortUp {
-	background-image: url(i/asc.gif);
-}
-table.tablesorter thead tr .headerSortDown {
-	background-image: url(i/desc.gif);
-}
-table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
-background-color: #83C948;
-}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css
deleted file mode 100644
index c79a17e..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css
+++ /dev/null
@@ -1,105 +0,0 @@
- at import "flora.css";
-
-/* Caution! Ensure accessibility in print and other media types... */
- at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
-    .ui-tabs-hide {
-        display: none;
-    }
-}
-
-/* Hide useless elements in print layouts... */
- at media print {
-    .ui-tabs-nav {
-        display: none;
-    }
-}
-
-/* Skin */
-.ui-tabs-nav, .ui-tabs-panel {
-    font-family: "Trebuchet MS", Trebuchet, Verdana, Helvetica, Arial, sans-serif;
-    font-size: 12px;
-}
-.ui-tabs-nav {
-    list-style: none;
-    margin: 0;
-    padding: 0 0 0 3px;
-}
-.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
-    display: block;
-    clear: both;
-    content: " ";
-}
-.ui-tabs-nav li {
-    float: left;
-    margin: 0 0 0 2px;
-    font-weight: bold;
-}
-.ui-tabs-nav a, .ui-tabs-nav a span {
-    float: left; /* fixes dir=ltr problem and other quirks IE */
-    padding: 0 12px;
-    background: url(i/tabs.png) no-repeat;
-}
-.ui-tabs-nav a {
-    margin: 5px 0 0; /* position: relative makes opacity fail for disabled tab in IE */
-    padding-left: 0;
-    background-position: 100% 0;
-    text-decoration: none;
-    white-space: nowrap; /* @ IE 6 */
-    outline: 0; /* @ Firefox, prevent dotted border after click */    
-}
-.ui-tabs-nav a:link, .ui-tabs-nav a:visited {
-    color: #fff;
-}
-.ui-tabs-nav .ui-tabs-selected a {
-    position: relative;
-    top: 1px;
-    z-index: 2;
-    margin-top: 0;
-    background-position: 100% -23px;
-}
-.ui-tabs-nav a span {
-    padding-top: 1px;
-    padding-right: 0;
-    height: 20px;
-    background-position: 0 0;
-    line-height: 20px;
-}
-.ui-tabs-nav .ui-tabs-selected a span {
-    padding-top: 0;
-    height: 27px;
-    background-position: 0 -23px;
-    line-height: 27px;
-}
-.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited,
-.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
-    cursor: text;
-}
-.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active,
-.ui-tabs-nav .ui-tabs-unselect a:hover, .ui-tabs-nav .ui-tabs-unselect a:focus, .ui-tabs-nav .ui-tabs-unselect a:active { /* @ Opera, we need to be explicit again here now... */
-    cursor: pointer;
-}
-.ui-tabs-disabled {
-    opacity: .4;
-    filter: alpha(opacity=40);
-}
-.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited {
-    color: #000;
-}
-.ui-tabs-panel {
-    border: 1px solid #519e2d;
-    padding: 10px;
-    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
-}
-/*.ui-tabs-loading em {
-    padding: 0 0 0 20px;
-    background: url(loading.gif) no-repeat 0 50%;
-}*/
-
-/* Additional IE specific bug fixes... */
-* html .ui-tabs-nav { /* auto clear @ IE 6 & IE 7 Quirks Mode */
-    display: inline-block;
-}
-*:first-child+html .ui-tabs-nav  { /* auto clear @ IE 7 Standards Mode - do not group selectors, otherwise IE 6 will ignore complete rule (because of the unknown + combinator)... */
-    display: inline-block;
-}
-
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css
deleted file mode 100644
index 6f2b55f..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css
+++ /dev/null
@@ -1,106 +0,0 @@
-/* This file skins toasterLite */
-
-.flora .ui-toasterLite,
-.flora.ui-toasterLite {
-	background-color: #e6f7d4;
-	width: 100px;
-	display: block;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-titlebar,
-.flora.ui-toasterLite .ui-toasterLite-titlebar {
-	border-bottom: 1px solid #d8d2aa;
-	background: #ff9900 url(i/dialog-title.gif) repeat-x;
-	padding: 0px;
-	height: 28px;
-	z-index: 5;
-	position: relative;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-title,
-.flora.ui-toasterLite .ui-toasterLite-title {
-	margin-left: 5px;
-	color: white;
-	font-weight: bold;
-	position: relative;
-	top: 7px;
-	left: 4px;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-content,
-.flora.ui-toasterLite .ui-toasterLite-content {
-	margin: 1.2em;
-	padding-bottom: 12px;
-}
-
-/* Toaster handle styles */
-.flora .ui-toasterLite .ui-toasterLite-n,
-.flora.ui-toasterLite .ui-toasterLite-n { height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/toaster-n.gif) repeat scroll center top; z-index: 6; }
-
-.flora .ui-toasterLite .ui-toasterLite-s,
-.flora.ui-toasterLite .ui-toasterLite-s { height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/toaster-s.gif) repeat scroll center top; z-index: 1; }
-
-.flora .ui-toasterLite .ui-toasterLite-e,
-.flora.ui-toasterLite .ui-toasterLite-e { width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/toaster-e.gif) repeat scroll right center; }
-
-.flora .ui-toasterLite .ui-toasterLite-w,
-.flora.ui-toasterLite .ui-toasterLite-w { width: 7px; left: 0px; top: 0px; height: 100%; background: url(i/toaster-w.gif) repeat scroll right center; }
-
-.flora .ui-toasterLite .ui-toasterLite-se,
-.flora.ui-toasterLite .ui-toasterLite-se { width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/toaster-se.gif); z-index: 2; }
-
-.flora .ui-toasterLite .ui-toasterLite-sw,
-.flora.ui-toasterLite .ui-toasterLite-sw { width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/toaster-sw.gif); z-index: 2; }
-
-.flora .ui-toasterLite .ui-toasterLite-nw,
-.flora.ui-toasterLite .ui-toasterLite-nw { width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/toaster-nw.gif); z-index: 6; }
-
-.flora .ui-toasterLite .ui-toasterLite-ne,
-.flora.ui-toasterLite .ui-toasterLite-ne { width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/toaster-ne.gif); z-index: 6; }
-
-/* Global handle styles */
-.ui-toasterLite-corner { position: absolute; font-size: 0.1px; }
-
-.flora .ui-toasterLite-holder,
-.flora.ui-toasterLite-holder {
-  position: absolute;
-}
-.flora .ui-toasterLite-holder-pos-tr,
-.flora.ui-toasterLite-holder-pos-tr {
-  top: 10px;
-  right: 10px;
-}
-
-.flora .ui-toasterLite-holder-pos-tl,
-.flora.ui-toasterLite-holder-pos-tl {
-  top: 10px;
-  left: 10px;
-}
-
-.flora .ui-toasterLite-holder-pos-br,
-.flora.ui-toasterLite-holder-pos-br {
-  bottom: 10px;
-  right: 10px;
-}
-
-.flora .ui-toasterLite-holder-pos-bl,
-.flora.ui-toasterLite-holder-pos-bl {
-  bottom: 10px;
-  left: 10px;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-titlebar-close,
-.flora.ui-toasterLite .ui-toasterLite-titlebar-close {
-	width: 16px;
-	height: 16px;
-	background: url(i/dialog-titlebar-close.png) no-repeat;
-	position:absolute;
-	top: 6px;
-	right: 7px;
-	cursor: default;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-titlebar-close-hover,
-.flora.ui-toasterLite .ui-toasterLite-titlebar-close-hover {
-	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
-}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css
deleted file mode 100644
index 8ad0588..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css
+++ /dev/null
@@ -1,241 +0,0 @@
-/* light.toolbar.css
- *
- *  Written: 05/09/07 4:38:01 PM
- *  Revision: 1.0.0
- *
- *
- * Credits:
- *  Miksago: Full Coding.
- */
-
-.flora .ui-toolbar {
-  position:relative;
-  padding:0px;
-  margin:0px;
-}
-.flora .ui-toolbar ul {
-  background:#E6F7D4;
-  padding:0px;
-  margin:0px;
-}
-  .flora .ui-toolbar ul li {
-    list-style-type: none;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-horiz {
-    border-top:1px solid #5AB500;
-    background:#E6F7D4 url("i/toolbars-bot-bg.gif") repeat-x bottom left;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-horiz li {
-    display:inline;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert {
-    padding: 0.025em 0em;
-    border-left: 1px solid #111;
-    border-right: 1px solid #444;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert li {
-    display:block;
-  }
-  /* This hides the text on buttons in a icon only toolbar */
-  .flora .ui-toolbar ul.ui-toolbar-icons li .ui-toolbar-btn-desc {
-    display:none;
-  }
-  /* This hides the icon on buttons in a text only toolbar */
-  .flora .ui-toolbar ul.ui-toolbar-text li .ui-toolbar-btn-icon {
-    display:none;
-  }
-  /* This is just for icon sizes, not really needed, but it's there so if icon sizes are defined.. */
-  .flora .ui-toolbar ul li.ui-toolbar-btn-icon-sixteen .ui-toolbar-btn-icon {
-    width:16px; height:16px;
-    overflow:hidden;
-    padding:2px;
-    padding-left:16px;
-    background:no-repeat;
-    background-position:50% 50%;
-  }
-  
-/************************************************
- * Factory Elements:
- *  - These are different kinds of items that
- *    can be in a toolbar.
- *
- *  Includes:
- *    @ ui-toolbar-btn
- *        toolbar buttons.
- *    @ ui-toolbar-sep
- *        toolbar separators.
- *
-*/
-
-
-
-/************************************************
- * UI-TOOLBAR-BTN
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-btn">
- *      <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
- *      <span class="ui-toolbar-btn-center">
- *        <button><span>{{text}}</span></button>
- *      </span>
- *      <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
- *    </li>
- *
- ************************************************/
-
-
-  .flora .ui-toolbar ul li.ui-toolbar-btn {
-    cursor:pointer;
-    white-space: nowrap;
-    position:relative;
-  }
-  .flora .ui-toolbar ul li .ui-toolbar-btn-left {
-    width:3px;
-    padding:5px 0px 1px 0;
-    position:absolute;
-    top:-3px;
-    bottom:0px;
-    left:-3px;
-    height:100%;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
-    width:3px; height:5px;
-    padding:0px 0px 0px 0px;
-    position:absolute;
-    bottom:0px;
-    left:0px;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center{
-    background:url("i/accordion-middle-over.png") repeat-x left top;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left {
-    background:url("i/accordion-left-over.png") no-repeat left top;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
-    background:url("i/accordion-left-over.png") no-repeat left bottom;
-  }
-  .flora .ui-toolbar ul li .ui-toolbar-btn-center {
-    padding: 0.2em 0em;
-    line-height:2.2em;
-  }
-    .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-btn {
-      vertical-align: middle;
-      margin:0.3em 0.2em;
-    }
-    .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-btn {
-      margin:0.2em;
-      line-height:1.6em;
-      vertical-align: middle;
-    }
-      .flora .ui-toolbar ul li button {
-        vertical-align: middle;
-        background:transparent;
-        color:#000;
-        border:0px none;
-        cursor:pointer;
-        overflow:visible;
-        -moz-outline:0 none;
-        outline:0 none;
-        padding: 0.1em 0.1em;
-      }
-        .flora .ui-toolbar ul li.ui-toolbar-btn button span {
-          vertical-align: middle;
-        }
-        /* This hides the text on buttons in a icon only toolbar */
-        .flora .ui-toolbar ul.ui-toobar-iconOnly li.ui-toolbar-btn button span {
-          display:none;
-        }
-  
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center button,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center button {
-    background: url("i/accordion-middle-over.png") repeat-x left bottom;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active {
-    
-  }
-  
-  .flora .ui-toolbar ul li.ui-toolbar-btn-disabled {
-    opacity:0.2;
-  }
-
-/************************************************
- * UI-TOOLBAR-BTN
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-sep">
- *      <span>
- *        &nbsp;
- *      </span>
- *    </li>
- *
- ************************************************/
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-sep {
-    border-left:1px solid #444;
-    border-right:1px solid #111;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-sep {
-    border-top:1px solid #111;
-    border-bottom:1px solid #444;
-  }
-
-/************************************************
- * UI-TOOLBAR-SLIDER
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-slider">
- *      <div class="ui-toolbar-slider-track ui-slider-track">
- *        <div class="ui-slider-handle"></div>
- *      </div>
- *   </li>
- *
- ************************************************/
-
-.flora .ui-toolbar ul li.ui-toolbar-slider .ui-toolbar-slider-track {
-  height: 20px!important;
-}
-
-/************************************************
- * UI-TOOLBAR-RADIOGRP
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-radioGrp">
- *      <ul class="DIRECTION">
- *        <li class="ui-toolbar-btn">
- *          <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
- *          <span class="ui-toolbar-btn-center">
- *            <button><span>{{text}}</span></button>
- *          </span>
- *          <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
- *        </li>
- *      </ul>
- *    </li>
- *      
- *
- ************************************************/
-
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp,
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul,
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul li{
-    display:inline;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul {
-    margin:0px;
-    padding:0px;
-  }
-
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp,
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul,
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul li{
-    display:block;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul {
-    margin:0px;
-    padding:0px;
-  }
-
-
-/* END OF FILE */
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png
deleted file mode 100644
index bf6ee99..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png
deleted file mode 100644
index 66378e0..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png
deleted file mode 100644
index 13344fc..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png
deleted file mode 100644
index cecf4f1..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png
deleted file mode 100644
index 251ad11..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png
deleted file mode 100644
index 5238fd4..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png
deleted file mode 100644
index 1fa4792..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png
deleted file mode 100644
index d676dad..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png
deleted file mode 100644
index 543991a..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif
deleted file mode 100644
index 7415786..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif
deleted file mode 100644
index fac668f..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif
deleted file mode 100644
index 3b30b3c..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif
deleted file mode 100644
index 3b8b521..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif
deleted file mode 100644
index 70887b8..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif
deleted file mode 100644
index ab9c38e..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif
deleted file mode 100644
index e934073..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif
deleted file mode 100644
index d5f6b99..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif
deleted file mode 100644
index 186a864..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif
deleted file mode 100644
index 025dfda..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif
deleted file mode 100644
index 156c59b..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png
deleted file mode 100644
index 67c1303..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png
deleted file mode 100644
index cec974c..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif
deleted file mode 100644
index 931ff4a..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif
deleted file mode 100644
index 77647d8..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif
deleted file mode 100644
index 7acf248..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif
deleted file mode 100644
index 59110f6..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif
deleted file mode 100644
index 515a3f8..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif
deleted file mode 100644
index 665f318..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif
deleted file mode 100644
index da2fb35..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif
deleted file mode 100644
index 6c258ef..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif
deleted file mode 100644
index 2fd8de4..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif
deleted file mode 100644
index 34b875b..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png
deleted file mode 100644
index 4c58c7f..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png
deleted file mode 100644
index b7d806e..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png
deleted file mode 100644
index 8b24cf0..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif
deleted file mode 100644
index 9b89f26..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png
deleted file mode 100644
index 8018e41..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif
deleted file mode 100644
index 55dcb2c..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif
deleted file mode 100644
index b0fbeb9..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif
deleted file mode 100644
index ab9c38e..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif
deleted file mode 100644
index e934073..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif
deleted file mode 100644
index 15640e8..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif
deleted file mode 100644
index fb7a7df..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif
deleted file mode 100644
index ad1ae1c..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif
deleted file mode 100644
index 8489de8..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif
deleted file mode 100644
index 15640e8..0000000
Binary files a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif and /dev/null differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.base.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.base.js
deleted file mode 100644
index 17115f0..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.base.js
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * jQuery UI @VERSION
- *
- * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * http://docs.jquery.com/UI
- *
- * $Date: 2008-04-01 09:23:47 -0400 (Tue, 01 Apr 2008) $
- * $Rev: 5174 $
- */
-;(function($) {
-
-	//If the UI scope is not available, add it
-	$.ui = $.ui || {};
-	
-	//Add methods that are vital for all mouse interaction stuff (plugin registering)
-	$.extend($.ui, {
-		plugin: {
-			add: function(module, option, set) {
-				var proto = $.ui[module].prototype;
-				for(var i in set) {
-					proto.plugins[i] = proto.plugins[i] || [];
-					proto.plugins[i].push([option, set[i]]);
-				}
-			},
-			call: function(instance, name, arguments) {
-				var set = instance.plugins[name]; if(!set) return;
-				for (var i = 0; i < set.length; i++) {
-					if (instance.options[set[i][0]]) set[i][1].apply(instance.element, arguments);
-				}
-			}	
-		},
-		cssCache: {},
-		css: function(name) {
-			if ($.ui.cssCache[name]) return $.ui.cssCache[name];
-			var tmp = $('<div class="ui-resizable-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
-			
-			//if (!$.browser.safari)
-				//tmp.appendTo('body'); 
-			
-			//Opera and Safari set width and height to 0px instead of auto
-			//Safari returns rgba(0,0,0,0) when bgcolor is not set
-			$.ui.cssCache[name] = !!(
-				(!/auto|default/.test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 
-				!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
-			);
-			try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
-			return $.ui.cssCache[name];
-		},
-		disableSelection: function(e) {
-			e.unselectable = "on";
-			e.onselectstart = function() {	return false; };
-			if (e.style) e.style.MozUserSelect = "none";
-		},
-		enableSelection: function(e) {
-			e.unselectable = "off";
-			e.onselectstart = function() { return true; };
-			if (e.style) e.style.MozUserSelect = "";
-		},
-		hasScroll: function(e, a) {
-      		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;
-      		if (e[scroll] > 0) return true; e[scroll] = 1;
-      		has = e[scroll] > 0 ? true : false; e[scroll] = 0;
-      		return has; 
-    	}
-	});
-
-	/******* fn scope modifications ********/
-
-	$.each( ['Left', 'Top'], function(i, name) {
-		if(!$.fn['scroll'+name]) $.fn['scroll'+name] = function(v) {
-			return v != undefined ?
-				this.each(function() { this == window || this == document ? window.scrollTo(name == 'Left' ? v : $(window)['scrollLeft'](), name == 'Top'  ? v : $(window)['scrollTop']()) : this['scroll'+name] = v; }) :
-				this[0] == window || this[0] == document ? self[(name == 'Left' ? 'pageXOffset' : 'pageYOffset')] || $.boxModel && document.documentElement['scroll'+name] || document.body['scroll'+name] : this[0][ 'scroll' + name ];
-		};
-	});
-
-	var _remove = $.fn.remove;
-	$.fn.extend({
-		position: function() {
-			var offset       = this.offset();
-			var offsetParent = this.offsetParent();
-			var parentOffset = offsetParent.offset();
-
-			return {
-				top:  offset.top - num(this[0], 'marginTop')  - parentOffset.top - num(offsetParent, 'borderTopWidth'),
-				left: offset.left - num(this[0], 'marginLeft')  - parentOffset.left - num(offsetParent, 'borderLeftWidth')
-			};
-		},
-		offsetParent: function() {
-			var offsetParent = this[0].offsetParent;
-			while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
-				offsetParent = offsetParent.offsetParent;
-			return $(offsetParent);
-		},
-		mouseInteraction: function(o) {
-			return this.each(function() {
-				new $.ui.mouseInteraction(this, o);
-			});
-		},
-		removeMouseInteraction: function(o) {
-			return this.each(function() {
-				if($.data(this, "ui-mouse"))
-					$.data(this, "ui-mouse").destroy();
-			});
-		},
-		remove: function() {
-			jQuery("*", this).add(this).trigger("remove");
-			return _remove.apply(this, arguments );
-		}
-	});
-	
-	function num(el, prop) {
-		return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
-	};
-	
-	
-	/********** Mouse Interaction Plugin *********/
-	
-	$.ui.mouseInteraction = function(element, options) {
-	
-		var self = this;
-		this.element = element;
-
-		$.data(this.element, "ui-mouse", this);
-		this.options = $.extend({}, options);
-		
-		$(element).bind('mousedown.draggable', function() { return self.click.apply(self, arguments); });
-		if($.browser.msie) $(element).attr('unselectable', 'on'); //Prevent text selection in IE
-		
-		// prevent draggable-options-delay bug #2553
-		$(element).mouseup(function() {
-			if(self.timer) clearInterval(self.timer);
-		});
-	};
-	
-	$.extend($.ui.mouseInteraction.prototype, {
-		
-		destroy: function() { $(this.element).unbind('mousedown.draggable'); },
-		trigger: function() { return this.click.apply(this, arguments); },
-		click: function(e) {
-			
-			if(
-				   e.which != 1 //only left click starts dragging
-				|| $.inArray(e.target.nodeName.toLowerCase(), this.options.dragPrevention || []) != -1 // Prevent execution on defined elements
-				|| (this.options.condition && !this.options.condition.apply(this.options.executor || this, [e, this.element])) //Prevent execution on condition
-			) return true;
-				
-			var self = this;
-			var initialize = function() {
-				self._MP = { left: e.pageX, top: e.pageY }; // Store the click mouse position
-				$(document).bind('mouseup.draggable', function() { return self.stop.apply(self, arguments); });
-				$(document).bind('mousemove.draggable', function() { return self.drag.apply(self, arguments); });
-				
-				if(!self.initalized && Math.abs(self._MP.left-e.pageX) >= self.options.distance || Math.abs(self._MP.top-e.pageY) >= self.options.distance) {				
-					if(self.options.start) self.options.start.call(self.options.executor || self, e, self.element);
-					if(self.options.drag) self.options.drag.call(self.options.executor || self, e, this.element); //This is actually not correct, but expected
-					self.initialized = true;
-				}
-			};
-
-			if(this.options.delay) {
-				if(this.timer) clearInterval(this.timer);
-				this.timer = setTimeout(initialize, this.options.delay);
-			} else {
-				initialize();
-			}
-				
-			return false;
-			
-		},
-		stop: function(e) {			
-			
-			var o = this.options;
-			if(!this.initialized) return $(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
-
-			if(this.options.stop) this.options.stop.call(this.options.executor || this, e, this.element);
-			$(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
-			this.initialized = false;
-			return false;
-			
-		},
-		drag: function(e) {
-
-			var o = this.options;
-			if ($.browser.msie && !e.button) return this.stop.apply(this, [e]); // IE mouseup check
-			
-			if(!this.initialized && (Math.abs(this._MP.left-e.pageX) >= o.distance || Math.abs(this._MP.top-e.pageY) >= o.distance)) {				
-				if(this.options.start) this.options.start.call(this.options.executor || this, e, this.element);
-				this.initialized = true;
-			} else {
-				if(!this.initialized) return false;
-			}
-
-			if(o.drag) o.drag.call(this.options.executor || this, e, this.element);
-			return false;
-			
-		}
-	});
-	
-})(jQuery);
- 
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.dialog.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.dialog.js
deleted file mode 100644
index 7a907bd..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.dialog.js
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * jQuery UI Dialog
- *
- * Copyright (c) 2008 Richard D. Worth (rdworth.org)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- * 
- * http://docs.jquery.com/UI/Dialog
- *
- * Depends:
- *   ui.base.js
- *   ui.draggable.js
- *   ui.resizable.js
- *
- * Revision: $Id: ui.dialog.js 5185 2008-04-03 15:39:51Z scott.gonzalez $
- */
-;(function($) {
-	
-	$.fn.extend({
-		dialog: function(options) {
-			var args = Array.prototype.slice.call(arguments, 1);
-
-			return this.each(function() {
-				if (typeof options == "string") {
-					var elem = $(this).is('.ui-dialog')
-						? this
-						: $(this).parents(".ui-dialog:first").find(".ui-dialog-content")[0];
-					var dialog = elem ? $.data(elem, "dialog") : {};
-					if (dialog[options])
-						dialog[options].apply(dialog, args);
-				// INIT with optional options
-				} else if (!$(this).is(".ui-dialog-content"))
-					new $.ui.dialog(this, options);
-			});
-		}
-	});
-
-	$.ui.dialog = function(el, options) {
-		
-		this.options = options = $.extend({}, $.ui.dialog.defaults, options);
-		this.element = el;
-		var self = this; //Do bindings
-
-		$.data(this.element, "dialog", this);
-
-		$(el).bind("remove", function() {
-			self.destroy();
-		});
-		
-		$(el).bind("setData.dialog", function(event, key, value){
-			switch (key) {
-				case "draggable":
-					uiDialog.draggable(value ? 'enable' : 'disable');
-					break;
-				case "dragStart":
-					uiDialog.data('start.draggable', value);
-					break;
-				case "drag":
-					uiDialog.data('drag.draggable', value);
-					break;
-				case "dragStop":
-					uiDialog.data('stop.draggable', value);
-					break;
-				case "height":
-					uiDialog.height(value);
-					break;
-				case "maxHeight":
-				case "minHeight":
-				case "maxWidth":
-				case "minWidth":
-					uiDialog.data(key + ".resizable", value);
-					break;
-				case "position":
-					self.position(value);
-					break;
-				case "resizable":
-					uiDialog.resizable(value ? 'enable' : 'disable');
-					break;
-				case "resizeStart":
-					uiDialog.data('start.resizable', value);
-					break;
-				case "resize":
-					uiDialog.data('resize.resizable', value);
-					break;
-				case "resizeStop":
-					uiDialog.data('stop.resizable', value);
-					break;
-				case "title":
-					$(".ui-dialog-title", uiDialogTitlebar).text(value);
-					break;
-				case "width":
-					break;
-			}
-			options[key] = value;
-		}).bind("getData.dialog", function(event, key){
-			return options[key];
-		});
-
-		var uiDialogContent = $(el).addClass('ui-dialog-content');
-
-		if (!uiDialogContent.parent().length) {
-			uiDialogContent.appendTo('body');
-		}
-		uiDialogContent
-			.wrap(document.createElement('div'))
-			.wrap(document.createElement('div'));
-		var uiDialogContainer = uiDialogContent.parent().addClass('ui-dialog-container').css({position: 'relative'});
-		var uiDialog = this.uiDialog = uiDialogContainer.parent().hide()
-			.addClass('ui-dialog')
-			.css({position: 'absolute', width: options.width, height: options.height, overflow: 'hidden'}); 
-
-		var classNames = uiDialogContent.attr('className').split(' ');
-
-		// Add content classes to dialog, to inherit theme at top level of element
-		$.each(classNames, function(i, className) {
-			if (className != 'ui-dialog-content')
-				uiDialog.addClass(className);
-		});
-
-		if ($.fn.resizable) {
-			uiDialog.append('<div class="ui-resizable-n ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-s ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-e ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-w ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-ne ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-se ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-sw ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-nw ui-resizable-handle"></div>');
-			uiDialog.resizable({
-				maxWidth: options.maxWidth,
-				maxHeight: options.maxHeight,
-				minWidth: options.minWidth,
-				minHeight: options.minHeight,
-				start: options.resizeStart,
-				resize: options.resize,
-				stop: function(e, ui) {
-					options.resizeStop && options.resizeStop.apply(this, arguments);
-					$.ui.dialog.overlay.resize();
-				}
-			});
-			if (!options.resizable)
-				uiDialog.resizable('disable');
-		}
-
-		uiDialogContainer.prepend('<div class="ui-dialog-titlebar"></div>');
-		var uiDialogTitlebar = $('.ui-dialog-titlebar', uiDialogContainer);
-		var title = (options.title) ? options.title : (uiDialogContent.attr('title')) ? uiDialogContent.attr('title') : '';
-		uiDialogTitlebar.append('<span class="ui-dialog-title">' + title + '</span>');
-		uiDialogTitlebar.append('<a href="#" class="ui-dialog-titlebar-close"><span>X</span></a>');
-		this.uiDialogTitlebarClose = $('.ui-dialog-titlebar-close', uiDialogTitlebar)
-			.hover(function() { $(this).addClass('ui-dialog-titlebar-close-hover'); }, 
-			       function() { $(this).removeClass('ui-dialog-titlebar-close-hover'); })
-			.mousedown(function(ev) {
-				ev.stopPropagation();
-			})
-			.click(function() {
-				self.close();
-				return false;
-			})
-			.keydown(function(ev) {
-				var ESC = 27;
-				ev.keyCode && ev.keyCode == ESC && self.close(); 
-			});
-
-		var l = 0;
-		$.each(options.buttons, function() { l = 1; return false; });
-		if (l == 1) {
-			uiDialog.append('<div class="ui-dialog-buttonpane"></div>');
-			var uiDialogButtonPane = $('.ui-dialog-buttonpane', uiDialog);
-			$.each(options.buttons, function(name, value) {
-				var btn = $(document.createElement('button')).text(name).click(value);
-				uiDialogButtonPane.append(btn);
-			});
-		}
-
-		if ($.fn.draggable) {
-			uiDialog.draggable({
-				handle: '.ui-dialog-titlebar',
-				start: function(e, ui) {
-					self.activate();
-					options.dragStart && options.dragStart.apply(this, arguments);
-				},
-				drag: options.drag,
-				stop: function(e, ui) {
-					options.dragStop && options.dragStop.apply(this, arguments);
-					$.ui.dialog.overlay.resize();
-				}
-			});
-			if (!options.draggable)
-				uiDialog.draggable('disable')
-		}
-	
-		uiDialog.mousedown(function() {
-			self.activate();
-		});
-		uiDialogTitlebar.click(function() {
-			self.activate();
-		});
-		
-		options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe();
-
-		this.position = function(pos) {
-			var wnd = $(window), doc = $(document), top = doc.scrollTop(), left = doc.scrollLeft();
-			if (pos.constructor == Array) {
-				// [x, y]
-				top += pos[1];
-				left += pos[0];
-			} else {
-				switch (pos) {
-					case 'center':
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-						break;
-					case 'top':
-						top += 0;
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-						break;
-					case 'right':
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += (wnd.width()) - (uiDialog.width());
-						break;
-					case 'bottom':
-						top += (wnd.height()) - (uiDialog.height());
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-						break;
-					case 'left':
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += 0;
-						break;
-					default:
-						//center
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-				}
-			}
-			top = top < doc.scrollTop() ? doc.scrollTop() : top;
-			uiDialog.css({top: top, left: left});
-		}
-		
-		this.open = function() {
-			this.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
-			uiDialog.appendTo('body');
-			this.position(options.position);
-			uiDialog.show();
-			self.moveToTop();
-			self.activate();
-			
-			// CALLBACK: open
-			var openEV = null;
-			var openUI = {
-				options: options
-			};
-			this.uiDialogTitlebarClose.focus();
-			$(this.element).triggerHandler("dialogopen", [openEV, openUI], options.open);
-		};
-
-		this.activate = function() {
-			// Move modeless dialogs to the top when they're activated.  Even
-			// if there is a modal dialog in the window, the modeless dialog
-			// should be on top because it must have been opened after the modal
-			// dialog.  Modal dialogs don't get moved to the top because that
-			// would make any modeless dialogs that it spawned unusable until
-			// the modal dialog is closed.
-			!options.modal && this.moveToTop();
-		};
-		
-		this.moveToTop = function() {
-			var maxZ = options.zIndex;
-			$('.ui-dialog:visible').each(function() {
-				maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10) || options.zIndex);
-			});
-			this.overlay && this.overlay.$el.css('z-index', ++maxZ);
-			uiDialog.css('z-index', ++maxZ);
-		};
-		
-		this.close = function() {
-			this.overlay && this.overlay.destroy();
-			uiDialog.hide();
-
-			// CALLBACK: close
-			var closeEV = null;
-			var closeUI = {
-				options: options
-			};
-			$(this.element).triggerHandler("dialogclose", [closeEV, closeUI], options.close);
-			$.ui.dialog.overlay.resize();
-		};
-
-		this.destroy = function() {
-			this.overlay && this.overlay.destroy();
-			uiDialog.hide();
-			$(el).unbind('.dialog').removeClass('ui-dialog-content').hide().appendTo('body');
-			uiDialog.remove();
-			$.removeData(this.element, "dialog");
-		};
-		
-		if (options.autoOpen) {
-			this.open();
-		};
-	};
-	
-	$.extend($.ui.dialog, {
-		defaults: {
-			autoOpen: true,
-			bgiframe: false,
-			buttons: [],
-			draggable: true,
-			height: 200,
-			minHeight: 100,
-			minWidth: 150,
-			modal: false,
-			overlay: {},
-			position: 'center',
-			resizable: true,
-			width: 300,
-			zIndex: 1000
-		},
-		
-		overlay: function(dialog) {
-			this.$el = $.ui.dialog.overlay.create(dialog);
-		}
-	});
-	
-	$.extend($.ui.dialog.overlay, {
-		instances: [],
-		events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
-			function(e) { return e + '.dialog-overlay'; }).join(' '),
-		create: function(dialog) {
-			if (this.instances.length === 0) {
-				// prevent use of anchors and inputs
-				$('a, :input').bind(this.events, function() {
-					// allow use of the element if inside a dialog and
-					// - there are no modal dialogs
-					// - there are modal dialogs, but we are in front of the
-					//   topmost modal dialog
-					var allow = false;
-					var $dialog = $(this).parents('.ui-dialog');
-					if ($dialog.length) {
-						var $overlays = $('.ui-dialog-overlay');
-						if ($overlays.length) {
-							var maxZ = parseInt($overlays.css('z-index'), 10);
-							$overlays.each(function() {
-								maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10));
-							});
-							allow = parseInt($dialog.css('z-index'), 10) > maxZ;
-						} else {
-							allow = true;
-						}
-					}
-					return allow;
-				});
-				
-				// allow closing by pressing the escape key
-				$(document).bind('keydown.dialog-overlay', function(e) {
-					var ESC = 27;
-					e.keyCode && e.keyCode == ESC && dialog.close(); 
-				});
-				
-				// handle window resize
-				$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
-			}
-			
-			var $el = $('<div/>').appendTo(document.body)
-				.addClass('ui-dialog-overlay').css($.extend({
-					borderWidth: 0, margin: 0, padding: 0,
-					position: 'absolute', top: 0, left: 0,
-					width: this.width(),
-					height: this.height()
-				}, dialog.options.overlay));
-			
-			dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe();
-			
-			this.instances.push($el);
-			return $el;
-		},
-		
-		destroy: function($el) {
-			this.instances.splice($.inArray(this.instances, $el), 1);
-			
-			if (this.instances.length === 0) {
-				$('a, :input').add([document, window]).unbind('.dialog-overlay');
-			}
-			
-			$el.remove();
-		},
-		
-		height: function() {
-			if ($.browser.msie && $.browser.version < 7) {
-				var scrollHeight = Math.max(
-					document.documentElement.scrollHeight,
-					document.body.scrollHeight
-				);
-				var offsetHeight = Math.max(
-					document.documentElement.offsetHeight,
-					document.body.offsetHeight
-				);
-				
-				if (scrollHeight < offsetHeight) {
-					return $(window).height() + 'px';
-				} else {
-					return scrollHeight + 'px';
-				}
-			} else {
-				return $(document).height() + 'px';
-			}
-		},
-		
-		width: function() {
-			if ($.browser.msie && $.browser.version < 7) {
-				var scrollWidth = Math.max(
-					document.documentElement.scrollWidth,
-					document.body.scrollWidth
-				);
-				var offsetWidth = Math.max(
-					document.documentElement.offsetWidth,
-					document.body.offsetWidth
-				);
-				
-				if (scrollWidth < offsetWidth) {
-					return $(window).width() + 'px';
-				} else {
-					return scrollWidth + 'px';
-				}
-			} else {
-				return $(document).width() + 'px';
-			}
-		},
-		
-		resize: function() {
-			/* If the dialog is draggable and the user drags it past the
-			 * right edge of the window, the document becomes wider so we
-			 * need to stretch the overlay.  If the user then drags the
-			 * dialog back to the left, the document will become narrower,
-			 * so we need to shrink the overlay to the appropriate size.
-			 * This is handled by shrinking the overlay before setting it
-			 * to the full document size.
-			 */
-			var $overlays = $([]);
-			$.each($.ui.dialog.overlay.instances, function() {
-				$overlays = $overlays.add(this);
-			});
-			
-			$overlays.css({
-				width: 0,
-				height: 0
-			}).css({
-				width: $.ui.dialog.overlay.width(),
-				height: $.ui.dialog.overlay.height()
-			});
-		}
-	});
-	
-	$.extend($.ui.dialog.overlay.prototype, {
-		destroy: function() {
-			$.ui.dialog.overlay.destroy(this.$el);
-		}
-	});
-
-})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.draggable.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.draggable.js
deleted file mode 100644
index ce209db..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.draggable.js
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * jQuery UI Draggable
- *
- * Copyright (c) 2008 Paul Bakaus
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- * 
- * http://docs.jquery.com/UI/Draggables
- *
- * Depends:
- *   ui.base.js
- *
- * Revision: $Id: ui.draggable.js 5194 2008-04-04 12:30:10Z paul.bakaus $
- */
-;(function($) {
-
-	$.fn.extend({
-		draggable: function(options) {
-			var args = Array.prototype.slice.call(arguments, 1);
-			
-			return this.each(function() {
-				if (typeof options == "string") {
-					var drag = $.data(this, "draggable");
-					if(drag) drag[options].apply(drag, args);
-
-				} else if(!$.data(this, "draggable"))
-					new $.ui.draggable(this, options);
-			});
-		}
-	});
-	
-	$.ui.draggable = function(element, options) {
-		//Initialize needed constants
-		var self = this;
-		
-		this.element = $(element);
-		
-		$.data(element, "draggable", this);
-		this.element.addClass("ui-draggable");
-		
-		//Prepare the passed options
-		this.options = $.extend({}, options);
-		var o = this.options;
-		$.extend(o, {
-			helper: o.ghosting == true ? 'clone' : (o.helper || 'original'),
-			handle : o.handle ? ($(o.handle, element)[0] ? $(o.handle, element) : this.element) : this.element,
-			appendTo: o.appendTo || 'parent'		
-		});
-		
-		$(element).bind("setData.draggable", function(event, key, value){
-			self.options[key] = value;
-		}).bind("getData.draggable", function(event, key){
-			return self.options[key];
-		});
-		
-		//Initialize mouse events for interaction
-		$(o.handle).mouseInteraction({
-			executor: this,
-			delay: o.delay,
-			distance: o.distance || 1,
-			dragPrevention: o.cancel || o.cancel === '' ? o.cancel.toLowerCase().split(',') : ['input','textarea','button','select','option'],
-			start: this.start,
-			stop: this.stop,
-			drag: this.drag,
-			condition: function(e) { return !(e.target.className.indexOf("ui-resizable-handle") != -1 || this.options.disabled); }
-		});
-		
-		//Position the node
-		if(o.helper == 'original' && (this.element.css('position') == 'static' || this.element.css('position') == ''))
-			this.element.css('position', 'relative');
-			
-		//Prepare cursorAt
-		if(o.cursorAt && o.cursorAt.constructor == Array)
-			o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] };
-		
-	};
-	
-	$.extend($.ui.draggable.prototype, {
-		plugins: {},
-		ui: function(e) {
-			return {
-				helper: this.helper,
-				position: this.position,
-				absolutePosition: this.positionAbs,
-				instance: this,
-				options: this.options,
-				element: this.element				
-			};
-		},
-		propagate: function(n,e) {
-			$.ui.plugin.call(this, n, [e, this.ui()]);
-			return this.element.triggerHandler(n == "drag" ? n : "drag"+n, [e, this.ui()], this.options[n]);
-		},
-		destroy: function() {
-			if(!$.data(this.element[0], 'draggable')) return;
-			this.options.handle.removeMouseInteraction();
-			this.element
-				.removeClass("ui-draggable ui-draggable-disabled")
-				.removeData("draggable")
-				.unbind(".draggable");
-		},
-		enable: function() {
-			this.element.removeClass("ui-draggable-disabled");
-			this.options.disabled = false;
-		},
-		disable: function() {
-			this.element.addClass("ui-draggable-disabled");
-			this.options.disabled = true;
-		},
-		setContrains: function(minLeft,maxLeft,minTop,maxTop) {
-			this.minLeft = minLeft; this.maxLeft = maxLeft;
-			this.minTop = minTop; this.maxTop = maxTop;
-			this.constrainsSet = true;
-		},
-		checkConstrains: function() {
-			if(!this.constrainsSet) return;
-			if(this.position.left < this.minLeft) this.position.left = this.minLeft;
-			if(this.position.left > this.maxLeft - this.helperProportions.width) this.position.left = this.maxLeft - this.helperProportions.width;
-			if(this.position.top < this.minTop) this.position.top = this.minTop;
-			if(this.position.top > this.maxTop - this.helperProportions.height) this.position.top = this.maxTop - this.helperProportions.height;
-		},
-		recallOffset: function(e) {
-
-			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
-			var r = this.helper.css('position') == 'relative';
-
-			//Generate the original position
-			this.originalPosition = {
-				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
-				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
-			};
-			
-			//Generate a flexible offset that will later be subtracted from e.pageX/Y
-			this.offset = {left: this._pageX - this.originalPosition.left, top: this._pageY - this.originalPosition.top };
-			
-		},
-		start: function(e) {
-			var o = this.options;
-			if($.ui.ddmanager) $.ui.ddmanager.current = this;
-			
-			//Create and append the visible helper
-			this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e])) : (o.helper == 'clone' ? this.element.clone().appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)) : this.element);
-			if(this.helper[0] != this.element[0]) this.helper.css('position', 'absolute');
-			if(!this.helper.parents('body').length) this.helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
-			
-			
-			//Find out the next positioned parent
-			this.offsetParent = (function(cp) {
-				while(cp) {
-					if(cp.style && (/(absolute|relative|fixed)/).test($.css(cp,'position'))) return $(cp);
-					cp = cp.parentNode ? cp.parentNode : null;
-				}; return $("body");		
-			})(this.helper[0].parentNode);
-			
-			//Prepare variables for position generation
-			this.elementOffset = this.element.offset();
-			this.offsetParentOffset = this.offsetParent.offset();
-			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
-			this._pageX = e.pageX; this._pageY = e.pageY;
-			this.clickOffset = { left: e.pageX - this.elementOffset.left, top: e.pageY - this.elementOffset.top };
-			var r = this.helper.css('position') == 'relative';
-
-			//Generate the original position
-			this.originalPosition = {
-				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
-				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
-			};
-			
-			//If we have a fixed element, we must subtract the scroll offset again
-			if(this.element.css('position') == 'fixed') {
-				this.originalPosition.top -= this.offsetParent[0] == document.body ? $(document).scrollTop() : this.offsetParent[0].scrollTop;
-				this.originalPosition.left -= this.offsetParent[0] == document.body ? $(document).scrollLeft() : this.offsetParent[0].scrollLeft;
-			}
-			
-			//Generate a flexible offset that will later be subtracted from e.pageX/Y
-			this.offset = {left: e.pageX - this.originalPosition.left, top: e.pageY - this.originalPosition.top };
-			
-			//Substract margins
-			if(this.element[0] != this.helper[0]) {
-				this.offset.left += parseInt(this.element.css('marginLeft'),10) || 0;
-				this.offset.top += parseInt(this.element.css('marginTop'),10) || 0;
-			}
-			
-			//Call plugins and callbacks
-			this.propagate("start", e);
-
-			this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };
-			if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e);
-			
-			//If we have something in cursorAt, we'll use it
-			if(o.cursorAt) {
-				if(o.cursorAt.top != undefined || o.cursorAt.bottom != undefined) {
-					this.offset.top -= this.clickOffset.top - (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
-					this.clickOffset.top = (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
-				}
-				if(o.cursorAt.left != undefined || o.cursorAt.right != undefined) {
-					this.offset.left -= this.clickOffset.left - (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
-					this.clickOffset.left = (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
-				}
-			}
-
-			return false;
-
-		},
-		clear: function() {
-			if($.ui.ddmanager) $.ui.ddmanager.current = null;
-			this.helper = null;
-		},
-		stop: function(e) {
-
-			//If we are using droppables, inform the manager about the drop
-			if ($.ui.ddmanager && !this.options.dropBehaviour)
-				$.ui.ddmanager.drop(this, e);
-				
-			//Call plugins and trigger callbacks
-			this.propagate("stop", e);
-			
-			if(this.cancelHelperRemoval) return false;			
-			if(this.options.helper != 'original') this.helper.remove();
-			this.clear();
-
-			return false;
-		},
-		drag: function(e) {
-
-			//Compute the helpers position
-			this.position = { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left };
-			this.positionAbs = { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top };
-
-			//Call plugins and callbacks
-			this.checkConstrains();			
-			this.position = this.propagate("drag", e) || this.position;
-			this.checkConstrains();
-			
-			$(this.helper).css({ left: this.position.left+'px', top: this.position.top+'px' }); // Stick the helper to the cursor
-			if($.ui.ddmanager) $.ui.ddmanager.drag(this, e);
-			return false;
-			
-		}
-	});
-	
-/*
- * Draggable Extensions
- */
-	 
-	$.ui.plugin.add("draggable", "cursor", {
-		start: function(e, ui) {
-			var t = $('body');
-			if (t.css("cursor")) ui.options._cursor = t.css("cursor");
-			t.css("cursor", ui.options.cursor);
-		},
-		stop: function(e, ui) {
-			if (ui.options._cursor) $('body').css("cursor", ui.options._cursor);
-		}
-	});
-
-	$.ui.plugin.add("draggable", "zIndex", {
-		start: function(e, ui) {
-			var t = $(ui.helper);
-			if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex");
-			t.css('zIndex', ui.options.zIndex);
-		},
-		stop: function(e, ui) {
-			if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex);
-		}
-	});
-
-	$.ui.plugin.add("draggable", "opacity", {
-		start: function(e, ui) {
-			var t = $(ui.helper);
-			if(t.css("opacity")) ui.options._opacity = t.css("opacity");
-			t.css('opacity', ui.options.opacity);
-		},
-		stop: function(e, ui) {
-			if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity);
-		}
-	});
-
-
-	$.ui.plugin.add("draggable", "revert", {
-		stop: function(e, ui) {
-			var self = ui.instance, helper = $(self.helper);
-			self.cancelHelperRemoval = true;
-			
-			$(ui.helper).animate({ left: self.originalPosition.left, top: self.originalPosition.top }, parseInt(ui.options.revert, 10) || 500, function() {
-				if(ui.options.helper != 'original') helper.remove();
-				if (!helper) self.clear();
-			});
-		}
-	});
-
-	$.ui.plugin.add("draggable", "iframeFix", {
-		start: function(e, ui) {
-
-			var o = ui.options;
-			if(ui.instance.slowMode) return; // Make clones on top of iframes (only if we are not in slowMode)
-			
-			if(o.iframeFix.constructor == Array) {
-				for(var i=0;i<o.iframeFix.length;i++) {
-					var co = $(o.iframeFix[i]).offset({ border: false });
-					$('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width", $(o.iframeFix[i])[0].offsetWidth+"px").css("height", $(o.iframeFix[i])[0].offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
-				}		
-			} else {
-				$("iframe").each(function() {					
-					var co = $(this).offset({ border: false });
-					$('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width", this.offsetWidth+"px").css("height", this.offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
-				});							
-			}
-
-		},
-		stop: function(e, ui) {
-			if(ui.options.iframeFix) $("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers	
-		}
-	});
-	
-	$.ui.plugin.add("draggable", "containment", {
-		start: function(e, ui) {
-
-			var o = ui.options;
-			var self = ui.instance;
-			if((o.containment.left != undefined || o.containment.constructor == Array) && !o._containment) return;
-			if(!o._containment) o._containment = o.containment;
-
-			if(o._containment == 'parent') o._containment = this[0].parentNode;
-			if(o._containment == 'document') {
-				o.containment = [
-					0,
-					0,
-					$(document).width(),
-					($(document).height() || document.body.parentNode.scrollHeight)
-				];
-			} else { //I'm a node, so compute top/left/right/bottom
-
-				var ce = $(o._containment)[0];
-				var co = $(o._containment).offset();
-
-				o.containment = [
-					co.left,
-					co.top,
-					co.left+(ce.offsetWidth || ce.scrollWidth),
-					co.top+(ce.offsetHeight || ce.scrollHeight)
-				];
-			}
-			
-			var c = o.containment;
-			ui.instance.setContrains(
-				c[0] - (self.offset.left - self.clickOffset.left), //min left
-				c[2] - (self.offset.left - self.clickOffset.left), //max left
-				c[1] - (self.offset.top - self.clickOffset.top), //min top
-				c[3] - (self.offset.top - self.clickOffset.top) //max top
-			);
-
-		}
-	});
-
-	$.ui.plugin.add("draggable", "grid", {
-		drag: function(e, ui) {
-			var o = ui.options;
-			var newLeft = ui.instance.originalPosition.left + Math.round((e.pageX - ui.instance._pageX) / o.grid[0]) * o.grid[0];
-			var newTop = ui.instance.originalPosition.top + Math.round((e.pageY - ui.instance._pageY) / o.grid[1]) * o.grid[1];
-			
-			ui.instance.position.left = newLeft;
-			ui.instance.position.top = newTop;
-
-		}
-	});
-
-	$.ui.plugin.add("draggable", "axis", {
-		drag: function(e, ui) {
-			var o = ui.options;
-			if(o.constraint) o.axis = o.constraint; //Legacy check
-			switch (o.axis) {
-				case 'x' : ui.instance.position.top = ui.instance.originalPosition.top; break;
-				case 'y' : ui.instance.position.left = ui.instance.originalPosition.left; break;
-			}
-		}
-	});
-
-	$.ui.plugin.add("draggable", "scroll", {
-		start: function(e, ui) {
-			var o = ui.options;
-			o.scrollSensitivity	= o.scrollSensitivity || 20;
-			o.scrollSpeed		= o.scrollSpeed || 20;
-
-			ui.instance.overflowY = function(el) {
-				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode);
-				return $(document);
-			}(this);
-			ui.instance.overflowX = function(el) {
-				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode);
-				return $(document);
-			}(this);
-		},
-		drag: function(e, ui) {
-			
-			var o = ui.options;
-			var i = ui.instance;
-
-			if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') {
-				if(i.overflowY[0].offsetHeight - (ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
-					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed;
-				if((ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
-					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;				
-			} else {
-				//$(document.body).append('<p>'+(e.pageY - $(document).scrollTop())+'</p>');
-				if(e.pageY - $(document).scrollTop() < o.scrollSensitivity)
-					$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
-				if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity)
-					$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
-			}
-			
-			if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') {
-				if(i.overflowX[0].offsetWidth - (ui.position.left - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
-					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed;
-				if((ui.position.top - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
-					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;				
-			} else {
-				if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity)
-					$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
-				if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
-					$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
-			}
-			
-			ui.instance.recallOffset(e);
-
-		}
-	});
-	
-	$.ui.plugin.add("draggable", "snap", {
-		start: function(e, ui) {
-			
-			ui.instance.snapElements = [];
-			$(ui.options.snap === true ? '.ui-draggable' : ui.options.snap).each(function() {
-				var $t = $(this); var $o = $t.offset();
-				if(this != ui.instance.element[0]) ui.instance.snapElements.push({
-					item: this,
-					width: $t.outerWidth(),
-					height: $t.outerHeight(),
-					top: $o.top,
-					left: $o.left
-				});
-			});
-			
-		},
-		drag: function(e, ui) {
-
-			var d = ui.options.snapTolerance || 20;
-			var x1 = ui.absolutePosition.left, x2 = x1 + ui.instance.helperProportions.width,
-			    y1 = ui.absolutePosition.top, y2 = y1 + ui.instance.helperProportions.height;
-
-			for (var i = ui.instance.snapElements.length - 1; i >= 0; i--){
-
-				var l = ui.instance.snapElements[i].left, r = l + ui.instance.snapElements[i].width, 
-				    t = ui.instance.snapElements[i].top,  b = t + ui.instance.snapElements[i].height;
-
-				//Yes, I know, this is insane ;)
-				if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) continue;
-
-				if(ui.options.snapMode != 'inner') {
-					var ts = Math.abs(t - y2) <= 20;
-					var bs = Math.abs(b - y1) <= 20;
-					var ls = Math.abs(l - x2) <= 20;
-					var rs = Math.abs(r - x1) <= 20;
-					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
-					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top;
-					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
-					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left;
-				}
-				
-				if(ui.options.snapMode != 'outer') {
-					var ts = Math.abs(t - y1) <= 20;
-					var bs = Math.abs(b - y2) <= 20;
-					var ls = Math.abs(l - x1) <= 20;
-					var rs = Math.abs(r - x2) <= 20;
-					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top;
-					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
-					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left;
-					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
-				}
-
-			};
-		}
-	});
-	
-	$.ui.plugin.add("draggable", "connectToSortable", {
-		start: function(e,ui) {
-			ui.instance.sortable = $.data($(ui.options.connectToSortable)[0], 'sortable');
-			ui.instance.sortableOffset = ui.instance.sortable.element.offset();
-			ui.instance.sortableOuterWidth = ui.instance.sortable.element.outerWidth();
-			ui.instance.sortableOuterHeight = ui.instance.sortable.element.outerHeight();
-			if(ui.instance.sortable.options.revert) ui.instance.sortable.shouldRevert = true;
-		},
-		stop: function(e,ui) {
-			//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
-			var inst = ui.instance.sortable;
-			if(inst.isOver) {
-				inst.isOver = 0;
-				ui.instance.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
-				inst.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
-				if(inst.shouldRevert) inst.options.revert = true; //revert here
-				inst.stop(e);
-				inst.options.helper = "original";
-			}
-		},
-		drag: function(e,ui) {
-			//This is handy: We reuse the intersectsWith method for checking if the current draggable helper
-			//intersects with the sortable container
-			var inst = ui.instance.sortable;
-			ui.instance.position.absolute = ui.absolutePosition; //Sorry, this is an ugly API fix
-			
-			if(inst.intersectsWith.call(ui.instance, {
-				left: ui.instance.sortableOffset.left, top: ui.instance.sortableOffset.top,
-				width: ui.instance.sortableOuterWidth, height: ui.instance.sortableOuterHeight
-			})) {
-				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
-				if(!inst.isOver) {
-					inst.isOver = 1;
-					
-					//Cache the width/height of the new helper
-					var height = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerHeight() : $(inst.options.items, inst.element).innerHeight();
-					var width = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerWidth() : $(inst.options.items, inst.element).innerWidth();
-
-					//Now we fake the start of dragging for the sortable instance,
-					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
-					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
-					inst.currentItem = $(this).clone().appendTo(inst.element);
-					inst.options.helper = function() { return ui.helper[0]; };
-					inst.start(e);
-					
-					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
-					inst.clickOffset.top = ui.instance.clickOffset.top;
-					inst.clickOffset.left = ui.instance.clickOffset.left;
-					inst.offset.left -= ui.absolutePosition.left - inst.position.absolute.left;
-					inst.offset.top -= ui.absolutePosition.top - inst.position.absolute.top;
-					
-					//Do a nifty little helper animation: Animate it to the portlet's size (just takes the first 'li' element in the sortable now)
-					inst.helperProportions = { width:  width, height: height}; //We have to reset the helper proportions, because we are doing our animation there
-					ui.helper.animate({ height: height, width: width}, 500);
-					ui.instance.propagate("toSortable", e);
-				
-				}
-
-				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
-				if(inst.currentItem) inst.drag(e);
-				
-			} else {
-				
-				//If it doesn't intersect with the sortable, and it intersected before,
-				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
-				if(inst.isOver) {
-					inst.isOver = 0;
-					inst.cancelHelperRemoval = true;
-					inst.options.revert = false; //No revert here
-					inst.stop(e);
-					inst.options.helper = "original";
-					
-					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
-					inst.currentItem.remove();
-					inst.placeholder.remove();
-					
-					ui.helper.animate({ height: this.innerHeight(), width: this.innerWidth() }, 500);
-					ui.instance.propagate("fromSortable", e);
-				}
-				
-			};
-		}
-	})
-
-	//TODO: wrapHelper
-
-})(jQuery);
-
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.resizable.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.resizable.js
deleted file mode 100644
index 409195e..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.resizable.js
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * jQuery UI Resizable
- *
- * Copyright (c) 2008 Paul Bakaus
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- * 
- * http://docs.jquery.com/UI/Resizables
- *
- * Depends:
- *   ui.base.js
- *
- * Revision: $Id: ui.resizable.js 5205 2008-04-06 16:12:50Z braeker $
- */
-;(function($) {
-	
-	$.fn.extend({
-		resizable: function(options, data) {
-			var args = Array.prototype.slice.call(arguments, 1);
-			
-			return this.each(function() {
-				if (typeof options == "string") {
-					var resize = $.data(this, "resizable");
-					if (resize) resize[options].apply(resize, args);
-	
-				} else if(!$(this).is(".ui-resizable"))
-					new $.ui.resizable(this, options);
-			});
-		}
-	});
-
-	$.ui.resizable = function(element, options) {
-		//Initialize needed constants
-		var self = this;
-		
-		this.element = $(element);
-		
-		$.data(element, "resizable", this);
-		
-		// simulate .ui-resizable { position: relative; }
-		var elpos = this.element.css('position');
-		this.element.addClass("ui-resizable").css({ position: /static/.test(elpos) ? 'relative' : elpos });
-		
-		//Prepare the passed options
-		this.options = $.extend({
-			preventDefault: true,
-			transparent: false,
-			minWidth: 10,
-			minHeight: 10,
-			aspectRatio: false,
-			disableSelection: true,
-			preserveCursor: true,
-			autohide: false,
-			knobHandles: false
-		}, options);
-		
-		this.options._aspectRatio = !!(this.options.aspectRatio);
-		
-		// force proxy if helper is enabled
-		this.options.proxy = this.options.proxy || this.options.ghost ? 'proxy' : null; 
-		
-		// force proxy if animation is enabled
-		this.options.proxy = this.options.proxy || this.options.animate ? 'proxy' : null; 
-		
-		// if knobHandles equals true set to ui-resizable-knob-handle
-		this.options.knobHandles = this.options.knobHandles === true ? 'ui-resizable-knob-handle' : this.options.knobHandles;
-		
-		$(element).bind("setData.resizable", function(event, key, value){
-			self.options[key] = value;
-		}).bind("getData.resizable", function(event, key){
-			return self.options[key];
-		});
-	
-		var o = this.options;
-	
-		//Default Theme
-		var aBorder = '1px solid #DEDEDE';
-	
-		o.defaultTheme = {
-			'ui-resizable': { display: 'block' },
-			'ui-resizable-handle': { position: 'absolute', background: '#F2F2F2', fontSize: '0.1px' },
-			'ui-resizable-n': { cursor: 'n-resize', height: '4px', left: '0px', right: '0px', borderTop: aBorder },
-			'ui-resizable-s': { cursor: 's-resize', height: '4px', left: '0px', right: '0px', borderBottom: aBorder },
-			'ui-resizable-e': { cursor: 'e-resize', width: '4px', top: '0px', bottom: '0px', borderRight: aBorder },
-			'ui-resizable-w': { cursor: 'w-resize', width: '4px', top: '0px', bottom: '0px', borderLeft: aBorder },
-			'ui-resizable-se': { cursor: 'se-resize', width: '4px', height: '4px', borderRight: aBorder, borderBottom: aBorder },
-			'ui-resizable-sw': { cursor: 'sw-resize', width: '4px', height: '4px', borderBottom: aBorder, borderLeft: aBorder },
-			'ui-resizable-ne': { cursor: 'ne-resize', width: '4px', height: '4px', borderRight: aBorder, borderTop: aBorder },
-			'ui-resizable-nw': { cursor: 'nw-resize', width: '4px', height: '4px', borderLeft: aBorder, borderTop: aBorder }
-		};
-		
-		o.knobTheme = {
-			'ui-resizable-handle': { background: '#F2F2F2', border: '1px solid #808080', height: '8px', width: '8px' },
-			'ui-resizable-n': { cursor: 'n-resize', top: '-4px', left: '45%' },
-			'ui-resizable-s': { cursor: 's-resize', bottom: '-4px', left: '45%' },
-			'ui-resizable-e': { cursor: 'e-resize', right: '-4px', top: '45%' },
-			'ui-resizable-w': { cursor: 'w-resize', left: '-4px', top: '45%' },
-			'ui-resizable-se': { cursor: 'se-resize', right: '-4px', bottom: '-4px' },
-			'ui-resizable-sw': { cursor: 'sw-resize', left: '-4px', bottom: '-4px' },
-			'ui-resizable-nw': { cursor: 'nw-resize', left: '-4px', top: '-4px' },
-			'ui-resizable-ne': { cursor: 'ne-resize', right: '-4px', top: '-4px' }
-		};
-	
-		//Position the node
-		if(!o.proxy && (this.element.css('position') == 'static' || this.element.css('position') === ''))
-			this.element.css('position', 'relative');
-	
-		o._nodeName = element.nodeName;
-	
-		//Wrap the element if it cannot hold child nodes
-		if(o._nodeName.match(/textarea|input|select|button|img/i)) {
-			var el = this.element;
-			
-			//Opera fixing relative position
-			if (/relative/.test(el.css('position')) && $.browser.opera)
-				el.css({ position: 'relative', top: 'auto', left: 'auto' });
-			
-			//Create a wrapper element and set the wrapper to the new current internal element
-			el.wrap(
-				$('<div class="ui-wrapper"	style="overflow: hidden;"></div>').css( {
-					position: el.css('position'),
-					width: el.outerWidth(),
-					height: el.outerHeight(),
-					top: el.css('top'),
-					left: el.css('left')
-				})
-			);
-			
-			var oel = this.element; element = element.parentNode; this.element = $(element);
-	
-			//Move margins to the wrapper
-			this.element.css({ marginLeft: oel.css("marginLeft"), marginTop: oel.css("marginTop"),
-				marginRight: oel.css("marginRight"), marginBottom: oel.css("marginBottom")
-			});
-	
-			oel.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
-	
-			//Prevent Safari textarea resize
-			if ($.browser.safari && o.preventDefault) oel.css('resize', 'none');
-	
-			o.proportionallyResize = oel.css({ position: 'static', zoom: 1, display: 'block' });
-			
-			// avoid IE jump
-			this.element.css({ margin: oel.css('margin') });
-			
-			// fix handlers offset
-			this._proportionallyResize();
-		}
-	
-		if(!o.handles) o.handles = !$('.ui-resizable-handle', element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' };
-		if(o.handles.constructor == String) {
-	
-			if(o.handles == 'all') o.handles = 'n,e,s,w,se,sw,ne,nw';
-	
-			var n = o.handles.split(","); o.handles = {};
-	
-			o.zIndex = o.zIndex || 1000;
-			
-			// insertions are applied when don't have theme loaded
-			var insertionsDefault = {
-				handle: 'position: absolute; display: none; overflow:hidden;',
-				n: 'top: 0pt; width:100%;',
-				e: 'right: 0pt; height:100%;',
-				s: 'bottom: 0pt; width:100%;',
-				w: 'left: 0pt; height:100%;',
-				se: 'bottom: 0pt; right: 0px;',
-				sw: 'bottom: 0pt; left: 0px;',
-				ne: 'top: 0pt; right: 0px;',
-				nw: 'top: 0pt; left: 0px;'
-			};
-	
-			for(var i = 0; i < n.length; i++) {
-				var handle = jQuery.trim(n[i]), dt = o.defaultTheme, hname = 'ui-resizable-'+handle, loadDefault = !$.ui.css(hname) && !o.knobHandles, userKnobClass = $.ui.css('ui-resizable-knob-handle'), 
-							allDefTheme = $.extend(dt[hname], dt['ui-resizable-handle']), allKnobTheme = $.extend(o.knobTheme[hname], !userKnobClass ? o.knobTheme['ui-resizable-handle'] : {});
-				
-				// increase zIndex of sw, se, ne, nw axis
-				var applyZIndex = /sw|se|ne|nw/.test(handle) ? { zIndex: ++o.zIndex } : {};
-				
-				var defCss = (loadDefault ? insertionsDefault[handle] : ''), 
-					axis = $(['<div class="ui-resizable-handle ', hname, '" style="', defCss, insertionsDefault.handle, '"></div>'].join('')).css( applyZIndex );
-				o.handles[handle] = '.ui-resizable-'+handle;
-				
-				this.element.append(
-					//Theme detection, if not loaded, load o.defaultTheme
-					axis.css( loadDefault ? allDefTheme : {} )
-						// Load the knobHandle css, fix width, height, top, left...
-						.css( o.knobHandles ? allKnobTheme : {} ).addClass(o.knobHandles ? 'ui-resizable-knob-handle' : '').addClass(o.knobHandles)
-				);
-			}
-			
-			if (o.knobHandles) this.element.addClass('ui-resizable-knob').css( !$.ui.css('ui-resizable-knob') ? { /*border: '1px #fff dashed'*/ } : {} );
-		}
-	
-		this._renderAxis = function(target) {
-			target = target || this.element;
-	
-			for(var i in o.handles) {
-				if(o.handles[i].constructor == String) 
-					o.handles[i] = $(o.handles[i], element).show();
-	
-				if (o.transparent)
-					o.handles[i].css({opacity:0});
-	
-				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
-				if (this.element.is('.ui-wrapper') && 
-					o._nodeName.match(/textarea|input|select|button/i)) {
-	
-					var axis = $(o.handles[i], element), padWrapper = 0;
-	
-					//Checking the correct pad and border
-					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
-	
-					//The padding type i have to apply...
-					var padPos = [ 'padding', 
-						/ne|nw|n/.test(i) ? 'Top' :
-						/se|sw|s/.test(i) ? 'Bottom' : 
-						/^e$/.test(i) ? 'Right' : 'Left' ].join(""); 
-	
-					if (!o.transparent)
-						target.css(padPos, padWrapper);
-	
-					this._proportionallyResize();
-				}
-				if(!$(o.handles[i]).length) continue;
-			}
-		};
-			
-		this._renderAxis(this.element);
-		o._handles = $('.ui-resizable-handle', self.element);
-		
-		if (o.disableSelection)
-			o._handles.each(function(i, e) { $.ui.disableSelection(e); });
-		
-		//Matching axis name
-		o._handles.mouseover(function() {
-			if (!o.resizing) {
-				if (this.className) 
-					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
-				//Axis, default = se
-				self.axis = o.axis = axis && axis[1] ? axis[1] : 'se';
-			}
-		});
-				
-		//If we want to auto hide the elements
-		if (o.autohide) {
-			o._handles.hide();
-			$(self.element).addClass("ui-resizable-autohide").hover(function() {
-				$(this).removeClass("ui-resizable-autohide");
-				o._handles.show();
-			},
-			function(){
-				if (!o.resizing) {
-					$(this).addClass("ui-resizable-autohide");
-					o._handles.hide();
-				}
-			});
-		}
-	
-		//Initialize mouse events for interaction
-		this.element.mouseInteraction({
-			executor: this,
-			delay: 0,
-			distance: 0,
-			dragPrevention: ['input','textarea','button','select','option'],
-			start: this.start,
-			stop: this.stop,
-			drag: this.drag,
-			condition: function(e) {
-				if(this.disabled) return false;
-				for(var i in this.options.handles) {
-					if($(this.options.handles[i])[0] == e.target) return true;
-				}
-				return false;
-			}
-		});
-	};
-
-	$.extend($.ui.resizable.prototype, {
-		plugins: {},
-		ui: function() {
-			return {
-				instance: this,
-				axis: this.options.axis,
-				options: this.options
-			};
-		},
-		_renderProxy: function() {
-			var el = this.element, o = this.options;
-			this.elementOffset = el.offset();
-	
-			if(o.proxy) {
-				this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
-	
-				// fix ie6 offset
-				var ie6 = $.browser.msie && $.browser.version  < 7, ie6offset = (ie6 ? 1 : 0),
-				pxyoffset = ( ie6 ? 2 : -1 );
-	
-				this.helper.addClass(o.proxy).css({
-					width: el.outerWidth() + pxyoffset,
-					height: el.outerHeight() + pxyoffset,
-					position: 'absolute',
-					left: this.elementOffset.left - ie6offset +'px',
-					top: this.elementOffset.top - ie6offset +'px',
-					zIndex: ++o.zIndex
-				});
-				
-				this.helper.appendTo("body");
-	
-				if (o.disableSelection)
-					$.ui.disableSelection(this.helper.get(0));
-	
-			} else {
-				this.helper = el; 
-			}
-		},
-		propagate: function(n,e) {
-			$.ui.plugin.call(this, n, [e, this.ui()]);
-			this.element.triggerHandler(n == "resize" ? n : ["resize", n].join(""), [e, this.ui()], this.options[n]);
-		},
-		destroy: function() {
-			var el = this.element, wrapped = el.children(".ui-resizable").get(0),
-			
-			_destroy = function(exp) {
-				$(exp).removeClass("ui-resizable ui-resizable-disabled")
-					.removeMouseInteraction().removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
-			};
-			
-			_destroy(el);
-			
-			if (el.is('.ui-wrapper') && wrapped) {
-		  		el.parent().append(
-					$(wrapped).css({
-			  		position: el.css('position'),
-			  		width: el.outerWidth(),
-			  		height: el.outerHeight(),
-			  		top: el.css('top'),
-			  		left: el.css('left')
-		  		})
-				).end().remove();
-				
-				_destroy(wrapped);
-	  		}
-		},
-		enable: function() {
-			this.element.removeClass("ui-resizable-disabled");
-			this.disabled = false;
-		},
-		disable: function() {
-			this.element.addClass("ui-resizable-disabled");
-			this.disabled = true;
-		},
-		start: function(e) {
-			var o = this.options, iniPos = this.element.position(), el = this.element, 
-				num = function(v) { return parseInt(v, 10) || 0; }, ie6 = $.browser.msie && $.browser.version < 7;
-			o.resizing = true;
-			o.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
-	
-			// bugfix #1749
-			if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
-				
-				// sOffset decides if document scrollOffset will be added to the top/left of the resizable element
-				var sOffset = $.browser.msie && !o.containment && (/absolute/).test(el.css('position')) && !(/relative/).test(el.parent().css('position'));
-				var dscrollt = sOffset ? o.documentScroll.top : 0, dscrolll = sOffset ? o.documentScroll.left : 0;
-				
-				el.css({ position: 'absolute', top: (iniPos.top + dscrollt), left: (iniPos.left + dscrolll) });
-			}
-			
-			//Opera fixing relative position
-			if (/relative/.test(el.css('position')) && $.browser.opera)
-				el.css({ position: 'relative', top: 'auto', left: 'auto' });
-	
-			this._renderProxy();
-	
-			var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
-			
-			//Store needed variables
-			this.offset = this.helper.offset();
-			this.position = { left: curleft, top: curtop };
-			this.size = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-			this.originalSize = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-			this.originalPosition = { left: curleft, top: curtop };
-			this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
-			this.originalMousePosition = { left: e.pageX, top: e.pageY };
-			
-			//Aspect Ratio
-			o.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.height / this.originalSize.width)||1);
-	
-			if (o.preserveCursor)
-				$('body').css('cursor', this.axis + '-resize');
-				
-			this.propagate("start", e); 	
-			return false;
-		},
-		stop: function(e) {
-			this.options.resizing = false;
-			var o = this.options, num = function(v) { return parseInt(v, 10) || 0; }, self = this;
-	
-			if(o.proxy) {
-				var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
-							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
-								soffsetw = ista ? 0 : self.sizeDiff.width;
-			
-				var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
-						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
-							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top);
-				
-				if (!o.animate)
-					this.element.css($.extend(style, { top: top, left: left }));
-				
-				if (o.proxy && !o.animate) this._proportionallyResize();
-				this.helper.remove();
-			}
-
-			if (o.preserveCursor)
-			$('body').css('cursor', 'auto');
-	
-			this.propagate("stop", e);	
-			return false;
-		},
-		drag: function(e) {
-			//Increase performance, avoid regex
-			var el = this.helper, o = this.options, props = {},
-				self = this, smp = this.originalMousePosition, a = this.axis;
-
-			var dx = (e.pageX-smp.left)||0, dy = (e.pageY-smp.top)||0;
-			var trigger = this.change[a];
-			if (!trigger) return false;
-		 
-			// Calculate the attrs that will be change
-			var data = trigger.apply(this, [e, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
-		 
-			if (o._aspectRatio || e.shiftKey)
-				data = this._updateRatio(data, e);
-			
-			data = this._respectSize(data, e);
-			
-			this.propagate("resize", e);
-			
-			el.css({
-				top: this.position.top + "px", left: this.position.left + "px", 
-				width: this.size.width + "px", height: this.size.height + "px"
-			});
-			
-			if (!o.proxy && o.proportionallyResize)
-				this._proportionallyResize();
-			
-			this._updateCache(data);
-			
-			return false;
-		},
-		
-		_updateCache: function(data) {
-			var o = this.options;
-			this.offset = this.helper.offset();
-			if (data.left) this.position.left = data.left;
-			if (data.top) this.position.top = data.top;
-			if (data.height) this.size.height = data.height;
-			if (data.width) this.size.width = data.width;
-		},
-		
-		_updateRatio: function(data, e) {
-			var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
-			
-			if (data.height) data.width = Math.round(csize.height / o.aspectRatio);
-			else if (data.width) data.height = Math.round(csize.width * o.aspectRatio);
-			
-			if (a == 'sw') {
-				data.left = cpos.left + (csize.width - data.width);
-				data.top = null;
-			}
-			if (a == 'nw') { 
-				data.top = cpos.top + (csize.height - data.height);
-				data.left = cpos.left + (csize.width - data.width);
-			}
-			
-			return data;
-		},
-		
-		_respectSize: function(data, e) {
-			
-			var el = this.helper, o = this.options, pRatio = o._aspectRatio || e.shiftKey,  a = this.axis, 
-					ismaxw = data.width && o.maxWidth && o.maxWidth < data.width, ismaxh = data.height && o.maxHeight && o.maxHeight < data.height,
-						isminw = data.width && o.minWidth && o.minWidth > data.width, isminh = data.height && o.minHeight && o.minHeight > data.height;
-			
-			if (isminw) data.width = o.minWidth;
-			if (isminh) data.height = o.minHeight;
-			if (ismaxw) data.width = o.maxWidth;
-			if (ismaxh) data.height = o.maxHeight;
-			
-			var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
-			var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
-			
-			if (isminw && cw) data.left = dw - o.minWidth;
-			if (ismaxw && cw) data.left = dw - o.maxWidth;
-			if (isminh && ch)	data.top = dh - o.minHeight;
-			if (ismaxh && ch)	data.top = dh - o.maxHeight;
-			
-			// fixing jump error on top/left - bug #2330
-			var isNotwh = !data.width && !data.height;
-			if (isNotwh && !data.left && data.top) data.top = null;
-			else if (isNotwh && !data.top && data.left) data.left = null;
-			
-			return data;
-		},
-		
-		_proportionallyResize: function() {
-			var o = this.options;
-			if (!o.proportionallyResize) return;
-			var prel = o.proportionallyResize, el = this.helper || this.element;
-		 
-			if (!o.borderDif) {
-				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
-					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
-				 
-				o.borderDif = $.map(b, function(v, i) {
-					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
-					return border + padding; 
-				});
-			}
-			prel.css({
-				height: (el.height() - o.borderDif[0] - o.borderDif[2]) + "px",
-				width: (el.width() - o.borderDif[1] - o.borderDif[3]) + "px"
-			});
-		},
-		
-		change: {
-			e: function(e, dx, dy) {
-				return { width: this.originalSize.width + dx };
-			},
-			w: function(e, dx, dy) {
-				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-				return { left: sp.left + dx, width: cs.width - dx };
-			},
-			n: function(e, dx, dy) {
-				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-				return { top: sp.top + dy, height: cs.height - dy };
-			},
-			s: function(e, dx, dy) {
-				return { height: this.originalSize.height + dy };
-			},
-			se: function(e, dx, dy) {
-				return $.extend(this.change.s.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
-			},
-			sw: function(e, dx, dy) {
-				return $.extend(this.change.s.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
-			},
-			ne: function(e, dx, dy) {
-				return $.extend(this.change.n.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
-			},
-			nw: function(e, dx, dy) {
-				return $.extend(this.change.n.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
-			}
-		}
-	});
-
-/*
- * Resizable Extensions
- */
-
-	$.ui.plugin.add("resizable", "containment", {
-		
-		start: function(e, ui) {
-			var o = ui.options, self = ui.instance, el = self.element;
-			var oc = o.containment,	ce = (oc instanceof jQuery) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
-			if (!ce) return;
-			
-			if (/document/.test(oc) || oc == document) {
-				self.containerOffset = { left: 0, top: 0 };
-
-				self.parentData = { 
-					element: $(document), left: 0, top: 0, width: $(document).width(),
-					height: $(document).height() || document.body.parentNode.scrollHeight
-				};
-			}
-			
-			// i'm a node, so compute top, left, right, bottom
-			else{
-				self.containerOffset = $(ce).offset(), self.containerSize = { height: $(ce).innerHeight(), width: $(ce).innerWidth() };
-			
-				var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width, 
-							width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
-			
-				self.parentData = { 
-					element: ce, left: co.left, top: co.top, width: width, height: height
-				};
-			}
-		},
-		
-		resize: function(e, ui) {
-			var o = ui.options, self = ui.instance, ps = self.containerSize, 
-						co = self.containerOffset, cs = self.size, cp = self.position,
-							pRatio = o._aspectRatio || e.shiftKey;
-			
-			if (cp.left < (o.proxy ? co.left : 0)) {
-				self.size.width = self.size.width + (o.proxy ? (self.position.left - co.left) : self.position.left);
-				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
-				self.position.left = o.proxy ? co.left : 0;
-			}
-			
-			if (cp.top < (o.proxy ? co.top : 0)) {
-				self.size.height = self.size.height + (o.proxy ? (self.position.top - co.top) : self.position.top);
-				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
-				self.position.top = o.proxy ? co.top : 0;
-			}
-			
-			var woset = (o.proxy ? self.offset.left - co.left : self.position.left) + self.sizeDiff.width, 
-						hoset = (o.proxy ? self.offset.top - co.top : self.position.top) + self.sizeDiff.height;
-			
-			if (woset + self.size.width >= self.parentData.width) {
-				self.size.width = self.parentData.width - woset;
-				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
-			}
-			
-			if (hoset + self.size.height >= self.parentData.height) {
-				self.size.height = self.parentData.height - hoset;
-				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
-			}
-		}
-	});
-	
-	$.ui.plugin.add("resizable", "grid", {
-		
-		resize: function(e, ui) {
-			var o = ui.options, self =  ui.instance, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || e.shiftKey;
-			o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
-			var ox = Math.round((cs.width - os.width) / o.grid[0]) * o.grid[0], oy = Math.round((cs.height - os.height) / o.grid[1]) * o.grid[1];
-			
-			if (/^(se|s|e)$/.test(a)) {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-			}
-			else if (/^(ne)$/.test(a)) {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-				self.position.top = op.top - oy;
-			}
-			else if (/^(sw)$/.test(a)) {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-				self.position.left = op.left - ox;
-			}
-			else {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-				self.position.top = op.top - oy;
-				self.position.left = op.left - ox;
-			}
-		}
-		
-	});
-	
-	$.ui.plugin.add("resizable", "animate", {
-		
-		stop: function(e, ui) {
-			var o = ui.options, self =  ui.instance;
-
-			var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
-							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
-								soffsetw = ista ? 0 : self.sizeDiff.width;
-			
-			var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
-						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
-							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top); 
-			
-			self.element.animate(
-				$.extend(style, { top: top, left: left }),
-				{ 
-					duration: o.animateDuration || "slow", 
-					easing: o.animateEasing || "swing", 
-					step: function() {
-						if (pr) pr.css({ width: self.element.css('width'), height: self.element.css('height') });
-					}
-				}
-			);
-		}
-		
-	});
-	
-	$.ui.plugin.add("resizable", "ghost", {
-		
-		start: function(e, ui) {
-			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize, cs = self.size;
-			
-			if (!pr) self.ghost = self.element.clone();
-			else self.ghost = pr.clone();
-			
-			self.ghost.css(
-				{ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }
-			)
-			.addClass('ui-resizable-ghost').addClass(typeof o.ghost == 'string' ? o.ghost : '');
-			
-			self.ghost.appendTo(self.helper);
-			
-		},
-		
-		resize: function(e, ui){
-			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
-			
-			if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
-			
-		},
-		
-		stop: function(e, ui){
-			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
-			if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
-		}
-		
-	});
-
-})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.css b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.css
deleted file mode 100644
index 0eabf94..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.css
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Caution! Ensure accessibility in print and other media types... */
- at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
-    .ui-tabs-hide {
-        display: none;
-    }
-}
-
-/* Hide useless elements in print layouts... */
- at media print {
-    .ui-tabs-nav {
-        display: none;
-    }
-}
-
-/* Skin */
-.ui-tabs-nav {
-    list-style: none;
-    margin: 0 !important;
-    padding: 0 0 0 4px;
-}
-.ui-tabs-nav li {
-    list-style-image: none !important;
-    margin: 0 !important;
-    padding: 0 0 0 4px;
-}
-
-.ui-tabs-panel {
-    border-top: #94ADA7 solid 1px;
-    padding-top: 5px;
-    clear: left;
-}
-
-/* IE6 hack */
-* html .ui-tabs-panel {
-    margin-top: -1.2em;
-}
-
-.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
-    display: block;
-    clear: both;
-    content: " ";
-}
-.ui-tabs-nav li {
-    float: left;
-    margin: 0 0 0 1px;
-    min-width: 84px; /* be nice to Opera */
-}
-.ui-tabs-nav a, .ui-tabs-nav a span {
-    display: block;
-    padding: 0 10px;
-    background: url(tab.png) no-repeat;
-}
-.ui-tabs-nav a {
-    position: relative;
-    top: 1px;
-    z-index: 2;
-    padding-left: 0;
-    color: #27537a;
-    font-size: 12px;
-    font-weight: bold;
-    line-height: 1.2;
-    text-align: center;
-    text-decoration: none;
-    white-space: nowrap; /* required in IE 6 */    
-}
-.ui-tabs-nav .ui-tabs-selected a {
-    color: #000;
-}
-.ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active {
-    background-position: 100% -150px;
-    outline: 0; /* prevent dotted border in Firefox */
-}
-.ui-tabs-nav a, .ui-tabs-nav .ui-tabs-disabled a:hover, .ui-tabs-nav .ui-tabs-disabled a:focus, .ui-tabs-nav .ui-tabs-disabled a:active {
-    background-position: 100% -100px;
-}
-.ui-tabs-nav a span {
-    width: 64px; /* IE 6 treats width as min-width */
-    min-width: 64px;
-    height: 18px; /* IE 6 treats height as min-height */
-    min-height: 18px;
-    padding-top: 6px;
-    padding-right: 0;
-}
-*>.ui-tabs-nav a span { /* hide from IE 6 */
-    width: auto;
-    height: auto;
-}
-.ui-tabs-nav .ui-tabs-selected a span {
-    padding-top: 7px;
-}
-.ui-tabs-nav .ui-tabs-selected a span, .ui-tabs-nav a:hover span, .ui-tabs-nav a:focus span, .ui-tabs-nav a:active span {
-    background-position: 0 -50px;
-}
-.ui-tabs-nav a span, .ui-tabs-nav .ui-tabs-disabled a:hover span, .ui-tabs-nav .ui-tabs-disabled a:focus span, .ui-tabs-nav .ui-tabs-disabled a:active span {
-    background-position: 0 0;
-}
-.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited, .ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
-    cursor: text;
-}
-.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active { /* @ Opera, we need to be explicit again here now... */
-    cursor: pointer;
-}
-.ui-tabs-nav .ui-tabs-disabled {
-    opacity: .4;
-}
-.ui-tabs-container {
-    border-top: 1px solid #97a5b0;
-    padding: 1em 8px;
-    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
-}
-.ui-tabs-loading em {
-    padding: 0 0 0 20px;
-    background: url(loading.gif) no-repeat 0 50%;
-}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.js
deleted file mode 100644
index f595c10..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.js
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * jQuery UI Tabs
- *
- * Copyright (c) 2007 Klaus Hartl (stilbuero.de)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * http://docs.jquery.com/UI/Tabs
- *
- * Depends:
- *   ui.base.js
- *
- * Revision: $Id: ui.tabs.js 5149 2008-03-31 10:51:18Z rdworth $
- */
-;(function($) {
-
-    // tabs API methods
-    $.fn.tabs = function() {
-        var method = typeof arguments[0] == 'string' && arguments[0];
-        var args = method && Array.prototype.slice.call(arguments, 1) || arguments;
-
-        return method == 'length' ?
-            $.data(this[0], 'tabs').$tabs.length :
-            this.each(function() {
-                if (method) {
-                    var tabs = $.data(this, 'tabs');
-                    if (tabs) tabs[method].apply(tabs, args);
-                } else
-                    new $.ui.tabs(this, args[0] || {});
-            });
-    };
-
-    // tabs class
-    $.ui.tabs = function(el, options) {
-        var self = this;
-        
-        this.options = $.extend({}, $.ui.tabs.defaults, options);
-        this.element = el;
-
-        // doesn't extend with null
-        if (options.selected === null)
-            this.options.selected = null;
-
-        this.options.event += '.tabs'; // namespace event
-
-        $(el).bind('setData.tabs', function(event, key, value) {
-            if ((/^selected/).test(key))
-                self.select(value);
-            else {
-                self.options[key] = value;
-                self.tabify();
-            }
-        }).bind('getData.tabs', function(event, key) {
-            return self.options[key];
-        });
-
-        // save instance for later
-        $.data(el, 'tabs', this);
-
-        // create tabs
-        this.tabify(true);
-    };
-    
-    $.ui.tabs.defaults = {
-        // basic setup
-        selected: 0,
-        unselect: false,
-        event: 'click',
-        disabled: [],
-        cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
-        // TODO history: false,
-
-        // Ajax
-        spinner: 'Loading&#8230;',
-        cache: false,
-        idPrefix: 'ui-tabs-',
-        ajaxOptions: {},
-
-        // animations
-        fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
-
-        // templates
-        tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>',
-        panelTemplate: '<div></div>',
-
-        // CSS classes
-        navClass: 'ui-tabs-nav',
-        selectedClass: 'ui-tabs-selected',
-        unselectClass: 'ui-tabs-unselect',
-        disabledClass: 'ui-tabs-disabled',
-        panelClass: 'ui-tabs-panel',
-        hideClass: 'ui-tabs-hide',
-        loadingClass: 'ui-tabs-loading'
-    };
-
-    // instance methods
-    $.extend($.ui.tabs.prototype, {
-        tabId: function(a) {
-            return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
-                || this.options.idPrefix + $.data(a);
-        },
-        ui: function(tab, panel) {
-            return {
-                instance: this,
-                options: this.options,
-                tab: tab,
-                panel: panel
-            };
-        },
-        tabify: function(init) {
-
-            this.$lis = $('li:has(a[href])', this.element);
-            this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
-            this.$panels = $([]);
-
-            var self = this, o = this.options;
-
-            this.$tabs.each(function(i, a) {
-                // inline tab
-                if (a.hash && a.hash.replace('#', '')) // Safari 2 reports '#' for an empty hash
-                    self.$panels = self.$panels.add(a.hash);
-                // remote tab
-                else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#"
-                    $.data(a, 'href.tabs', a.href); // required for restore on destroy
-
-                    var _cls = a.getAttribute('class');
-                    var use_iframe = _cls && (_cls.indexOf('use_iframe') > -1)? true: false;
-                    if (!use_iframe) {
-                        $.data(a, 'load.tabs', a.href); // mutable
-                    } else {
-                        $.data(a, 'load.iframe_src', a.href); // mutable
-                    }
-
-
-                    var id = self.tabId(a);
-                    a.href = '#' + id;
-                    var $panel = $('#' + id);
-                    var panelTemplate = use_iframe? '<div><iframe></iframe></div>': o.panelTemplate;
-                    if (!$panel.length) {
-                        $panel = $(panelTemplate).attr('id', id).addClass(o.panelClass)
-                            .insertAfter( self.$panels[i - 1] || self.element );
-                        $panel.data('destroy.tabs', true);
-                    }
-                    self.$panels = self.$panels.add( $panel );
-                }
-                // invalid tab href
-                else
-                    o.disabled.push(i + 1);
-            });
-
-            if (init) {
-
-                // attach necessary classes for styling if not present
-                $(this.element).hasClass(o.navClass) || $(this.element).addClass(o.navClass);
-                this.$panels.each(function() {
-                    var $this = $(this);
-                    $this.hasClass(o.panelClass) || $this.addClass(o.panelClass);
-                });
-
-                // Try to retrieve selected tab:
-                // 1. from fragment identifier in url if present
-                // 2. from cookie
-                // 3. from selected class attribute on <li>
-                // 4. otherwise use given "selected" option
-                // 5. check if tab is disabled
-                this.$tabs.each(function(i, a) {
-                    if (location.hash) {
-                        if (a.hash == location.hash) {
-                            o.selected = i;
-                            // prevent page scroll to fragment
-                            //if (($.browser.msie || $.browser.opera) && !o.remote) {
-                            if ($.browser.msie || $.browser.opera) {
-                                var $toShow = $(location.hash), toShowId = $toShow.attr('id');
-                                $toShow.attr('id', '');
-                                setTimeout(function() {
-                                    $toShow.attr('id', toShowId); // restore id
-                                }, 500);
-                            }
-                            scrollTo(0, 0);
-                            return false; // break
-                        }
-                    } else if (o.cookie) {
-                        var index = parseInt($.cookie('ui-tabs' + $.data(self.element)),10);
-                        if (index && self.$tabs[index]) {
-                            o.selected = index;
-                            return false; // break
-                        }
-                    } else if ( self.$lis.eq(i).hasClass(o.selectedClass) ) {
-                        o.selected = i;
-                        return false; // break
-                    }
-                });
-
-                // highlight selected tab
-                this.$panels.addClass(o.hideClass);
-                this.$lis.removeClass(o.selectedClass);
-                if (o.selected !== null) {
-                    this.$panels.eq(o.selected).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before
-                    this.$lis.eq(o.selected).addClass(o.selectedClass);
-                }
-
-                // load if remote tab
-                var href = o.selected !== null && $.data(this.$tabs[o.selected], 'load.tabs');
-                if (href)
-                    this.load(o.selected);
-
-                // Take disabling tabs via class attribute from HTML
-                // into account and update option properly...
-                o.disabled = $.unique(o.disabled.concat(
-                    $.map(this.$lis.filter('.' + o.disabledClass),
-                        function(n, i) { return self.$lis.index(n); } )
-                )).sort();
-                
-                // clean up to avoid memory leaks in certain versions of IE 6
-                $(window).bind('unload', function() {
-                    self.$tabs.unbind('.tabs');
-                    self.$lis = self.$tabs = self.$panels = null;
-                });
-
-            }
-
-            // disable tabs
-            for (var i = 0, li; li = this.$lis[i]; i++)
-                $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass(o.selectedClass) ? 'addClass' : 'removeClass'](o.disabledClass);
-
-            // reset cache if switching from cached to not cached
-            if (o.cache === false)
-                this.$tabs.removeData('cache.tabs');
-            
-            // set up animations
-            var hideFx, showFx, baseFx = { 'min-width': 0, duration: 1 }, baseDuration = 'normal';
-            if (o.fx && o.fx.constructor == Array)
-                hideFx = o.fx[0] || baseFx, showFx = o.fx[1] || baseFx;
-            else
-                hideFx = showFx = o.fx || baseFx;
-
-            // reset some styles to maintain print style sheets etc.
-            var resetCSS = { display: '', overflow: '', height: '' };
-            if (!$.browser.msie) // not in IE to prevent ClearType font issue
-                resetCSS.opacity = '';
-
-            // Hide a tab, animation prevents browser scrolling to fragment,
-            // $show is optional.
-            function hideTab(clicked, $hide, $show) {
-                $hide.animate(hideFx, hideFx.duration || baseDuration, function() { //
-                    $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
-                    if ($.browser.msie && hideFx.opacity)
-                        $hide[0].style.filter = '';
-                    if ($show)
-                        showTab(clicked, $show, $hide);
-                });
-            }
-
-            // Show a tab, animation prevents browser scrolling to fragment,
-            // $hide is optional.
-            function showTab(clicked, $show, $hide) {
-                if (showFx === baseFx)
-                    $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels
-                $show.animate(showFx, showFx.duration || baseDuration, function() {
-                    $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
-                    if ($.browser.msie && showFx.opacity)
-                        $show[0].style.filter = '';
-
-                    // callback
-                    $(self.element).triggerHandler('tabsshow', [self.ui(clicked, $show[0])], o.show);
-
-                });
-            }
-
-            // switch a tab
-            function switchTab(clicked, $li, $hide, $show) {
-                /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
-                    $.ajaxHistory.update(clicked.hash);
-                }*/
-                $li.addClass(o.selectedClass)
-                    .siblings().removeClass(o.selectedClass);
-                hideTab(clicked, $hide, $show);
-            }
-
-            // attach tab event handler, unbind to avoid duplicates from former tabifying...
-            this.$tabs.unbind('.tabs').bind(o.event, function() {
-
-                //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
-                var $li = $(this).parents('li:eq(0)'),
-                    $hide = self.$panels.filter(':visible'),
-                    $show = $(this.hash);
-
-                // If tab is already selected and not unselectable or tab disabled or 
-                // or is already loading or click callback returns false stop here.
-                // Check if click handler returns false last so that it is not executed
-                // for a disabled or loading tab!
-                if (($li.hasClass(o.selectedClass) && !o.unselect)
-                    || $li.hasClass(o.disabledClass) 
-                    || $(this).hasClass(o.loadingClass)
-                    || $(self.element).triggerHandler('tabsselect', [self.ui(this, $show[0])], o.select) === false
-                    ) {
-                    this.blur();
-                    return false;
-                }
-
-                self.options.selected = self.$tabs.index(this);
-
-                // if tab may be closed
-                if (o.unselect) {
-                    if ($li.hasClass(o.selectedClass)) {
-                        self.options.selected = null;
-                        $li.removeClass(o.selectedClass);
-                        self.$panels.stop();
-                        hideTab(this, $hide);
-                        this.blur();
-                        return false;
-                    } else if (!$hide.length) {
-                        self.$panels.stop();
-                        var a = this;
-                        self.load(self.$tabs.index(this), function() {
-                            $li.addClass(o.selectedClass).addClass(o.unselectClass);
-                            showTab(a, $show);
-                        });
-                        this.blur();
-                        return false;
-                    }
-                }
-
-                if (o.cookie)
-                    $.cookie('ui-tabs' + $.data(self.element), self.options.selected, o.cookie);
-
-                // stop possibly running animations
-                self.$panels.stop();
-
-                // show new tab
-                if ($show.length) {
-
-                    // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
-                    /*if ($.browser.msie && o.bookmarkable) {
-                        var showId = this.hash.replace('#', '');
-                        $show.attr('id', '');
-                        setTimeout(function() {
-                            $show.attr('id', showId); // restore id
-                        }, 0);
-                    }*/
-
-                    var a = this;
-                    self.load(self.$tabs.index(this), $hide.length ? 
-                        function() {
-                            switchTab(a, $li, $hide, $show);
-                        } :
-                        function() {
-                            $li.addClass(o.selectedClass);
-                            showTab(a, $show);
-                        }
-                    );
-
-                    // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
-                    /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
-                    var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
-                    setTimeout(function() {
-                        scrollTo(scrollX, scrollY);
-                    }, 0);*/
-
-                } else
-                    throw 'jQuery UI Tabs: Mismatching fragment identifier.';
-
-                // Prevent IE from keeping other link focussed when using the back button
-                // and remove dotted border from clicked link. This is controlled in modern
-                // browsers via CSS, also blur removes focus from address bar in Firefox
-                // which can become a usability and annoying problem with tabsRotate.
-                if ($.browser.msie)
-                    this.blur();
-
-                //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE
-                return false;
-
-            });
-
-            // disable click if event is configured to something else
-            if (!(/^click/).test(o.event))
-                this.$tabs.bind('click.tabs', function() { return false; });
-
-        },
-        add: function(url, label, index) {
-            if (index == undefined) 
-                index = this.$tabs.length; // append by default
-
-            var o = this.options;
-            var $li = $(o.tabTemplate.replace(/#\{href\}/, url).replace(/#\{label\}/, label));
-            $li.data('destroy.tabs', true);
-
-            var id = url.indexOf('#') == 0 ? url.replace('#', '') : this.tabId( $('a:first-child', $li)[0] );
-
-            // try to find an existing element before creating a new one
-            var $panel = $('#' + id);
-            if (!$panel.length) {
-                $panel = $(o.panelTemplate).attr('id', id)
-                    .addClass(o.panelClass).addClass(o.hideClass);
-                $panel.data('destroy.tabs', true);
-            }
-            if (index >= this.$lis.length) {
-                $li.appendTo(this.element);
-                $panel.appendTo(this.element.parentNode);
-            } else {
-                $li.insertBefore(this.$lis[index]);
-                $panel.insertBefore(this.$panels[index]);
-            }
-            
-            o.disabled = $.map(o.disabled,
-                function(n, i) { return n >= index ? ++n : n });
-                
-            this.tabify();
-
-            if (this.$tabs.length == 1) {
-                 $li.addClass(o.selectedClass);
-                 $panel.removeClass(o.hideClass);
-                 var href = $.data(this.$tabs[0], 'load.tabs');
-                 if (href)
-                     this.load(index, href);
-            }
-
-            // callback
-            $(this.element).triggerHandler('tabsadd',
-                [this.ui(this.$tabs[index], this.$panels[index])], o.add
-            );
-        },
-        remove: function(index) {
-            var o = this.options, $li = this.$lis.eq(index).remove(),
-                $panel = this.$panels.eq(index).remove();
-
-            // If selected tab was removed focus tab to the right or
-            // in case the last tab was removed the tab to the left.
-            if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1)
-                this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));
-
-            o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
-                function(n, i) { return n >= index ? --n : n });
-
-            this.tabify();
-
-            // callback
-            $(this.element).triggerHandler('tabsremove',
-                [this.ui($li.find('a')[0], $panel[0])], o.remove
-            );
-        },
-        enable: function(index) {
-            var o = this.options;
-            if ($.inArray(index, o.disabled) == -1)
-                return;
-                
-            var $li = this.$lis.eq(index).removeClass(o.disabledClass);
-            if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2...
-                $li.css('display', 'inline-block');
-                setTimeout(function() {
-                    $li.css('display', 'block');
-                }, 0);
-            }
-
-            o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
-
-            // callback
-            $(this.element).triggerHandler('tabsenable',
-                [this.ui(this.$tabs[index], this.$panels[index])], o.enable
-            );
-
-        },
-        disable: function(index) {
-            var self = this, o = this.options;
-            if (index != o.selected) { // cannot disable already selected tab
-                this.$lis.eq(index).addClass(o.disabledClass);
-
-                o.disabled.push(index);
-                o.disabled.sort();
-
-                // callback
-                $(this.element).triggerHandler('tabsdisable',
-                    [this.ui(this.$tabs[index], this.$panels[index])], o.disable
-                );
-            }
-        },
-        select: function(index) {
-            if (typeof index == 'string')
-                index = this.$tabs.index( this.$tabs.filter('[href$=' + index + ']')[0] );
-            this.$tabs.eq(index).trigger(this.options.event);
-        },
-        load: function(index, callback) { // callback is for internal usage only
-            
-            var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
-                    bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
-
-            callback = callback || function() {};
-            
-            // no remote or from cache - just finish with callback
-            if (!url || ($.data(a, 'cache.tabs') && !bypassCache)) {
-                callback();
-                return;
-            }
-
-            // load remote from here on
-            if (o.spinner) {
-                var $span = $('span', a);
-                $span.data('label.tabs', $span.html()).html('<em>' + o.spinner + '</em>');
-            }
-            var finish = function() {
-                self.$tabs.filter('.' + o.loadingClass).each(function() {
-                    $(this).removeClass(o.loadingClass);
-                    if (o.spinner) {
-                        var $span = $('span', this);
-                        $span.html($span.data('label.tabs')).removeData('label.tabs');
-                    }
-                });
-                self.xhr = null;
-            };
-            var ajaxOptions = $.extend({}, o.ajaxOptions, {
-                url: url,
-                success: function(r, s) {
-                    $(a.hash).html(r);
-                    finish();
-                    
-                    // This callback is required because the switch has to take
-                    // place after loading has completed.
-                    callback();
-
-                    if (o.cache)
-                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
-
-                    // callback
-                    $(self.element).triggerHandler('tabsload',
-                        [self.ui(self.$tabs[index], self.$panels[index])], o.load
-                    );
-
-                    o.ajaxOptions.success && o.ajaxOptions.success(r, s);
-                }
-            });
-            if (this.xhr) {
-                // terminate pending requests from other tabs and restore tab label
-                this.xhr.abort();
-                finish();
-            }
-            $a.addClass(o.loadingClass);
-            setTimeout(function() { // timeout is again required in IE, "wait" for id being restored
-                self.xhr = $.ajax(ajaxOptions);
-            }, 0);
-
-        },
-        url: function(index, url) {
-            this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
-        },
-        destroy: function() {
-            var o = this.options;
-            $(this.element).unbind('.tabs')
-                .removeClass(o.navClass).removeData('tabs');
-            this.$tabs.each(function() {
-                var href = $.data(this, 'href.tabs');
-                if (href)
-                    this.href = href;
-                var $this = $(this).unbind('.tabs');
-                $.each(['href', 'load', 'cache'], function(i, prefix) {
-                      $this.removeData(prefix + '.tabs');
-                });
-            });
-            this.$lis.add(this.$panels).each(function() {
-                if ($.data(this, 'destroy.tabs'))
-                    $(this).remove();
-                else
-                    $(this).removeClass([o.selectedClass, o.unselectClass,
-                        o.disabledClass, o.panelClass, o.hideClass].join(' '));
-            });
-        }
-    });
-
-/*
- * Tabs Extensions
- */
-
-    /*
-     * Rotate
-     */
-    $.extend($.ui.tabs.prototype, {
-        rotation: null,
-        rotate: function(ms, continuing) {
-            
-            continuing = continuing || false;
-            
-            var self = this, t = this.options.selected;
-            
-            function start() {
-                self.rotation = setInterval(function() {
-                    t = ++t < self.$tabs.length ? t : 0;
-                    self.select(t);
-                }, ms);    
-            }
-            
-            function stop(e) {
-                if (!e || e.clientX) { // only in case of a true click
-                    clearInterval(self.rotation);
-                }
-            }
-            
-            // start interval
-            if (ms) {
-                start();
-                if (!continuing)
-                    this.$tabs.bind(this.options.event, stop);
-                else
-                    this.$tabs.bind(this.options.event, function() {
-                        stop();
-                        t = self.options.selected;
-                        start();
-                    });
-            }
-            // stop interval
-            else {
-                stop();
-                this.$tabs.unbind(this.options.event, stop);
-            }
-        }
-    });
-
-})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.css b/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.css
deleted file mode 100644
index 21a046d..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.css
+++ /dev/null
@@ -1,9 +0,0 @@
-.widgetbrowser iframe {
-    width: 100%;
-    border: 0;
-}
-div.small iframe { height: 50px; }
-div.medium iframe { height: 150px; }
-div.large iframe { height: 300px; }
-div.x-large iframe { height: 500px; }
-
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.js b/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.js
deleted file mode 100644
index c0b78e6..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.js
+++ /dev/null
@@ -1,13 +0,0 @@
-jQuery(function() {
-    jQuery('.widgetbrowser > ul').tabs({
-        selected: null,
-        unselect: true,
-        select: function (ui) {
-            var url = jQuery.data(ui.tab, 'load.iframe_src');
-            var iframe = jQuery('iframe', ui.panel);
-            if (url && !iframe.attr('src')) {
-                iframe.attr('src', url);
-            }
-        }
-    })
-});
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/__init__.py b/moksha/apps/widgetbrowser/widgetbrowser/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/home.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/home.html
deleted file mode 100644
index 012ce08..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/templates/home.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<?python
-from widgetbrowser import widgets
-?>
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-    <style>
-        .ui-tabs-panel {
-            border-bottom: solid 1px #94ada7;
-            padding-left: 1.5em;
-        }
-        .ui-tabs-panel iframe {
-            width: 100%;
-            border: 0;
-            min-height: 500px;
-        }
-        #home {
-            min-height: 450px;
-        }
-    </style>
-  </head>
-  <body class="flora">
-    <div id="main">
-        <ul>
-            <li><a href="#home"><span>Home</span></a></li>
-            <li><a href="#terminal" class="use_iframe"><span>Terminal</span></a></li>
-            <li><a href="${url('/widgets/')}" class="use_iframe"><span>Widgets</span></a></li>
-        </ul>
-        <div id="home">
-            <h1>Welcome to Toscawidgets' Browser</h1>
-            <p>
-            </p>
-        </div>
-        <div id="terminal">
-            ${widgets.repl(prefix=url('_repl/'))}
-        </div>
-    </div>
-    <div id="footer">
-    <p>&copy; 2008. Alberto Valverde González</p>
-    </div>
-    <script type="text/javascript">
-        //<![CDATA[
-        jQuery(function () {
-            jQuery('#main > ul').tabs({
-                select: function (ui) {
-                    var url = jQuery.data(ui.tab, 'load.iframe_src');
-                    var iframe = jQuery('iframe', ui.panel);
-                    if (url && !iframe.attr('src')) {
-                        iframe.attr('src', url);
-                    }
-                }
-            });
-        });
-        //]]>
-    </script>
-  </body>
-</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/list_widgets.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/list_widgets.html
deleted file mode 100644
index 2ef5dfe..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/templates/list_widgets.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser: Installed widgets</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body id="widgets">
-    <ul>
-        <li py:for="path, url in widgets">
-            <a href="$url">$path</a>
-        </li>
-    </ul>
-  </body>
-</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/show_widget.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/show_widget.html
deleted file mode 100644
index b75e063..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/templates/show_widget.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser: ${widget_name}</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body id="widget_browser">
-    <form py:if="interactive" method="GET">
-      <label for="display_args">Display arguments:</label>
-      <input id="display_args" name="_disp" type="text" size="50" value="${_disp}" />
-      <input type="submit" value="Display" />
-    </form>
-    <div py:replace="widget_output" />
-  </body>
-</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/validation_result.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/validation_result.html
deleted file mode 100644
index e43da7b..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/templates/validation_result.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser: ${widget_name}</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body id="widget_browser">
-    <h1 class="title">Validated data:</h1>
-    ${Markup(value)}
-    <a href="">Back</a>
-  </body>
-</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html
deleted file mode 100644
index 7edb374..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<div xmlns:py="http://genshi.edgewall.org/"
-     class="widgetbrowser ${size}">
-  <ul>
-    <li py:for="text, url in tabs">
-      <a href="${url}" class="${text == 'Demo' and 'use_iframe' or None}">
-        <span>${text}</span>
-      </a>
-    </li>
-  </ul>
-</div>
-
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_index.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_index.html
deleted file mode 100644
index 4759c25..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <?python
-      from widgetbrowser.widgets import WidgetBrowserTabs
-      from widgetbrowser.util import widget_path
-      browser = WidgetBrowserTabs(size='x-large')
-  ?>
-  <head>
-    <title>WidgetBrowser: ${widget_path(widget)}</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body>
-    <h1>${widget_path(widget)}</h1>
-    <p><a href="javascript:history.back()">Back</a></p>
-    ${browser(widget)}
-  </body>
-</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_parameters.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_parameters.html
deleted file mode 100644
index c95c195..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_parameters.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<div xmlns:py="http://genshi.edgewall.org/" class="widget_params">
-  <div py:if="parameters.local" class="widget_params local_params">
-    <h3>This widget's</h3>
-    <dl>
-        <py:for each="k in sorted(parameters.local)">
-            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
-            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
-        </py:for>
-    </dl>
-  </div>
-  <div py:if="parameters.inherited" class="widget_param inherited_params">
-    <h3>Inherited</h3>
-    <dl>
-        <py:for each="k in sorted(parameters.inherited)">
-            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
-            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
-        </py:for>
-    </dl>
-  </div>
-</div>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/__init__.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.html b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.html
deleted file mode 100644
index 7c9c42c..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.html
+++ /dev/null
@@ -1 +0,0 @@
-Dummy template $value
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak
deleted file mode 100644
index 1774ce6..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak
+++ /dev/null
@@ -1 +0,0 @@
-Dummy template $value mako version
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_template.html b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_template.html
deleted file mode 100644
index 7c9c42c..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_template.html
+++ /dev/null
@@ -1 +0,0 @@
-Dummy template $value
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/test_app.txt b/moksha/apps/widgetbrowser/widgetbrowser/tests/test_app.txt
deleted file mode 100644
index bacbc39..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/test_app.txt
+++ /dev/null
@@ -1,50 +0,0 @@
->>> from widgetbrowser import WidgetBrowser
->>> from webtest import TestApp
-
->>> app = TestApp(WidgetBrowser())
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo')
->>> assert 'default' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/')
->>> assert 'Demo' in r
-
->>> r = app.get('/os.open/demo', status=404)
-
-Test that code isn't executed if not allowed
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo?_disp="foo"')
->>> assert 'default' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/template')
->>> assert '$value' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/source')
->>> assert 'class' in r
->>> assert 'TestWidget' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/parameters')
->>> assert 'Inherited' in r
-
-Test posting:
-
->>> r = app.post('/widgetbrowser.tests.widgets.TestWidget/demo', {'some_key':'foo'})
->>> assert 'some_key' in r
-
-# the following is just to test the failed validation code-path
->>> r = app.post('/widgetbrowser.tests.widgets.TestWidget/demo', {'break':'y'})
->>> assert 'some_key' not in r
-
-Test unimplemented methods:
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/foobarize', status=501)
-
-Test custom controller
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/test')
->>> assert 'Testing TestWidget' in r
-
-Now with code execution
-
->>> app = TestApp(WidgetBrowser(interactive=True))
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo?_disp="foo"')
->>> assert 'foo' in r
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py
deleted file mode 100644
index fc2d10a..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import os
-import shutil
-from unittest import TestCase
-from pkg_resources import resource_filename
-import sphinx
-
-doc_dir = resource_filename('widgetbrowser.tests', 'testdocs')
-
-class TestSphinxExt(TestCase):
-    def setUp(self):
-        self.dest_dir = os.tempnam()
-        if not os.path.isdir(self.dest_dir):
-            os.makedirs(self.dest_dir)
-
-    def tearDown(self):
-        try:
-            shutil.rmtree(self.dest_dir)
-        except OSError:
-            pass
-
-    def test_generate(self):
-        out = sphinx.main(['sphinx-build', doc_dir, self.dest_dir])
-        self.failUnless(not out, out)
-        html = open(os.path.join(self.dest_dir, 'index.html')).read()
-        self.failUnless('widgetbrowser' in html)
-        self.failUnless('x-large' in html)
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/conf.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/conf.py
deleted file mode 100644
index 4bd428a..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/conf.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# TestDocs documentation build configuration file, created by
-# sphinx-quickstart on Fri May  9 09:56:10 2008.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# The contents of this file are pickled, so don't put values in the namespace
-# that aren't pickleable (module imports are okay, they're removed automatically).
-#
-# All configuration values have a default value; values that are commented out
-# serve to show the default value.
-
-import sys, os
-
-# If your extensions are in another directory, add it here. If the directory
-# is relative to the documentation root, use os.path.abspath to make it
-# absolute, like shown here.
-#sys.path.append(os.path.abspath('some/directory'))
-
-# General configuration
-# ---------------------
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['widgetbrowser.sphinx_ext']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = []
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General substitutions.
-project = 'TestDocs'
-copyright = '2008, Alberto'
-
-# The default replacements for |version| and |release|, also used in various
-# other places throughout the built documents.
-#
-# The short X.Y version.
-version = '0.1'
-# The full version, including alpha/beta/rc tags.
-release = '0.1'
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%B %d, %Y'
-
-# List of documents that shouldn't be included in the build.
-#unused_docs = []
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-
-# Options for HTML output
-# -----------------------
-
-# The style sheet to use for HTML and HTML Help pages. A file of that name
-# must exist either in Sphinx' static/ path, or in one of the custom paths
-# given in html_static_path.
-html_style = 'default.css'
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# The name of an image file (within the static path) to place at the top of
-# the sidebar.
-#html_logo = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_use_modindex = True
-
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.
-#html_use_opensearch = False
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'TestDocsdoc'
-
-
-# Options for LaTeX output
-# ------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, document class [howto/manual]).
-latex_documents = [
-  ('index', 'TestDocs.tex', 'TestDocs Documentation', 'Alberto', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_use_modindex = True
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/index.rst b/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/index.rst
deleted file mode 100644
index 6f70ced..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/index.rst
+++ /dev/null
@@ -1,12 +0,0 @@
-.. TestDocs documentation master file, created by sphinx-quickstart on Fri May  9 09:56:10 2008.
-   You can adapt this file completely to your liking, but it should at least
-   contain the root `toctree` directive.
-
-Testing the `widgetbroser` directive
-====================================
-
-Test an existing widget
------------------------
-.. widgetbrowser:: widgetbrowser.tests.widgets.TestWidget
-   :tabs: source, demo, parameters, template
-   :size: x-large
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/widgets.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/widgets.py
deleted file mode 100644
index 149139d..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/tests/widgets.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from tw.api import Widget
-from widgetbrowser import WidgetBrowser
-from formencode.api import Invalid
-
-class TestWidget(Widget):
-    template = "$value"
-    default = "default"
-
-    def validate(self, value, *args, **kw):
-        if 'break' in value.keys():
-            raise Invalid("Validation failed", value, None)
-        return value
-
- at WidgetBrowser.register_controller(TestWidget, 'test')
-def test_controller(request, response):
-    response.headers['Content-Type'] = 'text/plain'
-    return "Testing " + request.widget.__class__.__name__
-
-class TestWidgetExternalTemplate(Widget):
-    template = "toscawidgets:widgetbrowser.tests.dummy_template"
-    default = "default"
-
-class TestWidgetMultipleExternalTemplate(Widget):
-    template = "toscawidgets:widgetbrowser.tests.dummy_m_template"
-    default = "default"
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/util.py b/moksha/apps/widgetbrowser/widgetbrowser/util.py
deleted file mode 100644
index 648cd8c..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/util.py
+++ /dev/null
@@ -1,242 +0,0 @@
-import logging
-import os
-import errno
-import sys
-import pprint
-
-from pkg_resources import EntryPoint, iter_entry_points, resource_string
-
-import tw
-from tw.api import Widget, WidgetType
-from tw.core import view
-
-log = logging.getLogger(__name__)
-
-def import_widget(path):
-    """Import a widget given a dotted or entry point notation path.
-
-    Can import both widget instances or classes.
-
-       >>> import_widget('tw.core.base.Widget')
-       <class 'tw.core.base.Widget'>
-       >>> import_widget('tw.core.base:Widget')
-       <class 'tw.core.base.Widget'>
-       >>> import_widget('os.popen')
-
-    """
-    if ':' not in path:
-        parts = path.split('.')
-        path = '.'.join(parts[:-1]) + ':' + parts[-1]
-    widget = EntryPoint.parse("x="+path).load(False)
-    if not isinstance(widget, (WidgetType, Widget)):
-        widget = None
-    return widget
-
-
-def widget_path(widget):
-    """Returns the path of a widget instance or subclass
-
-    >>> from tw.api import Widget
-    >>> widget_path(Widget)
-    'tw.core.base.Widget'
-    >>> widget_path(Widget())
-    'tw.core.base.Widget'
-    """
-    if not isinstance(widget, (WidgetType, Widget)):
-        raise TypeError("Only widgets are allowed")
-    if isinstance(widget, Widget):
-        widget = widget.__class__
-    return '.'.join([widget.__module__, widget.__name__])
-
-def format_code(code, format='python'):
-    """Formats a chunk of code as html. If pygments is installed it will
-    pygmentize it.
-    
-    >>> code = "from __future__ import teletransportation"
-    >>> '<pre' in format_code(code)
-    True
-    """
-    try:
-        from pygments import highlight, formatters, lexers
-    except ImportError:
-        log.info("Pygments is not available to colorize")
-        return '<pre>' + code + '</pre>'
-    lexer = lexers.get_lexer_by_name(format)
-    formatter = formatters.get_formatter_by_name('html')
-    return highlight(code, lexer, formatter)
-
-#TODO: Memoize this function
-def widget_template(widget, extension='.html'):
-    """Returns the template of a widget as a string.
-
-    Loads external templates if needed.
-
-    >>> from widgetbrowser.tests.widgets import *
-    >>> widget_template(TestWidgetExternalTemplate())
-    'Dummy template $value\\n'
-
-    If more than one is available, it will use the extension to disambiguate.
-
-    >>> from widgetbrowser.tests.widgets import TestWidgetExternalTemplate
-    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.html')
-    'Dummy template $value\\n'
-    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.mak')
-    'Dummy template $value mako version\\n'
-    """
-    template = widget.template
-    if template and not view._is_inline_template(template):
-        # Template seems to refer to a file, look it up
-        parts = template.split('.')
-        possible_extensions = set(".html .mak .mako".split())
-        possible_extensions.remove(extension)
-        possible_extensions = [extension] + list(possible_extensions)
-        for ext in possible_extensions:
-            try:
-                return resource_string('.'.join(parts[:-1]), parts[-1]+ext)
-            except IOError, e:
-                if e.errno not in (0, errno.ENOENT):
-                    raise
-        return None
-    return template
-
-def pretty_print(obj):
-    """Pretty prints an object returning pygmentized code if possible."""
-    return format_code(pprint.pformat(obj), 'python')
-
-def display_widget(widget, argstr='', ctx=None):
-    """Displays a widget with optional arguments as a string.
-    
-
-    .. warning:: IT IS VERY UNSAFE TO EXECUTE UNTRUSTED CODE
-
-    Example::
-
-        >>> from tw.api import Widget
-        >>> class TestWidget(Widget):
-        ...     params = ['param']
-        ...     template = "$value-$param"
-        >>> display_widget(TestWidget())
-        u'None-None'
-        >>> display_widget(TestWidget(), '"hello", param=2')
-        u'hello-2'
-    """
-    ctx = ctx or {}
-    ctx['_w'] = widget
-    code = "_o = _w(%s)" % argstr
-    exec code in ctx
-    return ctx['_o']
-
-def widget_url(widget, action='', prefix=None):
-    """Returns the URL of the controller to perform `action` on `widget`.
-
-    If no `prefix` is passed the it will be tried to be fetched from
-    `tw.framework.request_local` where the :class:`WidgetBrowser` leaves it
-    on every request.
-
-    Example::
-
-        >>> from tw.core.base import Widget
-        >>> widget_url(Widget)
-        '/tw.core.base.Widget/'
-        >>> widget_url(Widget())
-        '/tw.core.base.Widget/'
-
-    You can also pass the `path` of the widget::
-
-        >>> widget_url('tw.api.Widget')
-        '/tw.api.Widget/'
-        >>> widget_url('tw.api.Widget', 'show')
-        '/tw.api.Widget/show'
-        >>> widget_url('tw.api.Widget', 'show', prefix='/widget')
-        '/widget/tw.api.Widget/show'
-
-    .. note::
-
-        You can pass any path the widget can be imported from when passing a
-        string but if you pass a widget instance or subclass then the real
-        module where it is defined will be generated.
-    """
-    if isinstance(widget, (Widget, WidgetType)):
-        widgeturi = widget_path(widget)
-    else:
-        widgeturi = widget
-        if import_widget(widgeturi) is None:
-            return
-    if prefix is None:
-        prefix = getattr(tw.framework.request_local, 'browser_prefix', '')
-    return '/'.join([prefix.rstrip('/'), widgeturi, action])
-
-def all_widgets():
-    """Iterates over all the Widget subclasses in the modules
-    that are declared as `toscawidgets.widgets` entrypoints
-
-    >>> len(list(all_widgets())) > 0
-    True
-    """
-    seen = set()
-    for ep in iter_entry_points('toscawidgets.widgets'):
-        try:
-            mod = ep.load(False)
-        except ImportError, e:
-            log.error("Could not load %r: %s", ep, e)
-            continue
-        for name in dir(mod):
-            obj = getattr(mod, name)
-            if isinstance(obj, WidgetType) and obj not in seen:
-                seen.add(obj)
-                yield obj
-
-class WidgetParameters(object):
-    """Wraps a widget and provides information on it's parameters.
-
-    Example::
-
-        >>> from tw.core.base import Widget
-        >>> params = WidgetParameters(Widget)
-        >>> len(params.all) > 0
-        True
-        >>> params.all - params.local == params.inherited
-        True
-    """
-    def __init__(self, widget):
-        if isinstance(widget, Widget):
-            widget = widget.__class__
-        self.widget = widget
-        self.all = widget.params
-        self.inherited = set()
-        for b in self.widget.__mro__:
-            if b is self.widget:
-                continue
-            self.inherited.update(getattr(b, 'params', set()))
-        self.local = self.all - self.inherited
-
-    def get_default(self, name, default=None):
-        """Returns a string representation of a parameter default value.
-
-        Example::
-
-            >>> from tw.core.base import Widget
-            >>> params = WidgetParameters(Widget)
-            >>> type(params.get_default('id'))
-            <type 'str'>
-        """
-        return repr(getattr(self.widget, name, default))
-
-    def get_doc(self, name, default='Undocumented'):
-        """Returns parameters's doc. If it is not documented it will return
-        ``default``
-
-        Example::
-
-            >>> from tw.core.base import Widget
-            >>> params = WidgetParameters(Widget)
-            >>> type(params.get_doc('id'))
-            <type 'str'>
-        """
-        return getattr(self.widget, name + '__doc', default)
-        
-def build_docs(src, dst):
-    import sphinx
-    if not os.path.exists(dst):
-        os.mkdir(dst)
-    return sphinx.main(['sphinx-build', src, dst])
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/widgets.py b/moksha/apps/widgetbrowser/widgetbrowser/widgets.py
deleted file mode 100644
index b40fdea..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/widgets.py
+++ /dev/null
@@ -1,71 +0,0 @@
-from tw.api import Widget, JSLink, CSSLink, js_function
-from widgetbrowser import util
-import string
-
-__all__ = ['WidgetBrowserTabs']
-
-mod = 'widgetbrowser'
-flora_all_css = CSSLink(modname=mod, filename="static/themes/flora/flora.all.css")
-tabs_css = CSSLink(modname=mod, filename="static/ui.tabs.css")
-wb_css = CSSLink(modname=mod, filename="static/widgetbrowser.css")
-pygments_css = CSSLink(modname=mod, filename="static/pygments.css")
-httprepl_css = CSSLink(modname=mod, filename="static/httprepl.css")
-jquery_js = JSLink(modname=mod, filename="static/jquery.js")
-# Do not pull jquery as an automatic dependency since Sphinx already includes
-# it
-ui_base_js = JSLink(modname=mod, filename="static/ui.base.js",
-                    location="bodybottom")
-ui_tabs_js = JSLink(modname=mod, filename="static/ui.tabs.js",
-                    location="bodybottom",
-                    javascript=[ui_base_js])
-ui_dragabble_js = JSLink(modname=mod, filename="static/ui.draggable.js",
-                         location="bodybottom")
-ui_resizable_js = JSLink(modname=mod, filename="static/ui.resizable.js",
-                         location="bodybottom")
-ui_dialog_js = JSLink(modname=mod, filename="static/ui.dialog.js",
-                      location="bodybottom",
-                      javascript=[ui_base_js, ui_dragabble_js, ui_resizable_js])
-widgetbrowser_js = JSLink(modname=mod, filename="static/widgetbrowser.js",
-                          javascript=[ui_tabs_js],
-                          css=[tabs_css, wb_css, pygments_css],
-                          location="bodybottom")
-
-httprepl_js = JSLink(modname=mod, filename='static/httprepl.js',
-                     javascript=[ui_dialog_js],
-                     css=[httprepl_css],
-                     location="bodybottom")
-
-class WidgetBrowserTabs(Widget):
-    template = "genshi:widgetbrowser.templates.widget_browser_tabs"
-    params = ["tabs", "prefix", "size", "in_sphinx"]
-    in_sphinx = False
-    javascript = [widgetbrowser_js]
-    size = "small"
-    tabs = ['demo', 'demo_source', 'source', 'template', 'parameters']
-    prefix = None
-     
-    def update_params(self, d):
-        super(WidgetBrowserTabs, self).update_params(d)
-        d.tabs = [(string.capwords(t.replace('_', ' ')), util.widget_url(d.value, t, prefix=d.prefix))
-                  for t in d.tabs]
-        if not d.in_sphinx:
-            # Not displayed inside Sphinx, include jquery and pygments
-            jquery_js.inject()
-            pygments_css.inject()
-
-
-class WidgetRepl(Widget):
-    template = '<div id="$id" class="$css_class"></div>'
-    params = ["prefix"]
-    prefix = '/_repl/' # show nicely in the browser tabs
-    include_dynamic_js_calls = True
-    javascript = [jquery_js, httprepl_js]
-    css = [flora_all_css]
-    def update_params(self, d):
-        super(WidgetRepl, self).update_params(d)
-        assert d.id, "This widget needs an id"
-        config = dict(prefix=d.prefix)
-        call = js_function('HTTPRepl.render')('#'+d.id, config)
-        self.add_call("jQuery(function () {%s});" %  call)
-
-repl = WidgetRepl("widgetrepl")
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/wsgiapp.py b/moksha/apps/widgetbrowser/widgetbrowser/wsgiapp.py
deleted file mode 100644
index d2dbedd..0000000
--- a/moksha/apps/widgetbrowser/widgetbrowser/wsgiapp.py
+++ /dev/null
@@ -1,251 +0,0 @@
-import sys
-import weakref
-import os
-import inspect
-import logging
-from pkg_resources import resource_filename
-from genshi.core import Markup
-from genshi.template import TemplateLoader, Context
-from webob import Request, Response, exc
-import tw
-from tw.api import Widget, WidgetType, make_middleware
-from widgetbrowser import util, widgets, repl
-
-try:
-    from formencode import Invalid
-    have_formencode = True
-except ImportError:
-    have_formencode = False
-
-from moksha.lib.helpers import cache_rendered
-
-__all__ = ['WidgetBrowser']
-
-log = logging.getLogger(__name__)
-
-def asbool(v):
-    if isinstance(v, basestring):
-        return v.lower().startswith('t') or v == '1' or v == 'on'
-    elif isinstance(v, bool):
-        return v
-    return False
-
-class WidgetBrowser(object):
-    """A widget browser WSGI app.
-
-    Parameters:
-
-      * `template_dirs`: A list of directories that shall be searched for
-        temlates used by the widget browser.
-      * `interactive`: Enable code execution. This is needed to for the REPL and
-        to override display arguments via the web interface. This is a BIG
-        SECURITY HOLE, enable only in a controlled environment.
-      * `docs_dir`: A directory where sphinx sources live.
-    """
-    def __init__(self, global_conf={}, template_dirs=None, interactive=False,
-                 docs_dir=None, full_stack=True):
-        if isinstance(template_dirs, basestring):
-            template_dirs = template_dirs.split()
-        template_dirs = template_dirs or []
-        template_dirs.append(resource_filename('widgetbrowser', 'templates'))
-        self.loader = TemplateLoader(template_dirs)
-        self.interactive = asbool(interactive)
-        if self.interactive:
-            self.http_repl = repl.WidgetReplApp(globals(), weakref.proxy(self))
-            self.context = self.http_repl.repl.locals
-        else:
-            self.context = None
-            self.http_repl = exc.HTTPForbidden("Interactive mode is disabled")
-        if docs_dir:
-            from paste.cascade import Cascade
-            dest_dir = os.path.abspath(os.path.join(docs_dir, '.build'))
-            log.info('Building docs...')
-            try:
-                util.build_docs(docs_dir, dest_dir)
-            except Exception, e:
-                log.warning('Skipping building docs: %s' % str(e))
-            self.built_docs = dest_dir
-            self.app = Cascade([self.docs_app, self.app])
-        if asbool(full_stack):
-            self.app = make_middleware(self.app, {
-                'toscawidgets.framework.default_view': 'genshi',
-                }, stack_registry = True)
-        self._default_controllers = dict(demo=self.show_demo,
-                                         index=self.show_index,
-                                         template=self.show_template,
-                                         parameters=self.show_parameters,
-                                         source=self.show_source,
-                                         demo_source=self.show_demo_source)
-
-
-    def docs_app(self, environ, start_response):
-        """Registers widgetbrowser_js as resources before serving static html
-        files so it is injected into the page"""
-        from paste.urlparser import StaticURLParser
-        app = StaticURLParser(self.built_docs)
-        resources = widgets.widgetbrowser_js.retrieve_resources()
-        tw.framework.register_resources(resources)
-        return app(environ, start_response)
-
-    _widget_controllers = {}
-    @classmethod
-    def register_controller(cls, widget, action):
-        """Registers function to act as a demo controller for a widget"""
-        def _register(controller):
-            cls._widget_controllers[(widget,action)] = controller
-            return controller
-        return _register
-
-    def lookup_controller(self, widget_cls, action):
-        try:
-            return self._widget_controllers[(widget_cls, action)]
-        except KeyError:
-            return self._default_controllers[action]
-
-    def lookup_widget_action(self, path_info):
-        try:
-            widget_path, action = path_info.strip('/').split('/')
-        except ValueError:
-            widget_path, action = path_info, 'index'
-        if widget_path:
-            try:
-                widget = util.import_widget(widget_path.strip('/'))
-            except (ImportError, ValueError):
-                widget = None
-            if widget:
-                return widget, action
-        raise LookupError(path_info)
-
-    def render(self, template, ns):
-        ns.pop('self',None)
-        stream = self.loader.load(template).generate(Context(**ns))
-        return stream.render(method='xhtml', doctype='xhtml')
-
-    def __call__(self, environ, start_response):
-        return self.app(environ, start_response)
-
-    @cache_rendered
-    def app(self, environ, start_response):
-        req = Request(environ)
-        resp = Response(request=req, content_type='text/html; charset=utf-8')
-        # Leave the interactive flag in tw.framework so demo controllers can know
-        # if it is safe to enable advanced/unsecure features.
-        tw.framework.request_local.interactive = self.interactive
-        tw.framework.request_local.browser_prefix = req.script_name
-
-        # Lookup widget XXX: Yuck!
-        if req.path_info == '/':
-            controller = self.home
-        elif req.path_info.startswith('/_repl') and self.http_repl:
-            req.path_info_pop()
-            return self.http_repl(environ, start_response)
-        elif req.path_info.startswith('/widgets'):
-            controller = self.widgets
-        else:
-            try:
-                widget, action = self.lookup_widget_action(req.path_info)
-            except LookupError:
-                resp = exc.HTTPNotFound('No widget at %s' % req.path_info)
-                return resp(environ, start_response)
-                
-
-            # Lookup controller
-            try:
-                controller = self.lookup_controller(widget, action)
-            except LookupError:
-                resp = exc.HTTPNotImplemented()
-                return resp(environ, start_response)
-                
-            # If it's a widget class instantiate it with no arguments 
-            if isinstance(widget, WidgetType):
-                widget = widget('test_widget')
-            req.widget = widget
-
-        # Call controller and handle output 
-        output = controller(req, resp)
-        if isinstance(output, str):
-            resp.body = output
-        elif isinstance(output, unicode):
-            resp.body = output.encode('utf-8')
-        elif output:
-            resp = output
-
-        return resp(environ, start_response)
-
-
-    def show_template(self, req, resp):
-        widget = req.widget
-        if getattr(widget, 'demo_for', None):
-            widget = req.widget.demo_for()
-        template = util.widget_template(widget)
-        if template:
-            return util.format_code(template, 'html')
-        else:
-            resp.content_type = "text/plain"
-            return widget.__class__.__name__ + ' has no template.'
-
-    def show_source(self, req, resp):
-        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
-        source = inspect.getsource(cls)
-        return util.format_code(source, 'python')
-
-    def show_demo_source(self, req, resp):
-        widget = req.widget
-        source = inspect.getsource(widget.__class__)
-        return util.format_code(source, 'python')
-
-    def show_parameters(self, req, resp):
-        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
-        parameters = util.WidgetParameters(cls)
-        return self.render('widget_parameters.html', locals())
-
-
-    def show_index(self, req, resp):
-        widget = req.widget
-        return self.render('widget_index.html', locals())
-
-    @cache_rendered
-    def show_demo(self, req, resp):
-        widget = req.widget
-        widget_name = widget.__class__.__name__
-        interactive = self.interactive
-        if have_formencode and req.method.upper() == "POST":
-            # A widget submission, try to validate.
-            try:
-                value = widget.validate(req.POST)
-                value = util.pretty_print(value)
-                return self.render('validation_result.html', locals())
-            except Invalid, error:
-                pass
-
-        if self.interactive:
-            _disp = req.GET.get('_disp', '')
-        else:
-            _disp = ''
-
-        widget_output = util.display_widget(widget, _disp, self.context)
-
-        # Wrap non-genshi things, like Mako based widgets, in a Genshi Markup object
-        if not callable(widget_output):
-            widget_output = Markup(widget_output)
-
-        # Inject moksha's global resources so we can get things like
-        # Orbited/Stomp/jQuery/etc.
-        from moksha.api.widgets.global_resources import global_resources
-        global_resources.register_resources()
-
-        return self.render('show_widget.html', locals())
-
-    def widgets(self, req, resp):
-        widgets = [(util.widget_path(w), util.widget_url(w))
-                       for w in util.all_widgets()]
-        widgets.sort()
-        return self.render('list_widgets.html', locals())
-
-    def home(self, req, resp):
-        widgets.jquery_js.inject()
-        widgets.tabs_css.inject()
-        widgets.ui_tabs_js.inject()
-        def url(s):
-            return req.script_name + s
-        return self.render('home.html', locals())


commit 650efbf03d33596f5f52093c52a95834f4a9e2df
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:39:32 2009 -0400

    More widgetbrowser app renaming & cleanups

diff --git a/moksha/apps/menus/MANIFEST b/moksha/apps/menus/MANIFEST
deleted file mode 100644
index 5121d7c..0000000
--- a/moksha/apps/menus/MANIFEST
+++ /dev/null
@@ -1 +0,0 @@
-recursive-include moksha *.mak *.html *.js *.png *.gif *.css *.jpg *.jpeg
diff --git a/moksha/apps/menus/MANIFEST.in b/moksha/apps/menus/MANIFEST.in
new file mode 100644
index 0000000..5121d7c
--- /dev/null
+++ b/moksha/apps/menus/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include moksha *.mak *.html *.js *.png *.gif *.css *.jpg *.jpeg
diff --git a/moksha/apps/widgetbrowser/paster.ini b/moksha/apps/widgetbrowser/paster.ini
new file mode 100644
index 0000000..c1b4d92
--- /dev/null
+++ b/moksha/apps/widgetbrowser/paster.ini
@@ -0,0 +1,21 @@
+#
+# Sample PasteDeploy ini file to launch the WidgetBrowser.
+# 
+# This is most useful while developing and debugging widgets since paster can autoreload the WidgetBrowser
+# whenever any imported module's source is modified. To enable reloading do:
+#
+#   $ paster serve --reload paster.ini
+#
+# The %(here)s variable will be replaced with the parent directory of this file
+#
+
+[server:main]
+use = egg:Paste#http
+# Bind only to the loopback interface since we're starting in intercative mode.
+host = 127.0.0.1
+port = 8000
+
+[app:main]
+use = egg:WidgetBrowser
+# Enable interactive mode so WebError (needs to be easy_installed first) and the Terminal are available
+interactive = true
diff --git a/moksha/apps/widgetbrowser/setup.cfg b/moksha/apps/widgetbrowser/setup.cfg
new file mode 100644
index 0000000..e00908b
--- /dev/null
+++ b/moksha/apps/widgetbrowser/setup.cfg
@@ -0,0 +1,14 @@
+[aliases]
+release = egg_info -RDb "" sdist bdist_egg register upload
+test = nosetests
+cover = nosetests --with-coverage
+
+#[egg_info]
+#tag_build = dev
+#tag_date = true
+
+[nosetests]
+with-coverage = false
+cover-package = widgetbrowser
+doctest-extension = .txt
+with-doctest = true
diff --git a/moksha/apps/widgetbrowser/setup.py b/moksha/apps/widgetbrowser/setup.py
new file mode 100644
index 0000000..967a1f9
--- /dev/null
+++ b/moksha/apps/widgetbrowser/setup.py
@@ -0,0 +1,39 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.1'
+
+setup(name='WidgetBrowser',
+      version=version,
+      description="ToscaWidgets browser",
+      long_description="""\
+""",
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords='toscawidgets',
+      author='Alberto Valverde Gonzalez',
+      author_email='alberto at toscat.net',
+      url='http://toscawidgets.org/',
+      license='MIT',
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      include_package_data=True,
+      zip_safe=True,
+      install_requires=[
+          "ToscaWidgets>=0.9.2dev-20080602",
+          "Genshi",
+          "WebOb",
+          "docutils",
+      ],
+      tests_require = ['nose', 'formencode', 'sphinx'],
+      extras_require = {
+          'full': ['Sphinx', 'Pygments', 'docutils', 'nose', 'WebTest',
+                   'WebError', 'coverage', 'FormEncode'],
+      },
+      entry_points="""
+      [console_scripts]
+      twbrowser = widgetbrowser.command:browser_command
+      [paste.app_factory]
+      main = widgetbrowser.wsgiapp:WidgetBrowser
+      [toscawidgets.widgets]
+      widgets = widgetbrowser.widgets
+      """,
+      )
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/__init__.py b/moksha/apps/widgetbrowser/widgetbrowser/__init__.py
new file mode 100644
index 0000000..c037ed3
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/__init__.py
@@ -0,0 +1,2 @@
+from wsgiapp import WidgetBrowser
+from util import widget_url
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/command.py b/moksha/apps/widgetbrowser/widgetbrowser/command.py
new file mode 100644
index 0000000..4b15fbe
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/command.py
@@ -0,0 +1,54 @@
+from wsgiref.simple_server import make_server
+from optparse import OptionParser
+
+from widgetbrowser.wsgiapp import WidgetBrowser
+
+
+_parser = OptionParser(usage = "%prog [OPTIONS] [widget_url]")
+_parser.add_option("-i", "--interactive",
+                   dest="interactive",
+                   action="store_true",
+                   default=False)
+_parser.add_option("-b", "--browser",
+                   dest="browser",
+                   action="store_true",
+                   default=False)
+_parser.add_option("-d", "--docs",
+                   dest="docs",
+                   default=None)
+_parser.add_option("-p", "--port",
+                   dest="port",
+                   default=8000)
+
+def browser_command(argv=None):
+    """Command line interface to launch the widgetbrowser"""
+    opts, args = _parser.parse_args(argv)
+
+    # Only allow passing display arguments in debug mode 
+    if args:
+        widget_url = args[0] + '/'
+    else:
+        widget_url = ''
+    app = WidgetBrowser(interactive=opts.interactive, docs_dir=opts.docs)
+    if opts.interactive:
+        try:
+            from weberror.evalexception import EvalException
+            app = EvalException(app)
+        except ImportError:
+            raise ImportError("You need to install WebError for interactive "
+                              "debugging")
+    url = "http://127.0.0.1:%s/" % opts.port
+    if opts.browser:
+        import webbrowser
+        webbrowser.open(url + widget_url)
+    server = make_server('127.0.0.1', int(opts.port), app)
+    print "Server started at " + url
+    try:
+        server.serve_forever()
+    except (KeyboardInterrupt, SystemExit):
+        pass
+
+if __name__ == '__main__':
+    import sys
+    sys.exit(browser_command(sys.argv))
+
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/repl.py b/moksha/apps/widgetbrowser/widgetbrowser/repl.py
new file mode 100644
index 0000000..5855068
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/repl.py
@@ -0,0 +1,305 @@
+"""
+Robert Brewer was the original author of the module this module has heavily
+inspired from.  http://www.aminus.net/wiki/HTTPREPL
+"""
+import warnings
+from itertools import count
+import codeop
+import inspect
+import os
+import re
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+import sys
+import traceback
+
+from webob import Request, Response, exc
+
+try:
+    from formencode import Invalid
+    have_formencode = True
+except ImportError:
+    have_formencode = False
+
+from genshi.util import LRUCache
+import tw
+from tw.api import make_middleware, Widget
+
+from widgetbrowser import util, widgets
+
+class HTTPREPL:
+    
+    def __init__(self, locals=None):
+        self.locals = {}
+        if locals:
+            self.locals.update(locals)
+        self.buffer = []
+    
+    def push(self, line):
+        """Push 'line' and return exec results (None if more input needed)."""
+        if line == "help":
+            return "Type help(object) for help about object."
+        if line == "help()":
+            return "You cannot call help() without an argument."
+        
+        self.buffer.append(line)
+        source = "\n".join(self.buffer)
+        
+        try:
+            code = codeop.compile_command(source, "<HTTP input>", 'single')
+        except (OverflowError, SyntaxError, ValueError):
+            self.buffer = []
+            return traceback.format_exc()
+        
+        if code is None:
+            # More lines needed.
+            return None
+        
+        self.buffer = []
+        return self.execute(code)
+    
+    def execute(self, code):
+        """Execute the given code in self.locals and return any stdout/sterr."""
+        out = StringIO()
+        oldout = sys.stdout
+        olderr = sys.stderr
+        sys.stdout = sys.stderr = out
+        try:
+            try:
+                exec code in self.locals
+            except:
+                result = traceback.format_exc()
+            else:
+                result = out.getvalue()
+        finally:
+            # FormEncode will break if _ is left in __builtins__ and it tries
+            # to use it as a translator
+            __builtins__.pop('_', None)
+            sys.stdout = oldout
+            sys.stderr = olderr
+        out.close()
+        return result
+    
+    def dir(self, line):
+        """Examine a partial line and provide attr list of final expr."""
+        line = re.split(r"\s", line)[-1].strip()
+        # Support lines like "thing.attr" as "thing.", because the browser
+        # may not finish calculating the partial line until after the user
+        # has clicked on a few more keys.
+        line = ".".join(line.split(".")[:-1])
+        try:
+            result = eval("dir(%s)" % line, {}, self.locals)
+        except:
+            return []
+        return result
+    
+    def doc(self, line):
+        """Examine a partial line and provide sig+doc of final expr."""
+        line = re.split(r"\s", line)[-1].strip()
+        # Support lines like "func(text" as "func(", because the browser
+        # may not finish calculating the partial line until after the user
+        # has clicked on a few more keys.
+        line = "(".join(line.split("(")[:-1])
+        try:
+            result = eval(line, {}, self.locals)
+            try:
+                if isinstance(result, type):
+                    func = result.__init__
+                else:
+                    func = result
+                args, varargs, varkw, defaults = inspect.getargspec(func)
+            except TypeError:
+                if callable(result):
+                    doc = getattr(result, "__doc__", "") or ""
+                    return "%s\n\n%s" % (line, doc)
+                return None
+        except:
+            return None
+        
+        if args and args[0] == 'self':
+            args.pop(0)
+        missing = object()
+        defaults = defaults or []
+        defaults = ([missing] * (len(args) - len(defaults))) + list(defaults)
+        arglist = []
+        for a, d in zip(args, defaults):
+            if d is missing:
+                arglist.append(a)
+            else:
+                arglist.append("%s=%s" % (a, d))
+        if varargs:
+            arglist.append("*%s" % varargs)
+        if varkw:
+            arglist.append("**%s" % varkw)
+        doc = getattr(result, "__doc__", "") or ""
+        return "%s(%s)\n%s" % (line, ", ".join(arglist), doc)
+
+
+class DeferredDisplay(object):
+    """Wraps a widget and the args passed to display/render so we can defer
+    its display to another request.
+    
+    .. note::
+        The JS code is dependent on the output of __repr__ since it parses it
+        to know a widget is being displayed so it can open an overlay.
+    """
+    _counter = count(0)
+    def __init__(self, widget, value, **kw):
+        self.id = self._counter.next()
+        self.value = value
+        self.widget = widget
+        self.kw = kw
+
+    def display(self):
+        """
+        Displays the widget as it was intended to be displayed when it was
+        wrapped.
+        """
+        return self.widget.display(self.value, **self.kw)
+
+    __call__ = display
+
+    def __repr__(self):
+        data = (self.id, self.widget.__class__)
+        return self.__class__.__name__ + repr(data)
+
+
+class WidgetReplApp(object):
+    def __init__(self, locals=None, widget_browser=None, max_dialogs=10):
+        self.repl = HTTPREPL(locals)
+        warnings.warn("\n"*2 + "*"*79 + "\n"
+                      "DISCLAIMER:\n"
+                      "Running this app poses a significant security threat "
+                      "if accessible to an \nattacker. Make sure the server is "
+                      "bound to the loopback interface or behind\na firewall "
+                      "and that there are no local untrusted users.\n" + "*"*79)
+        if widget_browser:
+            self.widget_browser = widget_browser
+            self.displayed_widgets = LRUCache(max_dialogs)
+            self.setup_tw()
+
+    def setup_tw(repl_app):
+        # Stack TW's middleware configured with dummy default_view to signal
+        # that a widget is being displayed so we can wrap and register its
+        # output.
+        conf = {'toscawidgets.framework.default_view' : 'tw_repl',
+                'toscawidgets.middleware.inject_resources' : True}
+        repl_app.app = make_middleware(repl_app.app, conf)
+        # monkey-patch display and render to hijack output
+        def wrap(f):
+            if f.func_name == 'wrapper':
+                return f
+            def wrapper(self, value=None, **kw):
+                if self.displays_on == 'tw_repl':
+                    o = DeferredDisplay(self, value, **kw)
+                    repl_app.displayed_widgets[o.id] = o
+                else:
+                    o = f(self, value, **kw)
+                return o
+            return wrapper
+        Widget.display = wrap(Widget.display)
+        Widget.render = wrap(Widget.render)
+
+    def __call__(self, environ, start_response):
+        assert not environ['wsgi.multiprocess'], "Cannot run in a multiprocess"\
+                                                 " environment"
+        return self.app(environ, start_response)
+
+    def app(self, environ, start_response):
+        """Main dispatcher. pops PATH_INFO and delegates to exposed methods."""
+        req = Request(environ.copy())
+        resp = Response(request=req, content_type='text/html; charset=UTF8')
+        first_part = req.path_info_pop() or 'index'
+        method = getattr(self, first_part, None)
+        if getattr(method, 'exposed', False):
+            output = method(req, resp)
+            if isinstance(output, unicode):
+                resp.body = output.encode('utf-8')
+            elif isinstance(output, str):
+                resp.body = output
+            elif output:
+                resp = output
+        else:
+            resp = exc.HTTPNotImplemented()
+        return resp(environ, start_response)
+        
+    def index(self, req, resp):
+        """Return an HTTP-based Read-Eval-Print-Loop terminal."""
+        # Override default_view so resources display properly
+        tw.framework.default_view = 'toscawidgets'
+        tpl = '<html><head><title>"%(title)s</title></head>' \
+              '<body class="flora">%(repl)s</body></html>'
+        prefix = req.script_name + '/'
+        return tpl % {'title': 'WidgetBrowser Terminal',
+                      'repl': widgets.repl(prefix=req.script_name + '/')}
+    index.exposed = True
+    
+    def push(self, req, resp):
+        """Push 'line' and return exec results as a bare response."""
+        line = req.params['line']
+        result = self.repl.push(line)
+        if result is None:
+            # More input lines needed.
+            resp.status_int = 204
+        return result
+    push.exposed = True
+    
+    def dir(self, req, resp):
+        """Push 'line' and return result of eval on the final expr."""
+        line = req.params['line']
+        result = self.repl.dir(line)
+        if not result:
+            resp.status_int = 204
+            return
+        return repr(result)
+    dir.exposed = True
+    
+    def doc(self, req, resp):
+        """Push 'line' and return result of getargspec on the final expr."""
+        line = req.params['line']
+        result = self.repl.doc(line)
+        if not result:
+            resp.status_int = 204
+        return result
+    doc.exposed = True
+    
+    def enrich_namespace(self, ns, request):
+        
+        _disp = request.GET.get('_disp', '')
+        
+        if not "_disp" in ns:
+            ns["_disp"]=_disp
+        if not "interactive" in ns:
+            ns["interactive"]=True
+        return ns
+    
+    def widget_output(self, req, resp):
+        try:
+            key = int(req.path_info.strip('/'))
+            dd = self.displayed_widgets[key]
+        except KeyError:
+            resp.status_int = 404
+            return "There's now widget output at this URL. Maybe it has "\
+                   "expired? Try increasing the 'max_dialogs' parameter"
+
+        widget = dd.widget
+        widget_name = widget.__class__.__name__
+        render = self.widget_browser.render
+        if have_formencode and req.method.upper() == "POST":
+            # A widget submission, try to validate.
+            try:
+                value = widget.validate(req.POST)
+                value = util.pretty_print(value)
+                return render('validation_result.html', locals())
+            except Invalid, error:
+                pass
+        # Override default_view because WidgetBrowser renders on Genshi, not
+        # 'tw_repl', this is needed so widget and resources display properly
+        tw.framework.default_view = 'genshi'
+        widget_output = dd.display()
+        return render('show_widget.html', self.enrich_namespace(locals(),request=req))
+    widget_output.exposed = True
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/sphinx_ext.py b/moksha/apps/widgetbrowser/widgetbrowser/sphinx_ext.py
new file mode 100644
index 0000000..f0c9bea
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/sphinx_ext.py
@@ -0,0 +1,43 @@
+import os
+from docutils import nodes, utils
+from docutils.parsers.rst import directives
+
+from widgetbrowser import util, widgets
+
+widget_tabs = widgets.WidgetBrowserTabs(in_sphinx=True)
+
+def widgetbrowser_directive(dirname, arguments, options, content, lineno,
+                            content_offset, block_text, state, state_machine):
+    """Processes the `widgetbrowser` reStructuredText directive.
+    
+    When generating the URL for the widget it peeks into os.environ for the
+    'TW_BROWSER_PREFIX' environment variable.
+    """
+    widget_path = arguments[0]
+    widget = util.import_widget(widget_path)
+    if not widget:
+        reporter = state.document.reporter
+        msg = reporter.warning(
+            'No widget found at %r' % widget_path, line=lineno)
+        prb = nodes.problematic(block_text, block_text, msg)
+        return [msg, prb]
+    tabs = options.get('tabs') or widget_tabs.tabs
+    prefix = os.environ.get('TW_BROWSER_PREFIX')
+    size = options.get('size')
+    html = widget_tabs(widget, tabs=tabs, prefix=prefix, size=size)
+    node = nodes.raw('', html, format='html')
+    return [node]
+
+
+def _get_tabs(arg):
+    if arg is None:
+        return []
+    return [s.strip() for s in arg.split(',')]
+    
+def _get_size(arg):
+    return arg or "small"
+
+def setup(app):
+    browser_options = {'tabs': _get_tabs, 'size':_get_size}
+    app.add_directive('widgetbrowser', widgetbrowser_directive, 1, (1, 0, 1),
+                      **browser_options)
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.css b/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.css
new file mode 100644
index 0000000..6eda851
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.css
@@ -0,0 +1,78 @@
+.httprepl .output pre {
+    font: 10pt monospace;
+    margin: 0;
+    padding: 1px;
+    border: 1px solid #E0E0FF;
+    background-color: #F8F8FF;
+    
+    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
+    white-space: -pre-wrap; /* Opera 4 - 6 */
+    white-space: -o-pre-wrap; /* Opera 7 */
+    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
+                            http://www.w3.org/TR/css3-text/#white-space */
+    word-wrap: break-word; /* IE 5.5+ */
+}
+
+.httprepl .output pre.stdin {
+    border: none;
+    background-color: transparent;
+}
+
+form {
+    font: 10pt monospace;
+    margin: 0;
+}
+
+.httprepl .input {
+    font: 10pt monospace;
+    width: 95%;
+    border-top: none;
+    border-right: 1px dotted #E0E0FF;
+    border-bottom: none;
+    border-left: 1px dotted #E0E0FF;
+}
+
+.httprepl .tipbar {
+    position: fixed;
+    top: 10px;
+    
+    /* See http://annevankesteren.nl/test/examples/ie/position-fixed.html */
+    _position:absolute;
+    _top:expression(eval(document.body.scrollTop) + 10);
+    
+    right: 10px;
+    
+    max-width: 50%;
+    max-height: 80%;
+    /* See http://www.svendtofte.com/code/max_width_in_ie/ */
+    width: expression(document.body.clientWidth / 2);
+    height: expression(document.body.clientHeight * 0.8);
+    
+    border: 2px outset #DDCCBB;
+    background-color: #FFEEDD;
+    font: 9pt monospace;
+    
+    margin: 0;
+    padding: 4px;
+    
+    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
+    white-space: -pre-wrap; /* Opera 4 - 6 */
+    white-space: -o-pre-wrap; /* Opera 7 */
+    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
+                            http://www.w3.org/TR/css3-text/#white-space */
+    word-wrap: break-word; /* IE 5.5+ */
+    
+    display: none;
+    overflow: auto;
+}
+
+.httprepl .tipbar a {
+    padding: 4px;
+    text-decoration: none;
+    color: #666666;
+}
+
+.widget-dialog  {
+    background: #fff;
+    z-index: 9999;
+}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.js b/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.js
new file mode 100644
index 0000000..a85f1ef
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/httprepl.js
@@ -0,0 +1,432 @@
+var HTTPRepl = (function ($) {
+    function http() {
+        var h;
+        if (typeof(XMLHttpRequest) != "undefined") {
+            h = new XMLHttpRequest();
+        } else {
+            try { h = new ActiveXObject("Msxml2.XMLHTTP"); }
+            catch (e) {
+                try { h = new ActiveXObject("Microsoft.XMLHTTP"); }
+                catch (E) { alert("Your browser is not supported."); }
+            }
+        }
+        return h
+    }
+
+
+    //                           HISTORY NAVIGATION                           //
+
+    function use_history(elem) {
+        var content = get_text(elem);
+        // Strip the leading prompt
+        if (elem.className == 'stdin') content = content.substr(4);
+        input.value = content;
+        input.focus();
+    }
+
+    function history_hook() {
+        use_history(this);
+    }
+
+    var current_history = undefined;
+
+    function prev_history() {
+        if (current_history == undefined) {
+            var prev = output.lastChild;
+        } else {
+            var prev = current_history.previousSibling;
+        }
+        while (prev != null && prev.className != 'stdin') {
+            prev = prev.previousSibling;
+        }
+        if (prev != null) {
+            current_history = prev;
+            use_history(prev);
+        }
+    }
+
+    function next_history() {
+        if (current_history == undefined) return;
+        
+        var next = current_history.nextSibling;
+        while (next != null && next.className != 'stdin') {
+            next = next.nextSibling;
+        }
+        if (next != null) {
+            current_history = next;
+            use_history(next);
+        }
+    }
+
+
+    //                            CODE COMPLETION                            //
+
+    current_range = undefined;
+
+    function partial_line() {
+        if (document.selection) {
+            // Internet Explorer
+            current_range = document.selection.createRange();
+            var end = current_range.getBookmark().charCodeAt(2) - 2;
+        } else {
+            var end = input.selectionEnd;
+        }
+        return input.value.substring(0, end);
+    }
+
+    function insert_text(newtext) {
+        if (document.selection) {
+            // Internet Explorer
+            current_range.text = newtext;
+            current_range.select();
+        } else {
+            var start = input.selectionStart;
+            input.value = input.value.substring(0, start) + newtext + input.value.substr(input.selectionEnd);
+            var end = start + newtext.length;
+            input.setSelectionRange(end, end);
+        }
+    }
+
+    function clear_tips() {
+        tipbar.style.display = '';
+        while (tipbar.hasChildNodes()) {
+            tipbar.removeChild(tipbar.lastChild);
+        }
+    }
+
+    function show_tips() {
+        tipbar.style.display = 'block';
+    }
+
+    var intip = false;
+
+    function use_tip() {
+        insert_text(get_text(this));
+        clear_tips();
+        intip = true;
+        input.focus();
+    }
+
+    function dir() {
+        var data = partial_line();
+        
+        clear_tips();
+        
+        var h = http();
+        h.onreadystatechange = function() {
+            if (h.readyState == 4) {
+                try {
+                    var status = h.status;
+                } catch(e) {
+                    var status = "NO HTTP RESPONSE";
+                }
+                switch (status) {
+                    case 200:
+                        var tips = eval(h.responseText);
+                        for (var i=0; i < tips.length; i++) {
+                            var tiplink = document.createElement("a");
+                            tiplink.onclick = use_tip;
+                            tiplink.href = "javascript:void(0)";
+                            set_text(tiplink, tips[i]);
+                            tipbar.appendChild(tiplink);
+                            tipbar.appendChild(document.createElement("br"));
+                        }
+                        show_tips()
+                        input.focus();
+                        break;
+                    // Internet Explorer might return 1223 for 204
+                    case 1223:
+                    case 204:
+                        // No tips available
+                        break;
+                    case 12029:
+                        // Internet Explorer client could not connect to server
+                        status = "NO HTTP RESPONSE";
+                    case 403:
+                        stdout_write("Interactive mode is disabled", false);
+                        break;
+                    default:
+                        stdout_write(status + "\n" + h.responseText, false);
+                }
+            }
+        }
+        h.open("GET", prefix + "dir?line=" + escape(data), true);
+        h.send(null);
+    }
+
+    function doc() {
+        var data = partial_line();
+        
+        clear_tips();
+        
+        var h = http();
+        h.onreadystatechange = function() {
+            if (h.readyState == 4) {
+                try {
+                    var status = h.status;
+                } catch(e) {
+                    var status = "NO HTTP RESPONSE";
+                }
+                switch (status) {
+                    case 200:
+                        tipbar.appendChild(document.createTextNode(h.responseText));
+                        show_tips();
+                        input.focus();
+                        break;
+                    // Internet Explorer might return 1223 for 204
+                    case 1223:
+                    case 403:
+                        stdout_write("Interactive mode is disabled", false);
+                        break;
+                    case 204:
+                        // No tips available
+                        break;
+                    case 12029:
+                        // Internet Explorer client could not connect to server
+                        status = "NO HTTP RESPONSE";
+                    default:
+                        stdout_write(status + "\n" + h.responseText, false);
+                }
+            }
+        }
+        h.open("GET", prefix + "doc?line=" + escape(data), true);
+        h.send(null);
+    }
+
+    //                           COMMAND EXECUTION                           //
+
+    function get_text(elem) {
+        if (elem.innerText != undefined) {
+            // Internet Explorer
+            return elem.innerText;
+        } else {
+            // Mozilla
+            return elem.textContent;
+        }
+    }
+
+    function set_text(elem, newvalue) {
+        if (elem.innerText != undefined) {
+            // Internet Explorer
+            elem.innerText = newvalue;
+        } else {
+            // Mozilla
+            elem.textContent = newvalue;
+        }
+    }
+
+    function get_prompt() {
+        return get_text(prompt_);
+    }
+
+    function set_prompt(newvalue) {
+        set_text(prompt_, newvalue);
+    }
+
+    function stdout_write(content, stdin) {
+        current_history = undefined;
+        if (content == "") return;
+        
+        var block = document.createElement("pre");
+        block.ondblclick = history_hook;
+        if (stdin) {
+            content = get_prompt() + content;
+            block.className = 'stdin';
+        }
+        if (block.innerText != undefined) {
+            // Internet Explorer quirkiness
+            block.innerText = content;
+        } else {
+            block.appendChild(document.createTextNode(content));
+        }
+        output.appendChild(block);
+    }
+
+    whitespace = /^\s+$/;
+
+    function push() {
+        var data = input.value;
+        // Uncomment to treat a line with only whitespace like a blank line
+        // if (whitespace.test(data)) data = "";
+        
+        input.value = "";
+        
+        var h = http();
+        h.onreadystatechange = function() {
+            if (h.readyState == 4) {
+                stdout_write(data, true);
+                try {
+                    var status = h.status;
+                } catch(e) {
+                    var status = "NO HTTP RESPONSE";
+                }
+                switch (status) {
+                    case 200:
+                        set_prompt(">>> ");
+                        var response = h.responseText;
+                        if (!handle_widget_output(response)) {
+                            stdout_write(response, false);
+                        }
+                        break;
+                    // Internet Explorer might return 1223 for 204
+                    case 1223:
+                    case 204:
+                        set_prompt("... ");
+                        // input.value *should* be blank, but just in case...
+                        input.value = "    " + input.value;
+                        break;
+                    case 403:
+                        stdout_write("Interactive mode is disabled", false);
+                        break;
+                    case 12029:
+                        // Internet Explorer client could not connect to server
+                        status = "NO HTTP RESPONSE";
+                    default:
+                        stdout_write(status + "\n" + h.responseText, false);
+                }
+                input.focus();
+            }
+        }
+        h.open("POST", prefix + "push", true);
+        h.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+        h.send("line=" + escape(data));
+    }
+
+
+    function escape(data) {
+        data = data.replace(/%/gi, "%25");
+        data = data.replace(/&/gi, "%26");
+        data = data.replace(/[+]/gi, "%2B");
+        data = data.replace(/;/gi, "%3B");
+        return data;
+    }
+
+
+    //                                 SETUP                                 //
+
+    function mapKeys(key_code) {
+        if (intip) {
+            intip = false;
+            // Trap the bubbling keyup event from a tiplink. This means that,
+            // if you actually click a tiplink instead of tab and hit 'enter',
+            // you have to hit 'enter' twice to push the line. :(
+            if (key_code == 13) return;
+        }
+        switch(key_code) {
+            case 8:    // backspace
+                clear_tips();
+                break;
+            case 13:   // enter
+                clear_tips();
+                push();
+                break;
+            case 38:   // up arrow
+                prev_history();
+                break;
+            case 40:   // down arrow
+                next_history();
+                break;
+            case 48:  // close paren "("
+                clear_tips();
+                break;
+            case 57:  // open paren "("
+                doc();
+                break;
+            case 190:  // period "."
+                dir();
+                break;
+        }
+    }
+
+    function trapKeys(e) {
+        if (!e) var e = window.event;
+        mapKeys(e.keyCode);
+    }
+
+    //                   WIDGET DIALOGS                                      //
+
+    var new_id = (function make_counter(value) {
+        var state = {value: value || 0};
+        function next() {
+            state.value ++;
+            return 'widget-dialog-' + state.value;
+        }
+        return next;
+    })();
+
+    function open_dialog(config) {
+        var c = $.extend({}, {height:450, width:600}, config);
+        var iframe = $('<iframe><iframe>');
+        iframe.attr({id: new_id(), 'class': 'widget-dialog'});
+        function setSize(size) {
+            var attr = {
+                height: Math.max(0, Math.round(size.height-60)),
+                width: Math.max(0, Math.round(size.width-40))
+            }
+            iframe.attr(attr);
+        }
+        function onResizeStart(event, data) {
+            // Hide the iframe so it doesn't captute mouse events while dragging
+            // the resize handlers
+            iframe.hide();
+        }
+        function onResizeStop(event, data) {
+            setSize(data.instance.size);
+            iframe.show();
+        }
+        function onClose() {
+            iframe.remove();
+            input.focus();
+        }
+        iframe.appendTo(httprepl).dialog(config)
+              .bind('dialogclose', onClose)
+              .trigger('setData.dialog', ['resizeStart', onResizeStart])
+              .trigger('setData.dialog', ['resizeStop', onResizeStop])
+              .attr('src', config.url)
+              .dialog('open');
+        setSize(c);
+    }
+
+    var displayed_widget = /DeferredDisplay\((\d+)[^']*'([^']+)'/;
+
+    function handle_widget_output(response) {
+        var match = displayed_widget(response);
+        if (match) {
+            var config = {
+                url: prefix + 'widget_output/' + match[1],
+                height: 500,
+                width: 750,
+                title: match[2]
+            }
+            open_dialog(config);
+            return true;
+        }
+        return false;
+    }
+    var httprepl = $(''
+        +'<div class="httprepl">' 
+        +  '<div class="output"></div>'
+        +  '<form action="" class="terminal">'
+        +    '<div class="tipbar"></div>'
+        +    '<nobr>'
+        +      '<span class="prompt">&gt;&gt;&gt; </span>'
+        +      '<input type="text" class="input" size=60" />'
+        +    '</nobr>'
+        +  '</form>'
+        +'</div>'
+    );
+    var prefix = '';
+    var input = $('.input', httprepl)[0];
+    input.onkeyup = trapKeys;
+    var output = $('.output', httprepl)[0];
+    var tipbar = $('.tipbar', httprepl)[0];
+    var prompt_ = $('.prompt', httprepl)[0];
+    $('form', httprepl).submit(function() { return false });
+
+    return {
+        render: function(el, config) {
+            prefix = config.prefix || '';
+            httprepl.appendTo($(el));
+        }
+    }
+})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/jquery.js b/moksha/apps/widgetbrowser/widgetbrowser/static/jquery.js
new file mode 100644
index 0000000..ea64073
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/jquery.js
@@ -0,0 +1,3436 @@
+(function(){
+/*
+ * jQuery 1.2.4a - New Wave Javascript
+ *
+ * Copyright (c) 2008 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-04-08 13:40:03 -0300 (ter, 08 abr 2008) $
+ * $Rev: 5214 $
+ */
+
+// Map over jQuery in case of overwrite
+if ( window.jQuery )
+	var _jQuery = window.jQuery;
+
+var jQuery = window.jQuery = function( selector, context ) {
+	// The jQuery object is actually just the init constructor 'enhanced'
+	return new jQuery.prototype.init( selector, context );
+};
+
+// Map over the $ in case of overwrite
+if ( window.$ )
+	var _$ = window.$;
+	
+// Map the jQuery namespace to the '$' one
+window.$ = jQuery;
+
+// A simple way to check for HTML strings or ID strings
+// (both of which we optimize for)
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+
+// Is it a simple selector
+var isSimple = /^.[^:#\[\.]*$/;
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		// Make sure that a selection was provided
+		selector = selector || document;
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// Handle HTML strings
+		} else if ( typeof selector == "string" ) {
+			// Are we dealing with HTML string or an ID?
+			var match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] )
+					selector = jQuery.clean( [ match[1] ], context );
+
+				// HANDLE: $("#id")
+				else {
+					var elem = document.getElementById( match[3] );
+
+					// Make sure an element was located
+					if ( elem )
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id != match[3] )
+							return jQuery().find( selector );
+
+						// Otherwise, we inject the element directly into the jQuery object
+						else {
+							this[0] = elem;
+							this.length = 1;
+							return this;
+						}
+
+					else
+						selector = [];
+				}
+
+			// HANDLE: $(expr, [context])
+			// (which is just equivalent to: $(content).find(expr)
+			} else
+				return new jQuery( context ).find( selector );
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) )
+			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
+
+		return this.setArray(
+			// HANDLE: $(array)
+			selector.constructor == Array && selector ||
+
+			// HANDLE: $(arraylike)
+			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
+			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
+
+			// HANDLE: $(*)
+			[ selector ] );
+	},
+	
+	// The current version of jQuery being used
+	jquery: "1.2.4a",
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+	
+	// The number of elements contained in the matched element set
+	length: 0,
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == undefined ?
+
+			// Return a 'clean' array
+			jQuery.makeArray( this ) :
+
+			// Return just the object
+			this[ num ];
+	},
+	
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery( elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+	
+	// Force the current matched set of elements to become
+	// the specified array of elements (destroying the stack in the process)
+	// You should use pushStack() in order to do this, but maintain the stack
+	setArray: function( elems ) {
+		// Resetting the length to 0, then using the native Array push
+		// is a super-fast way to populate an object with array-like properties
+		this.length = 0;
+		Array.prototype.push.apply( this, elems );
+		
+		return this;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	// Determine the position of an element within 
+	// the matched set of elements
+	index: function( elem ) {
+		var ret = -1;
+
+		// Locate the position of the desired element
+		this.each(function(i){
+			if ( this == elem )
+				ret = i;
+		});
+
+		return ret;
+	},
+
+	attr: function( name, value, type ) {
+		var options = name;
+		
+		// Look for the case where we're accessing a style value
+		if ( name.constructor == String )
+			if ( value == undefined )
+				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
+
+			else {
+				options = {};
+				options[ name ] = value;
+			}
+		
+		// Check to see if we're setting style values
+		return this.each(function(i){
+			// Set all the styles
+			for ( name in options )
+				jQuery.attr(
+					type ?
+						this.style :
+						this,
+					name, jQuery.prop( this, options[ name ], type, i, name )
+				);
+		});
+	},
+
+	css: function( key, value ) {
+		// ignore negative width and height values
+		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+			value = undefined;
+		return this.attr( key, value, "curCSS" );
+	},
+
+	text: function( text ) {
+		if ( typeof text != "object" && text != null )
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+		var ret = "";
+
+		jQuery.each( text || this, function(){
+			jQuery.each( this.childNodes, function(){
+				if ( this.nodeType != 8 )
+					ret += this.nodeType != 1 ?
+						this.nodeValue :
+						jQuery.fn.text( [ this ] );
+			});
+		});
+
+		return ret;
+	},
+
+	wrapAll: function( html ) {
+		if ( this[0] )
+			// The elements to wrap the target around
+			jQuery( html, this[0].ownerDocument )
+				.clone()
+				.insertBefore( this[0] )
+				.map(function(){
+					var elem = this;
+
+					while ( elem.firstChild )
+						elem = elem.firstChild;
+
+					return elem;
+				})
+				.append(this);
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		return this.each(function(){
+			jQuery( this ).contents().wrapAll( html );
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function(){
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, false, function(elem){
+			if (this.nodeType == 1)
+				this.appendChild( elem );
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, true, function(elem){
+			if (this.nodeType == 1)
+				this.insertBefore( elem, this.firstChild );
+		});
+	},
+	
+	before: function() {
+		return this.domManip(arguments, false, false, function(elem){
+			this.parentNode.insertBefore( elem, this );
+		});
+	},
+
+	after: function() {
+		return this.domManip(arguments, false, true, function(elem){
+			this.parentNode.insertBefore( elem, this.nextSibling );
+		});
+	},
+
+	end: function() {
+		return this.prevObject || jQuery( [] );
+	},
+
+	find: function( selector ) {
+		var elems = jQuery.map(this, function(elem){
+			return jQuery.find( selector, elem );
+		});
+
+		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
+			jQuery.unique( elems ) :
+			elems );
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function(){
+			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to 
+				// attributes in IE that are actually only stored 
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var clone = this.cloneNode(true),
+					container = document.createElement("div");
+				container.appendChild(clone);
+				return jQuery.clean([container.innerHTML])[0];
+			} else
+				return this.cloneNode(true);
+		});
+
+		// Need to set the expando to null on the cloned set if it exists
+		// removeData doesn't work here, IE removes it from the original as well
+		// this is primarily for IE but the data expando shouldn't be copied over in any browser
+		var clone = ret.find("*").andSelf().each(function(){
+			if ( this[ expando ] != undefined )
+				this[ expando ] = null;
+		});
+		
+		// Copy the events from the original to the clone
+		if ( events === true )
+			this.find("*").andSelf().each(function(i){
+				if (this.nodeType == 3)
+					return;
+				var events = jQuery.data( this, "events" );
+
+				for ( var type in events )
+					for ( var handler in events[ type ] )
+						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+			});
+
+		// Return the cloned set
+		return ret;
+	},
+
+	filter: function( selector ) {
+		return this.pushStack(
+			jQuery.isFunction( selector ) &&
+			jQuery.grep(this, function(elem, i){
+				return selector.call( elem, i );
+			}) ||
+
+			jQuery.multiFilter( selector, this ) );
+	},
+
+	not: function( selector ) {
+		if ( selector.constructor == String )
+			// test special case where just one selector is passed in
+			if ( isSimple.test( selector ) )
+				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
+			else
+				selector = jQuery.multiFilter( selector, this );
+
+		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+		return this.filter(function() {
+			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+		});
+	},
+
+	add: function( selector ) {
+		return !selector ? this : this.pushStack( jQuery.merge( 
+			this.get(),
+			selector.constructor == String ? 
+				jQuery( selector ).get() :
+				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
+					selector : [selector] ) );
+	},
+
+	is: function( selector ) {
+		return selector ?
+			jQuery.multiFilter( selector, this ).length > 0 :
+			false;
+	},
+
+	hasClass: function( selector ) {
+		return this.is( "." + selector );
+	},
+	
+	val: function( value ) {
+		if ( value == undefined ) {
+
+			if ( this.length ) {
+				var elem = this[0];
+
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type == "select-one";
+					
+					// Nothing was selected
+					if ( index < 0 )
+						return null;
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						if ( option.selected ) {
+							// Get the specifc value for the option
+							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
+							
+							// We don't need an array for one selects
+							if ( one )
+								return value;
+							
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+					
+					return values;
+					
+				// Everything else, we just grab the value
+				} else
+					return (this[0].value || "").replace(/\r/g, "");
+
+			}
+
+			return undefined;
+		}
+
+		return this.each(function(){
+			if ( this.nodeType != 1 )
+				return;
+
+			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
+				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+					jQuery.inArray(this.name, value) >= 0);
+
+			else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = value.constructor == Array ?
+					value :
+					[ value ];
+
+				jQuery( "option", this ).each(function(){
+					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+						jQuery.inArray( this.text, values ) >= 0);
+				});
+
+				if ( !values.length )
+					this.selectedIndex = -1;
+
+			} else
+				this.value = value;
+		});
+	},
+	
+	html: function( value ) {
+		return value == undefined ?
+			(this.length ?
+				this[0].innerHTML :
+				null) :
+			this.empty().append( value );
+	},
+
+	replaceWith: function( value ) {
+		return this.after( value ).remove();
+	},
+
+	eq: function( i ) {
+		return this.slice( i, i + 1 );
+	},
+
+	slice: function() {
+		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function(elem, i){
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	},
+
+	data: function( key, value ){
+		var parts = key.split(".");
+		parts[1] = parts[1] ? "." + parts[1] : "";
+
+		if ( value == null ) {
+			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+			
+			if ( data == undefined && this.length )
+				data = jQuery.data( this[0], key );
+
+			return data == null && parts[1] ?
+				this.data( parts[0] ) :
+				data;
+		} else
+			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+				jQuery.data( this, key, value );
+			});
+	},
+
+	removeData: function( key ){
+		return this.each(function(){
+			jQuery.removeData( this, key );
+		});
+	},
+	
+	domManip: function( args, table, reverse, callback ) {
+		var clone = this.length > 1, elems; 
+
+		return this.each(function(){
+			if ( !elems ) {
+				elems = jQuery.clean( args, this.ownerDocument );
+
+				if ( reverse )
+					elems.reverse();
+			}
+
+			var obj = this;
+
+			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
+				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
+
+			var scripts = jQuery( [] );
+
+			jQuery.each(elems, function(){
+				var elem = clone ?
+					jQuery( this ).clone( true )[0] :
+					this;
+
+				// execute all scripts after the elements have been injected
+				if ( jQuery.nodeName( elem, "script" ) ) {
+					scripts = scripts.add( elem );
+				} else {
+					// Remove any inner scripts for later evaluation
+					if ( elem.nodeType == 1 )
+						scripts = scripts.add( jQuery( "script", elem ).remove() );
+
+					// Inject the elements into the document
+					callback.call( obj, elem );
+				}
+			});
+
+			scripts.each( evalScript );
+		});
+	}
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.prototype.init.prototype = jQuery.prototype;
+
+function evalScript( i, elem ) {
+	if ( elem.src )
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+
+	else
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+	if ( elem.parentNode )
+		elem.parentNode.removeChild( elem );
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+	// copy reference to target object
+	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+	// Handle a deep copy situation
+	if ( target.constructor == Boolean ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target != "object" && typeof target != "function" )
+		target = {};
+
+	// extend jQuery itself if only one argument is passed
+	if ( length == 1 ) {
+		target = this;
+		i = 0;
+	}
+
+	for ( ; i < length; i++ )
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null )
+			// Extend the base object
+			for ( var name in options ) {
+				// Prevent never-ending loop
+				if ( target === options[ name ] )
+					continue;
+
+				// Recurse if we're merging object values
+				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
+					target[ name ] = jQuery.extend( deep, target[ name ], options[ name ] );
+
+				// Don't bring in undefined values
+				else if ( options[ name ] != undefined )
+					target[ name ] = options[ name ];
+
+			}
+
+	// Return the modified object
+	return target;
+};
+
+var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
+
+// exclude the following css properties to add px
+var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep )
+			window.jQuery = _jQuery;
+
+		return jQuery;
+	},
+
+	// See test/unit/core.js for details concerning this function.
+	isFunction: function( fn ) {
+		return !!fn && typeof fn != "string" && !fn.nodeName && 
+			fn.constructor != Array && /function/i.test( fn + "" );
+	},
+	
+	// check if an element is in a (or is an) XML document
+	isXMLDoc: function( elem ) {
+		return elem.documentElement && !elem.body ||
+			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+	},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		data = jQuery.trim( data );
+
+		if ( data ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+			if ( jQuery.browser.msie )
+				script.text = data;
+			else
+				script.appendChild( document.createTextNode( data ) );
+
+			head.appendChild( script );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+	},
+	
+	cache: {},
+	
+	data: function( elem, name, data ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// Compute a unique ID for the element
+		if ( !id ) 
+			id = elem[ expando ] = ++uuid;
+
+		// Only generate the data cache if we're
+		// trying to access or manipulate it
+		if ( name && !jQuery.cache[ id ] )
+			jQuery.cache[ id ] = {};
+		
+		// Prevent overriding the named cache with undefined values
+		if ( data != undefined )
+			jQuery.cache[ id ][ name ] = data;
+		
+		// Return the named cache data, or the ID for the element	
+		return name ?
+			jQuery.cache[ id ][ name ] :
+			id;
+	},
+	
+	removeData: function( elem, name ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// If we want to remove a specific section of the element's data
+		if ( name ) {
+			if ( jQuery.cache[ id ] ) {
+				// Remove the section of cache data
+				delete jQuery.cache[ id ][ name ];
+
+				// If we've removed all the data, remove the element's cache
+				name = "";
+
+				for ( name in jQuery.cache[ id ] )
+					break;
+
+				if ( !name )
+					jQuery.removeData( elem );
+			}
+
+		// Otherwise, we want to remove all of the element's data
+		} else {
+			// Clean up the element expando
+			try {
+				delete elem[ expando ];
+			} catch(e){
+				// IE has trouble directly removing the expando
+				// but it's ok with using removeAttribute
+				if ( elem.removeAttribute )
+					elem.removeAttribute( expando );
+			}
+
+			// Completely remove the data cache
+			delete jQuery.cache[ id ];
+		}
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		if ( args ) {
+			if ( object.length == undefined ) {
+				for ( var name in object )
+					if ( callback.apply( object[ name ], args ) === false )
+						break;
+			} else
+				for ( var i = 0, length = object.length; i < length; i++ )
+					if ( callback.apply( object[ i ], args ) === false )
+						break;
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( object.length == undefined ) {
+				for ( var name in object )
+					if ( callback.call( object[ name ], name, object[ name ] ) === false )
+						break;
+			} else
+				for ( var i = 0, length = object.length, value = object[0]; 
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+		}
+
+		return object;
+	},
+	
+	prop: function( elem, value, type, i, name ) {
+			// Handle executable functions
+			if ( jQuery.isFunction( value ) )
+				value = value.call( elem, i );
+				
+			// Handle passing in a number to a CSS property
+			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
+				value + "px" :
+				value;
+	},
+
+	className: {
+		// internal only, use addClass("class")
+		add: function( elem, classNames ) {
+			jQuery.each((classNames || "").split(/\s+/), function(i, className){
+				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+					elem.className += (elem.className ? " " : "") + className;
+			});
+		},
+
+		// internal only, use removeClass("class")
+		remove: function( elem, classNames ) {
+			if (elem.nodeType == 1)
+				elem.className = classNames != undefined ?
+					jQuery.grep(elem.className.split(/\s+/), function(className){
+						return !jQuery.className.has( classNames, className );	
+					}).join(" ") :
+					"";
+		},
+
+		// internal only, use is(".class")
+		has: function( elem, className ) {
+			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( var name in options )
+			elem.style[ name ] = old[ name ];
+	},
+
+	css: function( elem, name, force ) {
+		if ( name == "width" || name == "height" ) {
+			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+		
+			function getWH() {
+				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+				var padding = 0, border = 0;
+				jQuery.each( which, function() {
+					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+				});
+				val -= Math.round(padding + border);
+			}
+		
+			if ( jQuery(elem).is(":visible") )
+				getWH();
+			else
+				jQuery.swap( elem, props, getWH );
+			
+			return Math.max(0, val);
+		}
+		
+		return jQuery.curCSS( elem, name, force );
+	},
+
+	curCSS: function( elem, name, force ) {
+		var ret;
+
+		// A helper method for determining if an element's values are broken
+		function color( elem ) {
+			if ( !jQuery.browser.safari )
+				return false;
+
+			var ret = document.defaultView.getComputedStyle( elem, null );
+			return !ret || ret.getPropertyValue("color") == "";
+		}
+
+		// We need to handle opacity special in IE
+		if ( name == "opacity" && jQuery.browser.msie ) {
+			ret = jQuery.attr( elem.style, "opacity" );
+
+			return ret == "" ?
+				"1" :
+				ret;
+		}
+		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
+		if ( jQuery.browser.opera && name == "display" ) {
+			var save = elem.style.outline;
+			elem.style.outline = "0 solid black";
+			elem.style.outline = save;
+		}
+		
+		// Make sure we're using the right name for getting the float value
+		if ( name.match( /float/i ) )
+			name = styleFloat;
+
+		if ( !force && elem.style && elem.style[ name ] )
+			ret = elem.style[ name ];
+
+		else if ( document.defaultView && document.defaultView.getComputedStyle ) {
+
+			// Only "float" is needed here
+			if ( name.match( /float/i ) )
+				name = "float";
+
+			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+			var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
+
+			if ( getComputedStyle && !color( elem ) )
+				ret = getComputedStyle.getPropertyValue( name );
+
+			// If the element isn't reporting its values properly in Safari
+			// then some display: none elements are involved
+			else {
+				var swap = [], stack = [];
+
+				// Locate all of the parent display: none elements
+				for ( var a = elem; a && color(a); a = a.parentNode )
+					stack.unshift(a);
+
+				// Go through and make them visible, but in reverse
+				// (It would be better if we knew the exact display type that they had)
+				for ( var i = 0; i < stack.length; i++ )
+					if ( color( stack[ i ] ) ) {
+						swap[ i ] = stack[ i ].style.display;
+						stack[ i ].style.display = "block";
+					}
+
+				// Since we flip the display style, we have to handle that
+				// one special, otherwise get the value
+				ret = name == "display" && swap[ stack.length - 1 ] != null ?
+					"none" :
+					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
+
+				// Finally, revert the display styles back
+				for ( var i = 0; i < swap.length; i++ )
+					if ( swap[ i ] != null )
+						stack[ i ].style.display = swap[ i ];
+			}
+
+			// We should always get a number back from opacity
+			if ( name == "opacity" && ret == "" )
+				ret = "1";
+
+		} else if ( elem.currentStyle ) {
+			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+			// From the awesome hack by Dean Edwards
+			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+			// If we're not dealing with a regular pixel number
+			// but a number that has a weird ending, we need to convert it to pixels
+			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+				// Remember the original values
+				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
+
+				// Put in the new values to get a computed value out
+				elem.runtimeStyle.left = elem.currentStyle.left;
+				elem.style.left = ret || 0;
+				ret = elem.style.pixelLeft + "px";
+
+				// Revert the changed values
+				elem.style.left = style;
+				elem.runtimeStyle.left = runtimeStyle;
+			}
+		}
+
+		return ret;
+	},
+	
+	clean: function( elems, context ) {
+		var ret = [];
+		context = context || document;
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if (typeof context.createElement == 'undefined') 
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+		jQuery.each(elems, function(i, elem){
+			if ( !elem )
+				return;
+
+			if ( elem.constructor == Number )
+				elem = elem.toString();
+			
+			// Convert html string into DOM nodes
+			if ( typeof elem == "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+						all :
+						front + "></" + tag + ">";
+				});
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
+
+				var wrap =
+					// option or optgroup
+					!tags.indexOf("<opt") &&
+					[ 1, "<select multiple='multiple'>", "</select>" ] ||
+					
+					!tags.indexOf("<leg") &&
+					[ 1, "<fieldset>", "</fieldset>" ] ||
+					
+					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+					[ 1, "<table>", "</table>" ] ||
+					
+					!tags.indexOf("<tr") &&
+					[ 2, "<table><tbody>", "</tbody></table>" ] ||
+					
+				 	// <thead> matched above
+					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+					
+					!tags.indexOf("<col") &&
+					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+					// IE can't serialize <link> and <script> tags normally
+					jQuery.browser.msie &&
+					[ 1, "div<div>", "</div>" ] ||
+					
+					[ 0, "", "" ];
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+				
+				// Move to the right depth
+				while ( wrap[0]-- )
+					div = div.lastChild;
+				
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( jQuery.browser.msie ) {
+					
+					// String was a <table>, *may* have spurious <tbody>
+					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
+						div.firstChild && div.firstChild.childNodes :
+						
+						// String was a bare <thead> or <tfoot>
+						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+							div.childNodes :
+							[];
+				
+					for ( var j = tbody.length - 1; j >= 0 ; --j )
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+					
+					// IE completely kills leading whitespace when innerHTML is used	
+					if ( /^\s/.test( elem ) )	
+						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+				
+				}
+				
+				elem = jQuery.makeArray( div.childNodes );
+			}
+
+			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
+				return;
+
+			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
+				ret.push( elem );
+
+			else
+				ret = jQuery.merge( ret, elem );
+
+		});
+
+		return ret;
+	},
+	
+	attr: function( elem, name, value ) {
+		// don't set attributes on text and comment nodes
+		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+			return undefined;
+
+		var fix = jQuery.isXMLDoc( elem ) ?
+			{} :
+			jQuery.props;
+
+		// Safari mis-reports the default selected property of a hidden option
+		// Accessing the parent's selectedIndex property fixes it
+		if ( name == "selected" && jQuery.browser.safari )
+			elem.parentNode.selectedIndex;
+		
+		// Certain attributes only work when accessed via the old DOM 0 way
+		if ( fix[ name ] ) {
+			if ( value != undefined )
+				elem[ fix[ name ] ] = value;
+
+			return elem[ fix[ name ] ];
+
+		} else if ( jQuery.browser.msie && name == "style" )
+			return jQuery.attr( elem.style, "cssText", value );
+
+		else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
+			return elem.getAttributeNode( name ).nodeValue;
+
+		// IE elem.getAttribute passes even for style
+		else if ( elem.tagName ) {
+
+			if ( value != undefined ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+					throw "type property can't be changed";
+
+				// convert the value to a string (all browsers do this but IE) see #1070
+				elem.setAttribute( name, "" + value );
+			}
+
+			if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) ) 
+				return elem.getAttribute( name, 2 );
+
+			return elem.getAttribute( name );
+
+		// elem is actually elem.style ... set the style
+		} else {
+			// IE actually uses filters for opacity
+			if ( name == "opacity" && jQuery.browser.msie ) {
+				if ( value != undefined ) {
+					// IE has trouble with opacity if it does not have layout
+					// Force it by setting the zoom level
+					elem.zoom = 1; 
+	
+					// Set the alpha filter to set the opacity
+					elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+						(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+				}
+	
+				return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+					(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
+					"";
+			}
+
+			name = name.replace(/-([a-z])/ig, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			if ( value != undefined )
+				elem[ name ] = value;
+
+			return elem[ name ];
+		}
+	},
+	
+	trim: function( text ) {
+		return (text || "").replace( /^\s+|\s+$/g, "" );
+	},
+
+	makeArray: function( array ) {
+		var ret = [];
+
+		// Need to use typeof to fight Safari childNodes crashes
+		if ( array.constructor != Array )
+			for ( var i = 0, length = array.length; i < length; i++ )
+				ret.push( array[ i ] );
+		else
+			ret = array.slice( 0 );
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		for ( var i = 0, length = array.length; i < length; i++ )
+			if ( array[ i ] == elem )
+				return i;
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		// We have to loop this way because IE & Opera overwrite the length
+		// expando of getElementsByTagName
+
+		// Also, we need to make sure that the correct elements are being returned
+		// (IE returns comment nodes in a '*' query)
+		if ( jQuery.browser.msie ) {
+			for ( var i = 0; second[ i ]; i++ )
+				if ( second[ i ].nodeType != 8 )
+					first.push( second[ i ] );
+
+		} else
+			for ( var i = 0; second[ i ]; i++ )
+				first.push( second[ i ] );
+
+		return first;
+	},
+
+	unique: function( array ) {
+		var ret = [], done = {};
+
+		try {
+
+			for ( var i = 0, length = array.length; i < length; i++ ) {
+				var id = jQuery.data( array[ i ] );
+
+				if ( !done[ id ] ) {
+					done[ id ] = true;
+					ret.push( array[ i ] );
+				}
+			}
+
+		} catch( e ) {
+			ret = array;
+		}
+
+		return ret;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [];
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ )
+			if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
+				ret.push( elems[ i ] );
+
+		return ret;
+	},
+
+	map: function( elems, callback ) {
+		var ret = [];
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			var value = callback( elems[ i ], i );
+
+			if ( value !== null && value != undefined ) {
+				if ( value.constructor != Array )
+					value = [ value ];
+
+				ret = ret.concat( value );
+			}
+		}
+
+		return ret;
+	}
+});
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
+	safari: /webkit/.test( userAgent ),
+	opera: /opera/.test( userAgent ),
+	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+var styleFloat = jQuery.browser.msie ?
+	"styleFloat" :
+	"cssFloat";
+	
+jQuery.extend({
+	// Check to see if the W3C box model is being used
+	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
+	
+	props: {
+		"for": "htmlFor",
+		"class": "className",
+		"float": styleFloat,
+		cssFloat: styleFloat,
+		styleFloat: styleFloat,
+		innerHTML: "innerHTML",
+		className: "className",
+		value: "value",
+		disabled: "disabled",
+		checked: "checked",
+		readonly: "readOnly",
+		selected: "selected",
+		maxlength: "maxLength",
+		selectedIndex: "selectedIndex",
+		defaultValue: "defaultValue",
+		tagName: "tagName",
+		nodeName: "nodeName"
+	}
+});
+
+jQuery.each({
+	parent: function(elem){return elem.parentNode;},
+	parents: function(elem){return jQuery.dir(elem,"parentNode");},
+	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+	children: function(elem){return jQuery.sibling(elem.firstChild);},
+	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = jQuery.map( this, fn );
+
+		if ( selector && typeof selector == "string" )
+			ret = jQuery.multiFilter( selector, ret );
+
+		return this.pushStack( jQuery.unique( ret ) );
+	};
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function(name, original){
+	jQuery.fn[ name ] = function() {
+		var args = arguments;
+
+		return this.each(function(){
+			for ( var i = 0, length = args.length; i < length; i++ )
+				jQuery( args[ i ] )[ original ]( this );
+		});
+	};
+});
+
+jQuery.each({
+	removeAttr: function( name ) {
+		jQuery.attr( this, name, "" );
+		if (this.nodeType == 1) 
+			this.removeAttribute( name );
+	},
+
+	addClass: function( classNames ) {
+		jQuery.className.add( this, classNames );
+	},
+
+	removeClass: function( classNames ) {
+		jQuery.className.remove( this, classNames );
+	},
+
+	toggleClass: function( classNames ) {
+		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
+	},
+
+	remove: function( selector ) {
+		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
+			// Prevent memory leaks
+			jQuery( "*", this ).add(this).each(function(){
+				jQuery.event.remove(this);
+				jQuery.removeData(this);
+			});
+			if (this.parentNode)
+				this.parentNode.removeChild( this );
+		}
+	},
+
+	empty: function() {
+		// Remove element nodes and prevent memory leaks
+		jQuery( ">*", this ).remove();
+		
+		// Remove any remaining nodes
+		while ( this.firstChild )
+			this.removeChild( this.firstChild );
+	}
+}, function(name, fn){
+	jQuery.fn[ name ] = function(){
+		return this.each( fn, arguments );
+	};
+});
+
+jQuery.each([ "Height", "Width" ], function(i, name){
+	var type = name.toLowerCase();
+	
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		return this[0] == window ?
+			// Opera reports document.body.client[Width/Height] properly in both quirks and standards
+			jQuery.browser.opera && document.body[ "client" + name ] || 
+			
+			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
+			jQuery.browser.safari && window[ "inner" + name ] ||
+			
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
+		
+			// Get document width or height
+			this[0] == document ?
+				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+				Math.max( 
+					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), 
+					Math.max(document.body["offset" + name], document.documentElement["offset" + name]) 
+				) :
+
+				// Get or set width or height on the element
+				size == undefined ?
+					// Get width or height on the element
+					(this.length ? jQuery.css( this[0], type ) : null) :
+
+					// Set the width or height on the element (default to pixels if value is unitless)
+					this.css( type, size.constructor == String ? size : size + "px" );
+	};
+});
+
+var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
+		"(?:[\\w*_-]|\\\\.)" :
+		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
+	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
+	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
+	quickClass = new RegExp("^([#.]?)(" + chars + "*)");
+
+jQuery.extend({
+	expr: {
+		"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
+		"#": function(a,i,m){return a.getAttribute("id")==m[2];},
+		":": {
+			// Position Checks
+			lt: function(a,i,m){return i<m[3]-0;},
+			gt: function(a,i,m){return i>m[3]-0;},
+			nth: function(a,i,m){return m[3]-0==i;},
+			eq: function(a,i,m){return m[3]-0==i;},
+			first: function(a,i){return i==0;},
+			last: function(a,i,m,r){return i==r.length-1;},
+			even: function(a,i){return i%2==0;},
+			odd: function(a,i){return i%2;},
+
+			// Child Checks
+			"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
+			"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
+			"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
+
+			// Parent Checks
+			parent: function(a){return a.firstChild;},
+			empty: function(a){return !a.firstChild;},
+
+			// Text Check
+			contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
+
+			// Visibility
+			visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
+			hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
+
+			// Form attributes
+			enabled: function(a){return !a.disabled;},
+			disabled: function(a){return a.disabled;},
+			checked: function(a){return a.checked;},
+			selected: function(a){return a.selected||jQuery.attr(a,"selected");},
+
+			// Form elements
+			text: function(a){return "text"==a.type;},
+			radio: function(a){return "radio"==a.type;},
+			checkbox: function(a){return "checkbox"==a.type;},
+			file: function(a){return "file"==a.type;},
+			password: function(a){return "password"==a.type;},
+			submit: function(a){return "submit"==a.type;},
+			image: function(a){return "image"==a.type;},
+			reset: function(a){return "reset"==a.type;},
+			button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
+			input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
+
+			// :has()
+			has: function(a,i,m){return jQuery.find(m[3],a).length;},
+
+			// :header
+			header: function(a){return /h\d/i.test(a.nodeName);},
+
+			// :animated
+			animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
+		}
+	},
+	
+	// The regular expressions that power the parsing engine
+	parse: [
+		// Match: [@value='test'], [@foo]
+		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
+
+		// Match: :contains('foo')
+		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
+
+		// Match: :even, :last-chlid, #id, .class
+		new RegExp("^([:.#]*)(" + chars + "+)")
+	],
+
+	multiFilter: function( expr, elems, not ) {
+		var old, cur = [];
+
+		while ( expr && expr != old ) {
+			old = expr;
+			var f = jQuery.filter( expr, elems, not );
+			expr = f.t.replace(/^\s*,\s*/, "" );
+			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
+		}
+
+		return cur;
+	},
+
+	find: function( t, context ) {
+		// Quickly handle non-string expressions
+		if ( typeof t != "string" )
+			return [ t ];
+
+		// check to make sure context is a DOM element or a document
+		if ( context && context.nodeType != 1 && context.nodeType != 9)
+			return [ ];
+
+		// Set the correct context (if none is provided)
+		context = context || document;
+
+		// Initialize the search
+		var ret = [context], done = [], last, nodeName;
+
+		// Continue while a selector expression exists, and while
+		// we're no longer looping upon ourselves
+		while ( t && last != t ) {
+			var r = [];
+			last = t;
+
+			t = jQuery.trim(t);
+
+			var foundToken = false;
+
+			// An attempt at speeding up child selectors that
+			// point to a specific element tag
+			var re = quickChild;
+			var m = re.exec(t);
+
+			if ( m ) {
+				nodeName = m[1].toUpperCase();
+
+				// Perform our own iteration and filter
+				for ( var i = 0; ret[i]; i++ )
+					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
+						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
+							r.push( c );
+
+				ret = r;
+				t = t.replace( re, "" );
+				if ( t.indexOf(" ") == 0 ) continue;
+				foundToken = true;
+			} else {
+				re = /^([>+~])\s*(\w*)/i;
+
+				if ( (m = re.exec(t)) != null ) {
+					r = [];
+
+					var merge = {};
+					nodeName = m[2].toUpperCase();
+					m = m[1];
+
+					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
+						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
+						for ( ; n; n = n.nextSibling )
+							if ( n.nodeType == 1 ) {
+								var id = jQuery.data(n);
+
+								if ( m == "~" && merge[id] ) break;
+								
+								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
+									if ( m == "~" ) merge[id] = true;
+									r.push( n );
+								}
+								
+								if ( m == "+" ) break;
+							}
+					}
+
+					ret = r;
+
+					// And remove the token
+					t = jQuery.trim( t.replace( re, "" ) );
+					foundToken = true;
+				}
+			}
+
+			// See if there's still an expression, and that we haven't already
+			// matched a token
+			if ( t && !foundToken ) {
+				// Handle multiple expressions
+				if ( !t.indexOf(",") ) {
+					// Clean the result set
+					if ( context == ret[0] ) ret.shift();
+
+					// Merge the result sets
+					done = jQuery.merge( done, ret );
+
+					// Reset the context
+					r = ret = [context];
+
+					// Touch up the selector string
+					t = " " + t.substr(1,t.length);
+
+				} else {
+					// Optimize for the case nodeName#idName
+					var re2 = quickID;
+					var m = re2.exec(t);
+					
+					// Re-organize the results, so that they're consistent
+					if ( m ) {
+						m = [ 0, m[2], m[3], m[1] ];
+
+					} else {
+						// Otherwise, do a traditional filter check for
+						// ID, class, and element selectors
+						re2 = quickClass;
+						m = re2.exec(t);
+					}
+
+					m[2] = m[2].replace(/\\/g, "");
+
+					var elem = ret[ret.length-1];
+
+					// Try to do a global search by ID, where we can
+					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
+						// Optimization for HTML document case
+						var oid = elem.getElementById(m[2]);
+						
+						// Do a quick check for the existence of the actual ID attribute
+						// to avoid selecting by the name attribute in IE
+						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
+						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
+							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
+
+						// Do a quick check for node name (where applicable) so
+						// that div#foo searches will be really fast
+						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
+					} else {
+						// We need to find all descendant elements
+						for ( var i = 0; ret[i]; i++ ) {
+							// Grab the tag name being searched for
+							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
+
+							// Handle IE7 being really dumb about <object>s
+							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
+								tag = "param";
+
+							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
+						}
+
+						// It's faster to filter by class and be done with it
+						if ( m[1] == "." )
+							r = jQuery.classFilter( r, m[2] );
+
+						// Same with ID filtering
+						if ( m[1] == "#" ) {
+							var tmp = [];
+
+							// Try to find the element with the ID
+							for ( var i = 0; r[i]; i++ )
+								if ( r[i].getAttribute("id") == m[2] ) {
+									tmp = [ r[i] ];
+									break;
+								}
+
+							r = tmp;
+						}
+
+						ret = r;
+					}
+
+					t = t.replace( re2, "" );
+				}
+
+			}
+
+			// If a selector string still exists
+			if ( t ) {
+				// Attempt to filter it
+				var val = jQuery.filter(t,r);
+				ret = r = val.r;
+				t = jQuery.trim(val.t);
+			}
+		}
+
+		// An error occurred with the selector;
+		// just return an empty set instead
+		if ( t )
+			ret = [];
+
+		// Remove the root context
+		if ( ret && context == ret[0] )
+			ret.shift();
+
+		// And combine the results
+		done = jQuery.merge( done, ret );
+
+		return done;
+	},
+
+	classFilter: function(r,m,not){
+		m = " " + m + " ";
+		var tmp = [];
+		for ( var i = 0; r[i]; i++ ) {
+			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
+			if ( !not && pass || not && !pass )
+				tmp.push( r[i] );
+		}
+		return tmp;
+	},
+
+	filter: function(t,r,not) {
+		var last;
+
+		// Look for common filter expressions
+		while ( t && t != last ) {
+			last = t;
+
+			var p = jQuery.parse, m;
+
+			for ( var i = 0; p[i]; i++ ) {
+				m = p[i].exec( t );
+
+				if ( m ) {
+					// Remove what we just matched
+					t = t.substring( m[0].length );
+
+					m[2] = m[2].replace(/\\/g, "");
+					break;
+				}
+			}
+
+			if ( !m )
+				break;
+
+			// :not() is a special case that can be optimized by
+			// keeping it out of the expression list
+			if ( m[1] == ":" && m[2] == "not" )
+				// optimize if only one selector found (most common case)
+				r = isSimple.test( m[3] ) ?
+					jQuery.filter(m[3], r, true).r :
+					jQuery( r ).not( m[3] );
+
+			// We can get a big speed boost by filtering by class here
+			else if ( m[1] == "." )
+				r = jQuery.classFilter(r, m[2], not);
+
+			else if ( m[1] == "[" ) {
+				var tmp = [], type = m[3];
+				
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
+					
+					if ( z == null || /href|src|selected/.test(m[2]) )
+						z = jQuery.attr(a,m[2]) || '';
+
+					if ( (type == "" && !!z ||
+						 type == "=" && z == m[5] ||
+						 type == "!=" && z != m[5] ||
+						 type == "^=" && z && !z.indexOf(m[5]) ||
+						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
+						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
+							tmp.push( a );
+				}
+				
+				r = tmp;
+
+			// We can get a speed boost by handling nth-child here
+			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
+				var merge = {}, tmp = [],
+					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
+						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
+					// calculate the numbers (first)n+(last) including if they are negative
+					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
+ 
+				// loop through all the elements left in the jQuery object
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
+
+					if ( !merge[id] ) {
+						var c = 1;
+
+						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
+							if ( n.nodeType == 1 )
+								n.nodeIndex = c++;
+
+						merge[id] = true;
+					}
+
+					var add = false;
+
+					if ( first == 0 ) {
+						if ( node.nodeIndex == last )
+							add = true;
+					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
+						add = true;
+
+					if ( add ^ not )
+						tmp.push( node );
+				}
+
+				r = tmp;
+
+			// Otherwise, find the expression to execute
+			} else {
+				var fn = jQuery.expr[ m[1] ];
+				if ( typeof fn == "object" )
+					fn = fn[ m[2] ];
+
+				if ( typeof fn == "string" )
+					fn = eval("false||function(a,i){return " + fn + ";}");
+
+				// Execute it against the current filter
+				r = jQuery.grep( r, function(elem, i){
+					return fn(elem, i, m, r);
+				}, not );
+			}
+		}
+
+		// Return an array of filtered elements (r)
+		// and the modified expression string (t)
+		return { r: r, t: t };
+	},
+
+	dir: function( elem, dir ){
+		var matched = [];
+		var cur = elem[dir];
+		while ( cur && cur != document ) {
+			if ( cur.nodeType == 1 )
+				matched.push( cur );
+			cur = cur[dir];
+		}
+		return matched;
+	},
+	
+	nth: function(cur,result,dir,elem){
+		result = result || 1;
+		var num = 0;
+
+		for ( ; cur; cur = cur[dir] )
+			if ( cur.nodeType == 1 && ++num == result )
+				break;
+
+		return cur;
+	},
+	
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType == 1 && (!elem || n != elem) )
+				r.push( n );
+		}
+
+		return r;
+	}
+});
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code orignated from 
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function(elem, types, handler, data) {
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( jQuery.browser.msie && elem.setInterval != undefined )
+			elem = window;
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid )
+			handler.guid = this.guid++;
+			
+		// if data is passed, bind to handler 
+		if( data != undefined ) { 
+			// Create temporary function pointer to original handler 
+			var fn = handler; 
+
+			// Create unique handler function, wrapped around original handler 
+			handler = function() { 
+				// Pass arguments and context to original handler 
+				return fn.apply(this, arguments); 
+			};
+
+			// Store data in unique handler 
+			handler.data = data;
+
+			// Set the guid of unique handler to the same of original handler, so it can be removed 
+			handler.guid = fn.guid;
+		}
+
+		// Init the element's event structure
+		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+				// returned undefined or false
+				var val;
+
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				if ( typeof jQuery == "undefined" || jQuery.event.triggered )
+					return val;
+		
+				val = jQuery.event.handle.apply(arguments.callee.elem, arguments);
+		
+				return val;
+			});
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native
+		// event in IE.
+		handle.elem = elem;
+			
+			// Handle multiple events seperated by a space
+			// jQuery(...).bind("mouseover mouseout", fn);
+			jQuery.each(types.split(/\s+/), function(index, type) {
+				// Namespaced event handlers
+				var parts = type.split(".");
+				type = parts[0];
+				handler.type = parts[1];
+
+				// Get the current list of functions bound to this event
+				var handlers = events[type];
+
+				// Init the event handler queue
+				if (!handlers) {
+					handlers = events[type] = {};
+		
+					// Check for a special event handler
+					// Only use addEventListener/attachEvent if the special
+					// events handler returns false
+					if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
+						// Bind the global event handler to the element
+						if (elem.addEventListener)
+							elem.addEventListener(type, handle, false);
+						else if (elem.attachEvent)
+							elem.attachEvent("on" + type, handle);
+					}
+				}
+
+				// Add the function to the element's handler list
+				handlers[handler.guid] = handler;
+
+				// Keep track of which events have been used, for global triggering
+				jQuery.event.global[type] = true;
+			});
+		
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	guid: 1,
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function(elem, types, handler) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		var events = jQuery.data(elem, "events"), ret, index;
+
+		if ( events ) {
+			// Unbind all events for the element
+			if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
+				for ( var type in events )
+					this.remove( elem, type + (types || "") );
+			else {
+				// types is actually an event object here
+				if ( types.type ) {
+					handler = types.handler;
+					types = types.type;
+				}
+				
+				// Handle multiple events seperated by a space
+				// jQuery(...).unbind("mouseover mouseout", fn);
+				jQuery.each(types.split(/\s+/), function(index, type){
+					// Namespaced event handlers
+					var parts = type.split(".");
+					type = parts[0];
+					
+					if ( events[type] ) {
+						// remove the given handler for the given type
+						if ( handler )
+							delete events[type][handler.guid];
+			
+						// remove all handlers for the given type
+						else
+							for ( handler in events[type] )
+								// Handle the removal of namespaced events
+								if ( !parts[1] || events[type][handler].type == parts[1] )
+									delete events[type][handler];
+
+						// remove generic event handler if no more handlers exist
+						for ( ret in events[type] ) break;
+						if ( !ret ) {
+							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
+								if (elem.removeEventListener)
+									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+								else if (elem.detachEvent)
+									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+							}
+							ret = null;
+							delete events[type];
+						}
+					}
+				});
+			}
+
+			// Remove the expando if it's no longer used
+			for ( ret in events ) break;
+			if ( !ret ) {
+				var handle = jQuery.data( elem, "handle" );
+				if ( handle ) handle.elem = null;
+				jQuery.removeData( elem, "events" );
+				jQuery.removeData( elem, "handle" );
+			}
+		}
+	},
+
+	trigger: function(type, data, elem, donative, extra) {
+		// Clone the incoming data, if any
+		data = jQuery.makeArray(data || []);
+
+		if ( type.indexOf("!") >= 0 ) {
+			type = type.slice(0, -1);
+			var exclusive = true;
+		}
+
+		// Handle a global trigger
+		if ( !elem ) {
+			// Only trigger if we've ever bound an event for it
+			if ( this.global[type] )
+				jQuery("*").add([window, document]).trigger(type, data);
+
+		// Handle triggering a single element
+		} else {
+			// don't do events on text and comment nodes
+			if ( elem.nodeType == 3 || elem.nodeType == 8 )
+				return undefined;
+
+			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
+				// Check to see if we need to provide a fake event, or not
+				event = !data[0] || !data[0].preventDefault;
+			
+			// Pass along a fake event
+			if ( event )
+				data.unshift( this.fix({ type: type, target: elem }) );
+
+			// Enforce the right trigger type
+			data[0].type = type;
+			if ( exclusive )
+				data[0].exclusive = true;
+
+			// Trigger the event
+			if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
+				val = jQuery.data(elem, "handle").apply( elem, data );
+
+			// Handle triggering native .onfoo handlers
+			if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+				val = false;
+
+			// Extra functions don't get the custom event object
+			if ( event )
+				data.shift();
+
+			// Handle triggering of extra function
+			if ( extra && jQuery.isFunction( extra ) ) {
+				// call the extra function and tack the current return value on the end for possible inspection
+				ret = extra.apply( elem, val == null ? data : data.concat( val ) );
+				// if anything is returned, give it precedence and have it overwrite the previous value
+				if (ret !== undefined)
+					val = ret;
+			}
+
+			// Trigger the native events (except for clicks on links)
+			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+				this.triggered = true;
+				try {
+					elem[ type ]();
+				// prevent IE from throwing an error for some hidden elements
+				} catch (e) {}
+			}
+
+			this.triggered = false;
+		}
+
+		return val;
+	},
+
+	handle: function(event) {
+		// returned undefined or false
+		var val;
+
+		// Empty object is for triggered events with no data
+		event = jQuery.event.fix( event || window.event || {} ); 
+
+		// Namespaced event handlers
+		var parts = event.type.split(".");
+		event.type = parts[0];
+
+		var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
+		args.unshift( event );
+
+		for ( var j in handlers ) {
+			var handler = handlers[j];
+			// Pass in a reference to the handler function itself
+			// So that we can later remove it
+			args[0].handler = handler;
+			args[0].data = handler.data;
+
+			// Filter the functions by class
+			if ( !parts[1] && !event.exclusive || handler.type == parts[1] ) {
+				var ret = handler.apply( this, args );
+
+				if ( val !== false )
+					val = ret;
+
+				if ( ret === false ) {
+					event.preventDefault();
+					event.stopPropagation();
+				}
+			}
+		}
+
+		// Clean up added properties in IE to prevent memory leak
+		if (jQuery.browser.msie)
+			event.target = event.preventDefault = event.stopPropagation =
+				event.handler = event.data = null;
+
+		return val;
+	},
+
+	fix: function(event) {
+		// store a copy of the original event object 
+		// and clone to set read-only properties
+		var originalEvent = event;
+		event = jQuery.extend({}, originalEvent);
+		
+		// add preventDefault and stopPropagation since 
+		// they will not work on the clone
+		event.preventDefault = function() {
+			// if preventDefault exists run it on the original event
+			if (originalEvent.preventDefault)
+				originalEvent.preventDefault();
+			// otherwise set the returnValue property of the original event to false (IE)
+			originalEvent.returnValue = false;
+		};
+		event.stopPropagation = function() {
+			// if stopPropagation exists run it on the original event
+			if (originalEvent.stopPropagation)
+				originalEvent.stopPropagation();
+			// otherwise set the cancelBubble property of the original event to true (IE)
+			originalEvent.cancelBubble = true;
+		};
+		
+		// Fix target property, if necessary
+		if ( !event.target )
+			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+				
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType == 3 )
+			event.target = originalEvent.target.parentNode;
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement )
+			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement, body = document.body;
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+		}
+			
+		// Add which for key events
+		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+			event.which = event.charCode || event.keyCode;
+		
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey )
+			event.metaKey = event.ctrlKey;
+
+		// Add which for click: 1 == left; 2 == middle; 3 == right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button )
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+			
+		return event;
+	},
+	
+	special: {
+		ready: {
+			setup: function() {
+				// Make sure the ready event is setup
+				bindReady();
+				return;
+			},
+			
+			teardown: function() { return; }
+		},
+		
+		mouseenter: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+		
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+			
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseenter
+				arguments[0].type = "mouseenter";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		},
+	
+		mouseleave: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+		
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+			
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseleave
+				arguments[0].type = "mouseleave";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		}
+	}
+};
+
+jQuery.fn.extend({
+	bind: function( type, data, fn ) {
+		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+			jQuery.event.add( this, type, fn || data, fn && data );
+		});
+	},
+	
+	one: function( type, data, fn ) {
+		return this.each(function(){
+			jQuery.event.add( this, type, function(event) {
+				jQuery(this).unbind(event);
+				return (fn || data).apply( this, arguments);
+			}, fn && data);
+		});
+	},
+
+	unbind: function( type, fn ) {
+		return this.each(function(){
+			jQuery.event.remove( this, type, fn );
+		});
+	},
+
+	trigger: function( type, data, fn ) {
+		return this.each(function(){
+			jQuery.event.trigger( type, data, this, true, fn );
+		});
+	},
+
+	triggerHandler: function( type, data, fn ) {
+		if ( this[0] )
+			return jQuery.event.trigger( type, data, this[0], false, fn );
+		return undefined;
+	},
+
+	toggle: function() {
+		// Save reference to arguments for access in closure
+		var args = arguments;
+
+		return this.click(function(event) {
+			// Figure out which function to execute
+			this.lastToggle = 0 == this.lastToggle ? 1 : 0;
+			
+			// Make sure that clicks stop
+			event.preventDefault();
+			
+			// and execute the function
+			return args[this.lastToggle].apply( this, arguments ) || false;
+		});
+	},
+
+	hover: function(fnOver, fnOut) {
+		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
+	},
+	
+	ready: function(fn) {
+		// Attach the listeners
+		bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady )
+			// Execute the function immediately
+			fn.call( document, jQuery );
+			
+		// Otherwise, remember the function for later
+		else
+			// Add the function to the wait list
+			jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
+	
+		return this;
+	}
+});
+
+jQuery.extend({
+	isReady: false,
+	readyList: [],
+	// Handle when the DOM is ready
+	ready: function() {
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.isReady ) {
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+			
+			// If there are functions bound, to execute
+			if ( jQuery.readyList ) {
+				// Execute all of them
+				jQuery.each( jQuery.readyList, function(){
+					this.apply( document );
+				});
+				
+				// Reset the list of functions
+				jQuery.readyList = null;
+			}
+		
+			// Trigger any bound ready events
+			jQuery(document).triggerHandler("ready");
+		}
+	}
+});
+
+var readyBound = false;
+
+function bindReady(){
+	if ( readyBound ) return;
+	readyBound = true;
+
+	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
+	if ( document.addEventListener && !jQuery.browser.opera)
+		// Use the handy event callback
+		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
+	
+	// If IE is used and is not in a frame
+	// Continually check to see if the document is ready
+	if ( jQuery.browser.msie && window == top ) (function(){
+		if (jQuery.isReady) return;
+		try {
+			// If IE is used, use the trick by Diego Perini
+			// http://javascript.nwbox.com/IEContentLoaded/
+			document.documentElement.doScroll("left");
+		} catch( error ) {
+			setTimeout( arguments.callee, 0 );
+			return;
+		}
+		// and execute any waiting functions
+		jQuery.ready();
+	})();
+
+	if ( jQuery.browser.opera )
+		document.addEventListener( "DOMContentLoaded", function () {
+			if (jQuery.isReady) return;
+			for (var i = 0; i < document.styleSheets.length; i++)
+				if (document.styleSheets[i].disabled) {
+					setTimeout( arguments.callee, 0 );
+					return;
+				}
+			// and execute any waiting functions
+			jQuery.ready();
+		}, false);
+
+	if ( jQuery.browser.safari ) {
+		var numStyles;
+		(function(){
+			if (jQuery.isReady) return;
+			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			if ( numStyles === undefined )
+				numStyles = jQuery("style, link[rel=stylesheet]").length;
+			if ( document.styleSheets.length != numStyles ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			// and execute any waiting functions
+			jQuery.ready();
+		})();
+	}
+
+	// A fallback to window.onload, that will always work
+	jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
+	"submit,keydown,keypress,keyup,error").split(","), function(i, name){
+	
+	// Handle event binding
+	jQuery.fn[name] = function(fn){
+		return fn ? this.bind(name, fn) : this.trigger(name);
+	};
+});
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event, elem) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+	// Traverse up the tree
+	while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
+	// Return true if we actually just moused on to a sub-element
+	return parent == elem;
+};
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery(window).bind("unload", function() {
+	jQuery("*").add(document).unbind();
+});
+jQuery.fn.extend({
+	load: function( url, params, callback ) {
+		if ( jQuery.isFunction( url ) )
+			return this.bind("load", url);
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		callback = callback || function(){};
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params )
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else {
+				params = jQuery.param( params );
+				type = "POST";
+			}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function(res, status){
+				// If successful, inject the HTML into all the matched elements
+				if ( status == "success" || status == "notmodified" )
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div/>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+
+				self.each( callback, [res.responseText, status, res] );
+			}
+		});
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+	serializeArray: function() {
+		return this.map(function(){
+			return jQuery.nodeName(this, "form") ?
+				jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled && 
+				(this.checked || /select|textarea/i.test(this.nodeName) || 
+					/text|hidden|password/i.test(this.type));
+		})
+		.map(function(i, elem){
+			var val = jQuery(this).val();
+			return val == null ? null :
+				val.constructor == Array ?
+					jQuery.map( val, function(val, i){
+						return {name: elem.name, value: val};
+					}) :
+					{name: elem.name, value: val};
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+	jQuery.fn[o] = function(f){
+		return this.bind(o, f);
+	};
+});
+
+var jsc = (new Date).getTime();
+
+jQuery.extend({
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was ommited
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = null;
+		}
+		
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		global: true,
+		type: "GET",
+		timeout: 0,
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		data: null,
+		username: null,
+		password: null,
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			script: "text/javascript, application/javascript",
+			json: "application/json, text/javascript",
+			text: "text/plain",
+			_default: "*/*"
+		}
+	},
+	
+	// Last-Modified header cache for next request
+	lastModified: {},
+
+	ajax: function( s ) {
+		var jsonp, jsre = /=\?(&|$)/g, status, data;
+
+		// Extend the settings, but re-extend 's' so that it can be
+		// checked again later (in the test suite, specifically)
+		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data != "string" )
+			s.data = jQuery.param(s.data);
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType == "jsonp" ) {
+			if ( s.type.toLowerCase() == "get" ) {
+				if ( !s.url.match(jsre) )
+					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+			} else if ( !s.data || !s.data.match(jsre) )
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+			jsonp = "jsonp" + jsc++;
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data )
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			window[ jsonp ] = function(tmp){
+				data = tmp;
+				success();
+				complete();
+				// Garbage collect
+				window[ jsonp ] = undefined;
+				try{ delete window[ jsonp ]; } catch(e){}
+				if ( head )
+					head.removeChild( script );
+			};
+		}
+
+		if ( s.dataType == "script" && s.cache == null )
+			s.cache = false;
+
+		if ( s.cache === false && s.type.toLowerCase() == "get" ) {
+			var ts = (new Date()).getTime();
+			// try replacing _= if it is there
+			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for get requests
+		if ( s.data && s.type.toLowerCase() == "get" ) {
+			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+			// IE likes to send both get and post data, prevent this
+			s.data = null;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && ! jQuery.active++ )
+			jQuery.event.trigger( "ajaxStart" );
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get" ) {
+			var head = document.getElementsByTagName("head")[0];
+			var script = document.createElement("script");
+			script.src = s.url;
+			if (s.scriptCharset)
+				script.charset = s.scriptCharset;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function(){
+					if ( !done && (!this.readyState || 
+							this.readyState == "loaded" || this.readyState == "complete") ) {
+						done = true;
+						success();
+						complete();
+						head.removeChild( script );
+					}
+				};
+			}
+
+			head.appendChild(script);
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object; Microsoft failed to properly
+		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+		var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+
+		// Open the socket
+		xml.open(s.type, s.url, s.async, s.username, s.password);
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set the correct header, if data is being sent
+			if ( s.data )
+				xml.setRequestHeader("Content-Type", s.contentType);
+
+			// Set the If-Modified-Since header, if ifModified mode.
+			if ( s.ifModified )
+				xml.setRequestHeader("If-Modified-Since",
+					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+			// Set the Accepts header for the server, depending on the dataType
+			xml.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+				s.accepts[ s.dataType ] + ", */*" :
+				s.accepts._default );
+		} catch(e){}
+
+		// Allow custom headers/mimetypes
+		if ( s.beforeSend )
+			s.beforeSend(xml);
+			
+		if ( s.global )
+			jQuery.event.trigger("ajaxSend", [xml, s]);
+
+		// Wait for a response to come back
+		var onreadystatechange = function(isTimeout){
+			// The transfer is complete and the data is available, or the request timed out
+			if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
+				requestDone = true;
+				
+				// clear poll interval
+				if (ival) {
+					clearInterval(ival);
+					ival = null;
+				}
+				
+				status = isTimeout == "timeout" && "timeout" ||
+					!jQuery.httpSuccess( xml ) && "error" ||
+					s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
+					"success";
+
+				if ( status == "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xml, s.dataType );
+					} catch(e) {
+						status = "parsererror";
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status == "success" ) {
+					// Cache Last-Modified header, if ifModified mode.
+					var modRes;
+					try {
+						modRes = xml.getResponseHeader("Last-Modified");
+					} catch(e) {} // swallow exception thrown by FF if header is not available
+	
+					if ( s.ifModified && modRes )
+						jQuery.lastModified[s.url] = modRes;
+
+					// JSONP handles its own success callback
+					if ( !jsonp )
+						success();	
+				} else
+					jQuery.handleError(s, xml, status);
+
+				// Fire the complete handlers
+				complete();
+
+				// Stop memory leaks
+				if ( s.async )
+					xml = null;
+			}
+		};
+		
+		if ( s.async ) {
+			// don't attach the handler to the request, just poll it instead
+			var ival = setInterval(onreadystatechange, 13); 
+
+			// Timeout checker
+			if ( s.timeout > 0 )
+				setTimeout(function(){
+					// Check to see if the request is still happening
+					if ( xml ) {
+						// Cancel the request
+						xml.abort();
+	
+						if( !requestDone )
+							onreadystatechange( "timeout" );
+					}
+				}, s.timeout);
+		}
+			
+		// Send the data
+		try {
+			xml.send(s.data);
+		} catch(e) {
+			jQuery.handleError(s, xml, null, e);
+		}
+		
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async )
+			onreadystatechange();
+
+		function success(){
+			// If a local callback was specified, fire it and pass it the data
+			if ( s.success )
+				s.success( data, status );
+
+			// Fire the global callback
+			if ( s.global )
+				jQuery.event.trigger( "ajaxSuccess", [xml, s] );
+		}
+
+		function complete(){
+			// Process result
+			if ( s.complete )
+				s.complete(xml, status);
+
+			// The request was completed
+			if ( s.global )
+				jQuery.event.trigger( "ajaxComplete", [xml, s] );
+
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+		}
+		
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xml;
+	},
+
+	handleError: function( s, xml, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) s.error( xml, status, e );
+
+		// Fire the global callback
+		if ( s.global )
+			jQuery.event.trigger( "ajaxError", [xml, s, e] );
+	},
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( r ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !r.status && location.protocol == "file:" ||
+				( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
+				jQuery.browser.safari && r.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xml, url ) {
+		try {
+			var xmlRes = xml.getResponseHeader("Last-Modified");
+
+			// Firefox always returns 200. check Last-Modified date
+			return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
+				jQuery.browser.safari && xml.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	httpData: function( r, type ) {
+		var ct = r.getResponseHeader("content-type");
+		var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
+		var data = xml ? r.responseXML : r.responseText;
+
+		if ( xml && data.documentElement.tagName == "parsererror" )
+			throw "parsererror";
+
+		// If the type is "script", eval it in global context
+		if ( type == "script" )
+			jQuery.globalEval( data );
+
+		// Get the JavaScript object, if JSON is used.
+		if ( type == "json" )
+			data = eval("(" + data + ")");
+
+		return data;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a ) {
+		var s = [];
+
+		// If an array was passed in, assume that it is an array
+		// of form elements
+		if ( a.constructor == Array || a.jquery )
+			// Serialize the form elements
+			jQuery.each( a, function(){
+				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
+			});
+
+		// Otherwise, assume that it's an object of key/value pairs
+		else
+			// Serialize the key/values
+			for ( var j in a )
+				// If the value is an array then the key names need to be repeated
+				if ( a[j] && a[j].constructor == Array )
+					jQuery.each( a[j], function(){
+						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
+					});
+				else
+					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
+
+		// Return the resulting serialization
+		return s.join("&").replace(/%20/g, "+");
+	}
+
+});
+jQuery.fn.extend({
+	show: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "show", width: "show", opacity: "show"
+			}, speed, callback) :
+			
+			this.filter(":hidden").each(function(){
+				this.style.display = this.oldblock || "";
+				if ( jQuery.css(this,"display") == "none" ) {
+					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
+					this.style.display = elem.css("display");
+					// handle an edge condition where css is - div { display:none; } or similar
+					if (this.style.display == "none")
+						this.style.display = "block";
+					elem.remove();
+				}
+			}).end();
+	},
+	
+	hide: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "hide", width: "hide", opacity: "hide"
+			}, speed, callback) :
+			
+			this.filter(":visible").each(function(){
+				this.oldblock = this.oldblock || jQuery.css(this,"display");
+				this.style.display = "none";
+			}).end();
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+	
+	toggle: function( fn, fn2 ){
+		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+			this._toggle( fn, fn2 ) :
+			fn ?
+				this.animate({
+					height: "toggle", width: "toggle", opacity: "toggle"
+				}, fn, fn2) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+				});
+	},
+	
+	slideDown: function(speed,callback){
+		return this.animate({height: "show"}, speed, callback);
+	},
+	
+	slideUp: function(speed,callback){
+		return this.animate({height: "hide"}, speed, callback);
+	},
+
+	slideToggle: function(speed, callback){
+		return this.animate({height: "toggle"}, speed, callback);
+	},
+	
+	fadeIn: function(speed, callback){
+		return this.animate({opacity: "show"}, speed, callback);
+	},
+	
+	fadeOut: function(speed, callback){
+		return this.animate({opacity: "hide"}, speed, callback);
+	},
+	
+	fadeTo: function(speed,to,callback){
+		return this.animate({opacity: to}, speed, callback);
+	},
+	
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		return this[ optall.queue === false ? "each" : "queue" ](function(){
+			if ( this.nodeType != 1)
+				return false;
+
+			var opt = jQuery.extend({}, optall);
+			var hidden = jQuery(this).is(":hidden"), self = this;
+			
+			for ( var p in prop ) {
+				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+					return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
+
+				if ( p == "height" || p == "width" ) {
+					// Store display property
+					opt.display = jQuery.css(this, "display");
+
+					// Make sure that nothing sneaks out
+					opt.overflow = this.style.overflow;
+				}
+			}
+
+			if ( opt.overflow != null )
+				this.style.overflow = "hidden";
+
+			opt.curAnim = jQuery.extend({}, prop);
+			
+			jQuery.each( prop, function(name, val){
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( /toggle|show|hide/.test(val) )
+					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+				else {
+					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+						start = e.cur(true) || 0;
+
+					if ( parts ) {
+						var end = parseFloat(parts[2]),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit != "px" ) {
+							self.style[ name ] = (end || 1) + unit;
+							start = ((end || 1) / e.cur(true)) * start;
+							self.style[ name ] = start + unit;
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] )
+							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+						e.custom( start, end, unit );
+					} else
+						e.custom( start, val, "" );
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+	
+	queue: function(type, fn){
+		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
+			fn = type;
+			type = "fx";
+		}
+
+		if ( !type || (typeof type == "string" && !fn) )
+			return queue( this[0], type );
+
+		return this.each(function(){
+			if ( fn.constructor == Array )
+				queue(this, type, fn);
+			else {
+				queue(this, type).push( fn );
+			
+				if ( queue(this, type).length == 1 )
+					fn.apply(this);
+			}
+		});
+	},
+
+	stop: function(clearQueue, gotoEnd){
+		var timers = jQuery.timers;
+
+		if (clearQueue)
+			this.queue([]);
+
+		this.each(function(){
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- )
+				if ( timers[i].elem == this ) {
+					if (gotoEnd)
+						// force the next step to be the last
+						timers[i](true);
+					timers.splice(i, 1);
+				}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if (!gotoEnd)
+			this.dequeue();
+
+		return this;
+	}
+
+});
+
+var queue = function( elem, type, array ) {
+	if ( !elem )
+		return undefined;
+
+	type = type || "fx";
+
+	var q = jQuery.data( elem, type + "queue" );
+
+	if ( !q || array )
+		q = jQuery.data( elem, type + "queue", 
+			array ? jQuery.makeArray(array) : [] );
+
+	return q;
+};
+
+jQuery.fn.dequeue = function(type){
+	type = type || "fx";
+
+	return this.each(function(){
+		var q = queue(this, type);
+
+		q.shift();
+
+		if ( q.length )
+			q[0].apply( this );
+	});
+};
+
+jQuery.extend({
+	
+	speed: function(speed, easing, fn) {
+		var opt = speed && speed.constructor == Object ? speed : {
+			complete: fn || !fn && easing || 
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && easing.constructor != Function && easing
+		};
+
+		opt.duration = (opt.duration && opt.duration.constructor == Number ? 
+			opt.duration : 
+			{ slow: 600, fast: 200 }[opt.duration]) || 400;
+	
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function(){
+			if ( opt.queue !== false )
+				jQuery(this).dequeue();
+			if ( jQuery.isFunction( opt.old ) )
+				opt.old.apply( this );
+		};
+	
+		return opt;
+	},
+	
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+	
+	timers: [],
+	timerId: null,
+
+	fx: function( elem, options, prop ){
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig )
+			options.orig = {};
+	}
+
+});
+
+jQuery.fx.prototype = {
+
+	// Simple function for setting a style value
+	update: function(){
+		if ( this.options.step )
+			this.options.step.apply( this.elem, [ this.now, this ] );
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+		// Set display property to block for height/width animations
+		if ( this.prop == "height" || this.prop == "width" )
+			this.elem.style.display = "block";
+	},
+
+	// Get the current size
+	cur: function(force){
+		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
+			return this.elem[ this.prop ];
+
+		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function(from, to, unit){
+		this.startTime = (new Date()).getTime();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+		this.update();
+
+		var self = this;
+		function t(gotoEnd){
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		jQuery.timers.push(t);
+
+		if ( jQuery.timerId == null ) {
+			jQuery.timerId = setInterval(function(){
+				var timers = jQuery.timers;
+				
+				for ( var i = 0; i < timers.length; i++ )
+					if ( !timers[i]() )
+						timers.splice(i--, 1);
+
+				if ( !timers.length ) {
+					clearInterval( jQuery.timerId );
+					jQuery.timerId = null;
+				}
+			}, 13);
+		}
+	},
+
+	// Simple 'show' function
+	show: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		this.custom(0, this.cur());
+
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		if ( this.prop == "width" || this.prop == "height" )
+			this.elem.style[this.prop] = "1px";
+		
+		// Start by showing the element
+		jQuery(this.elem).show();
+	},
+
+	// Simple 'hide' function
+	hide: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function(gotoEnd){
+		var t = (new Date()).getTime();
+
+		if ( gotoEnd || t > this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			var done = true;
+			for ( var i in this.options.curAnim )
+				if ( this.options.curAnim[i] !== true )
+					done = false;
+
+			if ( done ) {
+				if ( this.options.display != null ) {
+					// Reset the overflow
+					this.elem.style.overflow = this.options.overflow;
+				
+					// Reset the display
+					this.elem.style.display = this.options.display;
+					if ( jQuery.css(this.elem, "display") == "none" )
+						this.elem.style.display = "block";
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide )
+					this.elem.style.display = "none";
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show )
+					for ( var p in this.options.curAnim )
+						jQuery.attr(this.elem.style, p, this.options.orig[p]);
+			}
+
+			// If a callback was provided, execute it
+			if ( done && jQuery.isFunction( this.options.complete ) )
+				// Execute the complete function
+				this.options.complete.apply( this.elem );
+
+			return false;
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+
+};
+
+jQuery.fx.step = {
+	scrollLeft: function(fx){
+		fx.elem.scrollLeft = fx.now;
+	},
+
+	scrollTop: function(fx){
+		fx.elem.scrollTop = fx.now;
+	},
+
+	opacity: function(fx){
+		jQuery.attr(fx.elem.style, "opacity", fx.now);
+	},
+
+	_default: function(fx){
+		fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+	}
+};
+// The Offset Method
+// Originally By Brandon Aaron, part of the Dimension Plugin
+// http://jquery.com/plugins/project/dimensions
+jQuery.fn.offset = function() {
+	var left = 0, top = 0, elem = this[0], results;
+	
+	if ( elem ) with ( jQuery.browser ) {
+		var parent       = elem.parentNode, 
+		    offsetChild  = elem,
+		    offsetParent = elem.offsetParent, 
+		    doc          = elem.ownerDocument,
+		    safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
+		    fixed        = jQuery.css(elem, "position") == "fixed";
+	
+		// Use getBoundingClientRect if available
+		if ( elem.getBoundingClientRect ) {
+			var box = elem.getBoundingClientRect();
+		
+			// Add the document scroll offsets
+			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+		
+			// IE adds the HTML element's border, by default it is medium which is 2px
+			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
+			// IE 7 standards mode, the border is always 2px
+			// This border/offset is typically represented by the clientLeft and clientTop properties
+			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
+			// Therefore this method will be off by 2px in IE while in quirksmode
+			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
+	
+		// Otherwise loop through the offsetParents and parentNodes
+		} else {
+		
+			// Initial element offsets
+			add( elem.offsetLeft, elem.offsetTop );
+			
+			// Get parent offsets
+			while ( offsetParent ) {
+				// Add offsetParent offsets
+				add( offsetParent.offsetLeft, offsetParent.offsetTop );
+			
+				// Mozilla and Safari > 2 does not include the border on offset parents
+				// However Mozilla adds the border for table or table cells
+				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
+					border( offsetParent );
+					
+				// Add the document scroll offsets if position is fixed on any offsetParent
+				if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
+					fixed = true;
+			
+				// Set offsetChild to previous offsetParent unless it is the body element
+				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
+				// Get next offsetParent
+				offsetParent = offsetParent.offsetParent;
+			}
+		
+			// Get parent scroll offsets
+			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
+				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
+				if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
+					// Subtract parent scroll offsets
+					add( -parent.scrollLeft, -parent.scrollTop );
+			
+				// Mozilla does not add the border for a parent that has overflow != visible
+				if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
+					border( parent );
+			
+				// Get next parent
+				parent = parent.parentNode;
+			}
+		
+			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
+			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
+			if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) || 
+				(mozilla && jQuery.css(offsetChild, "position") != "absolute") )
+					add( -doc.body.offsetLeft, -doc.body.offsetTop );
+			
+			// Add the document scroll offsets if position is fixed
+			if ( fixed )
+				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+		}
+
+		// Return an object with top and left properties
+		results = { top: top, left: left };
+	}
+
+	function border(elem) {
+		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
+	}
+
+	function add(l, t) {
+		left += parseInt(l) || 0;
+		top += parseInt(t) || 0;
+	}
+
+	return results;
+};
+
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each(["Height", "Width"], function(i, name){
+
+	var tl = name == "Height" ? "Top"    : "Left",  // top or left
+		br = name == "Height" ? "Bottom" : "Right"; // bottom or right
+	
+	// innerHeight and innerWidth
+	jQuery.fn["inner" + name] = function(){
+		return this[ name.toLowerCase() ]() + 
+			num(this, "padding" + tl) + 
+			num(this, "padding" + br);
+	};
+	
+	// outerHeight and outerWidth
+	jQuery.fn["outer" + name] = function(margin) {
+		return this["inner" + name]() + 
+			num(this, "border" + tl + "Width") +
+			num(this, "border" + br + "Width") +
+			(!!margin ? 
+				num(this, "margin" + tl) + num(this, "margin" + br) : 0);
+	};
+	
+});
+
+function num(elem, prop) {
+	elem = elem.jquery ? elem[0] : elem;
+	return elem && parseInt( jQuery.curCSS(elem, prop, true) ) || 0;
+}})();
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/loading.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/loading.gif
new file mode 100644
index 0000000..85b99d4
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/loading.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/pygments.css b/moksha/apps/widgetbrowser/widgetbrowser/static/pygments.css
new file mode 100644
index 0000000..a55a324
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/pygments.css
@@ -0,0 +1,59 @@
+.c { color: #408090; font-style: italic } /* Comment */
+.err { border: 1px solid #FF0000 } /* Error */
+.k { color: #007020; font-weight: bold } /* Keyword */
+.o { color: #666666 } /* Operator */
+.cm { color: #408090; font-style: italic } /* Comment.Multiline */
+.cp { color: #007020 } /* Comment.Preproc */
+.c1 { color: #408090; font-style: italic } /* Comment.Single */
+.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
+.gd { color: #A00000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #FF0000 } /* Generic.Error */
+.gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.gi { color: #00A000 } /* Generic.Inserted */
+.go { color: #303030 } /* Generic.Output */
+.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.gs { font-weight: bold } /* Generic.Strong */
+.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.gt { color: #0040D0 } /* Generic.Traceback */
+.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.kp { color: #007020 } /* Keyword.Pseudo */
+.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.kt { color: #902000 } /* Keyword.Type */
+.m { color: #208050 } /* Literal.Number */
+.s { color: #4070a0 } /* Literal.String */
+.na { color: #4070a0 } /* Name.Attribute */
+.nb { color: #007020 } /* Name.Builtin */
+.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.no { color: #60add5 } /* Name.Constant */
+.nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.ne { color: #007020 } /* Name.Exception */
+.nf { color: #06287e } /* Name.Function */
+.nl { color: #002070; font-weight: bold } /* Name.Label */
+.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.nt { color: #062873; font-weight: bold } /* Name.Tag */
+.nv { color: #bb60d5 } /* Name.Variable */
+.ow { color: #007020; font-weight: bold } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mf { color: #208050 } /* Literal.Number.Float */
+.mh { color: #208050 } /* Literal.Number.Hex */
+.mi { color: #208050 } /* Literal.Number.Integer */
+.mo { color: #208050 } /* Literal.Number.Oct */
+.sb { color: #4070a0 } /* Literal.String.Backtick */
+.sc { color: #4070a0 } /* Literal.String.Char */
+.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.s2 { color: #4070a0 } /* Literal.String.Double */
+.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.sh { color: #4070a0 } /* Literal.String.Heredoc */
+.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.sx { color: #c65d09 } /* Literal.String.Other */
+.sr { color: #235388 } /* Literal.String.Regex */
+.s1 { color: #4070a0 } /* Literal.String.Single */
+.ss { color: #517918 } /* Literal.String.Symbol */
+.bp { color: #007020 } /* Name.Builtin.Pseudo */
+.vc { color: #bb60d5 } /* Name.Variable.Class */
+.vg { color: #bb60d5 } /* Name.Variable.Global */
+.vi { color: #bb60d5 } /* Name.Variable.Instance */
+.il { color: #208050 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/tab.png b/moksha/apps/widgetbrowser/widgetbrowser/static/tab.png
new file mode 100644
index 0000000..413c755
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/tab.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css
new file mode 100644
index 0000000..f45ed75
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css
@@ -0,0 +1,12 @@
+ul.ui-accordion { margin: 0; padding: 0; list-style-type: none; }
+ul.ui-accordion li { margin: 0; margin-bottom: 2px; padding: 0; background-image: url(i/accordion-left.png); background-repeat: no-repeat; }
+ul.ui-accordion li a.ui-accordion-header { display: block; padding-left: 5px; margin-right: 3px; height: 28px; background-image: url(i/accordion-middle.png); color: #000; text-decoration: none; line-height: 28px; }
+ul.ui-accordion li .ui-accordion-right { display: block; background-image: url(i/accordion-right.png); position: absolute; top: 0px; right: 0px; height: 28px; width: 3px;  }
+
+ul.ui-accordion li:hover { background-image: url(i/accordion-left-over.png); }
+ul.ui-accordion li:hover a.ui-accordion-header { background-image: url(i/accordion-middle-over.png); }
+ul.ui-accordion li:hover .ui-accordion-right { background-image: url(i/accordion-right-over.png); }
+
+ul.ui-accordion li.active { background-image: url(i/accordion-left-act.png); }
+ul.ui-accordion li.active a.ui-accordion-header { background-image: url(i/accordion-middle-act.png); }
+ul.ui-accordion li.active .ui-accordion-right { background-image: url(i/accordion-right-act.png); }
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css
new file mode 100644
index 0000000..3de5386
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css
@@ -0,0 +1,9 @@
+ at import "flora.css";
+ at import "flora.shadow.css";
+ at import "flora.resizable.css";
+ at import "flora.slider.css";
+ at import "flora.accordion.css";
+ at import "flora.tabs.css";
+ at import "flora.dialog.css";
+ at import "flora.tablesorter.css";
+ at import "flora.datepicker.css";
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css
new file mode 100644
index 0000000..dedcf0c
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css
@@ -0,0 +1,167 @@
+/* Main Style Sheet for jQuery Calendar */
+#calendar_div, .calendar_inline {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 14px;
+	padding: 0;
+	margin: 0;
+	background: #ddd;
+}
+#calendar_div {
+	display: none;
+	border: 1px solid #FF9900;
+	z-index: 10; /*must have*/ 
+}
+#calendar_div, .calendar_control, .calendar_links, .calendar_header, .calendar {
+	width: 185px;
+}
+.calendar_inline {
+	float: left;
+	display: block;
+	border: 0;
+}
+.calendar_dialog {
+	padding: 5px !important;
+	border: 4px ridge #ddd !important;
+}
+button.calendar_trigger {
+	width: 25px;
+}
+img.calendar_trigger {
+	margin: 2px;
+	vertical-align: middle;
+}
+.calendar_prompt {
+	float: left;
+	width: 181px;
+	padding: 2px;
+	background: #ddd;
+	color: #000;
+}
+* html .calendar_prompt {
+	width: 185px;
+}
+.calendar_control, .calendar_links, .calendar_header, .calendar {
+	clear: both;
+	float: left;
+	color: #fff;
+}
+.calendar_control {
+	background: #FF9900;
+}
+.calendar_links {
+	background: #E0F4D7;
+}
+.calendar_control, .calendar_links {
+	font-weight: bold;
+	font-size: 80%;
+	letter-spacing: 1px;
+}
+.calendar_links label { /* disabled links */
+	padding: 2px 5px;
+	color: #888;
+}
+.calendar_clear, .calendar_prev {
+	float: left;
+}
+.calendar_current {
+	float: left;
+	width: 35%;
+	text-align: center;
+}
+.calendar_close, .calendar_next {
+	float: right;
+}
+.calendar_header {
+	background: #83C948;
+	text-align: center;
+	font-weight: bold;
+}
+.calendar_header select {
+	background: #83C948;
+	color: #000;
+	border: 0px;
+	font-weight: bold;
+}
+.calendar {
+	background: #ccc;
+	text-align: center;
+	font-size: 100%;
+}
+.calendar a {
+	display: block;
+	width: 100%;
+}
+.calendar .calendar_titleRow {
+	background: #B1DB87;
+	color: #000 !important;
+}
+.calendar .calendar_daysRow {
+	background: #FFF;
+	color: #666;
+}
+.calendar .calendar_daysCell {
+	color: #000;
+	border: 1px solid #ddd;
+}
+#calendar .calendar_daysCell a{
+	display: block;
+}
+.calendar .calendar_weekEndCell {
+	background: #E0F4D7;
+}
+.calendar .calendar_daysCellOver {
+	background: #fff;
+	border: 1px solid #777;
+}
+.calendar .calendar_unselectable {
+	color: #888;
+}
+.calendar_today {
+	background: #ccc !important;
+}
+.calendar_currentDay {
+	background: #999 !important;
+}
+
+/* ________ CALENDAR LINKS _______
+
+** Reset link properties and then override them with !important */
+#calendar_div a, .calendar_inline a {
+	cursor: pointer;
+	margin: 0;
+	padding: 0;
+	background: none;
+	color: #000;
+}
+.calendar_inline .calendar_links a {
+	padding: 0 5px !important;
+}
+.calendar_control a, .calendar_links a {
+	padding: 2px 5px !important;
+	color: #000 !important;
+}
+.calendar_titleRow a {
+	color: #000 !important;
+}
+.calendar_control a:hover {
+	/*background: #fdd !important;*/
+	color: #333 !important;
+}
+.calendar_links a:hover, .calendar_titleRow a:hover {
+	background: #FFF !important;
+	color: #333 !important;
+}
+
+/* ___________ IE6 IFRAME FIX ________ */
+
+.calendar_cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 193px; /*must have to match width and borders*/
+    height: 200px; /*must have to match maximum height*/ 
+}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.css
new file mode 100644
index 0000000..761217d
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.css
@@ -0,0 +1,2 @@
+.ui-wrapper { border: 1px solid #50A029; }
+.ui-wrapper input, .ui-wrapper textarea { border: 0; }
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css
new file mode 100644
index 0000000..34ea650
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css
@@ -0,0 +1,179 @@
+/* Main Flora Style Sheet for jQuery UI Datepicker */
+#datepicker_div, .datepicker_inline {
+	font-family: Arial,Helvetica,sans-serif;
+	font-size: 14px;
+	padding: 0;
+	margin: 0;
+	background: #DDD;
+	width: 185px;
+}
+#datepicker_div {
+	display: none;
+	border: 1px solid #FF9900;
+	z-index: 10;
+}
+.datepicker_inline {
+	float: left;
+	display: block;
+	border: 0;
+}
+.datepicker_dialog {
+	padding: 5px !important;
+	border: 4px ridge #DDD !important;
+}
+button.datepicker_trigger {
+	width: 25px;
+}
+img.datepicker_trigger {
+	margin: 2px;
+	vertical-align: middle;
+}
+.datepicker_prompt {
+	float: left;
+	padding: 2px;
+	background: #DDD;
+	color: #000;
+}
+*html .datepicker_prompt {
+	width: 185px;
+}
+.datepicker_control, .datepicker_links, .datepicker_header, .datepicker {
+	clear: both;
+	float: left;
+	width: 100%;
+	color: #FFF;
+}
+.datepicker_control {
+	background: #FF9900;
+	padding: 2px 0px;
+}
+.datepicker_links {
+	background: #E0F4D7;
+	padding: 2px 0px;
+}
+.datepicker_control, .datepicker_links {
+	font-weight: bold;
+	font-size: 80%;
+	letter-spacing: 1px;
+}
+.datepicker_links label {
+	padding: 2px 5px;
+	color: #888;
+}
+.datepicker_clear, .datepicker_prev {
+	float: left;
+	width: 34%;
+}
+.datepicker_current {
+	float: left;
+	width: 30%;
+	text-align: center;
+}
+.datepicker_close, .datepicker_next {
+	float: right;
+	width: 34%;
+	text-align: right;
+}
+.datepicker_header {
+	padding: 1px 0 3px;
+	background: #83C948;
+	text-align: center;
+	font-weight: bold;
+	height: 1.3em;
+}
+.datepicker_header select {
+	background: #83C948;
+	color: #000;
+	border: 0px;
+	font-weight: bold;
+}
+.datepicker {
+	background: #CCC;
+	text-align: center;
+	font-size: 100%;
+}
+.datepicker a {
+	display: block;
+	width: 100%;
+}
+.datepicker .datepicker_titleRow {
+	background: #B1DB87;
+	color: #000;
+}
+.datepicker .datepicker_daysRow {
+	background: #FFF;
+	color: #666;
+}
+.datepicker_weekCol {
+	background: #B1DB87;
+	color: #000;
+}
+.datepicker .datepicker_daysCell {
+	color: #000;
+	border: 1px solid #DDD;
+}
+#datepicker .datepicker_daysCell a {
+	display: block;
+}
+.datepicker .datepicker_weekEndCell {
+	background: #E0F4D7;
+}
+.datepicker .datepicker_daysCellOver {
+	background: #FFF;
+	border: 1px solid #777;
+}
+.datepicker .datepicker_unselectable {
+	color: #888;
+}
+.datepicker_today {
+	background: #B1DB87 !important;
+}
+.datepicker_currentDay {
+	background: #83C948 !important;
+}
+#datepicker_div a, .datepicker_inline a {
+	cursor: pointer;
+	margin: 0;
+	padding: 0;
+	background: none;
+	color: #000;
+}
+.datepicker_inline .datepicker_links a {
+	padding: 0 5px !important;
+}
+.datepicker_control a, .datepicker_links a {
+	padding: 2px 5px !important;
+	color: #000 !important;
+}
+.datepicker_titleRow a {
+	color: #000 !important;
+}
+.datepicker_control a:hover {
+	background: #FDD !important;
+	color: #333 !important;
+}
+.datepicker_links a:hover, .datepicker_titleRow a:hover {
+	background: #FFF !important;
+	color: #333 !important;
+}
+.datepicker_multi .datepicker {
+	border: 1px solid #83C948;
+}
+.datepicker_oneMonth {
+	float: left;
+	width: 185px;
+}
+.datepicker_newRow {
+	clear: left;
+}
+.datepicker_cover {
+	display: none;
+	display/**/: block;
+	position: absolute;
+	z-index: -1;
+	filter: mask();
+	top: -4px;
+	left: -4px;
+	width: 193px;
+	height: 200px;
+}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css
new file mode 100644
index 0000000..efef1c4
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css
@@ -0,0 +1,95 @@
+/* This file skins dialog */
+
+.flora .ui-dialog,
+.flora.ui-dialog {
+	background-color: #e6f7d4;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar,
+.flora.ui-dialog .ui-dialog-titlebar {
+	border-bottom: 1px solid #d8d2aa;
+	background: #ff9900 url(i/dialog-title.gif) repeat-x;
+	padding: 0px;
+	height: 28px;
+	_height: 29px;
+}
+
+.flora .ui-dialog.ui-draggable .ui-dialog-titlebar,
+.flora.ui-dialog.ui-draggable .ui-dialog-titlebar {
+	cursor: move;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar-close,
+.flora.ui-dialog .ui-dialog-titlebar-close {
+	width: 16px;
+	height: 16px;
+	background: url(i/dialog-titlebar-close.png) no-repeat;
+	position:absolute;
+	top: 6px;
+	right: 7px;
+	cursor: default;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar-close span,
+.flora.ui-dialog .ui-dialog-titlebar-close span {
+	display: none;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar-close-hover,
+.flora.ui-dialog .ui-dialog-titlebar-close-hover {
+	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
+}
+
+.flora .ui-dialog .ui-dialog-title,
+.flora.ui-dialog .ui-dialog-title {
+	margin-left: 5px;
+	color: white;
+	font-weight: bold;
+	position: relative;
+	top: 7px;
+	left: 4px;
+}
+
+.flora .ui-dialog .ui-dialog-content,
+.flora.ui-dialog .ui-dialog-content {
+	margin: 1.2em;
+}
+
+.flora .ui-dialog .ui-dialog-buttonpane,
+.flora.ui-dialog .ui-dialog-buttonpane {
+	position: absolute;
+	bottom: 8px;
+	right: 12px;
+	width: 100%;
+	text-align: right;
+}
+
+.flora .ui-dialog .ui-dialog-buttonpane button,
+.flora.ui-dialog .ui-dialog-buttonpane button {
+	margin: 6px;
+}
+
+/* Dialog handle styles */
+.flora .ui-dialog .ui-resizable-n,
+.flora.ui-dialog .ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/dialog-n.gif) repeat scroll center top; }
+
+.flora .ui-dialog .ui-resizable-s,
+.flora.ui-dialog .ui-resizable-s { cursor: s-resize; height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/dialog-s.gif) repeat scroll center top; }
+
+.flora .ui-dialog .ui-resizable-e,
+.flora.ui-dialog .ui-resizable-e { cursor: e-resize; width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-e.gif) repeat scroll right center; }
+
+.flora .ui-dialog .ui-resizable-w,
+.flora.ui-dialog .ui-resizable-w { cursor: w-resize; width: 7px; left: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-w.gif) repeat scroll right center; }
+
+.flora .ui-dialog .ui-resizable-se,
+.flora.ui-dialog .ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/dialog-se.gif); }
+
+.flora .ui-dialog .ui-resizable-sw,
+.flora.ui-dialog .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/dialog-sw.gif); }
+
+.flora .ui-dialog .ui-resizable-nw,
+.flora.ui-dialog .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/dialog-nw.gif); }
+
+.flora .ui-dialog .ui-resizable-ne,
+.flora.ui-dialog .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/dialog-ne.gif); }
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css
new file mode 100644
index 0000000..6d2dd21
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css
@@ -0,0 +1,8 @@
+.ui-menu-toolbar {z-index:500; list-style:none;}
+.ui-menu-toolbar-button {float:left; padding:4px 20px; cursor:pointer;}
+.ui-menu-toolbar-button:hover {}
+.ui-menu-toolbar-button a {text-decoration:none;}
+.ui-menu-items {display:none; padding:0; z-index:500; list-style:none; padding:1px 4px; min-width:80px; *width:80px;}
+.ui-menu-item a { text-decoration:none;}
+.ui-menu-item-parent { background: url('i/menu-submenu.gif') no-repeat center right; }
+.ui-menu-item-disabled {}
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css
new file mode 100644
index 0000000..5e30c0c
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css
@@ -0,0 +1,20 @@
+/* This file skins resizables */
+
+.ui-resizable { position: relative; }
+
+/* Global handle styles */
+.ui-resizable-handle { position: absolute; display: none; font-size: 0.1px; }
+.ui-resizable .ui-resizable-handle { display: block; }
+body .ui-resizable-disabled .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
+body .ui-resizable-autohide .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
+
+.ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/resizable-n.gif) repeat scroll center top; }
+.ui-resizable-s { cursor: s-resize; height: 6px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/resizable-s.gif) repeat scroll center top; }
+
+.ui-resizable-e { cursor: e-resize; width: 6px; right: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-e.gif) repeat scroll right center; }
+.ui-resizable-w { cursor: w-resize; width: 6px; left: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-w.gif) repeat scroll right center; }
+
+.ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/resizable-se.gif); }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/resizable-sw.gif); }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: 0px; top: 0px; background: transparent url(i/resizable-nw.gif); }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: 0px; top: 0px; background: transparent url(i/resizable-ne.gif); }
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css
new file mode 100644
index 0000000..94827b3
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css
@@ -0,0 +1,11 @@
+/* This file skins sliders */
+
+.ui-slider { width: 200px; height: 23px; position: relative; background-repeat: no-repeat; background-position: center center; }
+.ui-slider-handle { position: absolute; z-index: 1; height: 23px; width: 12px; top: 0px; left: 0px; background-image: url(i/slider-handle.gif);  }
+.ui-slider-handle-active { border: 1px dotted black;  }
+.ui-slider-disabled .ui-slider-handle { opacity: 0.5; filter: alpha(opacity=50); }
+.ui-slider-range { position: absolute; background: #50A029; opacity: 0.3; filter: alpha(opacity=30); width: 100%; height: 100%; }
+
+/* Default slider backgrounds */
+.ui-slider, .ui-slider-1 { background-image: url(i/slider-bg-1.png); }
+.ui-slider-2 { background-image: url(i/slider-bg-2.png); }
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css
new file mode 100644
index 0000000..7d805a7
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css
@@ -0,0 +1,40 @@
+/* This file skins tableSorter */
+
+table.tablesorter {
+	font-family:arial;
+	background-color: #CDCDCD;
+	margin:10px 0pt 15px;
+	font-size: 8pt;
+	width: 100%;
+	text-align: left;
+}
+table.tablesorter thead tr th, table.tablesorter tfoot tr th {
+	background-color: #B1DB87;
+	border: 1px solid #FFF;
+	font-size: 8pt;
+	padding: 4px;
+}
+table.tablesorter thead tr .header {
+	background-image: url(i/bg.gif);
+	background-repeat: no-repeat;
+	background-position: center right;
+	cursor: pointer;
+}
+table.tablesorter tbody td {
+	color: #3D3D3D;
+	padding: 4px;
+	background-color: #FFF;
+	vertical-align: top;
+}
+table.tablesorter tbody tr.odd td {
+	background-color:#E0F4D7;
+}
+table.tablesorter thead tr .headerSortUp {
+	background-image: url(i/asc.gif);
+}
+table.tablesorter thead tr .headerSortDown {
+	background-image: url(i/desc.gif);
+}
+table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
+background-color: #83C948;
+}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css
new file mode 100644
index 0000000..c79a17e
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css
@@ -0,0 +1,105 @@
+ at import "flora.css";
+
+/* Caution! Ensure accessibility in print and other media types... */
+ at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
+    .ui-tabs-hide {
+        display: none;
+    }
+}
+
+/* Hide useless elements in print layouts... */
+ at media print {
+    .ui-tabs-nav {
+        display: none;
+    }
+}
+
+/* Skin */
+.ui-tabs-nav, .ui-tabs-panel {
+    font-family: "Trebuchet MS", Trebuchet, Verdana, Helvetica, Arial, sans-serif;
+    font-size: 12px;
+}
+.ui-tabs-nav {
+    list-style: none;
+    margin: 0;
+    padding: 0 0 0 3px;
+}
+.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
+    display: block;
+    clear: both;
+    content: " ";
+}
+.ui-tabs-nav li {
+    float: left;
+    margin: 0 0 0 2px;
+    font-weight: bold;
+}
+.ui-tabs-nav a, .ui-tabs-nav a span {
+    float: left; /* fixes dir=ltr problem and other quirks IE */
+    padding: 0 12px;
+    background: url(i/tabs.png) no-repeat;
+}
+.ui-tabs-nav a {
+    margin: 5px 0 0; /* position: relative makes opacity fail for disabled tab in IE */
+    padding-left: 0;
+    background-position: 100% 0;
+    text-decoration: none;
+    white-space: nowrap; /* @ IE 6 */
+    outline: 0; /* @ Firefox, prevent dotted border after click */    
+}
+.ui-tabs-nav a:link, .ui-tabs-nav a:visited {
+    color: #fff;
+}
+.ui-tabs-nav .ui-tabs-selected a {
+    position: relative;
+    top: 1px;
+    z-index: 2;
+    margin-top: 0;
+    background-position: 100% -23px;
+}
+.ui-tabs-nav a span {
+    padding-top: 1px;
+    padding-right: 0;
+    height: 20px;
+    background-position: 0 0;
+    line-height: 20px;
+}
+.ui-tabs-nav .ui-tabs-selected a span {
+    padding-top: 0;
+    height: 27px;
+    background-position: 0 -23px;
+    line-height: 27px;
+}
+.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited,
+.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
+    cursor: text;
+}
+.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active,
+.ui-tabs-nav .ui-tabs-unselect a:hover, .ui-tabs-nav .ui-tabs-unselect a:focus, .ui-tabs-nav .ui-tabs-unselect a:active { /* @ Opera, we need to be explicit again here now... */
+    cursor: pointer;
+}
+.ui-tabs-disabled {
+    opacity: .4;
+    filter: alpha(opacity=40);
+}
+.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited {
+    color: #000;
+}
+.ui-tabs-panel {
+    border: 1px solid #519e2d;
+    padding: 10px;
+    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
+}
+/*.ui-tabs-loading em {
+    padding: 0 0 0 20px;
+    background: url(loading.gif) no-repeat 0 50%;
+}*/
+
+/* Additional IE specific bug fixes... */
+* html .ui-tabs-nav { /* auto clear @ IE 6 & IE 7 Quirks Mode */
+    display: inline-block;
+}
+*:first-child+html .ui-tabs-nav  { /* auto clear @ IE 7 Standards Mode - do not group selectors, otherwise IE 6 will ignore complete rule (because of the unknown + combinator)... */
+    display: inline-block;
+}
+
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css
new file mode 100644
index 0000000..6f2b55f
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css
@@ -0,0 +1,106 @@
+/* This file skins toasterLite */
+
+.flora .ui-toasterLite,
+.flora.ui-toasterLite {
+	background-color: #e6f7d4;
+	width: 100px;
+	display: block;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-titlebar,
+.flora.ui-toasterLite .ui-toasterLite-titlebar {
+	border-bottom: 1px solid #d8d2aa;
+	background: #ff9900 url(i/dialog-title.gif) repeat-x;
+	padding: 0px;
+	height: 28px;
+	z-index: 5;
+	position: relative;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-title,
+.flora.ui-toasterLite .ui-toasterLite-title {
+	margin-left: 5px;
+	color: white;
+	font-weight: bold;
+	position: relative;
+	top: 7px;
+	left: 4px;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-content,
+.flora.ui-toasterLite .ui-toasterLite-content {
+	margin: 1.2em;
+	padding-bottom: 12px;
+}
+
+/* Toaster handle styles */
+.flora .ui-toasterLite .ui-toasterLite-n,
+.flora.ui-toasterLite .ui-toasterLite-n { height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/toaster-n.gif) repeat scroll center top; z-index: 6; }
+
+.flora .ui-toasterLite .ui-toasterLite-s,
+.flora.ui-toasterLite .ui-toasterLite-s { height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/toaster-s.gif) repeat scroll center top; z-index: 1; }
+
+.flora .ui-toasterLite .ui-toasterLite-e,
+.flora.ui-toasterLite .ui-toasterLite-e { width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/toaster-e.gif) repeat scroll right center; }
+
+.flora .ui-toasterLite .ui-toasterLite-w,
+.flora.ui-toasterLite .ui-toasterLite-w { width: 7px; left: 0px; top: 0px; height: 100%; background: url(i/toaster-w.gif) repeat scroll right center; }
+
+.flora .ui-toasterLite .ui-toasterLite-se,
+.flora.ui-toasterLite .ui-toasterLite-se { width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/toaster-se.gif); z-index: 2; }
+
+.flora .ui-toasterLite .ui-toasterLite-sw,
+.flora.ui-toasterLite .ui-toasterLite-sw { width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/toaster-sw.gif); z-index: 2; }
+
+.flora .ui-toasterLite .ui-toasterLite-nw,
+.flora.ui-toasterLite .ui-toasterLite-nw { width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/toaster-nw.gif); z-index: 6; }
+
+.flora .ui-toasterLite .ui-toasterLite-ne,
+.flora.ui-toasterLite .ui-toasterLite-ne { width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/toaster-ne.gif); z-index: 6; }
+
+/* Global handle styles */
+.ui-toasterLite-corner { position: absolute; font-size: 0.1px; }
+
+.flora .ui-toasterLite-holder,
+.flora.ui-toasterLite-holder {
+  position: absolute;
+}
+.flora .ui-toasterLite-holder-pos-tr,
+.flora.ui-toasterLite-holder-pos-tr {
+  top: 10px;
+  right: 10px;
+}
+
+.flora .ui-toasterLite-holder-pos-tl,
+.flora.ui-toasterLite-holder-pos-tl {
+  top: 10px;
+  left: 10px;
+}
+
+.flora .ui-toasterLite-holder-pos-br,
+.flora.ui-toasterLite-holder-pos-br {
+  bottom: 10px;
+  right: 10px;
+}
+
+.flora .ui-toasterLite-holder-pos-bl,
+.flora.ui-toasterLite-holder-pos-bl {
+  bottom: 10px;
+  left: 10px;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-titlebar-close,
+.flora.ui-toasterLite .ui-toasterLite-titlebar-close {
+	width: 16px;
+	height: 16px;
+	background: url(i/dialog-titlebar-close.png) no-repeat;
+	position:absolute;
+	top: 6px;
+	right: 7px;
+	cursor: default;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-titlebar-close-hover,
+.flora.ui-toasterLite .ui-toasterLite-titlebar-close-hover {
+	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
+}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css
new file mode 100644
index 0000000..8ad0588
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css
@@ -0,0 +1,241 @@
+/* light.toolbar.css
+ *
+ *  Written: 05/09/07 4:38:01 PM
+ *  Revision: 1.0.0
+ *
+ *
+ * Credits:
+ *  Miksago: Full Coding.
+ */
+
+.flora .ui-toolbar {
+  position:relative;
+  padding:0px;
+  margin:0px;
+}
+.flora .ui-toolbar ul {
+  background:#E6F7D4;
+  padding:0px;
+  margin:0px;
+}
+  .flora .ui-toolbar ul li {
+    list-style-type: none;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-horiz {
+    border-top:1px solid #5AB500;
+    background:#E6F7D4 url("i/toolbars-bot-bg.gif") repeat-x bottom left;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-horiz li {
+    display:inline;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert {
+    padding: 0.025em 0em;
+    border-left: 1px solid #111;
+    border-right: 1px solid #444;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert li {
+    display:block;
+  }
+  /* This hides the text on buttons in a icon only toolbar */
+  .flora .ui-toolbar ul.ui-toolbar-icons li .ui-toolbar-btn-desc {
+    display:none;
+  }
+  /* This hides the icon on buttons in a text only toolbar */
+  .flora .ui-toolbar ul.ui-toolbar-text li .ui-toolbar-btn-icon {
+    display:none;
+  }
+  /* This is just for icon sizes, not really needed, but it's there so if icon sizes are defined.. */
+  .flora .ui-toolbar ul li.ui-toolbar-btn-icon-sixteen .ui-toolbar-btn-icon {
+    width:16px; height:16px;
+    overflow:hidden;
+    padding:2px;
+    padding-left:16px;
+    background:no-repeat;
+    background-position:50% 50%;
+  }
+  
+/************************************************
+ * Factory Elements:
+ *  - These are different kinds of items that
+ *    can be in a toolbar.
+ *
+ *  Includes:
+ *    @ ui-toolbar-btn
+ *        toolbar buttons.
+ *    @ ui-toolbar-sep
+ *        toolbar separators.
+ *
+*/
+
+
+
+/************************************************
+ * UI-TOOLBAR-BTN
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-btn">
+ *      <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
+ *      <span class="ui-toolbar-btn-center">
+ *        <button><span>{{text}}</span></button>
+ *      </span>
+ *      <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
+ *    </li>
+ *
+ ************************************************/
+
+
+  .flora .ui-toolbar ul li.ui-toolbar-btn {
+    cursor:pointer;
+    white-space: nowrap;
+    position:relative;
+  }
+  .flora .ui-toolbar ul li .ui-toolbar-btn-left {
+    width:3px;
+    padding:5px 0px 1px 0;
+    position:absolute;
+    top:-3px;
+    bottom:0px;
+    left:-3px;
+    height:100%;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
+    width:3px; height:5px;
+    padding:0px 0px 0px 0px;
+    position:absolute;
+    bottom:0px;
+    left:0px;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center{
+    background:url("i/accordion-middle-over.png") repeat-x left top;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left {
+    background:url("i/accordion-left-over.png") no-repeat left top;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
+    background:url("i/accordion-left-over.png") no-repeat left bottom;
+  }
+  .flora .ui-toolbar ul li .ui-toolbar-btn-center {
+    padding: 0.2em 0em;
+    line-height:2.2em;
+  }
+    .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-btn {
+      vertical-align: middle;
+      margin:0.3em 0.2em;
+    }
+    .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-btn {
+      margin:0.2em;
+      line-height:1.6em;
+      vertical-align: middle;
+    }
+      .flora .ui-toolbar ul li button {
+        vertical-align: middle;
+        background:transparent;
+        color:#000;
+        border:0px none;
+        cursor:pointer;
+        overflow:visible;
+        -moz-outline:0 none;
+        outline:0 none;
+        padding: 0.1em 0.1em;
+      }
+        .flora .ui-toolbar ul li.ui-toolbar-btn button span {
+          vertical-align: middle;
+        }
+        /* This hides the text on buttons in a icon only toolbar */
+        .flora .ui-toolbar ul.ui-toobar-iconOnly li.ui-toolbar-btn button span {
+          display:none;
+        }
+  
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center button,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center button {
+    background: url("i/accordion-middle-over.png") repeat-x left bottom;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active {
+    
+  }
+  
+  .flora .ui-toolbar ul li.ui-toolbar-btn-disabled {
+    opacity:0.2;
+  }
+
+/************************************************
+ * UI-TOOLBAR-BTN
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-sep">
+ *      <span>
+ *        &nbsp;
+ *      </span>
+ *    </li>
+ *
+ ************************************************/
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-sep {
+    border-left:1px solid #444;
+    border-right:1px solid #111;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-sep {
+    border-top:1px solid #111;
+    border-bottom:1px solid #444;
+  }
+
+/************************************************
+ * UI-TOOLBAR-SLIDER
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-slider">
+ *      <div class="ui-toolbar-slider-track ui-slider-track">
+ *        <div class="ui-slider-handle"></div>
+ *      </div>
+ *   </li>
+ *
+ ************************************************/
+
+.flora .ui-toolbar ul li.ui-toolbar-slider .ui-toolbar-slider-track {
+  height: 20px!important;
+}
+
+/************************************************
+ * UI-TOOLBAR-RADIOGRP
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-radioGrp">
+ *      <ul class="DIRECTION">
+ *        <li class="ui-toolbar-btn">
+ *          <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
+ *          <span class="ui-toolbar-btn-center">
+ *            <button><span>{{text}}</span></button>
+ *          </span>
+ *          <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
+ *        </li>
+ *      </ul>
+ *    </li>
+ *      
+ *
+ ************************************************/
+
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp,
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul,
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul li{
+    display:inline;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul {
+    margin:0px;
+    padding:0px;
+  }
+
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp,
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul,
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul li{
+    display:block;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul {
+    margin:0px;
+    padding:0px;
+  }
+
+
+/* END OF FILE */
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png
new file mode 100644
index 0000000..bf6ee99
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png
new file mode 100644
index 0000000..66378e0
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png
new file mode 100644
index 0000000..13344fc
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png
new file mode 100644
index 0000000..cecf4f1
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png
new file mode 100644
index 0000000..251ad11
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png
new file mode 100644
index 0000000..5238fd4
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png
new file mode 100644
index 0000000..1fa4792
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png
new file mode 100644
index 0000000..d676dad
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png
new file mode 100644
index 0000000..543991a
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif
new file mode 100644
index 0000000..7415786
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif
new file mode 100644
index 0000000..fac668f
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif
new file mode 100644
index 0000000..3b30b3c
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif
new file mode 100644
index 0000000..3b8b521
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif
new file mode 100644
index 0000000..70887b8
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif
new file mode 100644
index 0000000..ab9c38e
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif
new file mode 100644
index 0000000..e934073
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif
new file mode 100644
index 0000000..d5f6b99
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif
new file mode 100644
index 0000000..186a864
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif
new file mode 100644
index 0000000..025dfda
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif
new file mode 100644
index 0000000..156c59b
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png
new file mode 100644
index 0000000..67c1303
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png
new file mode 100644
index 0000000..cec974c
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif
new file mode 100644
index 0000000..931ff4a
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif
new file mode 100644
index 0000000..77647d8
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif
new file mode 100644
index 0000000..7acf248
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif
new file mode 100644
index 0000000..59110f6
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif
new file mode 100644
index 0000000..515a3f8
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif
new file mode 100644
index 0000000..665f318
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif
new file mode 100644
index 0000000..da2fb35
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif
new file mode 100644
index 0000000..6c258ef
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif
new file mode 100644
index 0000000..2fd8de4
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif
new file mode 100644
index 0000000..34b875b
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png
new file mode 100644
index 0000000..4c58c7f
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png
new file mode 100644
index 0000000..b7d806e
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png
new file mode 100644
index 0000000..8b24cf0
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif
new file mode 100644
index 0000000..9b89f26
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png
new file mode 100644
index 0000000..8018e41
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif
new file mode 100644
index 0000000..55dcb2c
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif
new file mode 100644
index 0000000..b0fbeb9
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif
new file mode 100644
index 0000000..ab9c38e
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif
new file mode 100644
index 0000000..e934073
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif
new file mode 100644
index 0000000..15640e8
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif
new file mode 100644
index 0000000..fb7a7df
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif
new file mode 100644
index 0000000..ad1ae1c
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif
new file mode 100644
index 0000000..8489de8
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif
new file mode 100644
index 0000000..15640e8
Binary files /dev/null and b/moksha/apps/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif differ
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.base.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.base.js
new file mode 100644
index 0000000..17115f0
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.base.js
@@ -0,0 +1,204 @@
+/*
+ * jQuery UI @VERSION
+ *
+ * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ *
+ * $Date: 2008-04-01 09:23:47 -0400 (Tue, 01 Apr 2008) $
+ * $Rev: 5174 $
+ */
+;(function($) {
+
+	//If the UI scope is not available, add it
+	$.ui = $.ui || {};
+	
+	//Add methods that are vital for all mouse interaction stuff (plugin registering)
+	$.extend($.ui, {
+		plugin: {
+			add: function(module, option, set) {
+				var proto = $.ui[module].prototype;
+				for(var i in set) {
+					proto.plugins[i] = proto.plugins[i] || [];
+					proto.plugins[i].push([option, set[i]]);
+				}
+			},
+			call: function(instance, name, arguments) {
+				var set = instance.plugins[name]; if(!set) return;
+				for (var i = 0; i < set.length; i++) {
+					if (instance.options[set[i][0]]) set[i][1].apply(instance.element, arguments);
+				}
+			}	
+		},
+		cssCache: {},
+		css: function(name) {
+			if ($.ui.cssCache[name]) return $.ui.cssCache[name];
+			var tmp = $('<div class="ui-resizable-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
+			
+			//if (!$.browser.safari)
+				//tmp.appendTo('body'); 
+			
+			//Opera and Safari set width and height to 0px instead of auto
+			//Safari returns rgba(0,0,0,0) when bgcolor is not set
+			$.ui.cssCache[name] = !!(
+				(!/auto|default/.test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 
+				!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
+			);
+			try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
+			return $.ui.cssCache[name];
+		},
+		disableSelection: function(e) {
+			e.unselectable = "on";
+			e.onselectstart = function() {	return false; };
+			if (e.style) e.style.MozUserSelect = "none";
+		},
+		enableSelection: function(e) {
+			e.unselectable = "off";
+			e.onselectstart = function() { return true; };
+			if (e.style) e.style.MozUserSelect = "";
+		},
+		hasScroll: function(e, a) {
+      		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;
+      		if (e[scroll] > 0) return true; e[scroll] = 1;
+      		has = e[scroll] > 0 ? true : false; e[scroll] = 0;
+      		return has; 
+    	}
+	});
+
+	/******* fn scope modifications ********/
+
+	$.each( ['Left', 'Top'], function(i, name) {
+		if(!$.fn['scroll'+name]) $.fn['scroll'+name] = function(v) {
+			return v != undefined ?
+				this.each(function() { this == window || this == document ? window.scrollTo(name == 'Left' ? v : $(window)['scrollLeft'](), name == 'Top'  ? v : $(window)['scrollTop']()) : this['scroll'+name] = v; }) :
+				this[0] == window || this[0] == document ? self[(name == 'Left' ? 'pageXOffset' : 'pageYOffset')] || $.boxModel && document.documentElement['scroll'+name] || document.body['scroll'+name] : this[0][ 'scroll' + name ];
+		};
+	});
+
+	var _remove = $.fn.remove;
+	$.fn.extend({
+		position: function() {
+			var offset       = this.offset();
+			var offsetParent = this.offsetParent();
+			var parentOffset = offsetParent.offset();
+
+			return {
+				top:  offset.top - num(this[0], 'marginTop')  - parentOffset.top - num(offsetParent, 'borderTopWidth'),
+				left: offset.left - num(this[0], 'marginLeft')  - parentOffset.left - num(offsetParent, 'borderLeftWidth')
+			};
+		},
+		offsetParent: function() {
+			var offsetParent = this[0].offsetParent;
+			while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
+				offsetParent = offsetParent.offsetParent;
+			return $(offsetParent);
+		},
+		mouseInteraction: function(o) {
+			return this.each(function() {
+				new $.ui.mouseInteraction(this, o);
+			});
+		},
+		removeMouseInteraction: function(o) {
+			return this.each(function() {
+				if($.data(this, "ui-mouse"))
+					$.data(this, "ui-mouse").destroy();
+			});
+		},
+		remove: function() {
+			jQuery("*", this).add(this).trigger("remove");
+			return _remove.apply(this, arguments );
+		}
+	});
+	
+	function num(el, prop) {
+		return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
+	};
+	
+	
+	/********** Mouse Interaction Plugin *********/
+	
+	$.ui.mouseInteraction = function(element, options) {
+	
+		var self = this;
+		this.element = element;
+
+		$.data(this.element, "ui-mouse", this);
+		this.options = $.extend({}, options);
+		
+		$(element).bind('mousedown.draggable', function() { return self.click.apply(self, arguments); });
+		if($.browser.msie) $(element).attr('unselectable', 'on'); //Prevent text selection in IE
+		
+		// prevent draggable-options-delay bug #2553
+		$(element).mouseup(function() {
+			if(self.timer) clearInterval(self.timer);
+		});
+	};
+	
+	$.extend($.ui.mouseInteraction.prototype, {
+		
+		destroy: function() { $(this.element).unbind('mousedown.draggable'); },
+		trigger: function() { return this.click.apply(this, arguments); },
+		click: function(e) {
+			
+			if(
+				   e.which != 1 //only left click starts dragging
+				|| $.inArray(e.target.nodeName.toLowerCase(), this.options.dragPrevention || []) != -1 // Prevent execution on defined elements
+				|| (this.options.condition && !this.options.condition.apply(this.options.executor || this, [e, this.element])) //Prevent execution on condition
+			) return true;
+				
+			var self = this;
+			var initialize = function() {
+				self._MP = { left: e.pageX, top: e.pageY }; // Store the click mouse position
+				$(document).bind('mouseup.draggable', function() { return self.stop.apply(self, arguments); });
+				$(document).bind('mousemove.draggable', function() { return self.drag.apply(self, arguments); });
+				
+				if(!self.initalized && Math.abs(self._MP.left-e.pageX) >= self.options.distance || Math.abs(self._MP.top-e.pageY) >= self.options.distance) {				
+					if(self.options.start) self.options.start.call(self.options.executor || self, e, self.element);
+					if(self.options.drag) self.options.drag.call(self.options.executor || self, e, this.element); //This is actually not correct, but expected
+					self.initialized = true;
+				}
+			};
+
+			if(this.options.delay) {
+				if(this.timer) clearInterval(this.timer);
+				this.timer = setTimeout(initialize, this.options.delay);
+			} else {
+				initialize();
+			}
+				
+			return false;
+			
+		},
+		stop: function(e) {			
+			
+			var o = this.options;
+			if(!this.initialized) return $(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
+
+			if(this.options.stop) this.options.stop.call(this.options.executor || this, e, this.element);
+			$(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
+			this.initialized = false;
+			return false;
+			
+		},
+		drag: function(e) {
+
+			var o = this.options;
+			if ($.browser.msie && !e.button) return this.stop.apply(this, [e]); // IE mouseup check
+			
+			if(!this.initialized && (Math.abs(this._MP.left-e.pageX) >= o.distance || Math.abs(this._MP.top-e.pageY) >= o.distance)) {				
+				if(this.options.start) this.options.start.call(this.options.executor || this, e, this.element);
+				this.initialized = true;
+			} else {
+				if(!this.initialized) return false;
+			}
+
+			if(o.drag) o.drag.call(this.options.executor || this, e, this.element);
+			return false;
+			
+		}
+	});
+	
+})(jQuery);
+ 
\ No newline at end of file
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.dialog.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.dialog.js
new file mode 100644
index 0000000..7a907bd
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.dialog.js
@@ -0,0 +1,459 @@
+/*
+ * jQuery UI Dialog
+ *
+ * Copyright (c) 2008 Richard D. Worth (rdworth.org)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *   ui.base.js
+ *   ui.draggable.js
+ *   ui.resizable.js
+ *
+ * Revision: $Id: ui.dialog.js 5185 2008-04-03 15:39:51Z scott.gonzalez $
+ */
+;(function($) {
+	
+	$.fn.extend({
+		dialog: function(options) {
+			var args = Array.prototype.slice.call(arguments, 1);
+
+			return this.each(function() {
+				if (typeof options == "string") {
+					var elem = $(this).is('.ui-dialog')
+						? this
+						: $(this).parents(".ui-dialog:first").find(".ui-dialog-content")[0];
+					var dialog = elem ? $.data(elem, "dialog") : {};
+					if (dialog[options])
+						dialog[options].apply(dialog, args);
+				// INIT with optional options
+				} else if (!$(this).is(".ui-dialog-content"))
+					new $.ui.dialog(this, options);
+			});
+		}
+	});
+
+	$.ui.dialog = function(el, options) {
+		
+		this.options = options = $.extend({}, $.ui.dialog.defaults, options);
+		this.element = el;
+		var self = this; //Do bindings
+
+		$.data(this.element, "dialog", this);
+
+		$(el).bind("remove", function() {
+			self.destroy();
+		});
+		
+		$(el).bind("setData.dialog", function(event, key, value){
+			switch (key) {
+				case "draggable":
+					uiDialog.draggable(value ? 'enable' : 'disable');
+					break;
+				case "dragStart":
+					uiDialog.data('start.draggable', value);
+					break;
+				case "drag":
+					uiDialog.data('drag.draggable', value);
+					break;
+				case "dragStop":
+					uiDialog.data('stop.draggable', value);
+					break;
+				case "height":
+					uiDialog.height(value);
+					break;
+				case "maxHeight":
+				case "minHeight":
+				case "maxWidth":
+				case "minWidth":
+					uiDialog.data(key + ".resizable", value);
+					break;
+				case "position":
+					self.position(value);
+					break;
+				case "resizable":
+					uiDialog.resizable(value ? 'enable' : 'disable');
+					break;
+				case "resizeStart":
+					uiDialog.data('start.resizable', value);
+					break;
+				case "resize":
+					uiDialog.data('resize.resizable', value);
+					break;
+				case "resizeStop":
+					uiDialog.data('stop.resizable', value);
+					break;
+				case "title":
+					$(".ui-dialog-title", uiDialogTitlebar).text(value);
+					break;
+				case "width":
+					break;
+			}
+			options[key] = value;
+		}).bind("getData.dialog", function(event, key){
+			return options[key];
+		});
+
+		var uiDialogContent = $(el).addClass('ui-dialog-content');
+
+		if (!uiDialogContent.parent().length) {
+			uiDialogContent.appendTo('body');
+		}
+		uiDialogContent
+			.wrap(document.createElement('div'))
+			.wrap(document.createElement('div'));
+		var uiDialogContainer = uiDialogContent.parent().addClass('ui-dialog-container').css({position: 'relative'});
+		var uiDialog = this.uiDialog = uiDialogContainer.parent().hide()
+			.addClass('ui-dialog')
+			.css({position: 'absolute', width: options.width, height: options.height, overflow: 'hidden'}); 
+
+		var classNames = uiDialogContent.attr('className').split(' ');
+
+		// Add content classes to dialog, to inherit theme at top level of element
+		$.each(classNames, function(i, className) {
+			if (className != 'ui-dialog-content')
+				uiDialog.addClass(className);
+		});
+
+		if ($.fn.resizable) {
+			uiDialog.append('<div class="ui-resizable-n ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-s ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-e ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-w ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-ne ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-se ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-sw ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-nw ui-resizable-handle"></div>');
+			uiDialog.resizable({
+				maxWidth: options.maxWidth,
+				maxHeight: options.maxHeight,
+				minWidth: options.minWidth,
+				minHeight: options.minHeight,
+				start: options.resizeStart,
+				resize: options.resize,
+				stop: function(e, ui) {
+					options.resizeStop && options.resizeStop.apply(this, arguments);
+					$.ui.dialog.overlay.resize();
+				}
+			});
+			if (!options.resizable)
+				uiDialog.resizable('disable');
+		}
+
+		uiDialogContainer.prepend('<div class="ui-dialog-titlebar"></div>');
+		var uiDialogTitlebar = $('.ui-dialog-titlebar', uiDialogContainer);
+		var title = (options.title) ? options.title : (uiDialogContent.attr('title')) ? uiDialogContent.attr('title') : '';
+		uiDialogTitlebar.append('<span class="ui-dialog-title">' + title + '</span>');
+		uiDialogTitlebar.append('<a href="#" class="ui-dialog-titlebar-close"><span>X</span></a>');
+		this.uiDialogTitlebarClose = $('.ui-dialog-titlebar-close', uiDialogTitlebar)
+			.hover(function() { $(this).addClass('ui-dialog-titlebar-close-hover'); }, 
+			       function() { $(this).removeClass('ui-dialog-titlebar-close-hover'); })
+			.mousedown(function(ev) {
+				ev.stopPropagation();
+			})
+			.click(function() {
+				self.close();
+				return false;
+			})
+			.keydown(function(ev) {
+				var ESC = 27;
+				ev.keyCode && ev.keyCode == ESC && self.close(); 
+			});
+
+		var l = 0;
+		$.each(options.buttons, function() { l = 1; return false; });
+		if (l == 1) {
+			uiDialog.append('<div class="ui-dialog-buttonpane"></div>');
+			var uiDialogButtonPane = $('.ui-dialog-buttonpane', uiDialog);
+			$.each(options.buttons, function(name, value) {
+				var btn = $(document.createElement('button')).text(name).click(value);
+				uiDialogButtonPane.append(btn);
+			});
+		}
+
+		if ($.fn.draggable) {
+			uiDialog.draggable({
+				handle: '.ui-dialog-titlebar',
+				start: function(e, ui) {
+					self.activate();
+					options.dragStart && options.dragStart.apply(this, arguments);
+				},
+				drag: options.drag,
+				stop: function(e, ui) {
+					options.dragStop && options.dragStop.apply(this, arguments);
+					$.ui.dialog.overlay.resize();
+				}
+			});
+			if (!options.draggable)
+				uiDialog.draggable('disable')
+		}
+	
+		uiDialog.mousedown(function() {
+			self.activate();
+		});
+		uiDialogTitlebar.click(function() {
+			self.activate();
+		});
+		
+		options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe();
+
+		this.position = function(pos) {
+			var wnd = $(window), doc = $(document), top = doc.scrollTop(), left = doc.scrollLeft();
+			if (pos.constructor == Array) {
+				// [x, y]
+				top += pos[1];
+				left += pos[0];
+			} else {
+				switch (pos) {
+					case 'center':
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+						break;
+					case 'top':
+						top += 0;
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+						break;
+					case 'right':
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += (wnd.width()) - (uiDialog.width());
+						break;
+					case 'bottom':
+						top += (wnd.height()) - (uiDialog.height());
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+						break;
+					case 'left':
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += 0;
+						break;
+					default:
+						//center
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+				}
+			}
+			top = top < doc.scrollTop() ? doc.scrollTop() : top;
+			uiDialog.css({top: top, left: left});
+		}
+		
+		this.open = function() {
+			this.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
+			uiDialog.appendTo('body');
+			this.position(options.position);
+			uiDialog.show();
+			self.moveToTop();
+			self.activate();
+			
+			// CALLBACK: open
+			var openEV = null;
+			var openUI = {
+				options: options
+			};
+			this.uiDialogTitlebarClose.focus();
+			$(this.element).triggerHandler("dialogopen", [openEV, openUI], options.open);
+		};
+
+		this.activate = function() {
+			// Move modeless dialogs to the top when they're activated.  Even
+			// if there is a modal dialog in the window, the modeless dialog
+			// should be on top because it must have been opened after the modal
+			// dialog.  Modal dialogs don't get moved to the top because that
+			// would make any modeless dialogs that it spawned unusable until
+			// the modal dialog is closed.
+			!options.modal && this.moveToTop();
+		};
+		
+		this.moveToTop = function() {
+			var maxZ = options.zIndex;
+			$('.ui-dialog:visible').each(function() {
+				maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10) || options.zIndex);
+			});
+			this.overlay && this.overlay.$el.css('z-index', ++maxZ);
+			uiDialog.css('z-index', ++maxZ);
+		};
+		
+		this.close = function() {
+			this.overlay && this.overlay.destroy();
+			uiDialog.hide();
+
+			// CALLBACK: close
+			var closeEV = null;
+			var closeUI = {
+				options: options
+			};
+			$(this.element).triggerHandler("dialogclose", [closeEV, closeUI], options.close);
+			$.ui.dialog.overlay.resize();
+		};
+
+		this.destroy = function() {
+			this.overlay && this.overlay.destroy();
+			uiDialog.hide();
+			$(el).unbind('.dialog').removeClass('ui-dialog-content').hide().appendTo('body');
+			uiDialog.remove();
+			$.removeData(this.element, "dialog");
+		};
+		
+		if (options.autoOpen) {
+			this.open();
+		};
+	};
+	
+	$.extend($.ui.dialog, {
+		defaults: {
+			autoOpen: true,
+			bgiframe: false,
+			buttons: [],
+			draggable: true,
+			height: 200,
+			minHeight: 100,
+			minWidth: 150,
+			modal: false,
+			overlay: {},
+			position: 'center',
+			resizable: true,
+			width: 300,
+			zIndex: 1000
+		},
+		
+		overlay: function(dialog) {
+			this.$el = $.ui.dialog.overlay.create(dialog);
+		}
+	});
+	
+	$.extend($.ui.dialog.overlay, {
+		instances: [],
+		events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
+			function(e) { return e + '.dialog-overlay'; }).join(' '),
+		create: function(dialog) {
+			if (this.instances.length === 0) {
+				// prevent use of anchors and inputs
+				$('a, :input').bind(this.events, function() {
+					// allow use of the element if inside a dialog and
+					// - there are no modal dialogs
+					// - there are modal dialogs, but we are in front of the
+					//   topmost modal dialog
+					var allow = false;
+					var $dialog = $(this).parents('.ui-dialog');
+					if ($dialog.length) {
+						var $overlays = $('.ui-dialog-overlay');
+						if ($overlays.length) {
+							var maxZ = parseInt($overlays.css('z-index'), 10);
+							$overlays.each(function() {
+								maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10));
+							});
+							allow = parseInt($dialog.css('z-index'), 10) > maxZ;
+						} else {
+							allow = true;
+						}
+					}
+					return allow;
+				});
+				
+				// allow closing by pressing the escape key
+				$(document).bind('keydown.dialog-overlay', function(e) {
+					var ESC = 27;
+					e.keyCode && e.keyCode == ESC && dialog.close(); 
+				});
+				
+				// handle window resize
+				$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+			}
+			
+			var $el = $('<div/>').appendTo(document.body)
+				.addClass('ui-dialog-overlay').css($.extend({
+					borderWidth: 0, margin: 0, padding: 0,
+					position: 'absolute', top: 0, left: 0,
+					width: this.width(),
+					height: this.height()
+				}, dialog.options.overlay));
+			
+			dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe();
+			
+			this.instances.push($el);
+			return $el;
+		},
+		
+		destroy: function($el) {
+			this.instances.splice($.inArray(this.instances, $el), 1);
+			
+			if (this.instances.length === 0) {
+				$('a, :input').add([document, window]).unbind('.dialog-overlay');
+			}
+			
+			$el.remove();
+		},
+		
+		height: function() {
+			if ($.browser.msie && $.browser.version < 7) {
+				var scrollHeight = Math.max(
+					document.documentElement.scrollHeight,
+					document.body.scrollHeight
+				);
+				var offsetHeight = Math.max(
+					document.documentElement.offsetHeight,
+					document.body.offsetHeight
+				);
+				
+				if (scrollHeight < offsetHeight) {
+					return $(window).height() + 'px';
+				} else {
+					return scrollHeight + 'px';
+				}
+			} else {
+				return $(document).height() + 'px';
+			}
+		},
+		
+		width: function() {
+			if ($.browser.msie && $.browser.version < 7) {
+				var scrollWidth = Math.max(
+					document.documentElement.scrollWidth,
+					document.body.scrollWidth
+				);
+				var offsetWidth = Math.max(
+					document.documentElement.offsetWidth,
+					document.body.offsetWidth
+				);
+				
+				if (scrollWidth < offsetWidth) {
+					return $(window).width() + 'px';
+				} else {
+					return scrollWidth + 'px';
+				}
+			} else {
+				return $(document).width() + 'px';
+			}
+		},
+		
+		resize: function() {
+			/* If the dialog is draggable and the user drags it past the
+			 * right edge of the window, the document becomes wider so we
+			 * need to stretch the overlay.  If the user then drags the
+			 * dialog back to the left, the document will become narrower,
+			 * so we need to shrink the overlay to the appropriate size.
+			 * This is handled by shrinking the overlay before setting it
+			 * to the full document size.
+			 */
+			var $overlays = $([]);
+			$.each($.ui.dialog.overlay.instances, function() {
+				$overlays = $overlays.add(this);
+			});
+			
+			$overlays.css({
+				width: 0,
+				height: 0
+			}).css({
+				width: $.ui.dialog.overlay.width(),
+				height: $.ui.dialog.overlay.height()
+			});
+		}
+	});
+	
+	$.extend($.ui.dialog.overlay.prototype, {
+		destroy: function() {
+			$.ui.dialog.overlay.destroy(this.$el);
+		}
+	});
+
+})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.draggable.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.draggable.js
new file mode 100644
index 0000000..ce209db
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.draggable.js
@@ -0,0 +1,572 @@
+/*
+ * jQuery UI Draggable
+ *
+ * Copyright (c) 2008 Paul Bakaus
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *   ui.base.js
+ *
+ * Revision: $Id: ui.draggable.js 5194 2008-04-04 12:30:10Z paul.bakaus $
+ */
+;(function($) {
+
+	$.fn.extend({
+		draggable: function(options) {
+			var args = Array.prototype.slice.call(arguments, 1);
+			
+			return this.each(function() {
+				if (typeof options == "string") {
+					var drag = $.data(this, "draggable");
+					if(drag) drag[options].apply(drag, args);
+
+				} else if(!$.data(this, "draggable"))
+					new $.ui.draggable(this, options);
+			});
+		}
+	});
+	
+	$.ui.draggable = function(element, options) {
+		//Initialize needed constants
+		var self = this;
+		
+		this.element = $(element);
+		
+		$.data(element, "draggable", this);
+		this.element.addClass("ui-draggable");
+		
+		//Prepare the passed options
+		this.options = $.extend({}, options);
+		var o = this.options;
+		$.extend(o, {
+			helper: o.ghosting == true ? 'clone' : (o.helper || 'original'),
+			handle : o.handle ? ($(o.handle, element)[0] ? $(o.handle, element) : this.element) : this.element,
+			appendTo: o.appendTo || 'parent'		
+		});
+		
+		$(element).bind("setData.draggable", function(event, key, value){
+			self.options[key] = value;
+		}).bind("getData.draggable", function(event, key){
+			return self.options[key];
+		});
+		
+		//Initialize mouse events for interaction
+		$(o.handle).mouseInteraction({
+			executor: this,
+			delay: o.delay,
+			distance: o.distance || 1,
+			dragPrevention: o.cancel || o.cancel === '' ? o.cancel.toLowerCase().split(',') : ['input','textarea','button','select','option'],
+			start: this.start,
+			stop: this.stop,
+			drag: this.drag,
+			condition: function(e) { return !(e.target.className.indexOf("ui-resizable-handle") != -1 || this.options.disabled); }
+		});
+		
+		//Position the node
+		if(o.helper == 'original' && (this.element.css('position') == 'static' || this.element.css('position') == ''))
+			this.element.css('position', 'relative');
+			
+		//Prepare cursorAt
+		if(o.cursorAt && o.cursorAt.constructor == Array)
+			o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] };
+		
+	};
+	
+	$.extend($.ui.draggable.prototype, {
+		plugins: {},
+		ui: function(e) {
+			return {
+				helper: this.helper,
+				position: this.position,
+				absolutePosition: this.positionAbs,
+				instance: this,
+				options: this.options,
+				element: this.element				
+			};
+		},
+		propagate: function(n,e) {
+			$.ui.plugin.call(this, n, [e, this.ui()]);
+			return this.element.triggerHandler(n == "drag" ? n : "drag"+n, [e, this.ui()], this.options[n]);
+		},
+		destroy: function() {
+			if(!$.data(this.element[0], 'draggable')) return;
+			this.options.handle.removeMouseInteraction();
+			this.element
+				.removeClass("ui-draggable ui-draggable-disabled")
+				.removeData("draggable")
+				.unbind(".draggable");
+		},
+		enable: function() {
+			this.element.removeClass("ui-draggable-disabled");
+			this.options.disabled = false;
+		},
+		disable: function() {
+			this.element.addClass("ui-draggable-disabled");
+			this.options.disabled = true;
+		},
+		setContrains: function(minLeft,maxLeft,minTop,maxTop) {
+			this.minLeft = minLeft; this.maxLeft = maxLeft;
+			this.minTop = minTop; this.maxTop = maxTop;
+			this.constrainsSet = true;
+		},
+		checkConstrains: function() {
+			if(!this.constrainsSet) return;
+			if(this.position.left < this.minLeft) this.position.left = this.minLeft;
+			if(this.position.left > this.maxLeft - this.helperProportions.width) this.position.left = this.maxLeft - this.helperProportions.width;
+			if(this.position.top < this.minTop) this.position.top = this.minTop;
+			if(this.position.top > this.maxTop - this.helperProportions.height) this.position.top = this.maxTop - this.helperProportions.height;
+		},
+		recallOffset: function(e) {
+
+			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
+			var r = this.helper.css('position') == 'relative';
+
+			//Generate the original position
+			this.originalPosition = {
+				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
+				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
+			};
+			
+			//Generate a flexible offset that will later be subtracted from e.pageX/Y
+			this.offset = {left: this._pageX - this.originalPosition.left, top: this._pageY - this.originalPosition.top };
+			
+		},
+		start: function(e) {
+			var o = this.options;
+			if($.ui.ddmanager) $.ui.ddmanager.current = this;
+			
+			//Create and append the visible helper
+			this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e])) : (o.helper == 'clone' ? this.element.clone().appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)) : this.element);
+			if(this.helper[0] != this.element[0]) this.helper.css('position', 'absolute');
+			if(!this.helper.parents('body').length) this.helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
+			
+			
+			//Find out the next positioned parent
+			this.offsetParent = (function(cp) {
+				while(cp) {
+					if(cp.style && (/(absolute|relative|fixed)/).test($.css(cp,'position'))) return $(cp);
+					cp = cp.parentNode ? cp.parentNode : null;
+				}; return $("body");		
+			})(this.helper[0].parentNode);
+			
+			//Prepare variables for position generation
+			this.elementOffset = this.element.offset();
+			this.offsetParentOffset = this.offsetParent.offset();
+			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
+			this._pageX = e.pageX; this._pageY = e.pageY;
+			this.clickOffset = { left: e.pageX - this.elementOffset.left, top: e.pageY - this.elementOffset.top };
+			var r = this.helper.css('position') == 'relative';
+
+			//Generate the original position
+			this.originalPosition = {
+				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
+				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
+			};
+			
+			//If we have a fixed element, we must subtract the scroll offset again
+			if(this.element.css('position') == 'fixed') {
+				this.originalPosition.top -= this.offsetParent[0] == document.body ? $(document).scrollTop() : this.offsetParent[0].scrollTop;
+				this.originalPosition.left -= this.offsetParent[0] == document.body ? $(document).scrollLeft() : this.offsetParent[0].scrollLeft;
+			}
+			
+			//Generate a flexible offset that will later be subtracted from e.pageX/Y
+			this.offset = {left: e.pageX - this.originalPosition.left, top: e.pageY - this.originalPosition.top };
+			
+			//Substract margins
+			if(this.element[0] != this.helper[0]) {
+				this.offset.left += parseInt(this.element.css('marginLeft'),10) || 0;
+				this.offset.top += parseInt(this.element.css('marginTop'),10) || 0;
+			}
+			
+			//Call plugins and callbacks
+			this.propagate("start", e);
+
+			this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };
+			if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e);
+			
+			//If we have something in cursorAt, we'll use it
+			if(o.cursorAt) {
+				if(o.cursorAt.top != undefined || o.cursorAt.bottom != undefined) {
+					this.offset.top -= this.clickOffset.top - (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
+					this.clickOffset.top = (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
+				}
+				if(o.cursorAt.left != undefined || o.cursorAt.right != undefined) {
+					this.offset.left -= this.clickOffset.left - (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
+					this.clickOffset.left = (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
+				}
+			}
+
+			return false;
+
+		},
+		clear: function() {
+			if($.ui.ddmanager) $.ui.ddmanager.current = null;
+			this.helper = null;
+		},
+		stop: function(e) {
+
+			//If we are using droppables, inform the manager about the drop
+			if ($.ui.ddmanager && !this.options.dropBehaviour)
+				$.ui.ddmanager.drop(this, e);
+				
+			//Call plugins and trigger callbacks
+			this.propagate("stop", e);
+			
+			if(this.cancelHelperRemoval) return false;			
+			if(this.options.helper != 'original') this.helper.remove();
+			this.clear();
+
+			return false;
+		},
+		drag: function(e) {
+
+			//Compute the helpers position
+			this.position = { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left };
+			this.positionAbs = { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top };
+
+			//Call plugins and callbacks
+			this.checkConstrains();			
+			this.position = this.propagate("drag", e) || this.position;
+			this.checkConstrains();
+			
+			$(this.helper).css({ left: this.position.left+'px', top: this.position.top+'px' }); // Stick the helper to the cursor
+			if($.ui.ddmanager) $.ui.ddmanager.drag(this, e);
+			return false;
+			
+		}
+	});
+	
+/*
+ * Draggable Extensions
+ */
+	 
+	$.ui.plugin.add("draggable", "cursor", {
+		start: function(e, ui) {
+			var t = $('body');
+			if (t.css("cursor")) ui.options._cursor = t.css("cursor");
+			t.css("cursor", ui.options.cursor);
+		},
+		stop: function(e, ui) {
+			if (ui.options._cursor) $('body').css("cursor", ui.options._cursor);
+		}
+	});
+
+	$.ui.plugin.add("draggable", "zIndex", {
+		start: function(e, ui) {
+			var t = $(ui.helper);
+			if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex");
+			t.css('zIndex', ui.options.zIndex);
+		},
+		stop: function(e, ui) {
+			if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex);
+		}
+	});
+
+	$.ui.plugin.add("draggable", "opacity", {
+		start: function(e, ui) {
+			var t = $(ui.helper);
+			if(t.css("opacity")) ui.options._opacity = t.css("opacity");
+			t.css('opacity', ui.options.opacity);
+		},
+		stop: function(e, ui) {
+			if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity);
+		}
+	});
+
+
+	$.ui.plugin.add("draggable", "revert", {
+		stop: function(e, ui) {
+			var self = ui.instance, helper = $(self.helper);
+			self.cancelHelperRemoval = true;
+			
+			$(ui.helper).animate({ left: self.originalPosition.left, top: self.originalPosition.top }, parseInt(ui.options.revert, 10) || 500, function() {
+				if(ui.options.helper != 'original') helper.remove();
+				if (!helper) self.clear();
+			});
+		}
+	});
+
+	$.ui.plugin.add("draggable", "iframeFix", {
+		start: function(e, ui) {
+
+			var o = ui.options;
+			if(ui.instance.slowMode) return; // Make clones on top of iframes (only if we are not in slowMode)
+			
+			if(o.iframeFix.constructor == Array) {
+				for(var i=0;i<o.iframeFix.length;i++) {
+					var co = $(o.iframeFix[i]).offset({ border: false });
+					$('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width", $(o.iframeFix[i])[0].offsetWidth+"px").css("height", $(o.iframeFix[i])[0].offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
+				}		
+			} else {
+				$("iframe").each(function() {					
+					var co = $(this).offset({ border: false });
+					$('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width", this.offsetWidth+"px").css("height", this.offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
+				});							
+			}
+
+		},
+		stop: function(e, ui) {
+			if(ui.options.iframeFix) $("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers	
+		}
+	});
+	
+	$.ui.plugin.add("draggable", "containment", {
+		start: function(e, ui) {
+
+			var o = ui.options;
+			var self = ui.instance;
+			if((o.containment.left != undefined || o.containment.constructor == Array) && !o._containment) return;
+			if(!o._containment) o._containment = o.containment;
+
+			if(o._containment == 'parent') o._containment = this[0].parentNode;
+			if(o._containment == 'document') {
+				o.containment = [
+					0,
+					0,
+					$(document).width(),
+					($(document).height() || document.body.parentNode.scrollHeight)
+				];
+			} else { //I'm a node, so compute top/left/right/bottom
+
+				var ce = $(o._containment)[0];
+				var co = $(o._containment).offset();
+
+				o.containment = [
+					co.left,
+					co.top,
+					co.left+(ce.offsetWidth || ce.scrollWidth),
+					co.top+(ce.offsetHeight || ce.scrollHeight)
+				];
+			}
+			
+			var c = o.containment;
+			ui.instance.setContrains(
+				c[0] - (self.offset.left - self.clickOffset.left), //min left
+				c[2] - (self.offset.left - self.clickOffset.left), //max left
+				c[1] - (self.offset.top - self.clickOffset.top), //min top
+				c[3] - (self.offset.top - self.clickOffset.top) //max top
+			);
+
+		}
+	});
+
+	$.ui.plugin.add("draggable", "grid", {
+		drag: function(e, ui) {
+			var o = ui.options;
+			var newLeft = ui.instance.originalPosition.left + Math.round((e.pageX - ui.instance._pageX) / o.grid[0]) * o.grid[0];
+			var newTop = ui.instance.originalPosition.top + Math.round((e.pageY - ui.instance._pageY) / o.grid[1]) * o.grid[1];
+			
+			ui.instance.position.left = newLeft;
+			ui.instance.position.top = newTop;
+
+		}
+	});
+
+	$.ui.plugin.add("draggable", "axis", {
+		drag: function(e, ui) {
+			var o = ui.options;
+			if(o.constraint) o.axis = o.constraint; //Legacy check
+			switch (o.axis) {
+				case 'x' : ui.instance.position.top = ui.instance.originalPosition.top; break;
+				case 'y' : ui.instance.position.left = ui.instance.originalPosition.left; break;
+			}
+		}
+	});
+
+	$.ui.plugin.add("draggable", "scroll", {
+		start: function(e, ui) {
+			var o = ui.options;
+			o.scrollSensitivity	= o.scrollSensitivity || 20;
+			o.scrollSpeed		= o.scrollSpeed || 20;
+
+			ui.instance.overflowY = function(el) {
+				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode);
+				return $(document);
+			}(this);
+			ui.instance.overflowX = function(el) {
+				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode);
+				return $(document);
+			}(this);
+		},
+		drag: function(e, ui) {
+			
+			var o = ui.options;
+			var i = ui.instance;
+
+			if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') {
+				if(i.overflowY[0].offsetHeight - (ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
+					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed;
+				if((ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
+					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;				
+			} else {
+				//$(document.body).append('<p>'+(e.pageY - $(document).scrollTop())+'</p>');
+				if(e.pageY - $(document).scrollTop() < o.scrollSensitivity)
+					$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+				if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+					$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+			}
+			
+			if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') {
+				if(i.overflowX[0].offsetWidth - (ui.position.left - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
+					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed;
+				if((ui.position.top - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
+					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;				
+			} else {
+				if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+					$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+				if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+					$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+			}
+			
+			ui.instance.recallOffset(e);
+
+		}
+	});
+	
+	$.ui.plugin.add("draggable", "snap", {
+		start: function(e, ui) {
+			
+			ui.instance.snapElements = [];
+			$(ui.options.snap === true ? '.ui-draggable' : ui.options.snap).each(function() {
+				var $t = $(this); var $o = $t.offset();
+				if(this != ui.instance.element[0]) ui.instance.snapElements.push({
+					item: this,
+					width: $t.outerWidth(),
+					height: $t.outerHeight(),
+					top: $o.top,
+					left: $o.left
+				});
+			});
+			
+		},
+		drag: function(e, ui) {
+
+			var d = ui.options.snapTolerance || 20;
+			var x1 = ui.absolutePosition.left, x2 = x1 + ui.instance.helperProportions.width,
+			    y1 = ui.absolutePosition.top, y2 = y1 + ui.instance.helperProportions.height;
+
+			for (var i = ui.instance.snapElements.length - 1; i >= 0; i--){
+
+				var l = ui.instance.snapElements[i].left, r = l + ui.instance.snapElements[i].width, 
+				    t = ui.instance.snapElements[i].top,  b = t + ui.instance.snapElements[i].height;
+
+				//Yes, I know, this is insane ;)
+				if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) continue;
+
+				if(ui.options.snapMode != 'inner') {
+					var ts = Math.abs(t - y2) <= 20;
+					var bs = Math.abs(b - y1) <= 20;
+					var ls = Math.abs(l - x2) <= 20;
+					var rs = Math.abs(r - x1) <= 20;
+					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
+					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top;
+					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
+					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left;
+				}
+				
+				if(ui.options.snapMode != 'outer') {
+					var ts = Math.abs(t - y1) <= 20;
+					var bs = Math.abs(b - y2) <= 20;
+					var ls = Math.abs(l - x1) <= 20;
+					var rs = Math.abs(r - x2) <= 20;
+					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top;
+					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
+					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left;
+					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
+				}
+
+			};
+		}
+	});
+	
+	$.ui.plugin.add("draggable", "connectToSortable", {
+		start: function(e,ui) {
+			ui.instance.sortable = $.data($(ui.options.connectToSortable)[0], 'sortable');
+			ui.instance.sortableOffset = ui.instance.sortable.element.offset();
+			ui.instance.sortableOuterWidth = ui.instance.sortable.element.outerWidth();
+			ui.instance.sortableOuterHeight = ui.instance.sortable.element.outerHeight();
+			if(ui.instance.sortable.options.revert) ui.instance.sortable.shouldRevert = true;
+		},
+		stop: function(e,ui) {
+			//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
+			var inst = ui.instance.sortable;
+			if(inst.isOver) {
+				inst.isOver = 0;
+				ui.instance.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
+				inst.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
+				if(inst.shouldRevert) inst.options.revert = true; //revert here
+				inst.stop(e);
+				inst.options.helper = "original";
+			}
+		},
+		drag: function(e,ui) {
+			//This is handy: We reuse the intersectsWith method for checking if the current draggable helper
+			//intersects with the sortable container
+			var inst = ui.instance.sortable;
+			ui.instance.position.absolute = ui.absolutePosition; //Sorry, this is an ugly API fix
+			
+			if(inst.intersectsWith.call(ui.instance, {
+				left: ui.instance.sortableOffset.left, top: ui.instance.sortableOffset.top,
+				width: ui.instance.sortableOuterWidth, height: ui.instance.sortableOuterHeight
+			})) {
+				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
+				if(!inst.isOver) {
+					inst.isOver = 1;
+					
+					//Cache the width/height of the new helper
+					var height = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerHeight() : $(inst.options.items, inst.element).innerHeight();
+					var width = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerWidth() : $(inst.options.items, inst.element).innerWidth();
+
+					//Now we fake the start of dragging for the sortable instance,
+					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
+					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
+					inst.currentItem = $(this).clone().appendTo(inst.element);
+					inst.options.helper = function() { return ui.helper[0]; };
+					inst.start(e);
+					
+					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
+					inst.clickOffset.top = ui.instance.clickOffset.top;
+					inst.clickOffset.left = ui.instance.clickOffset.left;
+					inst.offset.left -= ui.absolutePosition.left - inst.position.absolute.left;
+					inst.offset.top -= ui.absolutePosition.top - inst.position.absolute.top;
+					
+					//Do a nifty little helper animation: Animate it to the portlet's size (just takes the first 'li' element in the sortable now)
+					inst.helperProportions = { width:  width, height: height}; //We have to reset the helper proportions, because we are doing our animation there
+					ui.helper.animate({ height: height, width: width}, 500);
+					ui.instance.propagate("toSortable", e);
+				
+				}
+
+				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
+				if(inst.currentItem) inst.drag(e);
+				
+			} else {
+				
+				//If it doesn't intersect with the sortable, and it intersected before,
+				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
+				if(inst.isOver) {
+					inst.isOver = 0;
+					inst.cancelHelperRemoval = true;
+					inst.options.revert = false; //No revert here
+					inst.stop(e);
+					inst.options.helper = "original";
+					
+					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
+					inst.currentItem.remove();
+					inst.placeholder.remove();
+					
+					ui.helper.animate({ height: this.innerHeight(), width: this.innerWidth() }, 500);
+					ui.instance.propagate("fromSortable", e);
+				}
+				
+			};
+		}
+	})
+
+	//TODO: wrapHelper
+
+})(jQuery);
+
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.resizable.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.resizable.js
new file mode 100644
index 0000000..409195e
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.resizable.js
@@ -0,0 +1,710 @@
+/*
+ * jQuery UI Resizable
+ *
+ * Copyright (c) 2008 Paul Bakaus
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *   ui.base.js
+ *
+ * Revision: $Id: ui.resizable.js 5205 2008-04-06 16:12:50Z braeker $
+ */
+;(function($) {
+	
+	$.fn.extend({
+		resizable: function(options, data) {
+			var args = Array.prototype.slice.call(arguments, 1);
+			
+			return this.each(function() {
+				if (typeof options == "string") {
+					var resize = $.data(this, "resizable");
+					if (resize) resize[options].apply(resize, args);
+	
+				} else if(!$(this).is(".ui-resizable"))
+					new $.ui.resizable(this, options);
+			});
+		}
+	});
+
+	$.ui.resizable = function(element, options) {
+		//Initialize needed constants
+		var self = this;
+		
+		this.element = $(element);
+		
+		$.data(element, "resizable", this);
+		
+		// simulate .ui-resizable { position: relative; }
+		var elpos = this.element.css('position');
+		this.element.addClass("ui-resizable").css({ position: /static/.test(elpos) ? 'relative' : elpos });
+		
+		//Prepare the passed options
+		this.options = $.extend({
+			preventDefault: true,
+			transparent: false,
+			minWidth: 10,
+			minHeight: 10,
+			aspectRatio: false,
+			disableSelection: true,
+			preserveCursor: true,
+			autohide: false,
+			knobHandles: false
+		}, options);
+		
+		this.options._aspectRatio = !!(this.options.aspectRatio);
+		
+		// force proxy if helper is enabled
+		this.options.proxy = this.options.proxy || this.options.ghost ? 'proxy' : null; 
+		
+		// force proxy if animation is enabled
+		this.options.proxy = this.options.proxy || this.options.animate ? 'proxy' : null; 
+		
+		// if knobHandles equals true set to ui-resizable-knob-handle
+		this.options.knobHandles = this.options.knobHandles === true ? 'ui-resizable-knob-handle' : this.options.knobHandles;
+		
+		$(element).bind("setData.resizable", function(event, key, value){
+			self.options[key] = value;
+		}).bind("getData.resizable", function(event, key){
+			return self.options[key];
+		});
+	
+		var o = this.options;
+	
+		//Default Theme
+		var aBorder = '1px solid #DEDEDE';
+	
+		o.defaultTheme = {
+			'ui-resizable': { display: 'block' },
+			'ui-resizable-handle': { position: 'absolute', background: '#F2F2F2', fontSize: '0.1px' },
+			'ui-resizable-n': { cursor: 'n-resize', height: '4px', left: '0px', right: '0px', borderTop: aBorder },
+			'ui-resizable-s': { cursor: 's-resize', height: '4px', left: '0px', right: '0px', borderBottom: aBorder },
+			'ui-resizable-e': { cursor: 'e-resize', width: '4px', top: '0px', bottom: '0px', borderRight: aBorder },
+			'ui-resizable-w': { cursor: 'w-resize', width: '4px', top: '0px', bottom: '0px', borderLeft: aBorder },
+			'ui-resizable-se': { cursor: 'se-resize', width: '4px', height: '4px', borderRight: aBorder, borderBottom: aBorder },
+			'ui-resizable-sw': { cursor: 'sw-resize', width: '4px', height: '4px', borderBottom: aBorder, borderLeft: aBorder },
+			'ui-resizable-ne': { cursor: 'ne-resize', width: '4px', height: '4px', borderRight: aBorder, borderTop: aBorder },
+			'ui-resizable-nw': { cursor: 'nw-resize', width: '4px', height: '4px', borderLeft: aBorder, borderTop: aBorder }
+		};
+		
+		o.knobTheme = {
+			'ui-resizable-handle': { background: '#F2F2F2', border: '1px solid #808080', height: '8px', width: '8px' },
+			'ui-resizable-n': { cursor: 'n-resize', top: '-4px', left: '45%' },
+			'ui-resizable-s': { cursor: 's-resize', bottom: '-4px', left: '45%' },
+			'ui-resizable-e': { cursor: 'e-resize', right: '-4px', top: '45%' },
+			'ui-resizable-w': { cursor: 'w-resize', left: '-4px', top: '45%' },
+			'ui-resizable-se': { cursor: 'se-resize', right: '-4px', bottom: '-4px' },
+			'ui-resizable-sw': { cursor: 'sw-resize', left: '-4px', bottom: '-4px' },
+			'ui-resizable-nw': { cursor: 'nw-resize', left: '-4px', top: '-4px' },
+			'ui-resizable-ne': { cursor: 'ne-resize', right: '-4px', top: '-4px' }
+		};
+	
+		//Position the node
+		if(!o.proxy && (this.element.css('position') == 'static' || this.element.css('position') === ''))
+			this.element.css('position', 'relative');
+	
+		o._nodeName = element.nodeName;
+	
+		//Wrap the element if it cannot hold child nodes
+		if(o._nodeName.match(/textarea|input|select|button|img/i)) {
+			var el = this.element;
+			
+			//Opera fixing relative position
+			if (/relative/.test(el.css('position')) && $.browser.opera)
+				el.css({ position: 'relative', top: 'auto', left: 'auto' });
+			
+			//Create a wrapper element and set the wrapper to the new current internal element
+			el.wrap(
+				$('<div class="ui-wrapper"	style="overflow: hidden;"></div>').css( {
+					position: el.css('position'),
+					width: el.outerWidth(),
+					height: el.outerHeight(),
+					top: el.css('top'),
+					left: el.css('left')
+				})
+			);
+			
+			var oel = this.element; element = element.parentNode; this.element = $(element);
+	
+			//Move margins to the wrapper
+			this.element.css({ marginLeft: oel.css("marginLeft"), marginTop: oel.css("marginTop"),
+				marginRight: oel.css("marginRight"), marginBottom: oel.css("marginBottom")
+			});
+	
+			oel.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
+	
+			//Prevent Safari textarea resize
+			if ($.browser.safari && o.preventDefault) oel.css('resize', 'none');
+	
+			o.proportionallyResize = oel.css({ position: 'static', zoom: 1, display: 'block' });
+			
+			// avoid IE jump
+			this.element.css({ margin: oel.css('margin') });
+			
+			// fix handlers offset
+			this._proportionallyResize();
+		}
+	
+		if(!o.handles) o.handles = !$('.ui-resizable-handle', element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' };
+		if(o.handles.constructor == String) {
+	
+			if(o.handles == 'all') o.handles = 'n,e,s,w,se,sw,ne,nw';
+	
+			var n = o.handles.split(","); o.handles = {};
+	
+			o.zIndex = o.zIndex || 1000;
+			
+			// insertions are applied when don't have theme loaded
+			var insertionsDefault = {
+				handle: 'position: absolute; display: none; overflow:hidden;',
+				n: 'top: 0pt; width:100%;',
+				e: 'right: 0pt; height:100%;',
+				s: 'bottom: 0pt; width:100%;',
+				w: 'left: 0pt; height:100%;',
+				se: 'bottom: 0pt; right: 0px;',
+				sw: 'bottom: 0pt; left: 0px;',
+				ne: 'top: 0pt; right: 0px;',
+				nw: 'top: 0pt; left: 0px;'
+			};
+	
+			for(var i = 0; i < n.length; i++) {
+				var handle = jQuery.trim(n[i]), dt = o.defaultTheme, hname = 'ui-resizable-'+handle, loadDefault = !$.ui.css(hname) && !o.knobHandles, userKnobClass = $.ui.css('ui-resizable-knob-handle'), 
+							allDefTheme = $.extend(dt[hname], dt['ui-resizable-handle']), allKnobTheme = $.extend(o.knobTheme[hname], !userKnobClass ? o.knobTheme['ui-resizable-handle'] : {});
+				
+				// increase zIndex of sw, se, ne, nw axis
+				var applyZIndex = /sw|se|ne|nw/.test(handle) ? { zIndex: ++o.zIndex } : {};
+				
+				var defCss = (loadDefault ? insertionsDefault[handle] : ''), 
+					axis = $(['<div class="ui-resizable-handle ', hname, '" style="', defCss, insertionsDefault.handle, '"></div>'].join('')).css( applyZIndex );
+				o.handles[handle] = '.ui-resizable-'+handle;
+				
+				this.element.append(
+					//Theme detection, if not loaded, load o.defaultTheme
+					axis.css( loadDefault ? allDefTheme : {} )
+						// Load the knobHandle css, fix width, height, top, left...
+						.css( o.knobHandles ? allKnobTheme : {} ).addClass(o.knobHandles ? 'ui-resizable-knob-handle' : '').addClass(o.knobHandles)
+				);
+			}
+			
+			if (o.knobHandles) this.element.addClass('ui-resizable-knob').css( !$.ui.css('ui-resizable-knob') ? { /*border: '1px #fff dashed'*/ } : {} );
+		}
+	
+		this._renderAxis = function(target) {
+			target = target || this.element;
+	
+			for(var i in o.handles) {
+				if(o.handles[i].constructor == String) 
+					o.handles[i] = $(o.handles[i], element).show();
+	
+				if (o.transparent)
+					o.handles[i].css({opacity:0});
+	
+				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
+				if (this.element.is('.ui-wrapper') && 
+					o._nodeName.match(/textarea|input|select|button/i)) {
+	
+					var axis = $(o.handles[i], element), padWrapper = 0;
+	
+					//Checking the correct pad and border
+					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+	
+					//The padding type i have to apply...
+					var padPos = [ 'padding', 
+						/ne|nw|n/.test(i) ? 'Top' :
+						/se|sw|s/.test(i) ? 'Bottom' : 
+						/^e$/.test(i) ? 'Right' : 'Left' ].join(""); 
+	
+					if (!o.transparent)
+						target.css(padPos, padWrapper);
+	
+					this._proportionallyResize();
+				}
+				if(!$(o.handles[i]).length) continue;
+			}
+		};
+			
+		this._renderAxis(this.element);
+		o._handles = $('.ui-resizable-handle', self.element);
+		
+		if (o.disableSelection)
+			o._handles.each(function(i, e) { $.ui.disableSelection(e); });
+		
+		//Matching axis name
+		o._handles.mouseover(function() {
+			if (!o.resizing) {
+				if (this.className) 
+					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+				//Axis, default = se
+				self.axis = o.axis = axis && axis[1] ? axis[1] : 'se';
+			}
+		});
+				
+		//If we want to auto hide the elements
+		if (o.autohide) {
+			o._handles.hide();
+			$(self.element).addClass("ui-resizable-autohide").hover(function() {
+				$(this).removeClass("ui-resizable-autohide");
+				o._handles.show();
+			},
+			function(){
+				if (!o.resizing) {
+					$(this).addClass("ui-resizable-autohide");
+					o._handles.hide();
+				}
+			});
+		}
+	
+		//Initialize mouse events for interaction
+		this.element.mouseInteraction({
+			executor: this,
+			delay: 0,
+			distance: 0,
+			dragPrevention: ['input','textarea','button','select','option'],
+			start: this.start,
+			stop: this.stop,
+			drag: this.drag,
+			condition: function(e) {
+				if(this.disabled) return false;
+				for(var i in this.options.handles) {
+					if($(this.options.handles[i])[0] == e.target) return true;
+				}
+				return false;
+			}
+		});
+	};
+
+	$.extend($.ui.resizable.prototype, {
+		plugins: {},
+		ui: function() {
+			return {
+				instance: this,
+				axis: this.options.axis,
+				options: this.options
+			};
+		},
+		_renderProxy: function() {
+			var el = this.element, o = this.options;
+			this.elementOffset = el.offset();
+	
+			if(o.proxy) {
+				this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
+	
+				// fix ie6 offset
+				var ie6 = $.browser.msie && $.browser.version  < 7, ie6offset = (ie6 ? 1 : 0),
+				pxyoffset = ( ie6 ? 2 : -1 );
+	
+				this.helper.addClass(o.proxy).css({
+					width: el.outerWidth() + pxyoffset,
+					height: el.outerHeight() + pxyoffset,
+					position: 'absolute',
+					left: this.elementOffset.left - ie6offset +'px',
+					top: this.elementOffset.top - ie6offset +'px',
+					zIndex: ++o.zIndex
+				});
+				
+				this.helper.appendTo("body");
+	
+				if (o.disableSelection)
+					$.ui.disableSelection(this.helper.get(0));
+	
+			} else {
+				this.helper = el; 
+			}
+		},
+		propagate: function(n,e) {
+			$.ui.plugin.call(this, n, [e, this.ui()]);
+			this.element.triggerHandler(n == "resize" ? n : ["resize", n].join(""), [e, this.ui()], this.options[n]);
+		},
+		destroy: function() {
+			var el = this.element, wrapped = el.children(".ui-resizable").get(0),
+			
+			_destroy = function(exp) {
+				$(exp).removeClass("ui-resizable ui-resizable-disabled")
+					.removeMouseInteraction().removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
+			};
+			
+			_destroy(el);
+			
+			if (el.is('.ui-wrapper') && wrapped) {
+		  		el.parent().append(
+					$(wrapped).css({
+			  		position: el.css('position'),
+			  		width: el.outerWidth(),
+			  		height: el.outerHeight(),
+			  		top: el.css('top'),
+			  		left: el.css('left')
+		  		})
+				).end().remove();
+				
+				_destroy(wrapped);
+	  		}
+		},
+		enable: function() {
+			this.element.removeClass("ui-resizable-disabled");
+			this.disabled = false;
+		},
+		disable: function() {
+			this.element.addClass("ui-resizable-disabled");
+			this.disabled = true;
+		},
+		start: function(e) {
+			var o = this.options, iniPos = this.element.position(), el = this.element, 
+				num = function(v) { return parseInt(v, 10) || 0; }, ie6 = $.browser.msie && $.browser.version < 7;
+			o.resizing = true;
+			o.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
+	
+			// bugfix #1749
+			if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
+				
+				// sOffset decides if document scrollOffset will be added to the top/left of the resizable element
+				var sOffset = $.browser.msie && !o.containment && (/absolute/).test(el.css('position')) && !(/relative/).test(el.parent().css('position'));
+				var dscrollt = sOffset ? o.documentScroll.top : 0, dscrolll = sOffset ? o.documentScroll.left : 0;
+				
+				el.css({ position: 'absolute', top: (iniPos.top + dscrollt), left: (iniPos.left + dscrolll) });
+			}
+			
+			//Opera fixing relative position
+			if (/relative/.test(el.css('position')) && $.browser.opera)
+				el.css({ position: 'relative', top: 'auto', left: 'auto' });
+	
+			this._renderProxy();
+	
+			var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
+			
+			//Store needed variables
+			this.offset = this.helper.offset();
+			this.position = { left: curleft, top: curtop };
+			this.size = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+			this.originalSize = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+			this.originalPosition = { left: curleft, top: curtop };
+			this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
+			this.originalMousePosition = { left: e.pageX, top: e.pageY };
+			
+			//Aspect Ratio
+			o.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.height / this.originalSize.width)||1);
+	
+			if (o.preserveCursor)
+				$('body').css('cursor', this.axis + '-resize');
+				
+			this.propagate("start", e); 	
+			return false;
+		},
+		stop: function(e) {
+			this.options.resizing = false;
+			var o = this.options, num = function(v) { return parseInt(v, 10) || 0; }, self = this;
+	
+			if(o.proxy) {
+				var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
+							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+								soffsetw = ista ? 0 : self.sizeDiff.width;
+			
+				var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
+							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top);
+				
+				if (!o.animate)
+					this.element.css($.extend(style, { top: top, left: left }));
+				
+				if (o.proxy && !o.animate) this._proportionallyResize();
+				this.helper.remove();
+			}
+
+			if (o.preserveCursor)
+			$('body').css('cursor', 'auto');
+	
+			this.propagate("stop", e);	
+			return false;
+		},
+		drag: function(e) {
+			//Increase performance, avoid regex
+			var el = this.helper, o = this.options, props = {},
+				self = this, smp = this.originalMousePosition, a = this.axis;
+
+			var dx = (e.pageX-smp.left)||0, dy = (e.pageY-smp.top)||0;
+			var trigger = this.change[a];
+			if (!trigger) return false;
+		 
+			// Calculate the attrs that will be change
+			var data = trigger.apply(this, [e, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
+		 
+			if (o._aspectRatio || e.shiftKey)
+				data = this._updateRatio(data, e);
+			
+			data = this._respectSize(data, e);
+			
+			this.propagate("resize", e);
+			
+			el.css({
+				top: this.position.top + "px", left: this.position.left + "px", 
+				width: this.size.width + "px", height: this.size.height + "px"
+			});
+			
+			if (!o.proxy && o.proportionallyResize)
+				this._proportionallyResize();
+			
+			this._updateCache(data);
+			
+			return false;
+		},
+		
+		_updateCache: function(data) {
+			var o = this.options;
+			this.offset = this.helper.offset();
+			if (data.left) this.position.left = data.left;
+			if (data.top) this.position.top = data.top;
+			if (data.height) this.size.height = data.height;
+			if (data.width) this.size.width = data.width;
+		},
+		
+		_updateRatio: function(data, e) {
+			var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
+			
+			if (data.height) data.width = Math.round(csize.height / o.aspectRatio);
+			else if (data.width) data.height = Math.round(csize.width * o.aspectRatio);
+			
+			if (a == 'sw') {
+				data.left = cpos.left + (csize.width - data.width);
+				data.top = null;
+			}
+			if (a == 'nw') { 
+				data.top = cpos.top + (csize.height - data.height);
+				data.left = cpos.left + (csize.width - data.width);
+			}
+			
+			return data;
+		},
+		
+		_respectSize: function(data, e) {
+			
+			var el = this.helper, o = this.options, pRatio = o._aspectRatio || e.shiftKey,  a = this.axis, 
+					ismaxw = data.width && o.maxWidth && o.maxWidth < data.width, ismaxh = data.height && o.maxHeight && o.maxHeight < data.height,
+						isminw = data.width && o.minWidth && o.minWidth > data.width, isminh = data.height && o.minHeight && o.minHeight > data.height;
+			
+			if (isminw) data.width = o.minWidth;
+			if (isminh) data.height = o.minHeight;
+			if (ismaxw) data.width = o.maxWidth;
+			if (ismaxh) data.height = o.maxHeight;
+			
+			var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
+			var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+			
+			if (isminw && cw) data.left = dw - o.minWidth;
+			if (ismaxw && cw) data.left = dw - o.maxWidth;
+			if (isminh && ch)	data.top = dh - o.minHeight;
+			if (ismaxh && ch)	data.top = dh - o.maxHeight;
+			
+			// fixing jump error on top/left - bug #2330
+			var isNotwh = !data.width && !data.height;
+			if (isNotwh && !data.left && data.top) data.top = null;
+			else if (isNotwh && !data.top && data.left) data.left = null;
+			
+			return data;
+		},
+		
+		_proportionallyResize: function() {
+			var o = this.options;
+			if (!o.proportionallyResize) return;
+			var prel = o.proportionallyResize, el = this.helper || this.element;
+		 
+			if (!o.borderDif) {
+				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
+					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
+				 
+				o.borderDif = $.map(b, function(v, i) {
+					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
+					return border + padding; 
+				});
+			}
+			prel.css({
+				height: (el.height() - o.borderDif[0] - o.borderDif[2]) + "px",
+				width: (el.width() - o.borderDif[1] - o.borderDif[3]) + "px"
+			});
+		},
+		
+		change: {
+			e: function(e, dx, dy) {
+				return { width: this.originalSize.width + dx };
+			},
+			w: function(e, dx, dy) {
+				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+				return { left: sp.left + dx, width: cs.width - dx };
+			},
+			n: function(e, dx, dy) {
+				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+				return { top: sp.top + dy, height: cs.height - dy };
+			},
+			s: function(e, dx, dy) {
+				return { height: this.originalSize.height + dy };
+			},
+			se: function(e, dx, dy) {
+				return $.extend(this.change.s.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
+			},
+			sw: function(e, dx, dy) {
+				return $.extend(this.change.s.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
+			},
+			ne: function(e, dx, dy) {
+				return $.extend(this.change.n.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
+			},
+			nw: function(e, dx, dy) {
+				return $.extend(this.change.n.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
+			}
+		}
+	});
+
+/*
+ * Resizable Extensions
+ */
+
+	$.ui.plugin.add("resizable", "containment", {
+		
+		start: function(e, ui) {
+			var o = ui.options, self = ui.instance, el = self.element;
+			var oc = o.containment,	ce = (oc instanceof jQuery) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
+			if (!ce) return;
+			
+			if (/document/.test(oc) || oc == document) {
+				self.containerOffset = { left: 0, top: 0 };
+
+				self.parentData = { 
+					element: $(document), left: 0, top: 0, width: $(document).width(),
+					height: $(document).height() || document.body.parentNode.scrollHeight
+				};
+			}
+			
+			// i'm a node, so compute top, left, right, bottom
+			else{
+				self.containerOffset = $(ce).offset(), self.containerSize = { height: $(ce).innerHeight(), width: $(ce).innerWidth() };
+			
+				var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width, 
+							width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
+			
+				self.parentData = { 
+					element: ce, left: co.left, top: co.top, width: width, height: height
+				};
+			}
+		},
+		
+		resize: function(e, ui) {
+			var o = ui.options, self = ui.instance, ps = self.containerSize, 
+						co = self.containerOffset, cs = self.size, cp = self.position,
+							pRatio = o._aspectRatio || e.shiftKey;
+			
+			if (cp.left < (o.proxy ? co.left : 0)) {
+				self.size.width = self.size.width + (o.proxy ? (self.position.left - co.left) : self.position.left);
+				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
+				self.position.left = o.proxy ? co.left : 0;
+			}
+			
+			if (cp.top < (o.proxy ? co.top : 0)) {
+				self.size.height = self.size.height + (o.proxy ? (self.position.top - co.top) : self.position.top);
+				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
+				self.position.top = o.proxy ? co.top : 0;
+			}
+			
+			var woset = (o.proxy ? self.offset.left - co.left : self.position.left) + self.sizeDiff.width, 
+						hoset = (o.proxy ? self.offset.top - co.top : self.position.top) + self.sizeDiff.height;
+			
+			if (woset + self.size.width >= self.parentData.width) {
+				self.size.width = self.parentData.width - woset;
+				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
+			}
+			
+			if (hoset + self.size.height >= self.parentData.height) {
+				self.size.height = self.parentData.height - hoset;
+				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
+			}
+		}
+	});
+	
+	$.ui.plugin.add("resizable", "grid", {
+		
+		resize: function(e, ui) {
+			var o = ui.options, self =  ui.instance, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || e.shiftKey;
+			o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
+			var ox = Math.round((cs.width - os.width) / o.grid[0]) * o.grid[0], oy = Math.round((cs.height - os.height) / o.grid[1]) * o.grid[1];
+			
+			if (/^(se|s|e)$/.test(a)) {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+			}
+			else if (/^(ne)$/.test(a)) {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+				self.position.top = op.top - oy;
+			}
+			else if (/^(sw)$/.test(a)) {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+				self.position.left = op.left - ox;
+			}
+			else {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+				self.position.top = op.top - oy;
+				self.position.left = op.left - ox;
+			}
+		}
+		
+	});
+	
+	$.ui.plugin.add("resizable", "animate", {
+		
+		stop: function(e, ui) {
+			var o = ui.options, self =  ui.instance;
+
+			var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
+							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+								soffsetw = ista ? 0 : self.sizeDiff.width;
+			
+			var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
+							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top); 
+			
+			self.element.animate(
+				$.extend(style, { top: top, left: left }),
+				{ 
+					duration: o.animateDuration || "slow", 
+					easing: o.animateEasing || "swing", 
+					step: function() {
+						if (pr) pr.css({ width: self.element.css('width'), height: self.element.css('height') });
+					}
+				}
+			);
+		}
+		
+	});
+	
+	$.ui.plugin.add("resizable", "ghost", {
+		
+		start: function(e, ui) {
+			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize, cs = self.size;
+			
+			if (!pr) self.ghost = self.element.clone();
+			else self.ghost = pr.clone();
+			
+			self.ghost.css(
+				{ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }
+			)
+			.addClass('ui-resizable-ghost').addClass(typeof o.ghost == 'string' ? o.ghost : '');
+			
+			self.ghost.appendTo(self.helper);
+			
+		},
+		
+		resize: function(e, ui){
+			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
+			
+			if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
+			
+		},
+		
+		stop: function(e, ui){
+			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
+			if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
+		}
+		
+	});
+
+})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.css b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.css
new file mode 100644
index 0000000..0eabf94
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.css
@@ -0,0 +1,114 @@
+/* Caution! Ensure accessibility in print and other media types... */
+ at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
+    .ui-tabs-hide {
+        display: none;
+    }
+}
+
+/* Hide useless elements in print layouts... */
+ at media print {
+    .ui-tabs-nav {
+        display: none;
+    }
+}
+
+/* Skin */
+.ui-tabs-nav {
+    list-style: none;
+    margin: 0 !important;
+    padding: 0 0 0 4px;
+}
+.ui-tabs-nav li {
+    list-style-image: none !important;
+    margin: 0 !important;
+    padding: 0 0 0 4px;
+}
+
+.ui-tabs-panel {
+    border-top: #94ADA7 solid 1px;
+    padding-top: 5px;
+    clear: left;
+}
+
+/* IE6 hack */
+* html .ui-tabs-panel {
+    margin-top: -1.2em;
+}
+
+.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
+    display: block;
+    clear: both;
+    content: " ";
+}
+.ui-tabs-nav li {
+    float: left;
+    margin: 0 0 0 1px;
+    min-width: 84px; /* be nice to Opera */
+}
+.ui-tabs-nav a, .ui-tabs-nav a span {
+    display: block;
+    padding: 0 10px;
+    background: url(tab.png) no-repeat;
+}
+.ui-tabs-nav a {
+    position: relative;
+    top: 1px;
+    z-index: 2;
+    padding-left: 0;
+    color: #27537a;
+    font-size: 12px;
+    font-weight: bold;
+    line-height: 1.2;
+    text-align: center;
+    text-decoration: none;
+    white-space: nowrap; /* required in IE 6 */    
+}
+.ui-tabs-nav .ui-tabs-selected a {
+    color: #000;
+}
+.ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active {
+    background-position: 100% -150px;
+    outline: 0; /* prevent dotted border in Firefox */
+}
+.ui-tabs-nav a, .ui-tabs-nav .ui-tabs-disabled a:hover, .ui-tabs-nav .ui-tabs-disabled a:focus, .ui-tabs-nav .ui-tabs-disabled a:active {
+    background-position: 100% -100px;
+}
+.ui-tabs-nav a span {
+    width: 64px; /* IE 6 treats width as min-width */
+    min-width: 64px;
+    height: 18px; /* IE 6 treats height as min-height */
+    min-height: 18px;
+    padding-top: 6px;
+    padding-right: 0;
+}
+*>.ui-tabs-nav a span { /* hide from IE 6 */
+    width: auto;
+    height: auto;
+}
+.ui-tabs-nav .ui-tabs-selected a span {
+    padding-top: 7px;
+}
+.ui-tabs-nav .ui-tabs-selected a span, .ui-tabs-nav a:hover span, .ui-tabs-nav a:focus span, .ui-tabs-nav a:active span {
+    background-position: 0 -50px;
+}
+.ui-tabs-nav a span, .ui-tabs-nav .ui-tabs-disabled a:hover span, .ui-tabs-nav .ui-tabs-disabled a:focus span, .ui-tabs-nav .ui-tabs-disabled a:active span {
+    background-position: 0 0;
+}
+.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited, .ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
+    cursor: text;
+}
+.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active { /* @ Opera, we need to be explicit again here now... */
+    cursor: pointer;
+}
+.ui-tabs-nav .ui-tabs-disabled {
+    opacity: .4;
+}
+.ui-tabs-container {
+    border-top: 1px solid #97a5b0;
+    padding: 1em 8px;
+    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
+}
+.ui-tabs-loading em {
+    padding: 0 0 0 20px;
+    background: url(loading.gif) no-repeat 0 50%;
+}
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.js b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.js
new file mode 100644
index 0000000..f595c10
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/ui.tabs.js
@@ -0,0 +1,616 @@
+/*
+ * jQuery UI Tabs
+ *
+ * Copyright (c) 2007 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *   ui.base.js
+ *
+ * Revision: $Id: ui.tabs.js 5149 2008-03-31 10:51:18Z rdworth $
+ */
+;(function($) {
+
+    // tabs API methods
+    $.fn.tabs = function() {
+        var method = typeof arguments[0] == 'string' && arguments[0];
+        var args = method && Array.prototype.slice.call(arguments, 1) || arguments;
+
+        return method == 'length' ?
+            $.data(this[0], 'tabs').$tabs.length :
+            this.each(function() {
+                if (method) {
+                    var tabs = $.data(this, 'tabs');
+                    if (tabs) tabs[method].apply(tabs, args);
+                } else
+                    new $.ui.tabs(this, args[0] || {});
+            });
+    };
+
+    // tabs class
+    $.ui.tabs = function(el, options) {
+        var self = this;
+        
+        this.options = $.extend({}, $.ui.tabs.defaults, options);
+        this.element = el;
+
+        // doesn't extend with null
+        if (options.selected === null)
+            this.options.selected = null;
+
+        this.options.event += '.tabs'; // namespace event
+
+        $(el).bind('setData.tabs', function(event, key, value) {
+            if ((/^selected/).test(key))
+                self.select(value);
+            else {
+                self.options[key] = value;
+                self.tabify();
+            }
+        }).bind('getData.tabs', function(event, key) {
+            return self.options[key];
+        });
+
+        // save instance for later
+        $.data(el, 'tabs', this);
+
+        // create tabs
+        this.tabify(true);
+    };
+    
+    $.ui.tabs.defaults = {
+        // basic setup
+        selected: 0,
+        unselect: false,
+        event: 'click',
+        disabled: [],
+        cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+        // TODO history: false,
+
+        // Ajax
+        spinner: 'Loading&#8230;',
+        cache: false,
+        idPrefix: 'ui-tabs-',
+        ajaxOptions: {},
+
+        // animations
+        fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+
+        // templates
+        tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>',
+        panelTemplate: '<div></div>',
+
+        // CSS classes
+        navClass: 'ui-tabs-nav',
+        selectedClass: 'ui-tabs-selected',
+        unselectClass: 'ui-tabs-unselect',
+        disabledClass: 'ui-tabs-disabled',
+        panelClass: 'ui-tabs-panel',
+        hideClass: 'ui-tabs-hide',
+        loadingClass: 'ui-tabs-loading'
+    };
+
+    // instance methods
+    $.extend($.ui.tabs.prototype, {
+        tabId: function(a) {
+            return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
+                || this.options.idPrefix + $.data(a);
+        },
+        ui: function(tab, panel) {
+            return {
+                instance: this,
+                options: this.options,
+                tab: tab,
+                panel: panel
+            };
+        },
+        tabify: function(init) {
+
+            this.$lis = $('li:has(a[href])', this.element);
+            this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
+            this.$panels = $([]);
+
+            var self = this, o = this.options;
+
+            this.$tabs.each(function(i, a) {
+                // inline tab
+                if (a.hash && a.hash.replace('#', '')) // Safari 2 reports '#' for an empty hash
+                    self.$panels = self.$panels.add(a.hash);
+                // remote tab
+                else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#"
+                    $.data(a, 'href.tabs', a.href); // required for restore on destroy
+
+                    var _cls = a.getAttribute('class');
+                    var use_iframe = _cls && (_cls.indexOf('use_iframe') > -1)? true: false;
+                    if (!use_iframe) {
+                        $.data(a, 'load.tabs', a.href); // mutable
+                    } else {
+                        $.data(a, 'load.iframe_src', a.href); // mutable
+                    }
+
+
+                    var id = self.tabId(a);
+                    a.href = '#' + id;
+                    var $panel = $('#' + id);
+                    var panelTemplate = use_iframe? '<div><iframe></iframe></div>': o.panelTemplate;
+                    if (!$panel.length) {
+                        $panel = $(panelTemplate).attr('id', id).addClass(o.panelClass)
+                            .insertAfter( self.$panels[i - 1] || self.element );
+                        $panel.data('destroy.tabs', true);
+                    }
+                    self.$panels = self.$panels.add( $panel );
+                }
+                // invalid tab href
+                else
+                    o.disabled.push(i + 1);
+            });
+
+            if (init) {
+
+                // attach necessary classes for styling if not present
+                $(this.element).hasClass(o.navClass) || $(this.element).addClass(o.navClass);
+                this.$panels.each(function() {
+                    var $this = $(this);
+                    $this.hasClass(o.panelClass) || $this.addClass(o.panelClass);
+                });
+
+                // Try to retrieve selected tab:
+                // 1. from fragment identifier in url if present
+                // 2. from cookie
+                // 3. from selected class attribute on <li>
+                // 4. otherwise use given "selected" option
+                // 5. check if tab is disabled
+                this.$tabs.each(function(i, a) {
+                    if (location.hash) {
+                        if (a.hash == location.hash) {
+                            o.selected = i;
+                            // prevent page scroll to fragment
+                            //if (($.browser.msie || $.browser.opera) && !o.remote) {
+                            if ($.browser.msie || $.browser.opera) {
+                                var $toShow = $(location.hash), toShowId = $toShow.attr('id');
+                                $toShow.attr('id', '');
+                                setTimeout(function() {
+                                    $toShow.attr('id', toShowId); // restore id
+                                }, 500);
+                            }
+                            scrollTo(0, 0);
+                            return false; // break
+                        }
+                    } else if (o.cookie) {
+                        var index = parseInt($.cookie('ui-tabs' + $.data(self.element)),10);
+                        if (index && self.$tabs[index]) {
+                            o.selected = index;
+                            return false; // break
+                        }
+                    } else if ( self.$lis.eq(i).hasClass(o.selectedClass) ) {
+                        o.selected = i;
+                        return false; // break
+                    }
+                });
+
+                // highlight selected tab
+                this.$panels.addClass(o.hideClass);
+                this.$lis.removeClass(o.selectedClass);
+                if (o.selected !== null) {
+                    this.$panels.eq(o.selected).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before
+                    this.$lis.eq(o.selected).addClass(o.selectedClass);
+                }
+
+                // load if remote tab
+                var href = o.selected !== null && $.data(this.$tabs[o.selected], 'load.tabs');
+                if (href)
+                    this.load(o.selected);
+
+                // Take disabling tabs via class attribute from HTML
+                // into account and update option properly...
+                o.disabled = $.unique(o.disabled.concat(
+                    $.map(this.$lis.filter('.' + o.disabledClass),
+                        function(n, i) { return self.$lis.index(n); } )
+                )).sort();
+                
+                // clean up to avoid memory leaks in certain versions of IE 6
+                $(window).bind('unload', function() {
+                    self.$tabs.unbind('.tabs');
+                    self.$lis = self.$tabs = self.$panels = null;
+                });
+
+            }
+
+            // disable tabs
+            for (var i = 0, li; li = this.$lis[i]; i++)
+                $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass(o.selectedClass) ? 'addClass' : 'removeClass'](o.disabledClass);
+
+            // reset cache if switching from cached to not cached
+            if (o.cache === false)
+                this.$tabs.removeData('cache.tabs');
+            
+            // set up animations
+            var hideFx, showFx, baseFx = { 'min-width': 0, duration: 1 }, baseDuration = 'normal';
+            if (o.fx && o.fx.constructor == Array)
+                hideFx = o.fx[0] || baseFx, showFx = o.fx[1] || baseFx;
+            else
+                hideFx = showFx = o.fx || baseFx;
+
+            // reset some styles to maintain print style sheets etc.
+            var resetCSS = { display: '', overflow: '', height: '' };
+            if (!$.browser.msie) // not in IE to prevent ClearType font issue
+                resetCSS.opacity = '';
+
+            // Hide a tab, animation prevents browser scrolling to fragment,
+            // $show is optional.
+            function hideTab(clicked, $hide, $show) {
+                $hide.animate(hideFx, hideFx.duration || baseDuration, function() { //
+                    $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
+                    if ($.browser.msie && hideFx.opacity)
+                        $hide[0].style.filter = '';
+                    if ($show)
+                        showTab(clicked, $show, $hide);
+                });
+            }
+
+            // Show a tab, animation prevents browser scrolling to fragment,
+            // $hide is optional.
+            function showTab(clicked, $show, $hide) {
+                if (showFx === baseFx)
+                    $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels
+                $show.animate(showFx, showFx.duration || baseDuration, function() {
+                    $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
+                    if ($.browser.msie && showFx.opacity)
+                        $show[0].style.filter = '';
+
+                    // callback
+                    $(self.element).triggerHandler('tabsshow', [self.ui(clicked, $show[0])], o.show);
+
+                });
+            }
+
+            // switch a tab
+            function switchTab(clicked, $li, $hide, $show) {
+                /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
+                    $.ajaxHistory.update(clicked.hash);
+                }*/
+                $li.addClass(o.selectedClass)
+                    .siblings().removeClass(o.selectedClass);
+                hideTab(clicked, $hide, $show);
+            }
+
+            // attach tab event handler, unbind to avoid duplicates from former tabifying...
+            this.$tabs.unbind('.tabs').bind(o.event, function() {
+
+                //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
+                var $li = $(this).parents('li:eq(0)'),
+                    $hide = self.$panels.filter(':visible'),
+                    $show = $(this.hash);
+
+                // If tab is already selected and not unselectable or tab disabled or 
+                // or is already loading or click callback returns false stop here.
+                // Check if click handler returns false last so that it is not executed
+                // for a disabled or loading tab!
+                if (($li.hasClass(o.selectedClass) && !o.unselect)
+                    || $li.hasClass(o.disabledClass) 
+                    || $(this).hasClass(o.loadingClass)
+                    || $(self.element).triggerHandler('tabsselect', [self.ui(this, $show[0])], o.select) === false
+                    ) {
+                    this.blur();
+                    return false;
+                }
+
+                self.options.selected = self.$tabs.index(this);
+
+                // if tab may be closed
+                if (o.unselect) {
+                    if ($li.hasClass(o.selectedClass)) {
+                        self.options.selected = null;
+                        $li.removeClass(o.selectedClass);
+                        self.$panels.stop();
+                        hideTab(this, $hide);
+                        this.blur();
+                        return false;
+                    } else if (!$hide.length) {
+                        self.$panels.stop();
+                        var a = this;
+                        self.load(self.$tabs.index(this), function() {
+                            $li.addClass(o.selectedClass).addClass(o.unselectClass);
+                            showTab(a, $show);
+                        });
+                        this.blur();
+                        return false;
+                    }
+                }
+
+                if (o.cookie)
+                    $.cookie('ui-tabs' + $.data(self.element), self.options.selected, o.cookie);
+
+                // stop possibly running animations
+                self.$panels.stop();
+
+                // show new tab
+                if ($show.length) {
+
+                    // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
+                    /*if ($.browser.msie && o.bookmarkable) {
+                        var showId = this.hash.replace('#', '');
+                        $show.attr('id', '');
+                        setTimeout(function() {
+                            $show.attr('id', showId); // restore id
+                        }, 0);
+                    }*/
+
+                    var a = this;
+                    self.load(self.$tabs.index(this), $hide.length ? 
+                        function() {
+                            switchTab(a, $li, $hide, $show);
+                        } :
+                        function() {
+                            $li.addClass(o.selectedClass);
+                            showTab(a, $show);
+                        }
+                    );
+
+                    // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
+                    /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
+                    var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
+                    setTimeout(function() {
+                        scrollTo(scrollX, scrollY);
+                    }, 0);*/
+
+                } else
+                    throw 'jQuery UI Tabs: Mismatching fragment identifier.';
+
+                // Prevent IE from keeping other link focussed when using the back button
+                // and remove dotted border from clicked link. This is controlled in modern
+                // browsers via CSS, also blur removes focus from address bar in Firefox
+                // which can become a usability and annoying problem with tabsRotate.
+                if ($.browser.msie)
+                    this.blur();
+
+                //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE
+                return false;
+
+            });
+
+            // disable click if event is configured to something else
+            if (!(/^click/).test(o.event))
+                this.$tabs.bind('click.tabs', function() { return false; });
+
+        },
+        add: function(url, label, index) {
+            if (index == undefined) 
+                index = this.$tabs.length; // append by default
+
+            var o = this.options;
+            var $li = $(o.tabTemplate.replace(/#\{href\}/, url).replace(/#\{label\}/, label));
+            $li.data('destroy.tabs', true);
+
+            var id = url.indexOf('#') == 0 ? url.replace('#', '') : this.tabId( $('a:first-child', $li)[0] );
+
+            // try to find an existing element before creating a new one
+            var $panel = $('#' + id);
+            if (!$panel.length) {
+                $panel = $(o.panelTemplate).attr('id', id)
+                    .addClass(o.panelClass).addClass(o.hideClass);
+                $panel.data('destroy.tabs', true);
+            }
+            if (index >= this.$lis.length) {
+                $li.appendTo(this.element);
+                $panel.appendTo(this.element.parentNode);
+            } else {
+                $li.insertBefore(this.$lis[index]);
+                $panel.insertBefore(this.$panels[index]);
+            }
+            
+            o.disabled = $.map(o.disabled,
+                function(n, i) { return n >= index ? ++n : n });
+                
+            this.tabify();
+
+            if (this.$tabs.length == 1) {
+                 $li.addClass(o.selectedClass);
+                 $panel.removeClass(o.hideClass);
+                 var href = $.data(this.$tabs[0], 'load.tabs');
+                 if (href)
+                     this.load(index, href);
+            }
+
+            // callback
+            $(this.element).triggerHandler('tabsadd',
+                [this.ui(this.$tabs[index], this.$panels[index])], o.add
+            );
+        },
+        remove: function(index) {
+            var o = this.options, $li = this.$lis.eq(index).remove(),
+                $panel = this.$panels.eq(index).remove();
+
+            // If selected tab was removed focus tab to the right or
+            // in case the last tab was removed the tab to the left.
+            if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1)
+                this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));
+
+            o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
+                function(n, i) { return n >= index ? --n : n });
+
+            this.tabify();
+
+            // callback
+            $(this.element).triggerHandler('tabsremove',
+                [this.ui($li.find('a')[0], $panel[0])], o.remove
+            );
+        },
+        enable: function(index) {
+            var o = this.options;
+            if ($.inArray(index, o.disabled) == -1)
+                return;
+                
+            var $li = this.$lis.eq(index).removeClass(o.disabledClass);
+            if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2...
+                $li.css('display', 'inline-block');
+                setTimeout(function() {
+                    $li.css('display', 'block');
+                }, 0);
+            }
+
+            o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
+
+            // callback
+            $(this.element).triggerHandler('tabsenable',
+                [this.ui(this.$tabs[index], this.$panels[index])], o.enable
+            );
+
+        },
+        disable: function(index) {
+            var self = this, o = this.options;
+            if (index != o.selected) { // cannot disable already selected tab
+                this.$lis.eq(index).addClass(o.disabledClass);
+
+                o.disabled.push(index);
+                o.disabled.sort();
+
+                // callback
+                $(this.element).triggerHandler('tabsdisable',
+                    [this.ui(this.$tabs[index], this.$panels[index])], o.disable
+                );
+            }
+        },
+        select: function(index) {
+            if (typeof index == 'string')
+                index = this.$tabs.index( this.$tabs.filter('[href$=' + index + ']')[0] );
+            this.$tabs.eq(index).trigger(this.options.event);
+        },
+        load: function(index, callback) { // callback is for internal usage only
+            
+            var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
+                    bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
+
+            callback = callback || function() {};
+            
+            // no remote or from cache - just finish with callback
+            if (!url || ($.data(a, 'cache.tabs') && !bypassCache)) {
+                callback();
+                return;
+            }
+
+            // load remote from here on
+            if (o.spinner) {
+                var $span = $('span', a);
+                $span.data('label.tabs', $span.html()).html('<em>' + o.spinner + '</em>');
+            }
+            var finish = function() {
+                self.$tabs.filter('.' + o.loadingClass).each(function() {
+                    $(this).removeClass(o.loadingClass);
+                    if (o.spinner) {
+                        var $span = $('span', this);
+                        $span.html($span.data('label.tabs')).removeData('label.tabs');
+                    }
+                });
+                self.xhr = null;
+            };
+            var ajaxOptions = $.extend({}, o.ajaxOptions, {
+                url: url,
+                success: function(r, s) {
+                    $(a.hash).html(r);
+                    finish();
+                    
+                    // This callback is required because the switch has to take
+                    // place after loading has completed.
+                    callback();
+
+                    if (o.cache)
+                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
+
+                    // callback
+                    $(self.element).triggerHandler('tabsload',
+                        [self.ui(self.$tabs[index], self.$panels[index])], o.load
+                    );
+
+                    o.ajaxOptions.success && o.ajaxOptions.success(r, s);
+                }
+            });
+            if (this.xhr) {
+                // terminate pending requests from other tabs and restore tab label
+                this.xhr.abort();
+                finish();
+            }
+            $a.addClass(o.loadingClass);
+            setTimeout(function() { // timeout is again required in IE, "wait" for id being restored
+                self.xhr = $.ajax(ajaxOptions);
+            }, 0);
+
+        },
+        url: function(index, url) {
+            this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
+        },
+        destroy: function() {
+            var o = this.options;
+            $(this.element).unbind('.tabs')
+                .removeClass(o.navClass).removeData('tabs');
+            this.$tabs.each(function() {
+                var href = $.data(this, 'href.tabs');
+                if (href)
+                    this.href = href;
+                var $this = $(this).unbind('.tabs');
+                $.each(['href', 'load', 'cache'], function(i, prefix) {
+                      $this.removeData(prefix + '.tabs');
+                });
+            });
+            this.$lis.add(this.$panels).each(function() {
+                if ($.data(this, 'destroy.tabs'))
+                    $(this).remove();
+                else
+                    $(this).removeClass([o.selectedClass, o.unselectClass,
+                        o.disabledClass, o.panelClass, o.hideClass].join(' '));
+            });
+        }
+    });
+
+/*
+ * Tabs Extensions
+ */
+
+    /*
+     * Rotate
+     */
+    $.extend($.ui.tabs.prototype, {
+        rotation: null,
+        rotate: function(ms, continuing) {
+            
+            continuing = continuing || false;
+            
+            var self = this, t = this.options.selected;
+            
+            function start() {
+                self.rotation = setInterval(function() {
+                    t = ++t < self.$tabs.length ? t : 0;
+                    self.select(t);
+                }, ms);    
+            }
+            
+            function stop(e) {
+                if (!e || e.clientX) { // only in case of a true click
+                    clearInterval(self.rotation);
+                }
+            }
+            
+            // start interval
+            if (ms) {
+                start();
+                if (!continuing)
+                    this.$tabs.bind(this.options.event, stop);
+                else
+                    this.$tabs.bind(this.options.event, function() {
+                        stop();
+                        t = self.options.selected;
+                        start();
+                    });
+            }
+            // stop interval
+            else {
+                stop();
+                this.$tabs.unbind(this.options.event, stop);
+            }
+        }
+    });
+
+})(jQuery);
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.css b/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.css
new file mode 100644
index 0000000..21a046d
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.css
@@ -0,0 +1,9 @@
+.widgetbrowser iframe {
+    width: 100%;
+    border: 0;
+}
+div.small iframe { height: 50px; }
+div.medium iframe { height: 150px; }
+div.large iframe { height: 300px; }
+div.x-large iframe { height: 500px; }
+
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.js b/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.js
new file mode 100644
index 0000000..c0b78e6
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/static/widgetbrowser.js
@@ -0,0 +1,13 @@
+jQuery(function() {
+    jQuery('.widgetbrowser > ul').tabs({
+        selected: null,
+        unselect: true,
+        select: function (ui) {
+            var url = jQuery.data(ui.tab, 'load.iframe_src');
+            var iframe = jQuery('iframe', ui.panel);
+            if (url && !iframe.attr('src')) {
+                iframe.attr('src', url);
+            }
+        }
+    })
+});
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/__init__.py b/moksha/apps/widgetbrowser/widgetbrowser/templates/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/home.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/home.html
new file mode 100644
index 0000000..012ce08
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/templates/home.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<?python
+from widgetbrowser import widgets
+?>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <style>
+        .ui-tabs-panel {
+            border-bottom: solid 1px #94ada7;
+            padding-left: 1.5em;
+        }
+        .ui-tabs-panel iframe {
+            width: 100%;
+            border: 0;
+            min-height: 500px;
+        }
+        #home {
+            min-height: 450px;
+        }
+    </style>
+  </head>
+  <body class="flora">
+    <div id="main">
+        <ul>
+            <li><a href="#home"><span>Home</span></a></li>
+            <li><a href="#terminal" class="use_iframe"><span>Terminal</span></a></li>
+            <li><a href="${url('/widgets/')}" class="use_iframe"><span>Widgets</span></a></li>
+        </ul>
+        <div id="home">
+            <h1>Welcome to Toscawidgets' Browser</h1>
+            <p>
+            </p>
+        </div>
+        <div id="terminal">
+            ${widgets.repl(prefix=url('_repl/'))}
+        </div>
+    </div>
+    <div id="footer">
+    <p>&copy; 2008. Alberto Valverde González</p>
+    </div>
+    <script type="text/javascript">
+        //<![CDATA[
+        jQuery(function () {
+            jQuery('#main > ul').tabs({
+                select: function (ui) {
+                    var url = jQuery.data(ui.tab, 'load.iframe_src');
+                    var iframe = jQuery('iframe', ui.panel);
+                    if (url && !iframe.attr('src')) {
+                        iframe.attr('src', url);
+                    }
+                }
+            });
+        });
+        //]]>
+    </script>
+  </body>
+</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/list_widgets.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/list_widgets.html
new file mode 100644
index 0000000..2ef5dfe
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/templates/list_widgets.html
@@ -0,0 +1,15 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser: Installed widgets</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body id="widgets">
+    <ul>
+        <li py:for="path, url in widgets">
+            <a href="$url">$path</a>
+        </li>
+    </ul>
+  </body>
+</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/show_widget.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/show_widget.html
new file mode 100644
index 0000000..b75e063
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/templates/show_widget.html
@@ -0,0 +1,16 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser: ${widget_name}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body id="widget_browser">
+    <form py:if="interactive" method="GET">
+      <label for="display_args">Display arguments:</label>
+      <input id="display_args" name="_disp" type="text" size="50" value="${_disp}" />
+      <input type="submit" value="Display" />
+    </form>
+    <div py:replace="widget_output" />
+  </body>
+</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/validation_result.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/validation_result.html
new file mode 100644
index 0000000..e43da7b
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/templates/validation_result.html
@@ -0,0 +1,13 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser: ${widget_name}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body id="widget_browser">
+    <h1 class="title">Validated data:</h1>
+    ${Markup(value)}
+    <a href="">Back</a>
+  </body>
+</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html
new file mode 100644
index 0000000..7edb374
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<div xmlns:py="http://genshi.edgewall.org/"
+     class="widgetbrowser ${size}">
+  <ul>
+    <li py:for="text, url in tabs">
+      <a href="${url}" class="${text == 'Demo' and 'use_iframe' or None}">
+        <span>${text}</span>
+      </a>
+    </li>
+  </ul>
+</div>
+
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_index.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_index.html
new file mode 100644
index 0000000..4759c25
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_index.html
@@ -0,0 +1,18 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <?python
+      from widgetbrowser.widgets import WidgetBrowserTabs
+      from widgetbrowser.util import widget_path
+      browser = WidgetBrowserTabs(size='x-large')
+  ?>
+  <head>
+    <title>WidgetBrowser: ${widget_path(widget)}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body>
+    <h1>${widget_path(widget)}</h1>
+    <p><a href="javascript:history.back()">Back</a></p>
+    ${browser(widget)}
+  </body>
+</html>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_parameters.html b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_parameters.html
new file mode 100644
index 0000000..c95c195
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/templates/widget_parameters.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<div xmlns:py="http://genshi.edgewall.org/" class="widget_params">
+  <div py:if="parameters.local" class="widget_params local_params">
+    <h3>This widget's</h3>
+    <dl>
+        <py:for each="k in sorted(parameters.local)">
+            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
+            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
+        </py:for>
+    </dl>
+  </div>
+  <div py:if="parameters.inherited" class="widget_param inherited_params">
+    <h3>Inherited</h3>
+    <dl>
+        <py:for each="k in sorted(parameters.inherited)">
+            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
+            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
+        </py:for>
+    </dl>
+  </div>
+</div>
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/__init__.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.html b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.html
new file mode 100644
index 0000000..7c9c42c
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.html
@@ -0,0 +1 @@
+Dummy template $value
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak
new file mode 100644
index 0000000..1774ce6
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak
@@ -0,0 +1 @@
+Dummy template $value mako version
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_template.html b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_template.html
new file mode 100644
index 0000000..7c9c42c
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/dummy_template.html
@@ -0,0 +1 @@
+Dummy template $value
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/test_app.txt b/moksha/apps/widgetbrowser/widgetbrowser/tests/test_app.txt
new file mode 100644
index 0000000..bacbc39
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/test_app.txt
@@ -0,0 +1,50 @@
+>>> from widgetbrowser import WidgetBrowser
+>>> from webtest import TestApp
+
+>>> app = TestApp(WidgetBrowser())
+
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo')
+>>> assert 'default' in r
+
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/')
+>>> assert 'Demo' in r
+
+>>> r = app.get('/os.open/demo', status=404)
+
+Test that code isn't executed if not allowed
+
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo?_disp="foo"')
+>>> assert 'default' in r
+
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/template')
+>>> assert '$value' in r
+
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/source')
+>>> assert 'class' in r
+>>> assert 'TestWidget' in r
+
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/parameters')
+>>> assert 'Inherited' in r
+
+Test posting:
+
+>>> r = app.post('/widgetbrowser.tests.widgets.TestWidget/demo', {'some_key':'foo'})
+>>> assert 'some_key' in r
+
+# the following is just to test the failed validation code-path
+>>> r = app.post('/widgetbrowser.tests.widgets.TestWidget/demo', {'break':'y'})
+>>> assert 'some_key' not in r
+
+Test unimplemented methods:
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/foobarize', status=501)
+
+Test custom controller
+
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/test')
+>>> assert 'Testing TestWidget' in r
+
+Now with code execution
+
+>>> app = TestApp(WidgetBrowser(interactive=True))
+>>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo?_disp="foo"')
+>>> assert 'foo' in r
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py
new file mode 100644
index 0000000..fc2d10a
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py
@@ -0,0 +1,26 @@
+import os
+import shutil
+from unittest import TestCase
+from pkg_resources import resource_filename
+import sphinx
+
+doc_dir = resource_filename('widgetbrowser.tests', 'testdocs')
+
+class TestSphinxExt(TestCase):
+    def setUp(self):
+        self.dest_dir = os.tempnam()
+        if not os.path.isdir(self.dest_dir):
+            os.makedirs(self.dest_dir)
+
+    def tearDown(self):
+        try:
+            shutil.rmtree(self.dest_dir)
+        except OSError:
+            pass
+
+    def test_generate(self):
+        out = sphinx.main(['sphinx-build', doc_dir, self.dest_dir])
+        self.failUnless(not out, out)
+        html = open(os.path.join(self.dest_dir, 'index.html')).read()
+        self.failUnless('widgetbrowser' in html)
+        self.failUnless('x-large' in html)
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/conf.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/conf.py
new file mode 100644
index 0000000..4bd428a
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/conf.py
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+#
+# TestDocs documentation build configuration file, created by
+# sphinx-quickstart on Fri May  9 09:56:10 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+#sys.path.append(os.path.abspath('some/directory'))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['widgetbrowser.sphinx_ext']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = []
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'TestDocs'
+copyright = '2008, Alberto'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '0.1'
+# The full version, including alpha/beta/rc tags.
+release = '0.1'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'default.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+#html_logo = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.
+#html_use_opensearch = False
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'TestDocsdoc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'TestDocs.tex', 'TestDocs Documentation', 'Alberto', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/index.rst b/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/index.rst
new file mode 100644
index 0000000..6f70ced
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/testdocs/index.rst
@@ -0,0 +1,12 @@
+.. TestDocs documentation master file, created by sphinx-quickstart on Fri May  9 09:56:10 2008.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Testing the `widgetbroser` directive
+====================================
+
+Test an existing widget
+-----------------------
+.. widgetbrowser:: widgetbrowser.tests.widgets.TestWidget
+   :tabs: source, demo, parameters, template
+   :size: x-large
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/tests/widgets.py b/moksha/apps/widgetbrowser/widgetbrowser/tests/widgets.py
new file mode 100644
index 0000000..149139d
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/tests/widgets.py
@@ -0,0 +1,25 @@
+from tw.api import Widget
+from widgetbrowser import WidgetBrowser
+from formencode.api import Invalid
+
+class TestWidget(Widget):
+    template = "$value"
+    default = "default"
+
+    def validate(self, value, *args, **kw):
+        if 'break' in value.keys():
+            raise Invalid("Validation failed", value, None)
+        return value
+
+ at WidgetBrowser.register_controller(TestWidget, 'test')
+def test_controller(request, response):
+    response.headers['Content-Type'] = 'text/plain'
+    return "Testing " + request.widget.__class__.__name__
+
+class TestWidgetExternalTemplate(Widget):
+    template = "toscawidgets:widgetbrowser.tests.dummy_template"
+    default = "default"
+
+class TestWidgetMultipleExternalTemplate(Widget):
+    template = "toscawidgets:widgetbrowser.tests.dummy_m_template"
+    default = "default"
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/util.py b/moksha/apps/widgetbrowser/widgetbrowser/util.py
new file mode 100644
index 0000000..648cd8c
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/util.py
@@ -0,0 +1,242 @@
+import logging
+import os
+import errno
+import sys
+import pprint
+
+from pkg_resources import EntryPoint, iter_entry_points, resource_string
+
+import tw
+from tw.api import Widget, WidgetType
+from tw.core import view
+
+log = logging.getLogger(__name__)
+
+def import_widget(path):
+    """Import a widget given a dotted or entry point notation path.
+
+    Can import both widget instances or classes.
+
+       >>> import_widget('tw.core.base.Widget')
+       <class 'tw.core.base.Widget'>
+       >>> import_widget('tw.core.base:Widget')
+       <class 'tw.core.base.Widget'>
+       >>> import_widget('os.popen')
+
+    """
+    if ':' not in path:
+        parts = path.split('.')
+        path = '.'.join(parts[:-1]) + ':' + parts[-1]
+    widget = EntryPoint.parse("x="+path).load(False)
+    if not isinstance(widget, (WidgetType, Widget)):
+        widget = None
+    return widget
+
+
+def widget_path(widget):
+    """Returns the path of a widget instance or subclass
+
+    >>> from tw.api import Widget
+    >>> widget_path(Widget)
+    'tw.core.base.Widget'
+    >>> widget_path(Widget())
+    'tw.core.base.Widget'
+    """
+    if not isinstance(widget, (WidgetType, Widget)):
+        raise TypeError("Only widgets are allowed")
+    if isinstance(widget, Widget):
+        widget = widget.__class__
+    return '.'.join([widget.__module__, widget.__name__])
+
+def format_code(code, format='python'):
+    """Formats a chunk of code as html. If pygments is installed it will
+    pygmentize it.
+    
+    >>> code = "from __future__ import teletransportation"
+    >>> '<pre' in format_code(code)
+    True
+    """
+    try:
+        from pygments import highlight, formatters, lexers
+    except ImportError:
+        log.info("Pygments is not available to colorize")
+        return '<pre>' + code + '</pre>'
+    lexer = lexers.get_lexer_by_name(format)
+    formatter = formatters.get_formatter_by_name('html')
+    return highlight(code, lexer, formatter)
+
+#TODO: Memoize this function
+def widget_template(widget, extension='.html'):
+    """Returns the template of a widget as a string.
+
+    Loads external templates if needed.
+
+    >>> from widgetbrowser.tests.widgets import *
+    >>> widget_template(TestWidgetExternalTemplate())
+    'Dummy template $value\\n'
+
+    If more than one is available, it will use the extension to disambiguate.
+
+    >>> from widgetbrowser.tests.widgets import TestWidgetExternalTemplate
+    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.html')
+    'Dummy template $value\\n'
+    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.mak')
+    'Dummy template $value mako version\\n'
+    """
+    template = widget.template
+    if template and not view._is_inline_template(template):
+        # Template seems to refer to a file, look it up
+        parts = template.split('.')
+        possible_extensions = set(".html .mak .mako".split())
+        possible_extensions.remove(extension)
+        possible_extensions = [extension] + list(possible_extensions)
+        for ext in possible_extensions:
+            try:
+                return resource_string('.'.join(parts[:-1]), parts[-1]+ext)
+            except IOError, e:
+                if e.errno not in (0, errno.ENOENT):
+                    raise
+        return None
+    return template
+
+def pretty_print(obj):
+    """Pretty prints an object returning pygmentized code if possible."""
+    return format_code(pprint.pformat(obj), 'python')
+
+def display_widget(widget, argstr='', ctx=None):
+    """Displays a widget with optional arguments as a string.
+    
+
+    .. warning:: IT IS VERY UNSAFE TO EXECUTE UNTRUSTED CODE
+
+    Example::
+
+        >>> from tw.api import Widget
+        >>> class TestWidget(Widget):
+        ...     params = ['param']
+        ...     template = "$value-$param"
+        >>> display_widget(TestWidget())
+        u'None-None'
+        >>> display_widget(TestWidget(), '"hello", param=2')
+        u'hello-2'
+    """
+    ctx = ctx or {}
+    ctx['_w'] = widget
+    code = "_o = _w(%s)" % argstr
+    exec code in ctx
+    return ctx['_o']
+
+def widget_url(widget, action='', prefix=None):
+    """Returns the URL of the controller to perform `action` on `widget`.
+
+    If no `prefix` is passed the it will be tried to be fetched from
+    `tw.framework.request_local` where the :class:`WidgetBrowser` leaves it
+    on every request.
+
+    Example::
+
+        >>> from tw.core.base import Widget
+        >>> widget_url(Widget)
+        '/tw.core.base.Widget/'
+        >>> widget_url(Widget())
+        '/tw.core.base.Widget/'
+
+    You can also pass the `path` of the widget::
+
+        >>> widget_url('tw.api.Widget')
+        '/tw.api.Widget/'
+        >>> widget_url('tw.api.Widget', 'show')
+        '/tw.api.Widget/show'
+        >>> widget_url('tw.api.Widget', 'show', prefix='/widget')
+        '/widget/tw.api.Widget/show'
+
+    .. note::
+
+        You can pass any path the widget can be imported from when passing a
+        string but if you pass a widget instance or subclass then the real
+        module where it is defined will be generated.
+    """
+    if isinstance(widget, (Widget, WidgetType)):
+        widgeturi = widget_path(widget)
+    else:
+        widgeturi = widget
+        if import_widget(widgeturi) is None:
+            return
+    if prefix is None:
+        prefix = getattr(tw.framework.request_local, 'browser_prefix', '')
+    return '/'.join([prefix.rstrip('/'), widgeturi, action])
+
+def all_widgets():
+    """Iterates over all the Widget subclasses in the modules
+    that are declared as `toscawidgets.widgets` entrypoints
+
+    >>> len(list(all_widgets())) > 0
+    True
+    """
+    seen = set()
+    for ep in iter_entry_points('toscawidgets.widgets'):
+        try:
+            mod = ep.load(False)
+        except ImportError, e:
+            log.error("Could not load %r: %s", ep, e)
+            continue
+        for name in dir(mod):
+            obj = getattr(mod, name)
+            if isinstance(obj, WidgetType) and obj not in seen:
+                seen.add(obj)
+                yield obj
+
+class WidgetParameters(object):
+    """Wraps a widget and provides information on it's parameters.
+
+    Example::
+
+        >>> from tw.core.base import Widget
+        >>> params = WidgetParameters(Widget)
+        >>> len(params.all) > 0
+        True
+        >>> params.all - params.local == params.inherited
+        True
+    """
+    def __init__(self, widget):
+        if isinstance(widget, Widget):
+            widget = widget.__class__
+        self.widget = widget
+        self.all = widget.params
+        self.inherited = set()
+        for b in self.widget.__mro__:
+            if b is self.widget:
+                continue
+            self.inherited.update(getattr(b, 'params', set()))
+        self.local = self.all - self.inherited
+
+    def get_default(self, name, default=None):
+        """Returns a string representation of a parameter default value.
+
+        Example::
+
+            >>> from tw.core.base import Widget
+            >>> params = WidgetParameters(Widget)
+            >>> type(params.get_default('id'))
+            <type 'str'>
+        """
+        return repr(getattr(self.widget, name, default))
+
+    def get_doc(self, name, default='Undocumented'):
+        """Returns parameters's doc. If it is not documented it will return
+        ``default``
+
+        Example::
+
+            >>> from tw.core.base import Widget
+            >>> params = WidgetParameters(Widget)
+            >>> type(params.get_doc('id'))
+            <type 'str'>
+        """
+        return getattr(self.widget, name + '__doc', default)
+        
+def build_docs(src, dst):
+    import sphinx
+    if not os.path.exists(dst):
+        os.mkdir(dst)
+    return sphinx.main(['sphinx-build', src, dst])
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/widgets.py b/moksha/apps/widgetbrowser/widgetbrowser/widgets.py
new file mode 100644
index 0000000..b40fdea
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/widgets.py
@@ -0,0 +1,71 @@
+from tw.api import Widget, JSLink, CSSLink, js_function
+from widgetbrowser import util
+import string
+
+__all__ = ['WidgetBrowserTabs']
+
+mod = 'widgetbrowser'
+flora_all_css = CSSLink(modname=mod, filename="static/themes/flora/flora.all.css")
+tabs_css = CSSLink(modname=mod, filename="static/ui.tabs.css")
+wb_css = CSSLink(modname=mod, filename="static/widgetbrowser.css")
+pygments_css = CSSLink(modname=mod, filename="static/pygments.css")
+httprepl_css = CSSLink(modname=mod, filename="static/httprepl.css")
+jquery_js = JSLink(modname=mod, filename="static/jquery.js")
+# Do not pull jquery as an automatic dependency since Sphinx already includes
+# it
+ui_base_js = JSLink(modname=mod, filename="static/ui.base.js",
+                    location="bodybottom")
+ui_tabs_js = JSLink(modname=mod, filename="static/ui.tabs.js",
+                    location="bodybottom",
+                    javascript=[ui_base_js])
+ui_dragabble_js = JSLink(modname=mod, filename="static/ui.draggable.js",
+                         location="bodybottom")
+ui_resizable_js = JSLink(modname=mod, filename="static/ui.resizable.js",
+                         location="bodybottom")
+ui_dialog_js = JSLink(modname=mod, filename="static/ui.dialog.js",
+                      location="bodybottom",
+                      javascript=[ui_base_js, ui_dragabble_js, ui_resizable_js])
+widgetbrowser_js = JSLink(modname=mod, filename="static/widgetbrowser.js",
+                          javascript=[ui_tabs_js],
+                          css=[tabs_css, wb_css, pygments_css],
+                          location="bodybottom")
+
+httprepl_js = JSLink(modname=mod, filename='static/httprepl.js',
+                     javascript=[ui_dialog_js],
+                     css=[httprepl_css],
+                     location="bodybottom")
+
+class WidgetBrowserTabs(Widget):
+    template = "genshi:widgetbrowser.templates.widget_browser_tabs"
+    params = ["tabs", "prefix", "size", "in_sphinx"]
+    in_sphinx = False
+    javascript = [widgetbrowser_js]
+    size = "small"
+    tabs = ['demo', 'demo_source', 'source', 'template', 'parameters']
+    prefix = None
+     
+    def update_params(self, d):
+        super(WidgetBrowserTabs, self).update_params(d)
+        d.tabs = [(string.capwords(t.replace('_', ' ')), util.widget_url(d.value, t, prefix=d.prefix))
+                  for t in d.tabs]
+        if not d.in_sphinx:
+            # Not displayed inside Sphinx, include jquery and pygments
+            jquery_js.inject()
+            pygments_css.inject()
+
+
+class WidgetRepl(Widget):
+    template = '<div id="$id" class="$css_class"></div>'
+    params = ["prefix"]
+    prefix = '/_repl/' # show nicely in the browser tabs
+    include_dynamic_js_calls = True
+    javascript = [jquery_js, httprepl_js]
+    css = [flora_all_css]
+    def update_params(self, d):
+        super(WidgetRepl, self).update_params(d)
+        assert d.id, "This widget needs an id"
+        config = dict(prefix=d.prefix)
+        call = js_function('HTTPRepl.render')('#'+d.id, config)
+        self.add_call("jQuery(function () {%s});" %  call)
+
+repl = WidgetRepl("widgetrepl")
diff --git a/moksha/apps/widgetbrowser/widgetbrowser/wsgiapp.py b/moksha/apps/widgetbrowser/widgetbrowser/wsgiapp.py
new file mode 100644
index 0000000..d2dbedd
--- /dev/null
+++ b/moksha/apps/widgetbrowser/widgetbrowser/wsgiapp.py
@@ -0,0 +1,251 @@
+import sys
+import weakref
+import os
+import inspect
+import logging
+from pkg_resources import resource_filename
+from genshi.core import Markup
+from genshi.template import TemplateLoader, Context
+from webob import Request, Response, exc
+import tw
+from tw.api import Widget, WidgetType, make_middleware
+from widgetbrowser import util, widgets, repl
+
+try:
+    from formencode import Invalid
+    have_formencode = True
+except ImportError:
+    have_formencode = False
+
+from moksha.lib.helpers import cache_rendered
+
+__all__ = ['WidgetBrowser']
+
+log = logging.getLogger(__name__)
+
+def asbool(v):
+    if isinstance(v, basestring):
+        return v.lower().startswith('t') or v == '1' or v == 'on'
+    elif isinstance(v, bool):
+        return v
+    return False
+
+class WidgetBrowser(object):
+    """A widget browser WSGI app.
+
+    Parameters:
+
+      * `template_dirs`: A list of directories that shall be searched for
+        temlates used by the widget browser.
+      * `interactive`: Enable code execution. This is needed to for the REPL and
+        to override display arguments via the web interface. This is a BIG
+        SECURITY HOLE, enable only in a controlled environment.
+      * `docs_dir`: A directory where sphinx sources live.
+    """
+    def __init__(self, global_conf={}, template_dirs=None, interactive=False,
+                 docs_dir=None, full_stack=True):
+        if isinstance(template_dirs, basestring):
+            template_dirs = template_dirs.split()
+        template_dirs = template_dirs or []
+        template_dirs.append(resource_filename('widgetbrowser', 'templates'))
+        self.loader = TemplateLoader(template_dirs)
+        self.interactive = asbool(interactive)
+        if self.interactive:
+            self.http_repl = repl.WidgetReplApp(globals(), weakref.proxy(self))
+            self.context = self.http_repl.repl.locals
+        else:
+            self.context = None
+            self.http_repl = exc.HTTPForbidden("Interactive mode is disabled")
+        if docs_dir:
+            from paste.cascade import Cascade
+            dest_dir = os.path.abspath(os.path.join(docs_dir, '.build'))
+            log.info('Building docs...')
+            try:
+                util.build_docs(docs_dir, dest_dir)
+            except Exception, e:
+                log.warning('Skipping building docs: %s' % str(e))
+            self.built_docs = dest_dir
+            self.app = Cascade([self.docs_app, self.app])
+        if asbool(full_stack):
+            self.app = make_middleware(self.app, {
+                'toscawidgets.framework.default_view': 'genshi',
+                }, stack_registry = True)
+        self._default_controllers = dict(demo=self.show_demo,
+                                         index=self.show_index,
+                                         template=self.show_template,
+                                         parameters=self.show_parameters,
+                                         source=self.show_source,
+                                         demo_source=self.show_demo_source)
+
+
+    def docs_app(self, environ, start_response):
+        """Registers widgetbrowser_js as resources before serving static html
+        files so it is injected into the page"""
+        from paste.urlparser import StaticURLParser
+        app = StaticURLParser(self.built_docs)
+        resources = widgets.widgetbrowser_js.retrieve_resources()
+        tw.framework.register_resources(resources)
+        return app(environ, start_response)
+
+    _widget_controllers = {}
+    @classmethod
+    def register_controller(cls, widget, action):
+        """Registers function to act as a demo controller for a widget"""
+        def _register(controller):
+            cls._widget_controllers[(widget,action)] = controller
+            return controller
+        return _register
+
+    def lookup_controller(self, widget_cls, action):
+        try:
+            return self._widget_controllers[(widget_cls, action)]
+        except KeyError:
+            return self._default_controllers[action]
+
+    def lookup_widget_action(self, path_info):
+        try:
+            widget_path, action = path_info.strip('/').split('/')
+        except ValueError:
+            widget_path, action = path_info, 'index'
+        if widget_path:
+            try:
+                widget = util.import_widget(widget_path.strip('/'))
+            except (ImportError, ValueError):
+                widget = None
+            if widget:
+                return widget, action
+        raise LookupError(path_info)
+
+    def render(self, template, ns):
+        ns.pop('self',None)
+        stream = self.loader.load(template).generate(Context(**ns))
+        return stream.render(method='xhtml', doctype='xhtml')
+
+    def __call__(self, environ, start_response):
+        return self.app(environ, start_response)
+
+    @cache_rendered
+    def app(self, environ, start_response):
+        req = Request(environ)
+        resp = Response(request=req, content_type='text/html; charset=utf-8')
+        # Leave the interactive flag in tw.framework so demo controllers can know
+        # if it is safe to enable advanced/unsecure features.
+        tw.framework.request_local.interactive = self.interactive
+        tw.framework.request_local.browser_prefix = req.script_name
+
+        # Lookup widget XXX: Yuck!
+        if req.path_info == '/':
+            controller = self.home
+        elif req.path_info.startswith('/_repl') and self.http_repl:
+            req.path_info_pop()
+            return self.http_repl(environ, start_response)
+        elif req.path_info.startswith('/widgets'):
+            controller = self.widgets
+        else:
+            try:
+                widget, action = self.lookup_widget_action(req.path_info)
+            except LookupError:
+                resp = exc.HTTPNotFound('No widget at %s' % req.path_info)
+                return resp(environ, start_response)
+                
+
+            # Lookup controller
+            try:
+                controller = self.lookup_controller(widget, action)
+            except LookupError:
+                resp = exc.HTTPNotImplemented()
+                return resp(environ, start_response)
+                
+            # If it's a widget class instantiate it with no arguments 
+            if isinstance(widget, WidgetType):
+                widget = widget('test_widget')
+            req.widget = widget
+
+        # Call controller and handle output 
+        output = controller(req, resp)
+        if isinstance(output, str):
+            resp.body = output
+        elif isinstance(output, unicode):
+            resp.body = output.encode('utf-8')
+        elif output:
+            resp = output
+
+        return resp(environ, start_response)
+
+
+    def show_template(self, req, resp):
+        widget = req.widget
+        if getattr(widget, 'demo_for', None):
+            widget = req.widget.demo_for()
+        template = util.widget_template(widget)
+        if template:
+            return util.format_code(template, 'html')
+        else:
+            resp.content_type = "text/plain"
+            return widget.__class__.__name__ + ' has no template.'
+
+    def show_source(self, req, resp):
+        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
+        source = inspect.getsource(cls)
+        return util.format_code(source, 'python')
+
+    def show_demo_source(self, req, resp):
+        widget = req.widget
+        source = inspect.getsource(widget.__class__)
+        return util.format_code(source, 'python')
+
+    def show_parameters(self, req, resp):
+        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
+        parameters = util.WidgetParameters(cls)
+        return self.render('widget_parameters.html', locals())
+
+
+    def show_index(self, req, resp):
+        widget = req.widget
+        return self.render('widget_index.html', locals())
+
+    @cache_rendered
+    def show_demo(self, req, resp):
+        widget = req.widget
+        widget_name = widget.__class__.__name__
+        interactive = self.interactive
+        if have_formencode and req.method.upper() == "POST":
+            # A widget submission, try to validate.
+            try:
+                value = widget.validate(req.POST)
+                value = util.pretty_print(value)
+                return self.render('validation_result.html', locals())
+            except Invalid, error:
+                pass
+
+        if self.interactive:
+            _disp = req.GET.get('_disp', '')
+        else:
+            _disp = ''
+
+        widget_output = util.display_widget(widget, _disp, self.context)
+
+        # Wrap non-genshi things, like Mako based widgets, in a Genshi Markup object
+        if not callable(widget_output):
+            widget_output = Markup(widget_output)
+
+        # Inject moksha's global resources so we can get things like
+        # Orbited/Stomp/jQuery/etc.
+        from moksha.api.widgets.global_resources import global_resources
+        global_resources.register_resources()
+
+        return self.render('show_widget.html', locals())
+
+    def widgets(self, req, resp):
+        widgets = [(util.widget_path(w), util.widget_url(w))
+                       for w in util.all_widgets()]
+        widgets.sort()
+        return self.render('list_widgets.html', locals())
+
+    def home(self, req, resp):
+        widgets.jquery_js.inject()
+        widgets.tabs_css.inject()
+        widgets.ui_tabs_js.inject()
+        def url(s):
+            return req.script_name + s
+        return self.render('home.html', locals())
diff --git a/moksha/widgetbrowser/paster.ini b/moksha/widgetbrowser/paster.ini
deleted file mode 100644
index c1b4d92..0000000
--- a/moksha/widgetbrowser/paster.ini
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Sample PasteDeploy ini file to launch the WidgetBrowser.
-# 
-# This is most useful while developing and debugging widgets since paster can autoreload the WidgetBrowser
-# whenever any imported module's source is modified. To enable reloading do:
-#
-#   $ paster serve --reload paster.ini
-#
-# The %(here)s variable will be replaced with the parent directory of this file
-#
-
-[server:main]
-use = egg:Paste#http
-# Bind only to the loopback interface since we're starting in intercative mode.
-host = 127.0.0.1
-port = 8000
-
-[app:main]
-use = egg:WidgetBrowser
-# Enable interactive mode so WebError (needs to be easy_installed first) and the Terminal are available
-interactive = true
diff --git a/moksha/widgetbrowser/setup.cfg b/moksha/widgetbrowser/setup.cfg
deleted file mode 100644
index e00908b..0000000
--- a/moksha/widgetbrowser/setup.cfg
+++ /dev/null
@@ -1,14 +0,0 @@
-[aliases]
-release = egg_info -RDb "" sdist bdist_egg register upload
-test = nosetests
-cover = nosetests --with-coverage
-
-#[egg_info]
-#tag_build = dev
-#tag_date = true
-
-[nosetests]
-with-coverage = false
-cover-package = widgetbrowser
-doctest-extension = .txt
-with-doctest = true
diff --git a/moksha/widgetbrowser/setup.py b/moksha/widgetbrowser/setup.py
deleted file mode 100644
index 967a1f9..0000000
--- a/moksha/widgetbrowser/setup.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from setuptools import setup, find_packages
-import sys, os
-
-version = '0.1'
-
-setup(name='WidgetBrowser',
-      version=version,
-      description="ToscaWidgets browser",
-      long_description="""\
-""",
-      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
-      keywords='toscawidgets',
-      author='Alberto Valverde Gonzalez',
-      author_email='alberto at toscat.net',
-      url='http://toscawidgets.org/',
-      license='MIT',
-      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
-      include_package_data=True,
-      zip_safe=True,
-      install_requires=[
-          "ToscaWidgets>=0.9.2dev-20080602",
-          "Genshi",
-          "WebOb",
-          "docutils",
-      ],
-      tests_require = ['nose', 'formencode', 'sphinx'],
-      extras_require = {
-          'full': ['Sphinx', 'Pygments', 'docutils', 'nose', 'WebTest',
-                   'WebError', 'coverage', 'FormEncode'],
-      },
-      entry_points="""
-      [console_scripts]
-      twbrowser = widgetbrowser.command:browser_command
-      [paste.app_factory]
-      main = widgetbrowser.wsgiapp:WidgetBrowser
-      [toscawidgets.widgets]
-      widgets = widgetbrowser.widgets
-      """,
-      )
diff --git a/moksha/widgetbrowser/widgetbrowser/__init__.py b/moksha/widgetbrowser/widgetbrowser/__init__.py
deleted file mode 100644
index c037ed3..0000000
--- a/moksha/widgetbrowser/widgetbrowser/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from wsgiapp import WidgetBrowser
-from util import widget_url
diff --git a/moksha/widgetbrowser/widgetbrowser/command.py b/moksha/widgetbrowser/widgetbrowser/command.py
deleted file mode 100644
index 4b15fbe..0000000
--- a/moksha/widgetbrowser/widgetbrowser/command.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from wsgiref.simple_server import make_server
-from optparse import OptionParser
-
-from widgetbrowser.wsgiapp import WidgetBrowser
-
-
-_parser = OptionParser(usage = "%prog [OPTIONS] [widget_url]")
-_parser.add_option("-i", "--interactive",
-                   dest="interactive",
-                   action="store_true",
-                   default=False)
-_parser.add_option("-b", "--browser",
-                   dest="browser",
-                   action="store_true",
-                   default=False)
-_parser.add_option("-d", "--docs",
-                   dest="docs",
-                   default=None)
-_parser.add_option("-p", "--port",
-                   dest="port",
-                   default=8000)
-
-def browser_command(argv=None):
-    """Command line interface to launch the widgetbrowser"""
-    opts, args = _parser.parse_args(argv)
-
-    # Only allow passing display arguments in debug mode 
-    if args:
-        widget_url = args[0] + '/'
-    else:
-        widget_url = ''
-    app = WidgetBrowser(interactive=opts.interactive, docs_dir=opts.docs)
-    if opts.interactive:
-        try:
-            from weberror.evalexception import EvalException
-            app = EvalException(app)
-        except ImportError:
-            raise ImportError("You need to install WebError for interactive "
-                              "debugging")
-    url = "http://127.0.0.1:%s/" % opts.port
-    if opts.browser:
-        import webbrowser
-        webbrowser.open(url + widget_url)
-    server = make_server('127.0.0.1', int(opts.port), app)
-    print "Server started at " + url
-    try:
-        server.serve_forever()
-    except (KeyboardInterrupt, SystemExit):
-        pass
-
-if __name__ == '__main__':
-    import sys
-    sys.exit(browser_command(sys.argv))
-
diff --git a/moksha/widgetbrowser/widgetbrowser/repl.py b/moksha/widgetbrowser/widgetbrowser/repl.py
deleted file mode 100644
index 5855068..0000000
--- a/moksha/widgetbrowser/widgetbrowser/repl.py
+++ /dev/null
@@ -1,305 +0,0 @@
-"""
-Robert Brewer was the original author of the module this module has heavily
-inspired from.  http://www.aminus.net/wiki/HTTPREPL
-"""
-import warnings
-from itertools import count
-import codeop
-import inspect
-import os
-import re
-
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
-
-import sys
-import traceback
-
-from webob import Request, Response, exc
-
-try:
-    from formencode import Invalid
-    have_formencode = True
-except ImportError:
-    have_formencode = False
-
-from genshi.util import LRUCache
-import tw
-from tw.api import make_middleware, Widget
-
-from widgetbrowser import util, widgets
-
-class HTTPREPL:
-    
-    def __init__(self, locals=None):
-        self.locals = {}
-        if locals:
-            self.locals.update(locals)
-        self.buffer = []
-    
-    def push(self, line):
-        """Push 'line' and return exec results (None if more input needed)."""
-        if line == "help":
-            return "Type help(object) for help about object."
-        if line == "help()":
-            return "You cannot call help() without an argument."
-        
-        self.buffer.append(line)
-        source = "\n".join(self.buffer)
-        
-        try:
-            code = codeop.compile_command(source, "<HTTP input>", 'single')
-        except (OverflowError, SyntaxError, ValueError):
-            self.buffer = []
-            return traceback.format_exc()
-        
-        if code is None:
-            # More lines needed.
-            return None
-        
-        self.buffer = []
-        return self.execute(code)
-    
-    def execute(self, code):
-        """Execute the given code in self.locals and return any stdout/sterr."""
-        out = StringIO()
-        oldout = sys.stdout
-        olderr = sys.stderr
-        sys.stdout = sys.stderr = out
-        try:
-            try:
-                exec code in self.locals
-            except:
-                result = traceback.format_exc()
-            else:
-                result = out.getvalue()
-        finally:
-            # FormEncode will break if _ is left in __builtins__ and it tries
-            # to use it as a translator
-            __builtins__.pop('_', None)
-            sys.stdout = oldout
-            sys.stderr = olderr
-        out.close()
-        return result
-    
-    def dir(self, line):
-        """Examine a partial line and provide attr list of final expr."""
-        line = re.split(r"\s", line)[-1].strip()
-        # Support lines like "thing.attr" as "thing.", because the browser
-        # may not finish calculating the partial line until after the user
-        # has clicked on a few more keys.
-        line = ".".join(line.split(".")[:-1])
-        try:
-            result = eval("dir(%s)" % line, {}, self.locals)
-        except:
-            return []
-        return result
-    
-    def doc(self, line):
-        """Examine a partial line and provide sig+doc of final expr."""
-        line = re.split(r"\s", line)[-1].strip()
-        # Support lines like "func(text" as "func(", because the browser
-        # may not finish calculating the partial line until after the user
-        # has clicked on a few more keys.
-        line = "(".join(line.split("(")[:-1])
-        try:
-            result = eval(line, {}, self.locals)
-            try:
-                if isinstance(result, type):
-                    func = result.__init__
-                else:
-                    func = result
-                args, varargs, varkw, defaults = inspect.getargspec(func)
-            except TypeError:
-                if callable(result):
-                    doc = getattr(result, "__doc__", "") or ""
-                    return "%s\n\n%s" % (line, doc)
-                return None
-        except:
-            return None
-        
-        if args and args[0] == 'self':
-            args.pop(0)
-        missing = object()
-        defaults = defaults or []
-        defaults = ([missing] * (len(args) - len(defaults))) + list(defaults)
-        arglist = []
-        for a, d in zip(args, defaults):
-            if d is missing:
-                arglist.append(a)
-            else:
-                arglist.append("%s=%s" % (a, d))
-        if varargs:
-            arglist.append("*%s" % varargs)
-        if varkw:
-            arglist.append("**%s" % varkw)
-        doc = getattr(result, "__doc__", "") or ""
-        return "%s(%s)\n%s" % (line, ", ".join(arglist), doc)
-
-
-class DeferredDisplay(object):
-    """Wraps a widget and the args passed to display/render so we can defer
-    its display to another request.
-    
-    .. note::
-        The JS code is dependent on the output of __repr__ since it parses it
-        to know a widget is being displayed so it can open an overlay.
-    """
-    _counter = count(0)
-    def __init__(self, widget, value, **kw):
-        self.id = self._counter.next()
-        self.value = value
-        self.widget = widget
-        self.kw = kw
-
-    def display(self):
-        """
-        Displays the widget as it was intended to be displayed when it was
-        wrapped.
-        """
-        return self.widget.display(self.value, **self.kw)
-
-    __call__ = display
-
-    def __repr__(self):
-        data = (self.id, self.widget.__class__)
-        return self.__class__.__name__ + repr(data)
-
-
-class WidgetReplApp(object):
-    def __init__(self, locals=None, widget_browser=None, max_dialogs=10):
-        self.repl = HTTPREPL(locals)
-        warnings.warn("\n"*2 + "*"*79 + "\n"
-                      "DISCLAIMER:\n"
-                      "Running this app poses a significant security threat "
-                      "if accessible to an \nattacker. Make sure the server is "
-                      "bound to the loopback interface or behind\na firewall "
-                      "and that there are no local untrusted users.\n" + "*"*79)
-        if widget_browser:
-            self.widget_browser = widget_browser
-            self.displayed_widgets = LRUCache(max_dialogs)
-            self.setup_tw()
-
-    def setup_tw(repl_app):
-        # Stack TW's middleware configured with dummy default_view to signal
-        # that a widget is being displayed so we can wrap and register its
-        # output.
-        conf = {'toscawidgets.framework.default_view' : 'tw_repl',
-                'toscawidgets.middleware.inject_resources' : True}
-        repl_app.app = make_middleware(repl_app.app, conf)
-        # monkey-patch display and render to hijack output
-        def wrap(f):
-            if f.func_name == 'wrapper':
-                return f
-            def wrapper(self, value=None, **kw):
-                if self.displays_on == 'tw_repl':
-                    o = DeferredDisplay(self, value, **kw)
-                    repl_app.displayed_widgets[o.id] = o
-                else:
-                    o = f(self, value, **kw)
-                return o
-            return wrapper
-        Widget.display = wrap(Widget.display)
-        Widget.render = wrap(Widget.render)
-
-    def __call__(self, environ, start_response):
-        assert not environ['wsgi.multiprocess'], "Cannot run in a multiprocess"\
-                                                 " environment"
-        return self.app(environ, start_response)
-
-    def app(self, environ, start_response):
-        """Main dispatcher. pops PATH_INFO and delegates to exposed methods."""
-        req = Request(environ.copy())
-        resp = Response(request=req, content_type='text/html; charset=UTF8')
-        first_part = req.path_info_pop() or 'index'
-        method = getattr(self, first_part, None)
-        if getattr(method, 'exposed', False):
-            output = method(req, resp)
-            if isinstance(output, unicode):
-                resp.body = output.encode('utf-8')
-            elif isinstance(output, str):
-                resp.body = output
-            elif output:
-                resp = output
-        else:
-            resp = exc.HTTPNotImplemented()
-        return resp(environ, start_response)
-        
-    def index(self, req, resp):
-        """Return an HTTP-based Read-Eval-Print-Loop terminal."""
-        # Override default_view so resources display properly
-        tw.framework.default_view = 'toscawidgets'
-        tpl = '<html><head><title>"%(title)s</title></head>' \
-              '<body class="flora">%(repl)s</body></html>'
-        prefix = req.script_name + '/'
-        return tpl % {'title': 'WidgetBrowser Terminal',
-                      'repl': widgets.repl(prefix=req.script_name + '/')}
-    index.exposed = True
-    
-    def push(self, req, resp):
-        """Push 'line' and return exec results as a bare response."""
-        line = req.params['line']
-        result = self.repl.push(line)
-        if result is None:
-            # More input lines needed.
-            resp.status_int = 204
-        return result
-    push.exposed = True
-    
-    def dir(self, req, resp):
-        """Push 'line' and return result of eval on the final expr."""
-        line = req.params['line']
-        result = self.repl.dir(line)
-        if not result:
-            resp.status_int = 204
-            return
-        return repr(result)
-    dir.exposed = True
-    
-    def doc(self, req, resp):
-        """Push 'line' and return result of getargspec on the final expr."""
-        line = req.params['line']
-        result = self.repl.doc(line)
-        if not result:
-            resp.status_int = 204
-        return result
-    doc.exposed = True
-    
-    def enrich_namespace(self, ns, request):
-        
-        _disp = request.GET.get('_disp', '')
-        
-        if not "_disp" in ns:
-            ns["_disp"]=_disp
-        if not "interactive" in ns:
-            ns["interactive"]=True
-        return ns
-    
-    def widget_output(self, req, resp):
-        try:
-            key = int(req.path_info.strip('/'))
-            dd = self.displayed_widgets[key]
-        except KeyError:
-            resp.status_int = 404
-            return "There's now widget output at this URL. Maybe it has "\
-                   "expired? Try increasing the 'max_dialogs' parameter"
-
-        widget = dd.widget
-        widget_name = widget.__class__.__name__
-        render = self.widget_browser.render
-        if have_formencode and req.method.upper() == "POST":
-            # A widget submission, try to validate.
-            try:
-                value = widget.validate(req.POST)
-                value = util.pretty_print(value)
-                return render('validation_result.html', locals())
-            except Invalid, error:
-                pass
-        # Override default_view because WidgetBrowser renders on Genshi, not
-        # 'tw_repl', this is needed so widget and resources display properly
-        tw.framework.default_view = 'genshi'
-        widget_output = dd.display()
-        return render('show_widget.html', self.enrich_namespace(locals(),request=req))
-    widget_output.exposed = True
diff --git a/moksha/widgetbrowser/widgetbrowser/sphinx_ext.py b/moksha/widgetbrowser/widgetbrowser/sphinx_ext.py
deleted file mode 100644
index f0c9bea..0000000
--- a/moksha/widgetbrowser/widgetbrowser/sphinx_ext.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import os
-from docutils import nodes, utils
-from docutils.parsers.rst import directives
-
-from widgetbrowser import util, widgets
-
-widget_tabs = widgets.WidgetBrowserTabs(in_sphinx=True)
-
-def widgetbrowser_directive(dirname, arguments, options, content, lineno,
-                            content_offset, block_text, state, state_machine):
-    """Processes the `widgetbrowser` reStructuredText directive.
-    
-    When generating the URL for the widget it peeks into os.environ for the
-    'TW_BROWSER_PREFIX' environment variable.
-    """
-    widget_path = arguments[0]
-    widget = util.import_widget(widget_path)
-    if not widget:
-        reporter = state.document.reporter
-        msg = reporter.warning(
-            'No widget found at %r' % widget_path, line=lineno)
-        prb = nodes.problematic(block_text, block_text, msg)
-        return [msg, prb]
-    tabs = options.get('tabs') or widget_tabs.tabs
-    prefix = os.environ.get('TW_BROWSER_PREFIX')
-    size = options.get('size')
-    html = widget_tabs(widget, tabs=tabs, prefix=prefix, size=size)
-    node = nodes.raw('', html, format='html')
-    return [node]
-
-
-def _get_tabs(arg):
-    if arg is None:
-        return []
-    return [s.strip() for s in arg.split(',')]
-    
-def _get_size(arg):
-    return arg or "small"
-
-def setup(app):
-    browser_options = {'tabs': _get_tabs, 'size':_get_size}
-    app.add_directive('widgetbrowser', widgetbrowser_directive, 1, (1, 0, 1),
-                      **browser_options)
diff --git a/moksha/widgetbrowser/widgetbrowser/static/httprepl.css b/moksha/widgetbrowser/widgetbrowser/static/httprepl.css
deleted file mode 100644
index 6eda851..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/httprepl.css
+++ /dev/null
@@ -1,78 +0,0 @@
-.httprepl .output pre {
-    font: 10pt monospace;
-    margin: 0;
-    padding: 1px;
-    border: 1px solid #E0E0FF;
-    background-color: #F8F8FF;
-    
-    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
-    white-space: -pre-wrap; /* Opera 4 - 6 */
-    white-space: -o-pre-wrap; /* Opera 7 */
-    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
-                            http://www.w3.org/TR/css3-text/#white-space */
-    word-wrap: break-word; /* IE 5.5+ */
-}
-
-.httprepl .output pre.stdin {
-    border: none;
-    background-color: transparent;
-}
-
-form {
-    font: 10pt monospace;
-    margin: 0;
-}
-
-.httprepl .input {
-    font: 10pt monospace;
-    width: 95%;
-    border-top: none;
-    border-right: 1px dotted #E0E0FF;
-    border-bottom: none;
-    border-left: 1px dotted #E0E0FF;
-}
-
-.httprepl .tipbar {
-    position: fixed;
-    top: 10px;
-    
-    /* See http://annevankesteren.nl/test/examples/ie/position-fixed.html */
-    _position:absolute;
-    _top:expression(eval(document.body.scrollTop) + 10);
-    
-    right: 10px;
-    
-    max-width: 50%;
-    max-height: 80%;
-    /* See http://www.svendtofte.com/code/max_width_in_ie/ */
-    width: expression(document.body.clientWidth / 2);
-    height: expression(document.body.clientHeight * 0.8);
-    
-    border: 2px outset #DDCCBB;
-    background-color: #FFEEDD;
-    font: 9pt monospace;
-    
-    margin: 0;
-    padding: 4px;
-    
-    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
-    white-space: -pre-wrap; /* Opera 4 - 6 */
-    white-space: -o-pre-wrap; /* Opera 7 */
-    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
-                            http://www.w3.org/TR/css3-text/#white-space */
-    word-wrap: break-word; /* IE 5.5+ */
-    
-    display: none;
-    overflow: auto;
-}
-
-.httprepl .tipbar a {
-    padding: 4px;
-    text-decoration: none;
-    color: #666666;
-}
-
-.widget-dialog  {
-    background: #fff;
-    z-index: 9999;
-}
diff --git a/moksha/widgetbrowser/widgetbrowser/static/httprepl.js b/moksha/widgetbrowser/widgetbrowser/static/httprepl.js
deleted file mode 100644
index a85f1ef..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/httprepl.js
+++ /dev/null
@@ -1,432 +0,0 @@
-var HTTPRepl = (function ($) {
-    function http() {
-        var h;
-        if (typeof(XMLHttpRequest) != "undefined") {
-            h = new XMLHttpRequest();
-        } else {
-            try { h = new ActiveXObject("Msxml2.XMLHTTP"); }
-            catch (e) {
-                try { h = new ActiveXObject("Microsoft.XMLHTTP"); }
-                catch (E) { alert("Your browser is not supported."); }
-            }
-        }
-        return h
-    }
-
-
-    //                           HISTORY NAVIGATION                           //
-
-    function use_history(elem) {
-        var content = get_text(elem);
-        // Strip the leading prompt
-        if (elem.className == 'stdin') content = content.substr(4);
-        input.value = content;
-        input.focus();
-    }
-
-    function history_hook() {
-        use_history(this);
-    }
-
-    var current_history = undefined;
-
-    function prev_history() {
-        if (current_history == undefined) {
-            var prev = output.lastChild;
-        } else {
-            var prev = current_history.previousSibling;
-        }
-        while (prev != null && prev.className != 'stdin') {
-            prev = prev.previousSibling;
-        }
-        if (prev != null) {
-            current_history = prev;
-            use_history(prev);
-        }
-    }
-
-    function next_history() {
-        if (current_history == undefined) return;
-        
-        var next = current_history.nextSibling;
-        while (next != null && next.className != 'stdin') {
-            next = next.nextSibling;
-        }
-        if (next != null) {
-            current_history = next;
-            use_history(next);
-        }
-    }
-
-
-    //                            CODE COMPLETION                            //
-
-    current_range = undefined;
-
-    function partial_line() {
-        if (document.selection) {
-            // Internet Explorer
-            current_range = document.selection.createRange();
-            var end = current_range.getBookmark().charCodeAt(2) - 2;
-        } else {
-            var end = input.selectionEnd;
-        }
-        return input.value.substring(0, end);
-    }
-
-    function insert_text(newtext) {
-        if (document.selection) {
-            // Internet Explorer
-            current_range.text = newtext;
-            current_range.select();
-        } else {
-            var start = input.selectionStart;
-            input.value = input.value.substring(0, start) + newtext + input.value.substr(input.selectionEnd);
-            var end = start + newtext.length;
-            input.setSelectionRange(end, end);
-        }
-    }
-
-    function clear_tips() {
-        tipbar.style.display = '';
-        while (tipbar.hasChildNodes()) {
-            tipbar.removeChild(tipbar.lastChild);
-        }
-    }
-
-    function show_tips() {
-        tipbar.style.display = 'block';
-    }
-
-    var intip = false;
-
-    function use_tip() {
-        insert_text(get_text(this));
-        clear_tips();
-        intip = true;
-        input.focus();
-    }
-
-    function dir() {
-        var data = partial_line();
-        
-        clear_tips();
-        
-        var h = http();
-        h.onreadystatechange = function() {
-            if (h.readyState == 4) {
-                try {
-                    var status = h.status;
-                } catch(e) {
-                    var status = "NO HTTP RESPONSE";
-                }
-                switch (status) {
-                    case 200:
-                        var tips = eval(h.responseText);
-                        for (var i=0; i < tips.length; i++) {
-                            var tiplink = document.createElement("a");
-                            tiplink.onclick = use_tip;
-                            tiplink.href = "javascript:void(0)";
-                            set_text(tiplink, tips[i]);
-                            tipbar.appendChild(tiplink);
-                            tipbar.appendChild(document.createElement("br"));
-                        }
-                        show_tips()
-                        input.focus();
-                        break;
-                    // Internet Explorer might return 1223 for 204
-                    case 1223:
-                    case 204:
-                        // No tips available
-                        break;
-                    case 12029:
-                        // Internet Explorer client could not connect to server
-                        status = "NO HTTP RESPONSE";
-                    case 403:
-                        stdout_write("Interactive mode is disabled", false);
-                        break;
-                    default:
-                        stdout_write(status + "\n" + h.responseText, false);
-                }
-            }
-        }
-        h.open("GET", prefix + "dir?line=" + escape(data), true);
-        h.send(null);
-    }
-
-    function doc() {
-        var data = partial_line();
-        
-        clear_tips();
-        
-        var h = http();
-        h.onreadystatechange = function() {
-            if (h.readyState == 4) {
-                try {
-                    var status = h.status;
-                } catch(e) {
-                    var status = "NO HTTP RESPONSE";
-                }
-                switch (status) {
-                    case 200:
-                        tipbar.appendChild(document.createTextNode(h.responseText));
-                        show_tips();
-                        input.focus();
-                        break;
-                    // Internet Explorer might return 1223 for 204
-                    case 1223:
-                    case 403:
-                        stdout_write("Interactive mode is disabled", false);
-                        break;
-                    case 204:
-                        // No tips available
-                        break;
-                    case 12029:
-                        // Internet Explorer client could not connect to server
-                        status = "NO HTTP RESPONSE";
-                    default:
-                        stdout_write(status + "\n" + h.responseText, false);
-                }
-            }
-        }
-        h.open("GET", prefix + "doc?line=" + escape(data), true);
-        h.send(null);
-    }
-
-    //                           COMMAND EXECUTION                           //
-
-    function get_text(elem) {
-        if (elem.innerText != undefined) {
-            // Internet Explorer
-            return elem.innerText;
-        } else {
-            // Mozilla
-            return elem.textContent;
-        }
-    }
-
-    function set_text(elem, newvalue) {
-        if (elem.innerText != undefined) {
-            // Internet Explorer
-            elem.innerText = newvalue;
-        } else {
-            // Mozilla
-            elem.textContent = newvalue;
-        }
-    }
-
-    function get_prompt() {
-        return get_text(prompt_);
-    }
-
-    function set_prompt(newvalue) {
-        set_text(prompt_, newvalue);
-    }
-
-    function stdout_write(content, stdin) {
-        current_history = undefined;
-        if (content == "") return;
-        
-        var block = document.createElement("pre");
-        block.ondblclick = history_hook;
-        if (stdin) {
-            content = get_prompt() + content;
-            block.className = 'stdin';
-        }
-        if (block.innerText != undefined) {
-            // Internet Explorer quirkiness
-            block.innerText = content;
-        } else {
-            block.appendChild(document.createTextNode(content));
-        }
-        output.appendChild(block);
-    }
-
-    whitespace = /^\s+$/;
-
-    function push() {
-        var data = input.value;
-        // Uncomment to treat a line with only whitespace like a blank line
-        // if (whitespace.test(data)) data = "";
-        
-        input.value = "";
-        
-        var h = http();
-        h.onreadystatechange = function() {
-            if (h.readyState == 4) {
-                stdout_write(data, true);
-                try {
-                    var status = h.status;
-                } catch(e) {
-                    var status = "NO HTTP RESPONSE";
-                }
-                switch (status) {
-                    case 200:
-                        set_prompt(">>> ");
-                        var response = h.responseText;
-                        if (!handle_widget_output(response)) {
-                            stdout_write(response, false);
-                        }
-                        break;
-                    // Internet Explorer might return 1223 for 204
-                    case 1223:
-                    case 204:
-                        set_prompt("... ");
-                        // input.value *should* be blank, but just in case...
-                        input.value = "    " + input.value;
-                        break;
-                    case 403:
-                        stdout_write("Interactive mode is disabled", false);
-                        break;
-                    case 12029:
-                        // Internet Explorer client could not connect to server
-                        status = "NO HTTP RESPONSE";
-                    default:
-                        stdout_write(status + "\n" + h.responseText, false);
-                }
-                input.focus();
-            }
-        }
-        h.open("POST", prefix + "push", true);
-        h.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
-        h.send("line=" + escape(data));
-    }
-
-
-    function escape(data) {
-        data = data.replace(/%/gi, "%25");
-        data = data.replace(/&/gi, "%26");
-        data = data.replace(/[+]/gi, "%2B");
-        data = data.replace(/;/gi, "%3B");
-        return data;
-    }
-
-
-    //                                 SETUP                                 //
-
-    function mapKeys(key_code) {
-        if (intip) {
-            intip = false;
-            // Trap the bubbling keyup event from a tiplink. This means that,
-            // if you actually click a tiplink instead of tab and hit 'enter',
-            // you have to hit 'enter' twice to push the line. :(
-            if (key_code == 13) return;
-        }
-        switch(key_code) {
-            case 8:    // backspace
-                clear_tips();
-                break;
-            case 13:   // enter
-                clear_tips();
-                push();
-                break;
-            case 38:   // up arrow
-                prev_history();
-                break;
-            case 40:   // down arrow
-                next_history();
-                break;
-            case 48:  // close paren "("
-                clear_tips();
-                break;
-            case 57:  // open paren "("
-                doc();
-                break;
-            case 190:  // period "."
-                dir();
-                break;
-        }
-    }
-
-    function trapKeys(e) {
-        if (!e) var e = window.event;
-        mapKeys(e.keyCode);
-    }
-
-    //                   WIDGET DIALOGS                                      //
-
-    var new_id = (function make_counter(value) {
-        var state = {value: value || 0};
-        function next() {
-            state.value ++;
-            return 'widget-dialog-' + state.value;
-        }
-        return next;
-    })();
-
-    function open_dialog(config) {
-        var c = $.extend({}, {height:450, width:600}, config);
-        var iframe = $('<iframe><iframe>');
-        iframe.attr({id: new_id(), 'class': 'widget-dialog'});
-        function setSize(size) {
-            var attr = {
-                height: Math.max(0, Math.round(size.height-60)),
-                width: Math.max(0, Math.round(size.width-40))
-            }
-            iframe.attr(attr);
-        }
-        function onResizeStart(event, data) {
-            // Hide the iframe so it doesn't captute mouse events while dragging
-            // the resize handlers
-            iframe.hide();
-        }
-        function onResizeStop(event, data) {
-            setSize(data.instance.size);
-            iframe.show();
-        }
-        function onClose() {
-            iframe.remove();
-            input.focus();
-        }
-        iframe.appendTo(httprepl).dialog(config)
-              .bind('dialogclose', onClose)
-              .trigger('setData.dialog', ['resizeStart', onResizeStart])
-              .trigger('setData.dialog', ['resizeStop', onResizeStop])
-              .attr('src', config.url)
-              .dialog('open');
-        setSize(c);
-    }
-
-    var displayed_widget = /DeferredDisplay\((\d+)[^']*'([^']+)'/;
-
-    function handle_widget_output(response) {
-        var match = displayed_widget(response);
-        if (match) {
-            var config = {
-                url: prefix + 'widget_output/' + match[1],
-                height: 500,
-                width: 750,
-                title: match[2]
-            }
-            open_dialog(config);
-            return true;
-        }
-        return false;
-    }
-    var httprepl = $(''
-        +'<div class="httprepl">' 
-        +  '<div class="output"></div>'
-        +  '<form action="" class="terminal">'
-        +    '<div class="tipbar"></div>'
-        +    '<nobr>'
-        +      '<span class="prompt">&gt;&gt;&gt; </span>'
-        +      '<input type="text" class="input" size=60" />'
-        +    '</nobr>'
-        +  '</form>'
-        +'</div>'
-    );
-    var prefix = '';
-    var input = $('.input', httprepl)[0];
-    input.onkeyup = trapKeys;
-    var output = $('.output', httprepl)[0];
-    var tipbar = $('.tipbar', httprepl)[0];
-    var prompt_ = $('.prompt', httprepl)[0];
-    $('form', httprepl).submit(function() { return false });
-
-    return {
-        render: function(el, config) {
-            prefix = config.prefix || '';
-            httprepl.appendTo($(el));
-        }
-    }
-})(jQuery);
diff --git a/moksha/widgetbrowser/widgetbrowser/static/jquery.js b/moksha/widgetbrowser/widgetbrowser/static/jquery.js
deleted file mode 100644
index ea64073..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/jquery.js
+++ /dev/null
@@ -1,3436 +0,0 @@
-(function(){
-/*
- * jQuery 1.2.4a - New Wave Javascript
- *
- * Copyright (c) 2008 John Resig (jquery.com)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * $Date: 2008-04-08 13:40:03 -0300 (ter, 08 abr 2008) $
- * $Rev: 5214 $
- */
-
-// Map over jQuery in case of overwrite
-if ( window.jQuery )
-	var _jQuery = window.jQuery;
-
-var jQuery = window.jQuery = function( selector, context ) {
-	// The jQuery object is actually just the init constructor 'enhanced'
-	return new jQuery.prototype.init( selector, context );
-};
-
-// Map over the $ in case of overwrite
-if ( window.$ )
-	var _$ = window.$;
-	
-// Map the jQuery namespace to the '$' one
-window.$ = jQuery;
-
-// A simple way to check for HTML strings or ID strings
-// (both of which we optimize for)
-var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
-
-// Is it a simple selector
-var isSimple = /^.[^:#\[\.]*$/;
-
-jQuery.fn = jQuery.prototype = {
-	init: function( selector, context ) {
-		// Make sure that a selection was provided
-		selector = selector || document;
-
-		// Handle $(DOMElement)
-		if ( selector.nodeType ) {
-			this[0] = selector;
-			this.length = 1;
-			return this;
-
-		// Handle HTML strings
-		} else if ( typeof selector == "string" ) {
-			// Are we dealing with HTML string or an ID?
-			var match = quickExpr.exec( selector );
-
-			// Verify a match, and that no context was specified for #id
-			if ( match && (match[1] || !context) ) {
-
-				// HANDLE: $(html) -> $(array)
-				if ( match[1] )
-					selector = jQuery.clean( [ match[1] ], context );
-
-				// HANDLE: $("#id")
-				else {
-					var elem = document.getElementById( match[3] );
-
-					// Make sure an element was located
-					if ( elem )
-						// Handle the case where IE and Opera return items
-						// by name instead of ID
-						if ( elem.id != match[3] )
-							return jQuery().find( selector );
-
-						// Otherwise, we inject the element directly into the jQuery object
-						else {
-							this[0] = elem;
-							this.length = 1;
-							return this;
-						}
-
-					else
-						selector = [];
-				}
-
-			// HANDLE: $(expr, [context])
-			// (which is just equivalent to: $(content).find(expr)
-			} else
-				return new jQuery( context ).find( selector );
-
-		// HANDLE: $(function)
-		// Shortcut for document ready
-		} else if ( jQuery.isFunction( selector ) )
-			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
-
-		return this.setArray(
-			// HANDLE: $(array)
-			selector.constructor == Array && selector ||
-
-			// HANDLE: $(arraylike)
-			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
-			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
-
-			// HANDLE: $(*)
-			[ selector ] );
-	},
-	
-	// The current version of jQuery being used
-	jquery: "1.2.4a",
-
-	// The number of elements contained in the matched element set
-	size: function() {
-		return this.length;
-	},
-	
-	// The number of elements contained in the matched element set
-	length: 0,
-
-	// Get the Nth element in the matched element set OR
-	// Get the whole matched element set as a clean array
-	get: function( num ) {
-		return num == undefined ?
-
-			// Return a 'clean' array
-			jQuery.makeArray( this ) :
-
-			// Return just the object
-			this[ num ];
-	},
-	
-	// Take an array of elements and push it onto the stack
-	// (returning the new matched element set)
-	pushStack: function( elems ) {
-		// Build a new jQuery matched element set
-		var ret = jQuery( elems );
-
-		// Add the old object onto the stack (as a reference)
-		ret.prevObject = this;
-
-		// Return the newly-formed element set
-		return ret;
-	},
-	
-	// Force the current matched set of elements to become
-	// the specified array of elements (destroying the stack in the process)
-	// You should use pushStack() in order to do this, but maintain the stack
-	setArray: function( elems ) {
-		// Resetting the length to 0, then using the native Array push
-		// is a super-fast way to populate an object with array-like properties
-		this.length = 0;
-		Array.prototype.push.apply( this, elems );
-		
-		return this;
-	},
-
-	// Execute a callback for every element in the matched set.
-	// (You can seed the arguments with an array of args, but this is
-	// only used internally.)
-	each: function( callback, args ) {
-		return jQuery.each( this, callback, args );
-	},
-
-	// Determine the position of an element within 
-	// the matched set of elements
-	index: function( elem ) {
-		var ret = -1;
-
-		// Locate the position of the desired element
-		this.each(function(i){
-			if ( this == elem )
-				ret = i;
-		});
-
-		return ret;
-	},
-
-	attr: function( name, value, type ) {
-		var options = name;
-		
-		// Look for the case where we're accessing a style value
-		if ( name.constructor == String )
-			if ( value == undefined )
-				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
-
-			else {
-				options = {};
-				options[ name ] = value;
-			}
-		
-		// Check to see if we're setting style values
-		return this.each(function(i){
-			// Set all the styles
-			for ( name in options )
-				jQuery.attr(
-					type ?
-						this.style :
-						this,
-					name, jQuery.prop( this, options[ name ], type, i, name )
-				);
-		});
-	},
-
-	css: function( key, value ) {
-		// ignore negative width and height values
-		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
-			value = undefined;
-		return this.attr( key, value, "curCSS" );
-	},
-
-	text: function( text ) {
-		if ( typeof text != "object" && text != null )
-			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
-
-		var ret = "";
-
-		jQuery.each( text || this, function(){
-			jQuery.each( this.childNodes, function(){
-				if ( this.nodeType != 8 )
-					ret += this.nodeType != 1 ?
-						this.nodeValue :
-						jQuery.fn.text( [ this ] );
-			});
-		});
-
-		return ret;
-	},
-
-	wrapAll: function( html ) {
-		if ( this[0] )
-			// The elements to wrap the target around
-			jQuery( html, this[0].ownerDocument )
-				.clone()
-				.insertBefore( this[0] )
-				.map(function(){
-					var elem = this;
-
-					while ( elem.firstChild )
-						elem = elem.firstChild;
-
-					return elem;
-				})
-				.append(this);
-
-		return this;
-	},
-
-	wrapInner: function( html ) {
-		return this.each(function(){
-			jQuery( this ).contents().wrapAll( html );
-		});
-	},
-
-	wrap: function( html ) {
-		return this.each(function(){
-			jQuery( this ).wrapAll( html );
-		});
-	},
-
-	append: function() {
-		return this.domManip(arguments, true, false, function(elem){
-			if (this.nodeType == 1)
-				this.appendChild( elem );
-		});
-	},
-
-	prepend: function() {
-		return this.domManip(arguments, true, true, function(elem){
-			if (this.nodeType == 1)
-				this.insertBefore( elem, this.firstChild );
-		});
-	},
-	
-	before: function() {
-		return this.domManip(arguments, false, false, function(elem){
-			this.parentNode.insertBefore( elem, this );
-		});
-	},
-
-	after: function() {
-		return this.domManip(arguments, false, true, function(elem){
-			this.parentNode.insertBefore( elem, this.nextSibling );
-		});
-	},
-
-	end: function() {
-		return this.prevObject || jQuery( [] );
-	},
-
-	find: function( selector ) {
-		var elems = jQuery.map(this, function(elem){
-			return jQuery.find( selector, elem );
-		});
-
-		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
-			jQuery.unique( elems ) :
-			elems );
-	},
-
-	clone: function( events ) {
-		// Do the clone
-		var ret = this.map(function(){
-			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
-				// IE copies events bound via attachEvent when
-				// using cloneNode. Calling detachEvent on the
-				// clone will also remove the events from the orignal
-				// In order to get around this, we use innerHTML.
-				// Unfortunately, this means some modifications to 
-				// attributes in IE that are actually only stored 
-				// as properties will not be copied (such as the
-				// the name attribute on an input).
-				var clone = this.cloneNode(true),
-					container = document.createElement("div");
-				container.appendChild(clone);
-				return jQuery.clean([container.innerHTML])[0];
-			} else
-				return this.cloneNode(true);
-		});
-
-		// Need to set the expando to null on the cloned set if it exists
-		// removeData doesn't work here, IE removes it from the original as well
-		// this is primarily for IE but the data expando shouldn't be copied over in any browser
-		var clone = ret.find("*").andSelf().each(function(){
-			if ( this[ expando ] != undefined )
-				this[ expando ] = null;
-		});
-		
-		// Copy the events from the original to the clone
-		if ( events === true )
-			this.find("*").andSelf().each(function(i){
-				if (this.nodeType == 3)
-					return;
-				var events = jQuery.data( this, "events" );
-
-				for ( var type in events )
-					for ( var handler in events[ type ] )
-						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
-			});
-
-		// Return the cloned set
-		return ret;
-	},
-
-	filter: function( selector ) {
-		return this.pushStack(
-			jQuery.isFunction( selector ) &&
-			jQuery.grep(this, function(elem, i){
-				return selector.call( elem, i );
-			}) ||
-
-			jQuery.multiFilter( selector, this ) );
-	},
-
-	not: function( selector ) {
-		if ( selector.constructor == String )
-			// test special case where just one selector is passed in
-			if ( isSimple.test( selector ) )
-				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
-			else
-				selector = jQuery.multiFilter( selector, this );
-
-		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
-		return this.filter(function() {
-			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
-		});
-	},
-
-	add: function( selector ) {
-		return !selector ? this : this.pushStack( jQuery.merge( 
-			this.get(),
-			selector.constructor == String ? 
-				jQuery( selector ).get() :
-				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
-					selector : [selector] ) );
-	},
-
-	is: function( selector ) {
-		return selector ?
-			jQuery.multiFilter( selector, this ).length > 0 :
-			false;
-	},
-
-	hasClass: function( selector ) {
-		return this.is( "." + selector );
-	},
-	
-	val: function( value ) {
-		if ( value == undefined ) {
-
-			if ( this.length ) {
-				var elem = this[0];
-
-				// We need to handle select boxes special
-				if ( jQuery.nodeName( elem, "select" ) ) {
-					var index = elem.selectedIndex,
-						values = [],
-						options = elem.options,
-						one = elem.type == "select-one";
-					
-					// Nothing was selected
-					if ( index < 0 )
-						return null;
-
-					// Loop through all the selected options
-					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
-						var option = options[ i ];
-
-						if ( option.selected ) {
-							// Get the specifc value for the option
-							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
-							
-							// We don't need an array for one selects
-							if ( one )
-								return value;
-							
-							// Multi-Selects return an array
-							values.push( value );
-						}
-					}
-					
-					return values;
-					
-				// Everything else, we just grab the value
-				} else
-					return (this[0].value || "").replace(/\r/g, "");
-
-			}
-
-			return undefined;
-		}
-
-		return this.each(function(){
-			if ( this.nodeType != 1 )
-				return;
-
-			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
-				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
-					jQuery.inArray(this.name, value) >= 0);
-
-			else if ( jQuery.nodeName( this, "select" ) ) {
-				var values = value.constructor == Array ?
-					value :
-					[ value ];
-
-				jQuery( "option", this ).each(function(){
-					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
-						jQuery.inArray( this.text, values ) >= 0);
-				});
-
-				if ( !values.length )
-					this.selectedIndex = -1;
-
-			} else
-				this.value = value;
-		});
-	},
-	
-	html: function( value ) {
-		return value == undefined ?
-			(this.length ?
-				this[0].innerHTML :
-				null) :
-			this.empty().append( value );
-	},
-
-	replaceWith: function( value ) {
-		return this.after( value ).remove();
-	},
-
-	eq: function( i ) {
-		return this.slice( i, i + 1 );
-	},
-
-	slice: function() {
-		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
-	},
-
-	map: function( callback ) {
-		return this.pushStack( jQuery.map(this, function(elem, i){
-			return callback.call( elem, i, elem );
-		}));
-	},
-
-	andSelf: function() {
-		return this.add( this.prevObject );
-	},
-
-	data: function( key, value ){
-		var parts = key.split(".");
-		parts[1] = parts[1] ? "." + parts[1] : "";
-
-		if ( value == null ) {
-			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-			
-			if ( data == undefined && this.length )
-				data = jQuery.data( this[0], key );
-
-			return data == null && parts[1] ?
-				this.data( parts[0] ) :
-				data;
-		} else
-			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
-				jQuery.data( this, key, value );
-			});
-	},
-
-	removeData: function( key ){
-		return this.each(function(){
-			jQuery.removeData( this, key );
-		});
-	},
-	
-	domManip: function( args, table, reverse, callback ) {
-		var clone = this.length > 1, elems; 
-
-		return this.each(function(){
-			if ( !elems ) {
-				elems = jQuery.clean( args, this.ownerDocument );
-
-				if ( reverse )
-					elems.reverse();
-			}
-
-			var obj = this;
-
-			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
-				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
-
-			var scripts = jQuery( [] );
-
-			jQuery.each(elems, function(){
-				var elem = clone ?
-					jQuery( this ).clone( true )[0] :
-					this;
-
-				// execute all scripts after the elements have been injected
-				if ( jQuery.nodeName( elem, "script" ) ) {
-					scripts = scripts.add( elem );
-				} else {
-					// Remove any inner scripts for later evaluation
-					if ( elem.nodeType == 1 )
-						scripts = scripts.add( jQuery( "script", elem ).remove() );
-
-					// Inject the elements into the document
-					callback.call( obj, elem );
-				}
-			});
-
-			scripts.each( evalScript );
-		});
-	}
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.prototype.init.prototype = jQuery.prototype;
-
-function evalScript( i, elem ) {
-	if ( elem.src )
-		jQuery.ajax({
-			url: elem.src,
-			async: false,
-			dataType: "script"
-		});
-
-	else
-		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
-
-	if ( elem.parentNode )
-		elem.parentNode.removeChild( elem );
-}
-
-jQuery.extend = jQuery.fn.extend = function() {
-	// copy reference to target object
-	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
-
-	// Handle a deep copy situation
-	if ( target.constructor == Boolean ) {
-		deep = target;
-		target = arguments[1] || {};
-		// skip the boolean and the target
-		i = 2;
-	}
-
-	// Handle case when target is a string or something (possible in deep copy)
-	if ( typeof target != "object" && typeof target != "function" )
-		target = {};
-
-	// extend jQuery itself if only one argument is passed
-	if ( length == 1 ) {
-		target = this;
-		i = 0;
-	}
-
-	for ( ; i < length; i++ )
-		// Only deal with non-null/undefined values
-		if ( (options = arguments[ i ]) != null )
-			// Extend the base object
-			for ( var name in options ) {
-				// Prevent never-ending loop
-				if ( target === options[ name ] )
-					continue;
-
-				// Recurse if we're merging object values
-				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
-					target[ name ] = jQuery.extend( deep, target[ name ], options[ name ] );
-
-				// Don't bring in undefined values
-				else if ( options[ name ] != undefined )
-					target[ name ] = options[ name ];
-
-			}
-
-	// Return the modified object
-	return target;
-};
-
-var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
-
-// exclude the following css properties to add px
-var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
-
-jQuery.extend({
-	noConflict: function( deep ) {
-		window.$ = _$;
-
-		if ( deep )
-			window.jQuery = _jQuery;
-
-		return jQuery;
-	},
-
-	// See test/unit/core.js for details concerning this function.
-	isFunction: function( fn ) {
-		return !!fn && typeof fn != "string" && !fn.nodeName && 
-			fn.constructor != Array && /function/i.test( fn + "" );
-	},
-	
-	// check if an element is in a (or is an) XML document
-	isXMLDoc: function( elem ) {
-		return elem.documentElement && !elem.body ||
-			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
-	},
-
-	// Evalulates a script in a global context
-	globalEval: function( data ) {
-		data = jQuery.trim( data );
-
-		if ( data ) {
-			// Inspired by code by Andrea Giammarchi
-			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
-			var head = document.getElementsByTagName("head")[0] || document.documentElement,
-				script = document.createElement("script");
-
-			script.type = "text/javascript";
-			if ( jQuery.browser.msie )
-				script.text = data;
-			else
-				script.appendChild( document.createTextNode( data ) );
-
-			head.appendChild( script );
-			head.removeChild( script );
-		}
-	},
-
-	nodeName: function( elem, name ) {
-		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
-	},
-	
-	cache: {},
-	
-	data: function( elem, name, data ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// Compute a unique ID for the element
-		if ( !id ) 
-			id = elem[ expando ] = ++uuid;
-
-		// Only generate the data cache if we're
-		// trying to access or manipulate it
-		if ( name && !jQuery.cache[ id ] )
-			jQuery.cache[ id ] = {};
-		
-		// Prevent overriding the named cache with undefined values
-		if ( data != undefined )
-			jQuery.cache[ id ][ name ] = data;
-		
-		// Return the named cache data, or the ID for the element	
-		return name ?
-			jQuery.cache[ id ][ name ] :
-			id;
-	},
-	
-	removeData: function( elem, name ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// If we want to remove a specific section of the element's data
-		if ( name ) {
-			if ( jQuery.cache[ id ] ) {
-				// Remove the section of cache data
-				delete jQuery.cache[ id ][ name ];
-
-				// If we've removed all the data, remove the element's cache
-				name = "";
-
-				for ( name in jQuery.cache[ id ] )
-					break;
-
-				if ( !name )
-					jQuery.removeData( elem );
-			}
-
-		// Otherwise, we want to remove all of the element's data
-		} else {
-			// Clean up the element expando
-			try {
-				delete elem[ expando ];
-			} catch(e){
-				// IE has trouble directly removing the expando
-				// but it's ok with using removeAttribute
-				if ( elem.removeAttribute )
-					elem.removeAttribute( expando );
-			}
-
-			// Completely remove the data cache
-			delete jQuery.cache[ id ];
-		}
-	},
-
-	// args is for internal usage only
-	each: function( object, callback, args ) {
-		if ( args ) {
-			if ( object.length == undefined ) {
-				for ( var name in object )
-					if ( callback.apply( object[ name ], args ) === false )
-						break;
-			} else
-				for ( var i = 0, length = object.length; i < length; i++ )
-					if ( callback.apply( object[ i ], args ) === false )
-						break;
-
-		// A special, fast, case for the most common use of each
-		} else {
-			if ( object.length == undefined ) {
-				for ( var name in object )
-					if ( callback.call( object[ name ], name, object[ name ] ) === false )
-						break;
-			} else
-				for ( var i = 0, length = object.length, value = object[0]; 
-					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
-		}
-
-		return object;
-	},
-	
-	prop: function( elem, value, type, i, name ) {
-			// Handle executable functions
-			if ( jQuery.isFunction( value ) )
-				value = value.call( elem, i );
-				
-			// Handle passing in a number to a CSS property
-			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
-				value + "px" :
-				value;
-	},
-
-	className: {
-		// internal only, use addClass("class")
-		add: function( elem, classNames ) {
-			jQuery.each((classNames || "").split(/\s+/), function(i, className){
-				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
-					elem.className += (elem.className ? " " : "") + className;
-			});
-		},
-
-		// internal only, use removeClass("class")
-		remove: function( elem, classNames ) {
-			if (elem.nodeType == 1)
-				elem.className = classNames != undefined ?
-					jQuery.grep(elem.className.split(/\s+/), function(className){
-						return !jQuery.className.has( classNames, className );	
-					}).join(" ") :
-					"";
-		},
-
-		// internal only, use is(".class")
-		has: function( elem, className ) {
-			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
-		}
-	},
-
-	// A method for quickly swapping in/out CSS properties to get correct calculations
-	swap: function( elem, options, callback ) {
-		var old = {};
-		// Remember the old values, and insert the new ones
-		for ( var name in options ) {
-			old[ name ] = elem.style[ name ];
-			elem.style[ name ] = options[ name ];
-		}
-
-		callback.call( elem );
-
-		// Revert the old values
-		for ( var name in options )
-			elem.style[ name ] = old[ name ];
-	},
-
-	css: function( elem, name, force ) {
-		if ( name == "width" || name == "height" ) {
-			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
-		
-			function getWH() {
-				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
-				var padding = 0, border = 0;
-				jQuery.each( which, function() {
-					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
-					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
-				});
-				val -= Math.round(padding + border);
-			}
-		
-			if ( jQuery(elem).is(":visible") )
-				getWH();
-			else
-				jQuery.swap( elem, props, getWH );
-			
-			return Math.max(0, val);
-		}
-		
-		return jQuery.curCSS( elem, name, force );
-	},
-
-	curCSS: function( elem, name, force ) {
-		var ret;
-
-		// A helper method for determining if an element's values are broken
-		function color( elem ) {
-			if ( !jQuery.browser.safari )
-				return false;
-
-			var ret = document.defaultView.getComputedStyle( elem, null );
-			return !ret || ret.getPropertyValue("color") == "";
-		}
-
-		// We need to handle opacity special in IE
-		if ( name == "opacity" && jQuery.browser.msie ) {
-			ret = jQuery.attr( elem.style, "opacity" );
-
-			return ret == "" ?
-				"1" :
-				ret;
-		}
-		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
-		if ( jQuery.browser.opera && name == "display" ) {
-			var save = elem.style.outline;
-			elem.style.outline = "0 solid black";
-			elem.style.outline = save;
-		}
-		
-		// Make sure we're using the right name for getting the float value
-		if ( name.match( /float/i ) )
-			name = styleFloat;
-
-		if ( !force && elem.style && elem.style[ name ] )
-			ret = elem.style[ name ];
-
-		else if ( document.defaultView && document.defaultView.getComputedStyle ) {
-
-			// Only "float" is needed here
-			if ( name.match( /float/i ) )
-				name = "float";
-
-			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
-
-			var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
-
-			if ( getComputedStyle && !color( elem ) )
-				ret = getComputedStyle.getPropertyValue( name );
-
-			// If the element isn't reporting its values properly in Safari
-			// then some display: none elements are involved
-			else {
-				var swap = [], stack = [];
-
-				// Locate all of the parent display: none elements
-				for ( var a = elem; a && color(a); a = a.parentNode )
-					stack.unshift(a);
-
-				// Go through and make them visible, but in reverse
-				// (It would be better if we knew the exact display type that they had)
-				for ( var i = 0; i < stack.length; i++ )
-					if ( color( stack[ i ] ) ) {
-						swap[ i ] = stack[ i ].style.display;
-						stack[ i ].style.display = "block";
-					}
-
-				// Since we flip the display style, we have to handle that
-				// one special, otherwise get the value
-				ret = name == "display" && swap[ stack.length - 1 ] != null ?
-					"none" :
-					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
-
-				// Finally, revert the display styles back
-				for ( var i = 0; i < swap.length; i++ )
-					if ( swap[ i ] != null )
-						stack[ i ].style.display = swap[ i ];
-			}
-
-			// We should always get a number back from opacity
-			if ( name == "opacity" && ret == "" )
-				ret = "1";
-
-		} else if ( elem.currentStyle ) {
-			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
-				return letter.toUpperCase();
-			});
-
-			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
-
-			// From the awesome hack by Dean Edwards
-			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
-			// If we're not dealing with a regular pixel number
-			// but a number that has a weird ending, we need to convert it to pixels
-			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
-				// Remember the original values
-				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
-
-				// Put in the new values to get a computed value out
-				elem.runtimeStyle.left = elem.currentStyle.left;
-				elem.style.left = ret || 0;
-				ret = elem.style.pixelLeft + "px";
-
-				// Revert the changed values
-				elem.style.left = style;
-				elem.runtimeStyle.left = runtimeStyle;
-			}
-		}
-
-		return ret;
-	},
-	
-	clean: function( elems, context ) {
-		var ret = [];
-		context = context || document;
-		// !context.createElement fails in IE with an error but returns typeof 'object'
-		if (typeof context.createElement == 'undefined') 
-			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
-
-		jQuery.each(elems, function(i, elem){
-			if ( !elem )
-				return;
-
-			if ( elem.constructor == Number )
-				elem = elem.toString();
-			
-			// Convert html string into DOM nodes
-			if ( typeof elem == "string" ) {
-				// Fix "XHTML"-style tags in all browsers
-				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
-					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
-						all :
-						front + "></" + tag + ">";
-				});
-
-				// Trim whitespace, otherwise indexOf won't work as expected
-				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
-
-				var wrap =
-					// option or optgroup
-					!tags.indexOf("<opt") &&
-					[ 1, "<select multiple='multiple'>", "</select>" ] ||
-					
-					!tags.indexOf("<leg") &&
-					[ 1, "<fieldset>", "</fieldset>" ] ||
-					
-					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
-					[ 1, "<table>", "</table>" ] ||
-					
-					!tags.indexOf("<tr") &&
-					[ 2, "<table><tbody>", "</tbody></table>" ] ||
-					
-				 	// <thead> matched above
-					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
-					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
-					
-					!tags.indexOf("<col") &&
-					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
-
-					// IE can't serialize <link> and <script> tags normally
-					jQuery.browser.msie &&
-					[ 1, "div<div>", "</div>" ] ||
-					
-					[ 0, "", "" ];
-
-				// Go to html and back, then peel off extra wrappers
-				div.innerHTML = wrap[1] + elem + wrap[2];
-				
-				// Move to the right depth
-				while ( wrap[0]-- )
-					div = div.lastChild;
-				
-				// Remove IE's autoinserted <tbody> from table fragments
-				if ( jQuery.browser.msie ) {
-					
-					// String was a <table>, *may* have spurious <tbody>
-					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
-						div.firstChild && div.firstChild.childNodes :
-						
-						// String was a bare <thead> or <tfoot>
-						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
-							div.childNodes :
-							[];
-				
-					for ( var j = tbody.length - 1; j >= 0 ; --j )
-						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
-							tbody[ j ].parentNode.removeChild( tbody[ j ] );
-					
-					// IE completely kills leading whitespace when innerHTML is used	
-					if ( /^\s/.test( elem ) )	
-						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
-				
-				}
-				
-				elem = jQuery.makeArray( div.childNodes );
-			}
-
-			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
-				return;
-
-			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
-				ret.push( elem );
-
-			else
-				ret = jQuery.merge( ret, elem );
-
-		});
-
-		return ret;
-	},
-	
-	attr: function( elem, name, value ) {
-		// don't set attributes on text and comment nodes
-		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
-			return undefined;
-
-		var fix = jQuery.isXMLDoc( elem ) ?
-			{} :
-			jQuery.props;
-
-		// Safari mis-reports the default selected property of a hidden option
-		// Accessing the parent's selectedIndex property fixes it
-		if ( name == "selected" && jQuery.browser.safari )
-			elem.parentNode.selectedIndex;
-		
-		// Certain attributes only work when accessed via the old DOM 0 way
-		if ( fix[ name ] ) {
-			if ( value != undefined )
-				elem[ fix[ name ] ] = value;
-
-			return elem[ fix[ name ] ];
-
-		} else if ( jQuery.browser.msie && name == "style" )
-			return jQuery.attr( elem.style, "cssText", value );
-
-		else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
-			return elem.getAttributeNode( name ).nodeValue;
-
-		// IE elem.getAttribute passes even for style
-		else if ( elem.tagName ) {
-
-			if ( value != undefined ) {
-				// We can't allow the type property to be changed (since it causes problems in IE)
-				if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
-					throw "type property can't be changed";
-
-				// convert the value to a string (all browsers do this but IE) see #1070
-				elem.setAttribute( name, "" + value );
-			}
-
-			if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) ) 
-				return elem.getAttribute( name, 2 );
-
-			return elem.getAttribute( name );
-
-		// elem is actually elem.style ... set the style
-		} else {
-			// IE actually uses filters for opacity
-			if ( name == "opacity" && jQuery.browser.msie ) {
-				if ( value != undefined ) {
-					// IE has trouble with opacity if it does not have layout
-					// Force it by setting the zoom level
-					elem.zoom = 1; 
-	
-					// Set the alpha filter to set the opacity
-					elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
-						(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
-				}
-	
-				return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
-					(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
-					"";
-			}
-
-			name = name.replace(/-([a-z])/ig, function(all, letter){
-				return letter.toUpperCase();
-			});
-
-			if ( value != undefined )
-				elem[ name ] = value;
-
-			return elem[ name ];
-		}
-	},
-	
-	trim: function( text ) {
-		return (text || "").replace( /^\s+|\s+$/g, "" );
-	},
-
-	makeArray: function( array ) {
-		var ret = [];
-
-		// Need to use typeof to fight Safari childNodes crashes
-		if ( array.constructor != Array )
-			for ( var i = 0, length = array.length; i < length; i++ )
-				ret.push( array[ i ] );
-		else
-			ret = array.slice( 0 );
-
-		return ret;
-	},
-
-	inArray: function( elem, array ) {
-		for ( var i = 0, length = array.length; i < length; i++ )
-			if ( array[ i ] == elem )
-				return i;
-
-		return -1;
-	},
-
-	merge: function( first, second ) {
-		// We have to loop this way because IE & Opera overwrite the length
-		// expando of getElementsByTagName
-
-		// Also, we need to make sure that the correct elements are being returned
-		// (IE returns comment nodes in a '*' query)
-		if ( jQuery.browser.msie ) {
-			for ( var i = 0; second[ i ]; i++ )
-				if ( second[ i ].nodeType != 8 )
-					first.push( second[ i ] );
-
-		} else
-			for ( var i = 0; second[ i ]; i++ )
-				first.push( second[ i ] );
-
-		return first;
-	},
-
-	unique: function( array ) {
-		var ret = [], done = {};
-
-		try {
-
-			for ( var i = 0, length = array.length; i < length; i++ ) {
-				var id = jQuery.data( array[ i ] );
-
-				if ( !done[ id ] ) {
-					done[ id ] = true;
-					ret.push( array[ i ] );
-				}
-			}
-
-		} catch( e ) {
-			ret = array;
-		}
-
-		return ret;
-	},
-
-	grep: function( elems, callback, inv ) {
-		var ret = [];
-
-		// Go through the array, only saving the items
-		// that pass the validator function
-		for ( var i = 0, length = elems.length; i < length; i++ )
-			if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
-				ret.push( elems[ i ] );
-
-		return ret;
-	},
-
-	map: function( elems, callback ) {
-		var ret = [];
-
-		// Go through the array, translating each of the items to their
-		// new value (or values).
-		for ( var i = 0, length = elems.length; i < length; i++ ) {
-			var value = callback( elems[ i ], i );
-
-			if ( value !== null && value != undefined ) {
-				if ( value.constructor != Array )
-					value = [ value ];
-
-				ret = ret.concat( value );
-			}
-		}
-
-		return ret;
-	}
-});
-
-var userAgent = navigator.userAgent.toLowerCase();
-
-// Figure out what browser is being used
-jQuery.browser = {
-	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
-	safari: /webkit/.test( userAgent ),
-	opera: /opera/.test( userAgent ),
-	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
-	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
-};
-
-var styleFloat = jQuery.browser.msie ?
-	"styleFloat" :
-	"cssFloat";
-	
-jQuery.extend({
-	// Check to see if the W3C box model is being used
-	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
-	
-	props: {
-		"for": "htmlFor",
-		"class": "className",
-		"float": styleFloat,
-		cssFloat: styleFloat,
-		styleFloat: styleFloat,
-		innerHTML: "innerHTML",
-		className: "className",
-		value: "value",
-		disabled: "disabled",
-		checked: "checked",
-		readonly: "readOnly",
-		selected: "selected",
-		maxlength: "maxLength",
-		selectedIndex: "selectedIndex",
-		defaultValue: "defaultValue",
-		tagName: "tagName",
-		nodeName: "nodeName"
-	}
-});
-
-jQuery.each({
-	parent: function(elem){return elem.parentNode;},
-	parents: function(elem){return jQuery.dir(elem,"parentNode");},
-	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
-	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
-	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
-	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
-	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
-	children: function(elem){return jQuery.sibling(elem.firstChild);},
-	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
-}, function(name, fn){
-	jQuery.fn[ name ] = function( selector ) {
-		var ret = jQuery.map( this, fn );
-
-		if ( selector && typeof selector == "string" )
-			ret = jQuery.multiFilter( selector, ret );
-
-		return this.pushStack( jQuery.unique( ret ) );
-	};
-});
-
-jQuery.each({
-	appendTo: "append",
-	prependTo: "prepend",
-	insertBefore: "before",
-	insertAfter: "after",
-	replaceAll: "replaceWith"
-}, function(name, original){
-	jQuery.fn[ name ] = function() {
-		var args = arguments;
-
-		return this.each(function(){
-			for ( var i = 0, length = args.length; i < length; i++ )
-				jQuery( args[ i ] )[ original ]( this );
-		});
-	};
-});
-
-jQuery.each({
-	removeAttr: function( name ) {
-		jQuery.attr( this, name, "" );
-		if (this.nodeType == 1) 
-			this.removeAttribute( name );
-	},
-
-	addClass: function( classNames ) {
-		jQuery.className.add( this, classNames );
-	},
-
-	removeClass: function( classNames ) {
-		jQuery.className.remove( this, classNames );
-	},
-
-	toggleClass: function( classNames ) {
-		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
-	},
-
-	remove: function( selector ) {
-		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
-			// Prevent memory leaks
-			jQuery( "*", this ).add(this).each(function(){
-				jQuery.event.remove(this);
-				jQuery.removeData(this);
-			});
-			if (this.parentNode)
-				this.parentNode.removeChild( this );
-		}
-	},
-
-	empty: function() {
-		// Remove element nodes and prevent memory leaks
-		jQuery( ">*", this ).remove();
-		
-		// Remove any remaining nodes
-		while ( this.firstChild )
-			this.removeChild( this.firstChild );
-	}
-}, function(name, fn){
-	jQuery.fn[ name ] = function(){
-		return this.each( fn, arguments );
-	};
-});
-
-jQuery.each([ "Height", "Width" ], function(i, name){
-	var type = name.toLowerCase();
-	
-	jQuery.fn[ type ] = function( size ) {
-		// Get window width or height
-		return this[0] == window ?
-			// Opera reports document.body.client[Width/Height] properly in both quirks and standards
-			jQuery.browser.opera && document.body[ "client" + name ] || 
-			
-			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
-			jQuery.browser.safari && window[ "inner" + name ] ||
-			
-			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
-			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
-		
-			// Get document width or height
-			this[0] == document ?
-				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
-				Math.max( 
-					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), 
-					Math.max(document.body["offset" + name], document.documentElement["offset" + name]) 
-				) :
-
-				// Get or set width or height on the element
-				size == undefined ?
-					// Get width or height on the element
-					(this.length ? jQuery.css( this[0], type ) : null) :
-
-					// Set the width or height on the element (default to pixels if value is unitless)
-					this.css( type, size.constructor == String ? size : size + "px" );
-	};
-});
-
-var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
-		"(?:[\\w*_-]|\\\\.)" :
-		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
-	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
-	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
-	quickClass = new RegExp("^([#.]?)(" + chars + "*)");
-
-jQuery.extend({
-	expr: {
-		"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
-		"#": function(a,i,m){return a.getAttribute("id")==m[2];},
-		":": {
-			// Position Checks
-			lt: function(a,i,m){return i<m[3]-0;},
-			gt: function(a,i,m){return i>m[3]-0;},
-			nth: function(a,i,m){return m[3]-0==i;},
-			eq: function(a,i,m){return m[3]-0==i;},
-			first: function(a,i){return i==0;},
-			last: function(a,i,m,r){return i==r.length-1;},
-			even: function(a,i){return i%2==0;},
-			odd: function(a,i){return i%2;},
-
-			// Child Checks
-			"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
-			"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
-			"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
-
-			// Parent Checks
-			parent: function(a){return a.firstChild;},
-			empty: function(a){return !a.firstChild;},
-
-			// Text Check
-			contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
-
-			// Visibility
-			visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
-			hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
-
-			// Form attributes
-			enabled: function(a){return !a.disabled;},
-			disabled: function(a){return a.disabled;},
-			checked: function(a){return a.checked;},
-			selected: function(a){return a.selected||jQuery.attr(a,"selected");},
-
-			// Form elements
-			text: function(a){return "text"==a.type;},
-			radio: function(a){return "radio"==a.type;},
-			checkbox: function(a){return "checkbox"==a.type;},
-			file: function(a){return "file"==a.type;},
-			password: function(a){return "password"==a.type;},
-			submit: function(a){return "submit"==a.type;},
-			image: function(a){return "image"==a.type;},
-			reset: function(a){return "reset"==a.type;},
-			button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
-			input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
-
-			// :has()
-			has: function(a,i,m){return jQuery.find(m[3],a).length;},
-
-			// :header
-			header: function(a){return /h\d/i.test(a.nodeName);},
-
-			// :animated
-			animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
-		}
-	},
-	
-	// The regular expressions that power the parsing engine
-	parse: [
-		// Match: [@value='test'], [@foo]
-		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
-
-		// Match: :contains('foo')
-		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
-
-		// Match: :even, :last-chlid, #id, .class
-		new RegExp("^([:.#]*)(" + chars + "+)")
-	],
-
-	multiFilter: function( expr, elems, not ) {
-		var old, cur = [];
-
-		while ( expr && expr != old ) {
-			old = expr;
-			var f = jQuery.filter( expr, elems, not );
-			expr = f.t.replace(/^\s*,\s*/, "" );
-			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
-		}
-
-		return cur;
-	},
-
-	find: function( t, context ) {
-		// Quickly handle non-string expressions
-		if ( typeof t != "string" )
-			return [ t ];
-
-		// check to make sure context is a DOM element or a document
-		if ( context && context.nodeType != 1 && context.nodeType != 9)
-			return [ ];
-
-		// Set the correct context (if none is provided)
-		context = context || document;
-
-		// Initialize the search
-		var ret = [context], done = [], last, nodeName;
-
-		// Continue while a selector expression exists, and while
-		// we're no longer looping upon ourselves
-		while ( t && last != t ) {
-			var r = [];
-			last = t;
-
-			t = jQuery.trim(t);
-
-			var foundToken = false;
-
-			// An attempt at speeding up child selectors that
-			// point to a specific element tag
-			var re = quickChild;
-			var m = re.exec(t);
-
-			if ( m ) {
-				nodeName = m[1].toUpperCase();
-
-				// Perform our own iteration and filter
-				for ( var i = 0; ret[i]; i++ )
-					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
-						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
-							r.push( c );
-
-				ret = r;
-				t = t.replace( re, "" );
-				if ( t.indexOf(" ") == 0 ) continue;
-				foundToken = true;
-			} else {
-				re = /^([>+~])\s*(\w*)/i;
-
-				if ( (m = re.exec(t)) != null ) {
-					r = [];
-
-					var merge = {};
-					nodeName = m[2].toUpperCase();
-					m = m[1];
-
-					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
-						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
-						for ( ; n; n = n.nextSibling )
-							if ( n.nodeType == 1 ) {
-								var id = jQuery.data(n);
-
-								if ( m == "~" && merge[id] ) break;
-								
-								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
-									if ( m == "~" ) merge[id] = true;
-									r.push( n );
-								}
-								
-								if ( m == "+" ) break;
-							}
-					}
-
-					ret = r;
-
-					// And remove the token
-					t = jQuery.trim( t.replace( re, "" ) );
-					foundToken = true;
-				}
-			}
-
-			// See if there's still an expression, and that we haven't already
-			// matched a token
-			if ( t && !foundToken ) {
-				// Handle multiple expressions
-				if ( !t.indexOf(",") ) {
-					// Clean the result set
-					if ( context == ret[0] ) ret.shift();
-
-					// Merge the result sets
-					done = jQuery.merge( done, ret );
-
-					// Reset the context
-					r = ret = [context];
-
-					// Touch up the selector string
-					t = " " + t.substr(1,t.length);
-
-				} else {
-					// Optimize for the case nodeName#idName
-					var re2 = quickID;
-					var m = re2.exec(t);
-					
-					// Re-organize the results, so that they're consistent
-					if ( m ) {
-						m = [ 0, m[2], m[3], m[1] ];
-
-					} else {
-						// Otherwise, do a traditional filter check for
-						// ID, class, and element selectors
-						re2 = quickClass;
-						m = re2.exec(t);
-					}
-
-					m[2] = m[2].replace(/\\/g, "");
-
-					var elem = ret[ret.length-1];
-
-					// Try to do a global search by ID, where we can
-					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
-						// Optimization for HTML document case
-						var oid = elem.getElementById(m[2]);
-						
-						// Do a quick check for the existence of the actual ID attribute
-						// to avoid selecting by the name attribute in IE
-						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
-						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
-							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
-
-						// Do a quick check for node name (where applicable) so
-						// that div#foo searches will be really fast
-						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
-					} else {
-						// We need to find all descendant elements
-						for ( var i = 0; ret[i]; i++ ) {
-							// Grab the tag name being searched for
-							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
-
-							// Handle IE7 being really dumb about <object>s
-							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
-								tag = "param";
-
-							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
-						}
-
-						// It's faster to filter by class and be done with it
-						if ( m[1] == "." )
-							r = jQuery.classFilter( r, m[2] );
-
-						// Same with ID filtering
-						if ( m[1] == "#" ) {
-							var tmp = [];
-
-							// Try to find the element with the ID
-							for ( var i = 0; r[i]; i++ )
-								if ( r[i].getAttribute("id") == m[2] ) {
-									tmp = [ r[i] ];
-									break;
-								}
-
-							r = tmp;
-						}
-
-						ret = r;
-					}
-
-					t = t.replace( re2, "" );
-				}
-
-			}
-
-			// If a selector string still exists
-			if ( t ) {
-				// Attempt to filter it
-				var val = jQuery.filter(t,r);
-				ret = r = val.r;
-				t = jQuery.trim(val.t);
-			}
-		}
-
-		// An error occurred with the selector;
-		// just return an empty set instead
-		if ( t )
-			ret = [];
-
-		// Remove the root context
-		if ( ret && context == ret[0] )
-			ret.shift();
-
-		// And combine the results
-		done = jQuery.merge( done, ret );
-
-		return done;
-	},
-
-	classFilter: function(r,m,not){
-		m = " " + m + " ";
-		var tmp = [];
-		for ( var i = 0; r[i]; i++ ) {
-			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
-			if ( !not && pass || not && !pass )
-				tmp.push( r[i] );
-		}
-		return tmp;
-	},
-
-	filter: function(t,r,not) {
-		var last;
-
-		// Look for common filter expressions
-		while ( t && t != last ) {
-			last = t;
-
-			var p = jQuery.parse, m;
-
-			for ( var i = 0; p[i]; i++ ) {
-				m = p[i].exec( t );
-
-				if ( m ) {
-					// Remove what we just matched
-					t = t.substring( m[0].length );
-
-					m[2] = m[2].replace(/\\/g, "");
-					break;
-				}
-			}
-
-			if ( !m )
-				break;
-
-			// :not() is a special case that can be optimized by
-			// keeping it out of the expression list
-			if ( m[1] == ":" && m[2] == "not" )
-				// optimize if only one selector found (most common case)
-				r = isSimple.test( m[3] ) ?
-					jQuery.filter(m[3], r, true).r :
-					jQuery( r ).not( m[3] );
-
-			// We can get a big speed boost by filtering by class here
-			else if ( m[1] == "." )
-				r = jQuery.classFilter(r, m[2], not);
-
-			else if ( m[1] == "[" ) {
-				var tmp = [], type = m[3];
-				
-				for ( var i = 0, rl = r.length; i < rl; i++ ) {
-					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
-					
-					if ( z == null || /href|src|selected/.test(m[2]) )
-						z = jQuery.attr(a,m[2]) || '';
-
-					if ( (type == "" && !!z ||
-						 type == "=" && z == m[5] ||
-						 type == "!=" && z != m[5] ||
-						 type == "^=" && z && !z.indexOf(m[5]) ||
-						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
-						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
-							tmp.push( a );
-				}
-				
-				r = tmp;
-
-			// We can get a speed boost by handling nth-child here
-			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
-				var merge = {}, tmp = [],
-					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
-					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
-						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
-						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
-					// calculate the numbers (first)n+(last) including if they are negative
-					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
- 
-				// loop through all the elements left in the jQuery object
-				for ( var i = 0, rl = r.length; i < rl; i++ ) {
-					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
-
-					if ( !merge[id] ) {
-						var c = 1;
-
-						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
-							if ( n.nodeType == 1 )
-								n.nodeIndex = c++;
-
-						merge[id] = true;
-					}
-
-					var add = false;
-
-					if ( first == 0 ) {
-						if ( node.nodeIndex == last )
-							add = true;
-					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
-						add = true;
-
-					if ( add ^ not )
-						tmp.push( node );
-				}
-
-				r = tmp;
-
-			// Otherwise, find the expression to execute
-			} else {
-				var fn = jQuery.expr[ m[1] ];
-				if ( typeof fn == "object" )
-					fn = fn[ m[2] ];
-
-				if ( typeof fn == "string" )
-					fn = eval("false||function(a,i){return " + fn + ";}");
-
-				// Execute it against the current filter
-				r = jQuery.grep( r, function(elem, i){
-					return fn(elem, i, m, r);
-				}, not );
-			}
-		}
-
-		// Return an array of filtered elements (r)
-		// and the modified expression string (t)
-		return { r: r, t: t };
-	},
-
-	dir: function( elem, dir ){
-		var matched = [];
-		var cur = elem[dir];
-		while ( cur && cur != document ) {
-			if ( cur.nodeType == 1 )
-				matched.push( cur );
-			cur = cur[dir];
-		}
-		return matched;
-	},
-	
-	nth: function(cur,result,dir,elem){
-		result = result || 1;
-		var num = 0;
-
-		for ( ; cur; cur = cur[dir] )
-			if ( cur.nodeType == 1 && ++num == result )
-				break;
-
-		return cur;
-	},
-	
-	sibling: function( n, elem ) {
-		var r = [];
-
-		for ( ; n; n = n.nextSibling ) {
-			if ( n.nodeType == 1 && (!elem || n != elem) )
-				r.push( n );
-		}
-
-		return r;
-	}
-});
-
-/*
- * A number of helper functions used for managing events.
- * Many of the ideas behind this code orignated from 
- * Dean Edwards' addEvent library.
- */
-jQuery.event = {
-
-	// Bind an event to an element
-	// Original by Dean Edwards
-	add: function(elem, types, handler, data) {
-		if ( elem.nodeType == 3 || elem.nodeType == 8 )
-			return;
-
-		// For whatever reason, IE has trouble passing the window object
-		// around, causing it to be cloned in the process
-		if ( jQuery.browser.msie && elem.setInterval != undefined )
-			elem = window;
-
-		// Make sure that the function being executed has a unique ID
-		if ( !handler.guid )
-			handler.guid = this.guid++;
-			
-		// if data is passed, bind to handler 
-		if( data != undefined ) { 
-			// Create temporary function pointer to original handler 
-			var fn = handler; 
-
-			// Create unique handler function, wrapped around original handler 
-			handler = function() { 
-				// Pass arguments and context to original handler 
-				return fn.apply(this, arguments); 
-			};
-
-			// Store data in unique handler 
-			handler.data = data;
-
-			// Set the guid of unique handler to the same of original handler, so it can be removed 
-			handler.guid = fn.guid;
-		}
-
-		// Init the element's event structure
-		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
-			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
-				// returned undefined or false
-				var val;
-
-				// Handle the second event of a trigger and when
-				// an event is called after a page has unloaded
-				if ( typeof jQuery == "undefined" || jQuery.event.triggered )
-					return val;
-		
-				val = jQuery.event.handle.apply(arguments.callee.elem, arguments);
-		
-				return val;
-			});
-		// Add elem as a property of the handle function
-		// This is to prevent a memory leak with non-native
-		// event in IE.
-		handle.elem = elem;
-			
-			// Handle multiple events seperated by a space
-			// jQuery(...).bind("mouseover mouseout", fn);
-			jQuery.each(types.split(/\s+/), function(index, type) {
-				// Namespaced event handlers
-				var parts = type.split(".");
-				type = parts[0];
-				handler.type = parts[1];
-
-				// Get the current list of functions bound to this event
-				var handlers = events[type];
-
-				// Init the event handler queue
-				if (!handlers) {
-					handlers = events[type] = {};
-		
-					// Check for a special event handler
-					// Only use addEventListener/attachEvent if the special
-					// events handler returns false
-					if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
-						// Bind the global event handler to the element
-						if (elem.addEventListener)
-							elem.addEventListener(type, handle, false);
-						else if (elem.attachEvent)
-							elem.attachEvent("on" + type, handle);
-					}
-				}
-
-				// Add the function to the element's handler list
-				handlers[handler.guid] = handler;
-
-				// Keep track of which events have been used, for global triggering
-				jQuery.event.global[type] = true;
-			});
-		
-		// Nullify elem to prevent memory leaks in IE
-		elem = null;
-	},
-
-	guid: 1,
-	global: {},
-
-	// Detach an event or set of events from an element
-	remove: function(elem, types, handler) {
-		// don't do events on text and comment nodes
-		if ( elem.nodeType == 3 || elem.nodeType == 8 )
-			return;
-
-		var events = jQuery.data(elem, "events"), ret, index;
-
-		if ( events ) {
-			// Unbind all events for the element
-			if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
-				for ( var type in events )
-					this.remove( elem, type + (types || "") );
-			else {
-				// types is actually an event object here
-				if ( types.type ) {
-					handler = types.handler;
-					types = types.type;
-				}
-				
-				// Handle multiple events seperated by a space
-				// jQuery(...).unbind("mouseover mouseout", fn);
-				jQuery.each(types.split(/\s+/), function(index, type){
-					// Namespaced event handlers
-					var parts = type.split(".");
-					type = parts[0];
-					
-					if ( events[type] ) {
-						// remove the given handler for the given type
-						if ( handler )
-							delete events[type][handler.guid];
-			
-						// remove all handlers for the given type
-						else
-							for ( handler in events[type] )
-								// Handle the removal of namespaced events
-								if ( !parts[1] || events[type][handler].type == parts[1] )
-									delete events[type][handler];
-
-						// remove generic event handler if no more handlers exist
-						for ( ret in events[type] ) break;
-						if ( !ret ) {
-							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
-								if (elem.removeEventListener)
-									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
-								else if (elem.detachEvent)
-									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
-							}
-							ret = null;
-							delete events[type];
-						}
-					}
-				});
-			}
-
-			// Remove the expando if it's no longer used
-			for ( ret in events ) break;
-			if ( !ret ) {
-				var handle = jQuery.data( elem, "handle" );
-				if ( handle ) handle.elem = null;
-				jQuery.removeData( elem, "events" );
-				jQuery.removeData( elem, "handle" );
-			}
-		}
-	},
-
-	trigger: function(type, data, elem, donative, extra) {
-		// Clone the incoming data, if any
-		data = jQuery.makeArray(data || []);
-
-		if ( type.indexOf("!") >= 0 ) {
-			type = type.slice(0, -1);
-			var exclusive = true;
-		}
-
-		// Handle a global trigger
-		if ( !elem ) {
-			// Only trigger if we've ever bound an event for it
-			if ( this.global[type] )
-				jQuery("*").add([window, document]).trigger(type, data);
-
-		// Handle triggering a single element
-		} else {
-			// don't do events on text and comment nodes
-			if ( elem.nodeType == 3 || elem.nodeType == 8 )
-				return undefined;
-
-			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
-				// Check to see if we need to provide a fake event, or not
-				event = !data[0] || !data[0].preventDefault;
-			
-			// Pass along a fake event
-			if ( event )
-				data.unshift( this.fix({ type: type, target: elem }) );
-
-			// Enforce the right trigger type
-			data[0].type = type;
-			if ( exclusive )
-				data[0].exclusive = true;
-
-			// Trigger the event
-			if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
-				val = jQuery.data(elem, "handle").apply( elem, data );
-
-			// Handle triggering native .onfoo handlers
-			if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
-				val = false;
-
-			// Extra functions don't get the custom event object
-			if ( event )
-				data.shift();
-
-			// Handle triggering of extra function
-			if ( extra && jQuery.isFunction( extra ) ) {
-				// call the extra function and tack the current return value on the end for possible inspection
-				ret = extra.apply( elem, val == null ? data : data.concat( val ) );
-				// if anything is returned, give it precedence and have it overwrite the previous value
-				if (ret !== undefined)
-					val = ret;
-			}
-
-			// Trigger the native events (except for clicks on links)
-			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
-				this.triggered = true;
-				try {
-					elem[ type ]();
-				// prevent IE from throwing an error for some hidden elements
-				} catch (e) {}
-			}
-
-			this.triggered = false;
-		}
-
-		return val;
-	},
-
-	handle: function(event) {
-		// returned undefined or false
-		var val;
-
-		// Empty object is for triggered events with no data
-		event = jQuery.event.fix( event || window.event || {} ); 
-
-		// Namespaced event handlers
-		var parts = event.type.split(".");
-		event.type = parts[0];
-
-		var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
-		args.unshift( event );
-
-		for ( var j in handlers ) {
-			var handler = handlers[j];
-			// Pass in a reference to the handler function itself
-			// So that we can later remove it
-			args[0].handler = handler;
-			args[0].data = handler.data;
-
-			// Filter the functions by class
-			if ( !parts[1] && !event.exclusive || handler.type == parts[1] ) {
-				var ret = handler.apply( this, args );
-
-				if ( val !== false )
-					val = ret;
-
-				if ( ret === false ) {
-					event.preventDefault();
-					event.stopPropagation();
-				}
-			}
-		}
-
-		// Clean up added properties in IE to prevent memory leak
-		if (jQuery.browser.msie)
-			event.target = event.preventDefault = event.stopPropagation =
-				event.handler = event.data = null;
-
-		return val;
-	},
-
-	fix: function(event) {
-		// store a copy of the original event object 
-		// and clone to set read-only properties
-		var originalEvent = event;
-		event = jQuery.extend({}, originalEvent);
-		
-		// add preventDefault and stopPropagation since 
-		// they will not work on the clone
-		event.preventDefault = function() {
-			// if preventDefault exists run it on the original event
-			if (originalEvent.preventDefault)
-				originalEvent.preventDefault();
-			// otherwise set the returnValue property of the original event to false (IE)
-			originalEvent.returnValue = false;
-		};
-		event.stopPropagation = function() {
-			// if stopPropagation exists run it on the original event
-			if (originalEvent.stopPropagation)
-				originalEvent.stopPropagation();
-			// otherwise set the cancelBubble property of the original event to true (IE)
-			originalEvent.cancelBubble = true;
-		};
-		
-		// Fix target property, if necessary
-		if ( !event.target )
-			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
-				
-		// check if target is a textnode (safari)
-		if ( event.target.nodeType == 3 )
-			event.target = originalEvent.target.parentNode;
-
-		// Add relatedTarget, if necessary
-		if ( !event.relatedTarget && event.fromElement )
-			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
-
-		// Calculate pageX/Y if missing and clientX/Y available
-		if ( event.pageX == null && event.clientX != null ) {
-			var doc = document.documentElement, body = document.body;
-			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
-			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
-		}
-			
-		// Add which for key events
-		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
-			event.which = event.charCode || event.keyCode;
-		
-		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
-		if ( !event.metaKey && event.ctrlKey )
-			event.metaKey = event.ctrlKey;
-
-		// Add which for click: 1 == left; 2 == middle; 3 == right
-		// Note: button is not normalized, so don't use it
-		if ( !event.which && event.button )
-			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
-			
-		return event;
-	},
-	
-	special: {
-		ready: {
-			setup: function() {
-				// Make sure the ready event is setup
-				bindReady();
-				return;
-			},
-			
-			teardown: function() { return; }
-		},
-		
-		mouseenter: {
-			setup: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
-				return true;
-			},
-		
-			teardown: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
-				return true;
-			},
-			
-			handler: function(event) {
-				// If we actually just moused on to a sub-element, ignore it
-				if ( withinElement(event, this) ) return true;
-				// Execute the right handlers by setting the event type to mouseenter
-				arguments[0].type = "mouseenter";
-				return jQuery.event.handle.apply(this, arguments);
-			}
-		},
-	
-		mouseleave: {
-			setup: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
-				return true;
-			},
-		
-			teardown: function() {
-				if ( jQuery.browser.msie ) return false;
-				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
-				return true;
-			},
-			
-			handler: function(event) {
-				// If we actually just moused on to a sub-element, ignore it
-				if ( withinElement(event, this) ) return true;
-				// Execute the right handlers by setting the event type to mouseleave
-				arguments[0].type = "mouseleave";
-				return jQuery.event.handle.apply(this, arguments);
-			}
-		}
-	}
-};
-
-jQuery.fn.extend({
-	bind: function( type, data, fn ) {
-		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
-			jQuery.event.add( this, type, fn || data, fn && data );
-		});
-	},
-	
-	one: function( type, data, fn ) {
-		return this.each(function(){
-			jQuery.event.add( this, type, function(event) {
-				jQuery(this).unbind(event);
-				return (fn || data).apply( this, arguments);
-			}, fn && data);
-		});
-	},
-
-	unbind: function( type, fn ) {
-		return this.each(function(){
-			jQuery.event.remove( this, type, fn );
-		});
-	},
-
-	trigger: function( type, data, fn ) {
-		return this.each(function(){
-			jQuery.event.trigger( type, data, this, true, fn );
-		});
-	},
-
-	triggerHandler: function( type, data, fn ) {
-		if ( this[0] )
-			return jQuery.event.trigger( type, data, this[0], false, fn );
-		return undefined;
-	},
-
-	toggle: function() {
-		// Save reference to arguments for access in closure
-		var args = arguments;
-
-		return this.click(function(event) {
-			// Figure out which function to execute
-			this.lastToggle = 0 == this.lastToggle ? 1 : 0;
-			
-			// Make sure that clicks stop
-			event.preventDefault();
-			
-			// and execute the function
-			return args[this.lastToggle].apply( this, arguments ) || false;
-		});
-	},
-
-	hover: function(fnOver, fnOut) {
-		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
-	},
-	
-	ready: function(fn) {
-		// Attach the listeners
-		bindReady();
-
-		// If the DOM is already ready
-		if ( jQuery.isReady )
-			// Execute the function immediately
-			fn.call( document, jQuery );
-			
-		// Otherwise, remember the function for later
-		else
-			// Add the function to the wait list
-			jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
-	
-		return this;
-	}
-});
-
-jQuery.extend({
-	isReady: false,
-	readyList: [],
-	// Handle when the DOM is ready
-	ready: function() {
-		// Make sure that the DOM is not already loaded
-		if ( !jQuery.isReady ) {
-			// Remember that the DOM is ready
-			jQuery.isReady = true;
-			
-			// If there are functions bound, to execute
-			if ( jQuery.readyList ) {
-				// Execute all of them
-				jQuery.each( jQuery.readyList, function(){
-					this.apply( document );
-				});
-				
-				// Reset the list of functions
-				jQuery.readyList = null;
-			}
-		
-			// Trigger any bound ready events
-			jQuery(document).triggerHandler("ready");
-		}
-	}
-});
-
-var readyBound = false;
-
-function bindReady(){
-	if ( readyBound ) return;
-	readyBound = true;
-
-	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
-	if ( document.addEventListener && !jQuery.browser.opera)
-		// Use the handy event callback
-		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
-	
-	// If IE is used and is not in a frame
-	// Continually check to see if the document is ready
-	if ( jQuery.browser.msie && window == top ) (function(){
-		if (jQuery.isReady) return;
-		try {
-			// If IE is used, use the trick by Diego Perini
-			// http://javascript.nwbox.com/IEContentLoaded/
-			document.documentElement.doScroll("left");
-		} catch( error ) {
-			setTimeout( arguments.callee, 0 );
-			return;
-		}
-		// and execute any waiting functions
-		jQuery.ready();
-	})();
-
-	if ( jQuery.browser.opera )
-		document.addEventListener( "DOMContentLoaded", function () {
-			if (jQuery.isReady) return;
-			for (var i = 0; i < document.styleSheets.length; i++)
-				if (document.styleSheets[i].disabled) {
-					setTimeout( arguments.callee, 0 );
-					return;
-				}
-			// and execute any waiting functions
-			jQuery.ready();
-		}, false);
-
-	if ( jQuery.browser.safari ) {
-		var numStyles;
-		(function(){
-			if (jQuery.isReady) return;
-			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
-				setTimeout( arguments.callee, 0 );
-				return;
-			}
-			if ( numStyles === undefined )
-				numStyles = jQuery("style, link[rel=stylesheet]").length;
-			if ( document.styleSheets.length != numStyles ) {
-				setTimeout( arguments.callee, 0 );
-				return;
-			}
-			// and execute any waiting functions
-			jQuery.ready();
-		})();
-	}
-
-	// A fallback to window.onload, that will always work
-	jQuery.event.add( window, "load", jQuery.ready );
-}
-
-jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
-	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
-	"submit,keydown,keypress,keyup,error").split(","), function(i, name){
-	
-	// Handle event binding
-	jQuery.fn[name] = function(fn){
-		return fn ? this.bind(name, fn) : this.trigger(name);
-	};
-});
-
-// Checks if an event happened on an element within another element
-// Used in jQuery.event.special.mouseenter and mouseleave handlers
-var withinElement = function(event, elem) {
-	// Check if mouse(over|out) are still within the same parent element
-	var parent = event.relatedTarget;
-	// Traverse up the tree
-	while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
-	// Return true if we actually just moused on to a sub-element
-	return parent == elem;
-};
-
-// Prevent memory leaks in IE
-// And prevent errors on refresh with events like mouseover in other browsers
-// Window isn't included so as not to unbind existing unload events
-jQuery(window).bind("unload", function() {
-	jQuery("*").add(document).unbind();
-});
-jQuery.fn.extend({
-	load: function( url, params, callback ) {
-		if ( jQuery.isFunction( url ) )
-			return this.bind("load", url);
-
-		var off = url.indexOf(" ");
-		if ( off >= 0 ) {
-			var selector = url.slice(off, url.length);
-			url = url.slice(0, off);
-		}
-
-		callback = callback || function(){};
-
-		// Default to a GET request
-		var type = "GET";
-
-		// If the second parameter was provided
-		if ( params )
-			// If it's a function
-			if ( jQuery.isFunction( params ) ) {
-				// We assume that it's the callback
-				callback = params;
-				params = null;
-
-			// Otherwise, build a param string
-			} else {
-				params = jQuery.param( params );
-				type = "POST";
-			}
-
-		var self = this;
-
-		// Request the remote document
-		jQuery.ajax({
-			url: url,
-			type: type,
-			dataType: "html",
-			data: params,
-			complete: function(res, status){
-				// If successful, inject the HTML into all the matched elements
-				if ( status == "success" || status == "notmodified" )
-					// See if a selector was specified
-					self.html( selector ?
-						// Create a dummy div to hold the results
-						jQuery("<div/>")
-							// inject the contents of the document in, removing the scripts
-							// to avoid any 'Permission Denied' errors in IE
-							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
-
-							// Locate the specified elements
-							.find(selector) :
-
-						// If not, just inject the full result
-						res.responseText );
-
-				self.each( callback, [res.responseText, status, res] );
-			}
-		});
-		return this;
-	},
-
-	serialize: function() {
-		return jQuery.param(this.serializeArray());
-	},
-	serializeArray: function() {
-		return this.map(function(){
-			return jQuery.nodeName(this, "form") ?
-				jQuery.makeArray(this.elements) : this;
-		})
-		.filter(function(){
-			return this.name && !this.disabled && 
-				(this.checked || /select|textarea/i.test(this.nodeName) || 
-					/text|hidden|password/i.test(this.type));
-		})
-		.map(function(i, elem){
-			var val = jQuery(this).val();
-			return val == null ? null :
-				val.constructor == Array ?
-					jQuery.map( val, function(val, i){
-						return {name: elem.name, value: val};
-					}) :
-					{name: elem.name, value: val};
-		}).get();
-	}
-});
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
-	jQuery.fn[o] = function(f){
-		return this.bind(o, f);
-	};
-});
-
-var jsc = (new Date).getTime();
-
-jQuery.extend({
-	get: function( url, data, callback, type ) {
-		// shift arguments if data argument was ommited
-		if ( jQuery.isFunction( data ) ) {
-			callback = data;
-			data = null;
-		}
-		
-		return jQuery.ajax({
-			type: "GET",
-			url: url,
-			data: data,
-			success: callback,
-			dataType: type
-		});
-	},
-
-	getScript: function( url, callback ) {
-		return jQuery.get(url, null, callback, "script");
-	},
-
-	getJSON: function( url, data, callback ) {
-		return jQuery.get(url, data, callback, "json");
-	},
-
-	post: function( url, data, callback, type ) {
-		if ( jQuery.isFunction( data ) ) {
-			callback = data;
-			data = {};
-		}
-
-		return jQuery.ajax({
-			type: "POST",
-			url: url,
-			data: data,
-			success: callback,
-			dataType: type
-		});
-	},
-
-	ajaxSetup: function( settings ) {
-		jQuery.extend( jQuery.ajaxSettings, settings );
-	},
-
-	ajaxSettings: {
-		global: true,
-		type: "GET",
-		timeout: 0,
-		contentType: "application/x-www-form-urlencoded",
-		processData: true,
-		async: true,
-		data: null,
-		username: null,
-		password: null,
-		accepts: {
-			xml: "application/xml, text/xml",
-			html: "text/html",
-			script: "text/javascript, application/javascript",
-			json: "application/json, text/javascript",
-			text: "text/plain",
-			_default: "*/*"
-		}
-	},
-	
-	// Last-Modified header cache for next request
-	lastModified: {},
-
-	ajax: function( s ) {
-		var jsonp, jsre = /=\?(&|$)/g, status, data;
-
-		// Extend the settings, but re-extend 's' so that it can be
-		// checked again later (in the test suite, specifically)
-		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
-
-		// convert data if not already a string
-		if ( s.data && s.processData && typeof s.data != "string" )
-			s.data = jQuery.param(s.data);
-
-		// Handle JSONP Parameter Callbacks
-		if ( s.dataType == "jsonp" ) {
-			if ( s.type.toLowerCase() == "get" ) {
-				if ( !s.url.match(jsre) )
-					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
-			} else if ( !s.data || !s.data.match(jsre) )
-				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
-			s.dataType = "json";
-		}
-
-		// Build temporary JSONP function
-		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
-			jsonp = "jsonp" + jsc++;
-
-			// Replace the =? sequence both in the query string and the data
-			if ( s.data )
-				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
-			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
-
-			// We need to make sure
-			// that a JSONP style response is executed properly
-			s.dataType = "script";
-
-			// Handle JSONP-style loading
-			window[ jsonp ] = function(tmp){
-				data = tmp;
-				success();
-				complete();
-				// Garbage collect
-				window[ jsonp ] = undefined;
-				try{ delete window[ jsonp ]; } catch(e){}
-				if ( head )
-					head.removeChild( script );
-			};
-		}
-
-		if ( s.dataType == "script" && s.cache == null )
-			s.cache = false;
-
-		if ( s.cache === false && s.type.toLowerCase() == "get" ) {
-			var ts = (new Date()).getTime();
-			// try replacing _= if it is there
-			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
-			// if nothing was replaced, add timestamp to the end
-			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
-		}
-
-		// If data is available, append data to url for get requests
-		if ( s.data && s.type.toLowerCase() == "get" ) {
-			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
-
-			// IE likes to send both get and post data, prevent this
-			s.data = null;
-		}
-
-		// Watch for a new set of requests
-		if ( s.global && ! jQuery.active++ )
-			jQuery.event.trigger( "ajaxStart" );
-
-		// If we're requesting a remote document
-		// and trying to load JSON or Script with a GET
-		if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get" ) {
-			var head = document.getElementsByTagName("head")[0];
-			var script = document.createElement("script");
-			script.src = s.url;
-			if (s.scriptCharset)
-				script.charset = s.scriptCharset;
-
-			// Handle Script loading
-			if ( !jsonp ) {
-				var done = false;
-
-				// Attach handlers for all browsers
-				script.onload = script.onreadystatechange = function(){
-					if ( !done && (!this.readyState || 
-							this.readyState == "loaded" || this.readyState == "complete") ) {
-						done = true;
-						success();
-						complete();
-						head.removeChild( script );
-					}
-				};
-			}
-
-			head.appendChild(script);
-
-			// We handle everything using the script element injection
-			return undefined;
-		}
-
-		var requestDone = false;
-
-		// Create the request object; Microsoft failed to properly
-		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
-		var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
-
-		// Open the socket
-		xml.open(s.type, s.url, s.async, s.username, s.password);
-
-		// Need an extra try/catch for cross domain requests in Firefox 3
-		try {
-			// Set the correct header, if data is being sent
-			if ( s.data )
-				xml.setRequestHeader("Content-Type", s.contentType);
-
-			// Set the If-Modified-Since header, if ifModified mode.
-			if ( s.ifModified )
-				xml.setRequestHeader("If-Modified-Since",
-					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
-
-			// Set header so the called script knows that it's an XMLHttpRequest
-			xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-
-			// Set the Accepts header for the server, depending on the dataType
-			xml.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
-				s.accepts[ s.dataType ] + ", */*" :
-				s.accepts._default );
-		} catch(e){}
-
-		// Allow custom headers/mimetypes
-		if ( s.beforeSend )
-			s.beforeSend(xml);
-			
-		if ( s.global )
-			jQuery.event.trigger("ajaxSend", [xml, s]);
-
-		// Wait for a response to come back
-		var onreadystatechange = function(isTimeout){
-			// The transfer is complete and the data is available, or the request timed out
-			if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
-				requestDone = true;
-				
-				// clear poll interval
-				if (ival) {
-					clearInterval(ival);
-					ival = null;
-				}
-				
-				status = isTimeout == "timeout" && "timeout" ||
-					!jQuery.httpSuccess( xml ) && "error" ||
-					s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
-					"success";
-
-				if ( status == "success" ) {
-					// Watch for, and catch, XML document parse errors
-					try {
-						// process the data (runs the xml through httpData regardless of callback)
-						data = jQuery.httpData( xml, s.dataType );
-					} catch(e) {
-						status = "parsererror";
-					}
-				}
-
-				// Make sure that the request was successful or notmodified
-				if ( status == "success" ) {
-					// Cache Last-Modified header, if ifModified mode.
-					var modRes;
-					try {
-						modRes = xml.getResponseHeader("Last-Modified");
-					} catch(e) {} // swallow exception thrown by FF if header is not available
-	
-					if ( s.ifModified && modRes )
-						jQuery.lastModified[s.url] = modRes;
-
-					// JSONP handles its own success callback
-					if ( !jsonp )
-						success();	
-				} else
-					jQuery.handleError(s, xml, status);
-
-				// Fire the complete handlers
-				complete();
-
-				// Stop memory leaks
-				if ( s.async )
-					xml = null;
-			}
-		};
-		
-		if ( s.async ) {
-			// don't attach the handler to the request, just poll it instead
-			var ival = setInterval(onreadystatechange, 13); 
-
-			// Timeout checker
-			if ( s.timeout > 0 )
-				setTimeout(function(){
-					// Check to see if the request is still happening
-					if ( xml ) {
-						// Cancel the request
-						xml.abort();
-	
-						if( !requestDone )
-							onreadystatechange( "timeout" );
-					}
-				}, s.timeout);
-		}
-			
-		// Send the data
-		try {
-			xml.send(s.data);
-		} catch(e) {
-			jQuery.handleError(s, xml, null, e);
-		}
-		
-		// firefox 1.5 doesn't fire statechange for sync requests
-		if ( !s.async )
-			onreadystatechange();
-
-		function success(){
-			// If a local callback was specified, fire it and pass it the data
-			if ( s.success )
-				s.success( data, status );
-
-			// Fire the global callback
-			if ( s.global )
-				jQuery.event.trigger( "ajaxSuccess", [xml, s] );
-		}
-
-		function complete(){
-			// Process result
-			if ( s.complete )
-				s.complete(xml, status);
-
-			// The request was completed
-			if ( s.global )
-				jQuery.event.trigger( "ajaxComplete", [xml, s] );
-
-			// Handle the global AJAX counter
-			if ( s.global && ! --jQuery.active )
-				jQuery.event.trigger( "ajaxStop" );
-		}
-		
-		// return XMLHttpRequest to allow aborting the request etc.
-		return xml;
-	},
-
-	handleError: function( s, xml, status, e ) {
-		// If a local callback was specified, fire it
-		if ( s.error ) s.error( xml, status, e );
-
-		// Fire the global callback
-		if ( s.global )
-			jQuery.event.trigger( "ajaxError", [xml, s, e] );
-	},
-
-	// Counter for holding the number of active queries
-	active: 0,
-
-	// Determines if an XMLHttpRequest was successful or not
-	httpSuccess: function( r ) {
-		try {
-			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
-			return !r.status && location.protocol == "file:" ||
-				( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
-				jQuery.browser.safari && r.status == undefined;
-		} catch(e){}
-		return false;
-	},
-
-	// Determines if an XMLHttpRequest returns NotModified
-	httpNotModified: function( xml, url ) {
-		try {
-			var xmlRes = xml.getResponseHeader("Last-Modified");
-
-			// Firefox always returns 200. check Last-Modified date
-			return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
-				jQuery.browser.safari && xml.status == undefined;
-		} catch(e){}
-		return false;
-	},
-
-	httpData: function( r, type ) {
-		var ct = r.getResponseHeader("content-type");
-		var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
-		var data = xml ? r.responseXML : r.responseText;
-
-		if ( xml && data.documentElement.tagName == "parsererror" )
-			throw "parsererror";
-
-		// If the type is "script", eval it in global context
-		if ( type == "script" )
-			jQuery.globalEval( data );
-
-		// Get the JavaScript object, if JSON is used.
-		if ( type == "json" )
-			data = eval("(" + data + ")");
-
-		return data;
-	},
-
-	// Serialize an array of form elements or a set of
-	// key/values into a query string
-	param: function( a ) {
-		var s = [];
-
-		// If an array was passed in, assume that it is an array
-		// of form elements
-		if ( a.constructor == Array || a.jquery )
-			// Serialize the form elements
-			jQuery.each( a, function(){
-				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
-			});
-
-		// Otherwise, assume that it's an object of key/value pairs
-		else
-			// Serialize the key/values
-			for ( var j in a )
-				// If the value is an array then the key names need to be repeated
-				if ( a[j] && a[j].constructor == Array )
-					jQuery.each( a[j], function(){
-						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
-					});
-				else
-					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
-
-		// Return the resulting serialization
-		return s.join("&").replace(/%20/g, "+");
-	}
-
-});
-jQuery.fn.extend({
-	show: function(speed,callback){
-		return speed ?
-			this.animate({
-				height: "show", width: "show", opacity: "show"
-			}, speed, callback) :
-			
-			this.filter(":hidden").each(function(){
-				this.style.display = this.oldblock || "";
-				if ( jQuery.css(this,"display") == "none" ) {
-					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
-					this.style.display = elem.css("display");
-					// handle an edge condition where css is - div { display:none; } or similar
-					if (this.style.display == "none")
-						this.style.display = "block";
-					elem.remove();
-				}
-			}).end();
-	},
-	
-	hide: function(speed,callback){
-		return speed ?
-			this.animate({
-				height: "hide", width: "hide", opacity: "hide"
-			}, speed, callback) :
-			
-			this.filter(":visible").each(function(){
-				this.oldblock = this.oldblock || jQuery.css(this,"display");
-				this.style.display = "none";
-			}).end();
-	},
-
-	// Save the old toggle function
-	_toggle: jQuery.fn.toggle,
-	
-	toggle: function( fn, fn2 ){
-		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
-			this._toggle( fn, fn2 ) :
-			fn ?
-				this.animate({
-					height: "toggle", width: "toggle", opacity: "toggle"
-				}, fn, fn2) :
-				this.each(function(){
-					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
-				});
-	},
-	
-	slideDown: function(speed,callback){
-		return this.animate({height: "show"}, speed, callback);
-	},
-	
-	slideUp: function(speed,callback){
-		return this.animate({height: "hide"}, speed, callback);
-	},
-
-	slideToggle: function(speed, callback){
-		return this.animate({height: "toggle"}, speed, callback);
-	},
-	
-	fadeIn: function(speed, callback){
-		return this.animate({opacity: "show"}, speed, callback);
-	},
-	
-	fadeOut: function(speed, callback){
-		return this.animate({opacity: "hide"}, speed, callback);
-	},
-	
-	fadeTo: function(speed,to,callback){
-		return this.animate({opacity: to}, speed, callback);
-	},
-	
-	animate: function( prop, speed, easing, callback ) {
-		var optall = jQuery.speed(speed, easing, callback);
-
-		return this[ optall.queue === false ? "each" : "queue" ](function(){
-			if ( this.nodeType != 1)
-				return false;
-
-			var opt = jQuery.extend({}, optall);
-			var hidden = jQuery(this).is(":hidden"), self = this;
-			
-			for ( var p in prop ) {
-				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
-					return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
-
-				if ( p == "height" || p == "width" ) {
-					// Store display property
-					opt.display = jQuery.css(this, "display");
-
-					// Make sure that nothing sneaks out
-					opt.overflow = this.style.overflow;
-				}
-			}
-
-			if ( opt.overflow != null )
-				this.style.overflow = "hidden";
-
-			opt.curAnim = jQuery.extend({}, prop);
-			
-			jQuery.each( prop, function(name, val){
-				var e = new jQuery.fx( self, opt, name );
-
-				if ( /toggle|show|hide/.test(val) )
-					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
-				else {
-					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
-						start = e.cur(true) || 0;
-
-					if ( parts ) {
-						var end = parseFloat(parts[2]),
-							unit = parts[3] || "px";
-
-						// We need to compute starting value
-						if ( unit != "px" ) {
-							self.style[ name ] = (end || 1) + unit;
-							start = ((end || 1) / e.cur(true)) * start;
-							self.style[ name ] = start + unit;
-						}
-
-						// If a +=/-= token was provided, we're doing a relative animation
-						if ( parts[1] )
-							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
-
-						e.custom( start, end, unit );
-					} else
-						e.custom( start, val, "" );
-				}
-			});
-
-			// For JS strict compliance
-			return true;
-		});
-	},
-	
-	queue: function(type, fn){
-		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
-			fn = type;
-			type = "fx";
-		}
-
-		if ( !type || (typeof type == "string" && !fn) )
-			return queue( this[0], type );
-
-		return this.each(function(){
-			if ( fn.constructor == Array )
-				queue(this, type, fn);
-			else {
-				queue(this, type).push( fn );
-			
-				if ( queue(this, type).length == 1 )
-					fn.apply(this);
-			}
-		});
-	},
-
-	stop: function(clearQueue, gotoEnd){
-		var timers = jQuery.timers;
-
-		if (clearQueue)
-			this.queue([]);
-
-		this.each(function(){
-			// go in reverse order so anything added to the queue during the loop is ignored
-			for ( var i = timers.length - 1; i >= 0; i-- )
-				if ( timers[i].elem == this ) {
-					if (gotoEnd)
-						// force the next step to be the last
-						timers[i](true);
-					timers.splice(i, 1);
-				}
-		});
-
-		// start the next in the queue if the last step wasn't forced
-		if (!gotoEnd)
-			this.dequeue();
-
-		return this;
-	}
-
-});
-
-var queue = function( elem, type, array ) {
-	if ( !elem )
-		return undefined;
-
-	type = type || "fx";
-
-	var q = jQuery.data( elem, type + "queue" );
-
-	if ( !q || array )
-		q = jQuery.data( elem, type + "queue", 
-			array ? jQuery.makeArray(array) : [] );
-
-	return q;
-};
-
-jQuery.fn.dequeue = function(type){
-	type = type || "fx";
-
-	return this.each(function(){
-		var q = queue(this, type);
-
-		q.shift();
-
-		if ( q.length )
-			q[0].apply( this );
-	});
-};
-
-jQuery.extend({
-	
-	speed: function(speed, easing, fn) {
-		var opt = speed && speed.constructor == Object ? speed : {
-			complete: fn || !fn && easing || 
-				jQuery.isFunction( speed ) && speed,
-			duration: speed,
-			easing: fn && easing || easing && easing.constructor != Function && easing
-		};
-
-		opt.duration = (opt.duration && opt.duration.constructor == Number ? 
-			opt.duration : 
-			{ slow: 600, fast: 200 }[opt.duration]) || 400;
-	
-		// Queueing
-		opt.old = opt.complete;
-		opt.complete = function(){
-			if ( opt.queue !== false )
-				jQuery(this).dequeue();
-			if ( jQuery.isFunction( opt.old ) )
-				opt.old.apply( this );
-		};
-	
-		return opt;
-	},
-	
-	easing: {
-		linear: function( p, n, firstNum, diff ) {
-			return firstNum + diff * p;
-		},
-		swing: function( p, n, firstNum, diff ) {
-			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
-		}
-	},
-	
-	timers: [],
-	timerId: null,
-
-	fx: function( elem, options, prop ){
-		this.options = options;
-		this.elem = elem;
-		this.prop = prop;
-
-		if ( !options.orig )
-			options.orig = {};
-	}
-
-});
-
-jQuery.fx.prototype = {
-
-	// Simple function for setting a style value
-	update: function(){
-		if ( this.options.step )
-			this.options.step.apply( this.elem, [ this.now, this ] );
-
-		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
-
-		// Set display property to block for height/width animations
-		if ( this.prop == "height" || this.prop == "width" )
-			this.elem.style.display = "block";
-	},
-
-	// Get the current size
-	cur: function(force){
-		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
-			return this.elem[ this.prop ];
-
-		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
-		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
-	},
-
-	// Start an animation from one number to another
-	custom: function(from, to, unit){
-		this.startTime = (new Date()).getTime();
-		this.start = from;
-		this.end = to;
-		this.unit = unit || this.unit || "px";
-		this.now = this.start;
-		this.pos = this.state = 0;
-		this.update();
-
-		var self = this;
-		function t(gotoEnd){
-			return self.step(gotoEnd);
-		}
-
-		t.elem = this.elem;
-
-		jQuery.timers.push(t);
-
-		if ( jQuery.timerId == null ) {
-			jQuery.timerId = setInterval(function(){
-				var timers = jQuery.timers;
-				
-				for ( var i = 0; i < timers.length; i++ )
-					if ( !timers[i]() )
-						timers.splice(i--, 1);
-
-				if ( !timers.length ) {
-					clearInterval( jQuery.timerId );
-					jQuery.timerId = null;
-				}
-			}, 13);
-		}
-	},
-
-	// Simple 'show' function
-	show: function(){
-		// Remember where we started, so that we can go back to it later
-		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
-		this.options.show = true;
-
-		// Begin the animation
-		this.custom(0, this.cur());
-
-		// Make sure that we start at a small width/height to avoid any
-		// flash of content
-		if ( this.prop == "width" || this.prop == "height" )
-			this.elem.style[this.prop] = "1px";
-		
-		// Start by showing the element
-		jQuery(this.elem).show();
-	},
-
-	// Simple 'hide' function
-	hide: function(){
-		// Remember where we started, so that we can go back to it later
-		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
-		this.options.hide = true;
-
-		// Begin the animation
-		this.custom(this.cur(), 0);
-	},
-
-	// Each step of an animation
-	step: function(gotoEnd){
-		var t = (new Date()).getTime();
-
-		if ( gotoEnd || t > this.options.duration + this.startTime ) {
-			this.now = this.end;
-			this.pos = this.state = 1;
-			this.update();
-
-			this.options.curAnim[ this.prop ] = true;
-
-			var done = true;
-			for ( var i in this.options.curAnim )
-				if ( this.options.curAnim[i] !== true )
-					done = false;
-
-			if ( done ) {
-				if ( this.options.display != null ) {
-					// Reset the overflow
-					this.elem.style.overflow = this.options.overflow;
-				
-					// Reset the display
-					this.elem.style.display = this.options.display;
-					if ( jQuery.css(this.elem, "display") == "none" )
-						this.elem.style.display = "block";
-				}
-
-				// Hide the element if the "hide" operation was done
-				if ( this.options.hide )
-					this.elem.style.display = "none";
-
-				// Reset the properties, if the item has been hidden or shown
-				if ( this.options.hide || this.options.show )
-					for ( var p in this.options.curAnim )
-						jQuery.attr(this.elem.style, p, this.options.orig[p]);
-			}
-
-			// If a callback was provided, execute it
-			if ( done && jQuery.isFunction( this.options.complete ) )
-				// Execute the complete function
-				this.options.complete.apply( this.elem );
-
-			return false;
-		} else {
-			var n = t - this.startTime;
-			this.state = n / this.options.duration;
-
-			// Perform the easing function, defaults to swing
-			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
-			this.now = this.start + ((this.end - this.start) * this.pos);
-
-			// Perform the next step of the animation
-			this.update();
-		}
-
-		return true;
-	}
-
-};
-
-jQuery.fx.step = {
-	scrollLeft: function(fx){
-		fx.elem.scrollLeft = fx.now;
-	},
-
-	scrollTop: function(fx){
-		fx.elem.scrollTop = fx.now;
-	},
-
-	opacity: function(fx){
-		jQuery.attr(fx.elem.style, "opacity", fx.now);
-	},
-
-	_default: function(fx){
-		fx.elem.style[ fx.prop ] = fx.now + fx.unit;
-	}
-};
-// The Offset Method
-// Originally By Brandon Aaron, part of the Dimension Plugin
-// http://jquery.com/plugins/project/dimensions
-jQuery.fn.offset = function() {
-	var left = 0, top = 0, elem = this[0], results;
-	
-	if ( elem ) with ( jQuery.browser ) {
-		var parent       = elem.parentNode, 
-		    offsetChild  = elem,
-		    offsetParent = elem.offsetParent, 
-		    doc          = elem.ownerDocument,
-		    safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
-		    fixed        = jQuery.css(elem, "position") == "fixed";
-	
-		// Use getBoundingClientRect if available
-		if ( elem.getBoundingClientRect ) {
-			var box = elem.getBoundingClientRect();
-		
-			// Add the document scroll offsets
-			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
-				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
-		
-			// IE adds the HTML element's border, by default it is medium which is 2px
-			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
-			// IE 7 standards mode, the border is always 2px
-			// This border/offset is typically represented by the clientLeft and clientTop properties
-			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
-			// Therefore this method will be off by 2px in IE while in quirksmode
-			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
-	
-		// Otherwise loop through the offsetParents and parentNodes
-		} else {
-		
-			// Initial element offsets
-			add( elem.offsetLeft, elem.offsetTop );
-			
-			// Get parent offsets
-			while ( offsetParent ) {
-				// Add offsetParent offsets
-				add( offsetParent.offsetLeft, offsetParent.offsetTop );
-			
-				// Mozilla and Safari > 2 does not include the border on offset parents
-				// However Mozilla adds the border for table or table cells
-				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
-					border( offsetParent );
-					
-				// Add the document scroll offsets if position is fixed on any offsetParent
-				if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
-					fixed = true;
-			
-				// Set offsetChild to previous offsetParent unless it is the body element
-				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
-				// Get next offsetParent
-				offsetParent = offsetParent.offsetParent;
-			}
-		
-			// Get parent scroll offsets
-			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
-				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
-				if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
-					// Subtract parent scroll offsets
-					add( -parent.scrollLeft, -parent.scrollTop );
-			
-				// Mozilla does not add the border for a parent that has overflow != visible
-				if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
-					border( parent );
-			
-				// Get next parent
-				parent = parent.parentNode;
-			}
-		
-			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
-			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
-			if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) || 
-				(mozilla && jQuery.css(offsetChild, "position") != "absolute") )
-					add( -doc.body.offsetLeft, -doc.body.offsetTop );
-			
-			// Add the document scroll offsets if position is fixed
-			if ( fixed )
-				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
-					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
-		}
-
-		// Return an object with top and left properties
-		results = { top: top, left: left };
-	}
-
-	function border(elem) {
-		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
-	}
-
-	function add(l, t) {
-		left += parseInt(l) || 0;
-		top += parseInt(t) || 0;
-	}
-
-	return results;
-};
-
-// Create innerHeight, innerWidth, outerHeight and outerWidth methods
-jQuery.each(["Height", "Width"], function(i, name){
-
-	var tl = name == "Height" ? "Top"    : "Left",  // top or left
-		br = name == "Height" ? "Bottom" : "Right"; // bottom or right
-	
-	// innerHeight and innerWidth
-	jQuery.fn["inner" + name] = function(){
-		return this[ name.toLowerCase() ]() + 
-			num(this, "padding" + tl) + 
-			num(this, "padding" + br);
-	};
-	
-	// outerHeight and outerWidth
-	jQuery.fn["outer" + name] = function(margin) {
-		return this["inner" + name]() + 
-			num(this, "border" + tl + "Width") +
-			num(this, "border" + br + "Width") +
-			(!!margin ? 
-				num(this, "margin" + tl) + num(this, "margin" + br) : 0);
-	};
-	
-});
-
-function num(elem, prop) {
-	elem = elem.jquery ? elem[0] : elem;
-	return elem && parseInt( jQuery.curCSS(elem, prop, true) ) || 0;
-}})();
diff --git a/moksha/widgetbrowser/widgetbrowser/static/loading.gif b/moksha/widgetbrowser/widgetbrowser/static/loading.gif
deleted file mode 100644
index 85b99d4..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/loading.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/pygments.css b/moksha/widgetbrowser/widgetbrowser/static/pygments.css
deleted file mode 100644
index a55a324..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/pygments.css
+++ /dev/null
@@ -1,59 +0,0 @@
-.c { color: #408090; font-style: italic } /* Comment */
-.err { border: 1px solid #FF0000 } /* Error */
-.k { color: #007020; font-weight: bold } /* Keyword */
-.o { color: #666666 } /* Operator */
-.cm { color: #408090; font-style: italic } /* Comment.Multiline */
-.cp { color: #007020 } /* Comment.Preproc */
-.c1 { color: #408090; font-style: italic } /* Comment.Single */
-.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
-.gd { color: #A00000 } /* Generic.Deleted */
-.ge { font-style: italic } /* Generic.Emph */
-.gr { color: #FF0000 } /* Generic.Error */
-.gh { color: #000080; font-weight: bold } /* Generic.Heading */
-.gi { color: #00A000 } /* Generic.Inserted */
-.go { color: #303030 } /* Generic.Output */
-.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
-.gs { font-weight: bold } /* Generic.Strong */
-.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
-.gt { color: #0040D0 } /* Generic.Traceback */
-.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
-.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
-.kp { color: #007020 } /* Keyword.Pseudo */
-.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
-.kt { color: #902000 } /* Keyword.Type */
-.m { color: #208050 } /* Literal.Number */
-.s { color: #4070a0 } /* Literal.String */
-.na { color: #4070a0 } /* Name.Attribute */
-.nb { color: #007020 } /* Name.Builtin */
-.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
-.no { color: #60add5 } /* Name.Constant */
-.nd { color: #555555; font-weight: bold } /* Name.Decorator */
-.ni { color: #d55537; font-weight: bold } /* Name.Entity */
-.ne { color: #007020 } /* Name.Exception */
-.nf { color: #06287e } /* Name.Function */
-.nl { color: #002070; font-weight: bold } /* Name.Label */
-.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
-.nt { color: #062873; font-weight: bold } /* Name.Tag */
-.nv { color: #bb60d5 } /* Name.Variable */
-.ow { color: #007020; font-weight: bold } /* Operator.Word */
-.w { color: #bbbbbb } /* Text.Whitespace */
-.mf { color: #208050 } /* Literal.Number.Float */
-.mh { color: #208050 } /* Literal.Number.Hex */
-.mi { color: #208050 } /* Literal.Number.Integer */
-.mo { color: #208050 } /* Literal.Number.Oct */
-.sb { color: #4070a0 } /* Literal.String.Backtick */
-.sc { color: #4070a0 } /* Literal.String.Char */
-.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
-.s2 { color: #4070a0 } /* Literal.String.Double */
-.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
-.sh { color: #4070a0 } /* Literal.String.Heredoc */
-.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
-.sx { color: #c65d09 } /* Literal.String.Other */
-.sr { color: #235388 } /* Literal.String.Regex */
-.s1 { color: #4070a0 } /* Literal.String.Single */
-.ss { color: #517918 } /* Literal.String.Symbol */
-.bp { color: #007020 } /* Name.Builtin.Pseudo */
-.vc { color: #bb60d5 } /* Name.Variable.Class */
-.vg { color: #bb60d5 } /* Name.Variable.Global */
-.vi { color: #bb60d5 } /* Name.Variable.Instance */
-.il { color: #208050 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/moksha/widgetbrowser/widgetbrowser/static/tab.png b/moksha/widgetbrowser/widgetbrowser/static/tab.png
deleted file mode 100644
index 413c755..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/tab.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css
deleted file mode 100644
index f45ed75..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.accordion.css
+++ /dev/null
@@ -1,12 +0,0 @@
-ul.ui-accordion { margin: 0; padding: 0; list-style-type: none; }
-ul.ui-accordion li { margin: 0; margin-bottom: 2px; padding: 0; background-image: url(i/accordion-left.png); background-repeat: no-repeat; }
-ul.ui-accordion li a.ui-accordion-header { display: block; padding-left: 5px; margin-right: 3px; height: 28px; background-image: url(i/accordion-middle.png); color: #000; text-decoration: none; line-height: 28px; }
-ul.ui-accordion li .ui-accordion-right { display: block; background-image: url(i/accordion-right.png); position: absolute; top: 0px; right: 0px; height: 28px; width: 3px;  }
-
-ul.ui-accordion li:hover { background-image: url(i/accordion-left-over.png); }
-ul.ui-accordion li:hover a.ui-accordion-header { background-image: url(i/accordion-middle-over.png); }
-ul.ui-accordion li:hover .ui-accordion-right { background-image: url(i/accordion-right-over.png); }
-
-ul.ui-accordion li.active { background-image: url(i/accordion-left-act.png); }
-ul.ui-accordion li.active a.ui-accordion-header { background-image: url(i/accordion-middle-act.png); }
-ul.ui-accordion li.active .ui-accordion-right { background-image: url(i/accordion-right-act.png); }
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css
deleted file mode 100644
index 3de5386..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.all.css
+++ /dev/null
@@ -1,9 +0,0 @@
- at import "flora.css";
- at import "flora.shadow.css";
- at import "flora.resizable.css";
- at import "flora.slider.css";
- at import "flora.accordion.css";
- at import "flora.tabs.css";
- at import "flora.dialog.css";
- at import "flora.tablesorter.css";
- at import "flora.datepicker.css";
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css
deleted file mode 100644
index dedcf0c..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.calendar.css
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Main Style Sheet for jQuery Calendar */
-#calendar_div, .calendar_inline {
-	font-family: Arial, Helvetica, sans-serif;
-	font-size: 14px;
-	padding: 0;
-	margin: 0;
-	background: #ddd;
-}
-#calendar_div {
-	display: none;
-	border: 1px solid #FF9900;
-	z-index: 10; /*must have*/ 
-}
-#calendar_div, .calendar_control, .calendar_links, .calendar_header, .calendar {
-	width: 185px;
-}
-.calendar_inline {
-	float: left;
-	display: block;
-	border: 0;
-}
-.calendar_dialog {
-	padding: 5px !important;
-	border: 4px ridge #ddd !important;
-}
-button.calendar_trigger {
-	width: 25px;
-}
-img.calendar_trigger {
-	margin: 2px;
-	vertical-align: middle;
-}
-.calendar_prompt {
-	float: left;
-	width: 181px;
-	padding: 2px;
-	background: #ddd;
-	color: #000;
-}
-* html .calendar_prompt {
-	width: 185px;
-}
-.calendar_control, .calendar_links, .calendar_header, .calendar {
-	clear: both;
-	float: left;
-	color: #fff;
-}
-.calendar_control {
-	background: #FF9900;
-}
-.calendar_links {
-	background: #E0F4D7;
-}
-.calendar_control, .calendar_links {
-	font-weight: bold;
-	font-size: 80%;
-	letter-spacing: 1px;
-}
-.calendar_links label { /* disabled links */
-	padding: 2px 5px;
-	color: #888;
-}
-.calendar_clear, .calendar_prev {
-	float: left;
-}
-.calendar_current {
-	float: left;
-	width: 35%;
-	text-align: center;
-}
-.calendar_close, .calendar_next {
-	float: right;
-}
-.calendar_header {
-	background: #83C948;
-	text-align: center;
-	font-weight: bold;
-}
-.calendar_header select {
-	background: #83C948;
-	color: #000;
-	border: 0px;
-	font-weight: bold;
-}
-.calendar {
-	background: #ccc;
-	text-align: center;
-	font-size: 100%;
-}
-.calendar a {
-	display: block;
-	width: 100%;
-}
-.calendar .calendar_titleRow {
-	background: #B1DB87;
-	color: #000 !important;
-}
-.calendar .calendar_daysRow {
-	background: #FFF;
-	color: #666;
-}
-.calendar .calendar_daysCell {
-	color: #000;
-	border: 1px solid #ddd;
-}
-#calendar .calendar_daysCell a{
-	display: block;
-}
-.calendar .calendar_weekEndCell {
-	background: #E0F4D7;
-}
-.calendar .calendar_daysCellOver {
-	background: #fff;
-	border: 1px solid #777;
-}
-.calendar .calendar_unselectable {
-	color: #888;
-}
-.calendar_today {
-	background: #ccc !important;
-}
-.calendar_currentDay {
-	background: #999 !important;
-}
-
-/* ________ CALENDAR LINKS _______
-
-** Reset link properties and then override them with !important */
-#calendar_div a, .calendar_inline a {
-	cursor: pointer;
-	margin: 0;
-	padding: 0;
-	background: none;
-	color: #000;
-}
-.calendar_inline .calendar_links a {
-	padding: 0 5px !important;
-}
-.calendar_control a, .calendar_links a {
-	padding: 2px 5px !important;
-	color: #000 !important;
-}
-.calendar_titleRow a {
-	color: #000 !important;
-}
-.calendar_control a:hover {
-	/*background: #fdd !important;*/
-	color: #333 !important;
-}
-.calendar_links a:hover, .calendar_titleRow a:hover {
-	background: #FFF !important;
-	color: #333 !important;
-}
-
-/* ___________ IE6 IFRAME FIX ________ */
-
-.calendar_cover {
-    display: none; /*sorry for IE5*/
-    display/**/: block; /*sorry for IE5*/
-    position: absolute; /*must have*/
-    z-index: -1; /*must have*/
-    filter: mask(); /*must have*/
-    top: -4px; /*must have*/
-    left: -4px; /*must have*/
-    width: 193px; /*must have to match width and borders*/
-    height: 200px; /*must have to match maximum height*/ 
-}
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.css
deleted file mode 100644
index 761217d..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.css
+++ /dev/null
@@ -1,2 +0,0 @@
-.ui-wrapper { border: 1px solid #50A029; }
-.ui-wrapper input, .ui-wrapper textarea { border: 0; }
\ No newline at end of file
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css
deleted file mode 100644
index 34ea650..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.datepicker.css
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Main Flora Style Sheet for jQuery UI Datepicker */
-#datepicker_div, .datepicker_inline {
-	font-family: Arial,Helvetica,sans-serif;
-	font-size: 14px;
-	padding: 0;
-	margin: 0;
-	background: #DDD;
-	width: 185px;
-}
-#datepicker_div {
-	display: none;
-	border: 1px solid #FF9900;
-	z-index: 10;
-}
-.datepicker_inline {
-	float: left;
-	display: block;
-	border: 0;
-}
-.datepicker_dialog {
-	padding: 5px !important;
-	border: 4px ridge #DDD !important;
-}
-button.datepicker_trigger {
-	width: 25px;
-}
-img.datepicker_trigger {
-	margin: 2px;
-	vertical-align: middle;
-}
-.datepicker_prompt {
-	float: left;
-	padding: 2px;
-	background: #DDD;
-	color: #000;
-}
-*html .datepicker_prompt {
-	width: 185px;
-}
-.datepicker_control, .datepicker_links, .datepicker_header, .datepicker {
-	clear: both;
-	float: left;
-	width: 100%;
-	color: #FFF;
-}
-.datepicker_control {
-	background: #FF9900;
-	padding: 2px 0px;
-}
-.datepicker_links {
-	background: #E0F4D7;
-	padding: 2px 0px;
-}
-.datepicker_control, .datepicker_links {
-	font-weight: bold;
-	font-size: 80%;
-	letter-spacing: 1px;
-}
-.datepicker_links label {
-	padding: 2px 5px;
-	color: #888;
-}
-.datepicker_clear, .datepicker_prev {
-	float: left;
-	width: 34%;
-}
-.datepicker_current {
-	float: left;
-	width: 30%;
-	text-align: center;
-}
-.datepicker_close, .datepicker_next {
-	float: right;
-	width: 34%;
-	text-align: right;
-}
-.datepicker_header {
-	padding: 1px 0 3px;
-	background: #83C948;
-	text-align: center;
-	font-weight: bold;
-	height: 1.3em;
-}
-.datepicker_header select {
-	background: #83C948;
-	color: #000;
-	border: 0px;
-	font-weight: bold;
-}
-.datepicker {
-	background: #CCC;
-	text-align: center;
-	font-size: 100%;
-}
-.datepicker a {
-	display: block;
-	width: 100%;
-}
-.datepicker .datepicker_titleRow {
-	background: #B1DB87;
-	color: #000;
-}
-.datepicker .datepicker_daysRow {
-	background: #FFF;
-	color: #666;
-}
-.datepicker_weekCol {
-	background: #B1DB87;
-	color: #000;
-}
-.datepicker .datepicker_daysCell {
-	color: #000;
-	border: 1px solid #DDD;
-}
-#datepicker .datepicker_daysCell a {
-	display: block;
-}
-.datepicker .datepicker_weekEndCell {
-	background: #E0F4D7;
-}
-.datepicker .datepicker_daysCellOver {
-	background: #FFF;
-	border: 1px solid #777;
-}
-.datepicker .datepicker_unselectable {
-	color: #888;
-}
-.datepicker_today {
-	background: #B1DB87 !important;
-}
-.datepicker_currentDay {
-	background: #83C948 !important;
-}
-#datepicker_div a, .datepicker_inline a {
-	cursor: pointer;
-	margin: 0;
-	padding: 0;
-	background: none;
-	color: #000;
-}
-.datepicker_inline .datepicker_links a {
-	padding: 0 5px !important;
-}
-.datepicker_control a, .datepicker_links a {
-	padding: 2px 5px !important;
-	color: #000 !important;
-}
-.datepicker_titleRow a {
-	color: #000 !important;
-}
-.datepicker_control a:hover {
-	background: #FDD !important;
-	color: #333 !important;
-}
-.datepicker_links a:hover, .datepicker_titleRow a:hover {
-	background: #FFF !important;
-	color: #333 !important;
-}
-.datepicker_multi .datepicker {
-	border: 1px solid #83C948;
-}
-.datepicker_oneMonth {
-	float: left;
-	width: 185px;
-}
-.datepicker_newRow {
-	clear: left;
-}
-.datepicker_cover {
-	display: none;
-	display/**/: block;
-	position: absolute;
-	z-index: -1;
-	filter: mask();
-	top: -4px;
-	left: -4px;
-	width: 193px;
-	height: 200px;
-}
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css
deleted file mode 100644
index efef1c4..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.dialog.css
+++ /dev/null
@@ -1,95 +0,0 @@
-/* This file skins dialog */
-
-.flora .ui-dialog,
-.flora.ui-dialog {
-	background-color: #e6f7d4;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar,
-.flora.ui-dialog .ui-dialog-titlebar {
-	border-bottom: 1px solid #d8d2aa;
-	background: #ff9900 url(i/dialog-title.gif) repeat-x;
-	padding: 0px;
-	height: 28px;
-	_height: 29px;
-}
-
-.flora .ui-dialog.ui-draggable .ui-dialog-titlebar,
-.flora.ui-dialog.ui-draggable .ui-dialog-titlebar {
-	cursor: move;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar-close,
-.flora.ui-dialog .ui-dialog-titlebar-close {
-	width: 16px;
-	height: 16px;
-	background: url(i/dialog-titlebar-close.png) no-repeat;
-	position:absolute;
-	top: 6px;
-	right: 7px;
-	cursor: default;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar-close span,
-.flora.ui-dialog .ui-dialog-titlebar-close span {
-	display: none;
-}
-
-.flora .ui-dialog .ui-dialog-titlebar-close-hover,
-.flora.ui-dialog .ui-dialog-titlebar-close-hover {
-	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
-}
-
-.flora .ui-dialog .ui-dialog-title,
-.flora.ui-dialog .ui-dialog-title {
-	margin-left: 5px;
-	color: white;
-	font-weight: bold;
-	position: relative;
-	top: 7px;
-	left: 4px;
-}
-
-.flora .ui-dialog .ui-dialog-content,
-.flora.ui-dialog .ui-dialog-content {
-	margin: 1.2em;
-}
-
-.flora .ui-dialog .ui-dialog-buttonpane,
-.flora.ui-dialog .ui-dialog-buttonpane {
-	position: absolute;
-	bottom: 8px;
-	right: 12px;
-	width: 100%;
-	text-align: right;
-}
-
-.flora .ui-dialog .ui-dialog-buttonpane button,
-.flora.ui-dialog .ui-dialog-buttonpane button {
-	margin: 6px;
-}
-
-/* Dialog handle styles */
-.flora .ui-dialog .ui-resizable-n,
-.flora.ui-dialog .ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/dialog-n.gif) repeat scroll center top; }
-
-.flora .ui-dialog .ui-resizable-s,
-.flora.ui-dialog .ui-resizable-s { cursor: s-resize; height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/dialog-s.gif) repeat scroll center top; }
-
-.flora .ui-dialog .ui-resizable-e,
-.flora.ui-dialog .ui-resizable-e { cursor: e-resize; width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-e.gif) repeat scroll right center; }
-
-.flora .ui-dialog .ui-resizable-w,
-.flora.ui-dialog .ui-resizable-w { cursor: w-resize; width: 7px; left: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-w.gif) repeat scroll right center; }
-
-.flora .ui-dialog .ui-resizable-se,
-.flora.ui-dialog .ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/dialog-se.gif); }
-
-.flora .ui-dialog .ui-resizable-sw,
-.flora.ui-dialog .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/dialog-sw.gif); }
-
-.flora .ui-dialog .ui-resizable-nw,
-.flora.ui-dialog .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/dialog-nw.gif); }
-
-.flora .ui-dialog .ui-resizable-ne,
-.flora.ui-dialog .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/dialog-ne.gif); }
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css
deleted file mode 100644
index 6d2dd21..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.menu.css
+++ /dev/null
@@ -1,8 +0,0 @@
-.ui-menu-toolbar {z-index:500; list-style:none;}
-.ui-menu-toolbar-button {float:left; padding:4px 20px; cursor:pointer;}
-.ui-menu-toolbar-button:hover {}
-.ui-menu-toolbar-button a {text-decoration:none;}
-.ui-menu-items {display:none; padding:0; z-index:500; list-style:none; padding:1px 4px; min-width:80px; *width:80px;}
-.ui-menu-item a { text-decoration:none;}
-.ui-menu-item-parent { background: url('i/menu-submenu.gif') no-repeat center right; }
-.ui-menu-item-disabled {}
\ No newline at end of file
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css
deleted file mode 100644
index 5e30c0c..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.resizable.css
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This file skins resizables */
-
-.ui-resizable { position: relative; }
-
-/* Global handle styles */
-.ui-resizable-handle { position: absolute; display: none; font-size: 0.1px; }
-.ui-resizable .ui-resizable-handle { display: block; }
-body .ui-resizable-disabled .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
-body .ui-resizable-autohide .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
-
-.ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/resizable-n.gif) repeat scroll center top; }
-.ui-resizable-s { cursor: s-resize; height: 6px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/resizable-s.gif) repeat scroll center top; }
-
-.ui-resizable-e { cursor: e-resize; width: 6px; right: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-e.gif) repeat scroll right center; }
-.ui-resizable-w { cursor: w-resize; width: 6px; left: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-w.gif) repeat scroll right center; }
-
-.ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/resizable-se.gif); }
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/resizable-sw.gif); }
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: 0px; top: 0px; background: transparent url(i/resizable-nw.gif); }
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: 0px; top: 0px; background: transparent url(i/resizable-ne.gif); }
\ No newline at end of file
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css
deleted file mode 100644
index 94827b3..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.slider.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This file skins sliders */
-
-.ui-slider { width: 200px; height: 23px; position: relative; background-repeat: no-repeat; background-position: center center; }
-.ui-slider-handle { position: absolute; z-index: 1; height: 23px; width: 12px; top: 0px; left: 0px; background-image: url(i/slider-handle.gif);  }
-.ui-slider-handle-active { border: 1px dotted black;  }
-.ui-slider-disabled .ui-slider-handle { opacity: 0.5; filter: alpha(opacity=50); }
-.ui-slider-range { position: absolute; background: #50A029; opacity: 0.3; filter: alpha(opacity=30); width: 100%; height: 100%; }
-
-/* Default slider backgrounds */
-.ui-slider, .ui-slider-1 { background-image: url(i/slider-bg-1.png); }
-.ui-slider-2 { background-image: url(i/slider-bg-2.png); }
\ No newline at end of file
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css
deleted file mode 100644
index 7d805a7..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tablesorter.css
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This file skins tableSorter */
-
-table.tablesorter {
-	font-family:arial;
-	background-color: #CDCDCD;
-	margin:10px 0pt 15px;
-	font-size: 8pt;
-	width: 100%;
-	text-align: left;
-}
-table.tablesorter thead tr th, table.tablesorter tfoot tr th {
-	background-color: #B1DB87;
-	border: 1px solid #FFF;
-	font-size: 8pt;
-	padding: 4px;
-}
-table.tablesorter thead tr .header {
-	background-image: url(i/bg.gif);
-	background-repeat: no-repeat;
-	background-position: center right;
-	cursor: pointer;
-}
-table.tablesorter tbody td {
-	color: #3D3D3D;
-	padding: 4px;
-	background-color: #FFF;
-	vertical-align: top;
-}
-table.tablesorter tbody tr.odd td {
-	background-color:#E0F4D7;
-}
-table.tablesorter thead tr .headerSortUp {
-	background-image: url(i/asc.gif);
-}
-table.tablesorter thead tr .headerSortDown {
-	background-image: url(i/desc.gif);
-}
-table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
-background-color: #83C948;
-}
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css
deleted file mode 100644
index c79a17e..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.tabs.css
+++ /dev/null
@@ -1,105 +0,0 @@
- at import "flora.css";
-
-/* Caution! Ensure accessibility in print and other media types... */
- at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
-    .ui-tabs-hide {
-        display: none;
-    }
-}
-
-/* Hide useless elements in print layouts... */
- at media print {
-    .ui-tabs-nav {
-        display: none;
-    }
-}
-
-/* Skin */
-.ui-tabs-nav, .ui-tabs-panel {
-    font-family: "Trebuchet MS", Trebuchet, Verdana, Helvetica, Arial, sans-serif;
-    font-size: 12px;
-}
-.ui-tabs-nav {
-    list-style: none;
-    margin: 0;
-    padding: 0 0 0 3px;
-}
-.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
-    display: block;
-    clear: both;
-    content: " ";
-}
-.ui-tabs-nav li {
-    float: left;
-    margin: 0 0 0 2px;
-    font-weight: bold;
-}
-.ui-tabs-nav a, .ui-tabs-nav a span {
-    float: left; /* fixes dir=ltr problem and other quirks IE */
-    padding: 0 12px;
-    background: url(i/tabs.png) no-repeat;
-}
-.ui-tabs-nav a {
-    margin: 5px 0 0; /* position: relative makes opacity fail for disabled tab in IE */
-    padding-left: 0;
-    background-position: 100% 0;
-    text-decoration: none;
-    white-space: nowrap; /* @ IE 6 */
-    outline: 0; /* @ Firefox, prevent dotted border after click */    
-}
-.ui-tabs-nav a:link, .ui-tabs-nav a:visited {
-    color: #fff;
-}
-.ui-tabs-nav .ui-tabs-selected a {
-    position: relative;
-    top: 1px;
-    z-index: 2;
-    margin-top: 0;
-    background-position: 100% -23px;
-}
-.ui-tabs-nav a span {
-    padding-top: 1px;
-    padding-right: 0;
-    height: 20px;
-    background-position: 0 0;
-    line-height: 20px;
-}
-.ui-tabs-nav .ui-tabs-selected a span {
-    padding-top: 0;
-    height: 27px;
-    background-position: 0 -23px;
-    line-height: 27px;
-}
-.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited,
-.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
-    cursor: text;
-}
-.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active,
-.ui-tabs-nav .ui-tabs-unselect a:hover, .ui-tabs-nav .ui-tabs-unselect a:focus, .ui-tabs-nav .ui-tabs-unselect a:active { /* @ Opera, we need to be explicit again here now... */
-    cursor: pointer;
-}
-.ui-tabs-disabled {
-    opacity: .4;
-    filter: alpha(opacity=40);
-}
-.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited {
-    color: #000;
-}
-.ui-tabs-panel {
-    border: 1px solid #519e2d;
-    padding: 10px;
-    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
-}
-/*.ui-tabs-loading em {
-    padding: 0 0 0 20px;
-    background: url(loading.gif) no-repeat 0 50%;
-}*/
-
-/* Additional IE specific bug fixes... */
-* html .ui-tabs-nav { /* auto clear @ IE 6 & IE 7 Quirks Mode */
-    display: inline-block;
-}
-*:first-child+html .ui-tabs-nav  { /* auto clear @ IE 7 Standards Mode - do not group selectors, otherwise IE 6 will ignore complete rule (because of the unknown + combinator)... */
-    display: inline-block;
-}
-
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css
deleted file mode 100644
index 6f2b55f..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toasterLite.css
+++ /dev/null
@@ -1,106 +0,0 @@
-/* This file skins toasterLite */
-
-.flora .ui-toasterLite,
-.flora.ui-toasterLite {
-	background-color: #e6f7d4;
-	width: 100px;
-	display: block;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-titlebar,
-.flora.ui-toasterLite .ui-toasterLite-titlebar {
-	border-bottom: 1px solid #d8d2aa;
-	background: #ff9900 url(i/dialog-title.gif) repeat-x;
-	padding: 0px;
-	height: 28px;
-	z-index: 5;
-	position: relative;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-title,
-.flora.ui-toasterLite .ui-toasterLite-title {
-	margin-left: 5px;
-	color: white;
-	font-weight: bold;
-	position: relative;
-	top: 7px;
-	left: 4px;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-content,
-.flora.ui-toasterLite .ui-toasterLite-content {
-	margin: 1.2em;
-	padding-bottom: 12px;
-}
-
-/* Toaster handle styles */
-.flora .ui-toasterLite .ui-toasterLite-n,
-.flora.ui-toasterLite .ui-toasterLite-n { height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/toaster-n.gif) repeat scroll center top; z-index: 6; }
-
-.flora .ui-toasterLite .ui-toasterLite-s,
-.flora.ui-toasterLite .ui-toasterLite-s { height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/toaster-s.gif) repeat scroll center top; z-index: 1; }
-
-.flora .ui-toasterLite .ui-toasterLite-e,
-.flora.ui-toasterLite .ui-toasterLite-e { width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/toaster-e.gif) repeat scroll right center; }
-
-.flora .ui-toasterLite .ui-toasterLite-w,
-.flora.ui-toasterLite .ui-toasterLite-w { width: 7px; left: 0px; top: 0px; height: 100%; background: url(i/toaster-w.gif) repeat scroll right center; }
-
-.flora .ui-toasterLite .ui-toasterLite-se,
-.flora.ui-toasterLite .ui-toasterLite-se { width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/toaster-se.gif); z-index: 2; }
-
-.flora .ui-toasterLite .ui-toasterLite-sw,
-.flora.ui-toasterLite .ui-toasterLite-sw { width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/toaster-sw.gif); z-index: 2; }
-
-.flora .ui-toasterLite .ui-toasterLite-nw,
-.flora.ui-toasterLite .ui-toasterLite-nw { width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/toaster-nw.gif); z-index: 6; }
-
-.flora .ui-toasterLite .ui-toasterLite-ne,
-.flora.ui-toasterLite .ui-toasterLite-ne { width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/toaster-ne.gif); z-index: 6; }
-
-/* Global handle styles */
-.ui-toasterLite-corner { position: absolute; font-size: 0.1px; }
-
-.flora .ui-toasterLite-holder,
-.flora.ui-toasterLite-holder {
-  position: absolute;
-}
-.flora .ui-toasterLite-holder-pos-tr,
-.flora.ui-toasterLite-holder-pos-tr {
-  top: 10px;
-  right: 10px;
-}
-
-.flora .ui-toasterLite-holder-pos-tl,
-.flora.ui-toasterLite-holder-pos-tl {
-  top: 10px;
-  left: 10px;
-}
-
-.flora .ui-toasterLite-holder-pos-br,
-.flora.ui-toasterLite-holder-pos-br {
-  bottom: 10px;
-  right: 10px;
-}
-
-.flora .ui-toasterLite-holder-pos-bl,
-.flora.ui-toasterLite-holder-pos-bl {
-  bottom: 10px;
-  left: 10px;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-titlebar-close,
-.flora.ui-toasterLite .ui-toasterLite-titlebar-close {
-	width: 16px;
-	height: 16px;
-	background: url(i/dialog-titlebar-close.png) no-repeat;
-	position:absolute;
-	top: 6px;
-	right: 7px;
-	cursor: default;
-}
-
-.flora .ui-toasterLite .ui-toasterLite-titlebar-close-hover,
-.flora.ui-toasterLite .ui-toasterLite-titlebar-close-hover {
-	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
-}
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css
deleted file mode 100644
index 8ad0588..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/flora.toolbar.css
+++ /dev/null
@@ -1,241 +0,0 @@
-/* light.toolbar.css
- *
- *  Written: 05/09/07 4:38:01 PM
- *  Revision: 1.0.0
- *
- *
- * Credits:
- *  Miksago: Full Coding.
- */
-
-.flora .ui-toolbar {
-  position:relative;
-  padding:0px;
-  margin:0px;
-}
-.flora .ui-toolbar ul {
-  background:#E6F7D4;
-  padding:0px;
-  margin:0px;
-}
-  .flora .ui-toolbar ul li {
-    list-style-type: none;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-horiz {
-    border-top:1px solid #5AB500;
-    background:#E6F7D4 url("i/toolbars-bot-bg.gif") repeat-x bottom left;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-horiz li {
-    display:inline;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert {
-    padding: 0.025em 0em;
-    border-left: 1px solid #111;
-    border-right: 1px solid #444;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert li {
-    display:block;
-  }
-  /* This hides the text on buttons in a icon only toolbar */
-  .flora .ui-toolbar ul.ui-toolbar-icons li .ui-toolbar-btn-desc {
-    display:none;
-  }
-  /* This hides the icon on buttons in a text only toolbar */
-  .flora .ui-toolbar ul.ui-toolbar-text li .ui-toolbar-btn-icon {
-    display:none;
-  }
-  /* This is just for icon sizes, not really needed, but it's there so if icon sizes are defined.. */
-  .flora .ui-toolbar ul li.ui-toolbar-btn-icon-sixteen .ui-toolbar-btn-icon {
-    width:16px; height:16px;
-    overflow:hidden;
-    padding:2px;
-    padding-left:16px;
-    background:no-repeat;
-    background-position:50% 50%;
-  }
-  
-/************************************************
- * Factory Elements:
- *  - These are different kinds of items that
- *    can be in a toolbar.
- *
- *  Includes:
- *    @ ui-toolbar-btn
- *        toolbar buttons.
- *    @ ui-toolbar-sep
- *        toolbar separators.
- *
-*/
-
-
-
-/************************************************
- * UI-TOOLBAR-BTN
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-btn">
- *      <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
- *      <span class="ui-toolbar-btn-center">
- *        <button><span>{{text}}</span></button>
- *      </span>
- *      <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
- *    </li>
- *
- ************************************************/
-
-
-  .flora .ui-toolbar ul li.ui-toolbar-btn {
-    cursor:pointer;
-    white-space: nowrap;
-    position:relative;
-  }
-  .flora .ui-toolbar ul li .ui-toolbar-btn-left {
-    width:3px;
-    padding:5px 0px 1px 0;
-    position:absolute;
-    top:-3px;
-    bottom:0px;
-    left:-3px;
-    height:100%;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
-    width:3px; height:5px;
-    padding:0px 0px 0px 0px;
-    position:absolute;
-    bottom:0px;
-    left:0px;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center{
-    background:url("i/accordion-middle-over.png") repeat-x left top;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left {
-    background:url("i/accordion-left-over.png") no-repeat left top;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
-    background:url("i/accordion-left-over.png") no-repeat left bottom;
-  }
-  .flora .ui-toolbar ul li .ui-toolbar-btn-center {
-    padding: 0.2em 0em;
-    line-height:2.2em;
-  }
-    .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-btn {
-      vertical-align: middle;
-      margin:0.3em 0.2em;
-    }
-    .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-btn {
-      margin:0.2em;
-      line-height:1.6em;
-      vertical-align: middle;
-    }
-      .flora .ui-toolbar ul li button {
-        vertical-align: middle;
-        background:transparent;
-        color:#000;
-        border:0px none;
-        cursor:pointer;
-        overflow:visible;
-        -moz-outline:0 none;
-        outline:0 none;
-        padding: 0.1em 0.1em;
-      }
-        .flora .ui-toolbar ul li.ui-toolbar-btn button span {
-          vertical-align: middle;
-        }
-        /* This hides the text on buttons in a icon only toolbar */
-        .flora .ui-toolbar ul.ui-toobar-iconOnly li.ui-toolbar-btn button span {
-          display:none;
-        }
-  
-  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center button,
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center button {
-    background: url("i/accordion-middle-over.png") repeat-x left bottom;
-  }
-  .flora .ui-toolbar ul li.ui-toolbar-btn-active {
-    
-  }
-  
-  .flora .ui-toolbar ul li.ui-toolbar-btn-disabled {
-    opacity:0.2;
-  }
-
-/************************************************
- * UI-TOOLBAR-BTN
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-sep">
- *      <span>
- *        &nbsp;
- *      </span>
- *    </li>
- *
- ************************************************/
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-sep {
-    border-left:1px solid #444;
-    border-right:1px solid #111;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-sep {
-    border-top:1px solid #111;
-    border-bottom:1px solid #444;
-  }
-
-/************************************************
- * UI-TOOLBAR-SLIDER
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-slider">
- *      <div class="ui-toolbar-slider-track ui-slider-track">
- *        <div class="ui-slider-handle"></div>
- *      </div>
- *   </li>
- *
- ************************************************/
-
-.flora .ui-toolbar ul li.ui-toolbar-slider .ui-toolbar-slider-track {
-  height: 20px!important;
-}
-
-/************************************************
- * UI-TOOLBAR-RADIOGRP
- *
- *  STRUCTURE:
- *    <li class="ui-toolbar-radioGrp">
- *      <ul class="DIRECTION">
- *        <li class="ui-toolbar-btn">
- *          <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
- *          <span class="ui-toolbar-btn-center">
- *            <button><span>{{text}}</span></button>
- *          </span>
- *          <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
- *        </li>
- *      </ul>
- *    </li>
- *      
- *
- ************************************************/
-
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp,
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul,
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul li{
-    display:inline;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul {
-    margin:0px;
-    padding:0px;
-  }
-
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp,
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul,
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul li{
-    display:block;
-  }
-  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul {
-    margin:0px;
-    padding:0px;
-  }
-
-
-/* END OF FILE */
\ No newline at end of file
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png
deleted file mode 100644
index bf6ee99..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-act.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png
deleted file mode 100644
index 66378e0..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left-over.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png
deleted file mode 100644
index 13344fc..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-left.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png
deleted file mode 100644
index cecf4f1..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-act.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png
deleted file mode 100644
index 251ad11..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle-over.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png
deleted file mode 100644
index 5238fd4..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-middle.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png
deleted file mode 100644
index 1fa4792..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-act.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png
deleted file mode 100644
index d676dad..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right-over.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png
deleted file mode 100644
index 543991a..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/accordion-right.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif
deleted file mode 100644
index 7415786..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/asc.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif
deleted file mode 100644
index fac668f..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/bg.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif
deleted file mode 100644
index 3b30b3c..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/desc.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif
deleted file mode 100644
index 3b8b521..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-e.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif
deleted file mode 100644
index 70887b8..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-n.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif
deleted file mode 100644
index ab9c38e..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-ne.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif
deleted file mode 100644
index e934073..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-nw.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif
deleted file mode 100644
index d5f6b99..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-s.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif
deleted file mode 100644
index 186a864..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-se.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif
deleted file mode 100644
index 025dfda..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-sw.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif
deleted file mode 100644
index 156c59b..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-title.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png
deleted file mode 100644
index 67c1303..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png
deleted file mode 100644
index cec974c..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif
deleted file mode 100644
index 931ff4a..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/dialog-w.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif
deleted file mode 100644
index 77647d8..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/menu-submenu.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif
deleted file mode 100644
index 7acf248..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-e.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif
deleted file mode 100644
index 59110f6..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-n.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif
deleted file mode 100644
index 515a3f8..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-ne.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif
deleted file mode 100644
index 665f318..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-nw.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif
deleted file mode 100644
index da2fb35..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-s.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif
deleted file mode 100644
index 6c258ef..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-se.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif
deleted file mode 100644
index 2fd8de4..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-sw.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif
deleted file mode 100644
index 34b875b..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/resizable-w.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png
deleted file mode 100644
index 4c58c7f..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/shadow.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png
deleted file mode 100644
index b7d806e..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-1.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png
deleted file mode 100644
index 8b24cf0..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-bg-2.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif
deleted file mode 100644
index 9b89f26..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/slider-handle.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png
deleted file mode 100644
index 8018e41..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/tabs.png and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif
deleted file mode 100644
index 55dcb2c..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-e.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif
deleted file mode 100644
index b0fbeb9..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-n.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif
deleted file mode 100644
index ab9c38e..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-ne.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif
deleted file mode 100644
index e934073..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-nw.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif
deleted file mode 100644
index 15640e8..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-s.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif
deleted file mode 100644
index fb7a7df..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-se.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif
deleted file mode 100644
index ad1ae1c..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-sw.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif
deleted file mode 100644
index 8489de8..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toaster-w.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif b/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif
deleted file mode 100644
index 15640e8..0000000
Binary files a/moksha/widgetbrowser/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif and /dev/null differ
diff --git a/moksha/widgetbrowser/widgetbrowser/static/ui.base.js b/moksha/widgetbrowser/widgetbrowser/static/ui.base.js
deleted file mode 100644
index 17115f0..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/ui.base.js
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * jQuery UI @VERSION
- *
- * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * http://docs.jquery.com/UI
- *
- * $Date: 2008-04-01 09:23:47 -0400 (Tue, 01 Apr 2008) $
- * $Rev: 5174 $
- */
-;(function($) {
-
-	//If the UI scope is not available, add it
-	$.ui = $.ui || {};
-	
-	//Add methods that are vital for all mouse interaction stuff (plugin registering)
-	$.extend($.ui, {
-		plugin: {
-			add: function(module, option, set) {
-				var proto = $.ui[module].prototype;
-				for(var i in set) {
-					proto.plugins[i] = proto.plugins[i] || [];
-					proto.plugins[i].push([option, set[i]]);
-				}
-			},
-			call: function(instance, name, arguments) {
-				var set = instance.plugins[name]; if(!set) return;
-				for (var i = 0; i < set.length; i++) {
-					if (instance.options[set[i][0]]) set[i][1].apply(instance.element, arguments);
-				}
-			}	
-		},
-		cssCache: {},
-		css: function(name) {
-			if ($.ui.cssCache[name]) return $.ui.cssCache[name];
-			var tmp = $('<div class="ui-resizable-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
-			
-			//if (!$.browser.safari)
-				//tmp.appendTo('body'); 
-			
-			//Opera and Safari set width and height to 0px instead of auto
-			//Safari returns rgba(0,0,0,0) when bgcolor is not set
-			$.ui.cssCache[name] = !!(
-				(!/auto|default/.test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 
-				!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
-			);
-			try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
-			return $.ui.cssCache[name];
-		},
-		disableSelection: function(e) {
-			e.unselectable = "on";
-			e.onselectstart = function() {	return false; };
-			if (e.style) e.style.MozUserSelect = "none";
-		},
-		enableSelection: function(e) {
-			e.unselectable = "off";
-			e.onselectstart = function() { return true; };
-			if (e.style) e.style.MozUserSelect = "";
-		},
-		hasScroll: function(e, a) {
-      		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;
-      		if (e[scroll] > 0) return true; e[scroll] = 1;
-      		has = e[scroll] > 0 ? true : false; e[scroll] = 0;
-      		return has; 
-    	}
-	});
-
-	/******* fn scope modifications ********/
-
-	$.each( ['Left', 'Top'], function(i, name) {
-		if(!$.fn['scroll'+name]) $.fn['scroll'+name] = function(v) {
-			return v != undefined ?
-				this.each(function() { this == window || this == document ? window.scrollTo(name == 'Left' ? v : $(window)['scrollLeft'](), name == 'Top'  ? v : $(window)['scrollTop']()) : this['scroll'+name] = v; }) :
-				this[0] == window || this[0] == document ? self[(name == 'Left' ? 'pageXOffset' : 'pageYOffset')] || $.boxModel && document.documentElement['scroll'+name] || document.body['scroll'+name] : this[0][ 'scroll' + name ];
-		};
-	});
-
-	var _remove = $.fn.remove;
-	$.fn.extend({
-		position: function() {
-			var offset       = this.offset();
-			var offsetParent = this.offsetParent();
-			var parentOffset = offsetParent.offset();
-
-			return {
-				top:  offset.top - num(this[0], 'marginTop')  - parentOffset.top - num(offsetParent, 'borderTopWidth'),
-				left: offset.left - num(this[0], 'marginLeft')  - parentOffset.left - num(offsetParent, 'borderLeftWidth')
-			};
-		},
-		offsetParent: function() {
-			var offsetParent = this[0].offsetParent;
-			while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
-				offsetParent = offsetParent.offsetParent;
-			return $(offsetParent);
-		},
-		mouseInteraction: function(o) {
-			return this.each(function() {
-				new $.ui.mouseInteraction(this, o);
-			});
-		},
-		removeMouseInteraction: function(o) {
-			return this.each(function() {
-				if($.data(this, "ui-mouse"))
-					$.data(this, "ui-mouse").destroy();
-			});
-		},
-		remove: function() {
-			jQuery("*", this).add(this).trigger("remove");
-			return _remove.apply(this, arguments );
-		}
-	});
-	
-	function num(el, prop) {
-		return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
-	};
-	
-	
-	/********** Mouse Interaction Plugin *********/
-	
-	$.ui.mouseInteraction = function(element, options) {
-	
-		var self = this;
-		this.element = element;
-
-		$.data(this.element, "ui-mouse", this);
-		this.options = $.extend({}, options);
-		
-		$(element).bind('mousedown.draggable', function() { return self.click.apply(self, arguments); });
-		if($.browser.msie) $(element).attr('unselectable', 'on'); //Prevent text selection in IE
-		
-		// prevent draggable-options-delay bug #2553
-		$(element).mouseup(function() {
-			if(self.timer) clearInterval(self.timer);
-		});
-	};
-	
-	$.extend($.ui.mouseInteraction.prototype, {
-		
-		destroy: function() { $(this.element).unbind('mousedown.draggable'); },
-		trigger: function() { return this.click.apply(this, arguments); },
-		click: function(e) {
-			
-			if(
-				   e.which != 1 //only left click starts dragging
-				|| $.inArray(e.target.nodeName.toLowerCase(), this.options.dragPrevention || []) != -1 // Prevent execution on defined elements
-				|| (this.options.condition && !this.options.condition.apply(this.options.executor || this, [e, this.element])) //Prevent execution on condition
-			) return true;
-				
-			var self = this;
-			var initialize = function() {
-				self._MP = { left: e.pageX, top: e.pageY }; // Store the click mouse position
-				$(document).bind('mouseup.draggable', function() { return self.stop.apply(self, arguments); });
-				$(document).bind('mousemove.draggable', function() { return self.drag.apply(self, arguments); });
-				
-				if(!self.initalized && Math.abs(self._MP.left-e.pageX) >= self.options.distance || Math.abs(self._MP.top-e.pageY) >= self.options.distance) {				
-					if(self.options.start) self.options.start.call(self.options.executor || self, e, self.element);
-					if(self.options.drag) self.options.drag.call(self.options.executor || self, e, this.element); //This is actually not correct, but expected
-					self.initialized = true;
-				}
-			};
-
-			if(this.options.delay) {
-				if(this.timer) clearInterval(this.timer);
-				this.timer = setTimeout(initialize, this.options.delay);
-			} else {
-				initialize();
-			}
-				
-			return false;
-			
-		},
-		stop: function(e) {			
-			
-			var o = this.options;
-			if(!this.initialized) return $(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
-
-			if(this.options.stop) this.options.stop.call(this.options.executor || this, e, this.element);
-			$(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
-			this.initialized = false;
-			return false;
-			
-		},
-		drag: function(e) {
-
-			var o = this.options;
-			if ($.browser.msie && !e.button) return this.stop.apply(this, [e]); // IE mouseup check
-			
-			if(!this.initialized && (Math.abs(this._MP.left-e.pageX) >= o.distance || Math.abs(this._MP.top-e.pageY) >= o.distance)) {				
-				if(this.options.start) this.options.start.call(this.options.executor || this, e, this.element);
-				this.initialized = true;
-			} else {
-				if(!this.initialized) return false;
-			}
-
-			if(o.drag) o.drag.call(this.options.executor || this, e, this.element);
-			return false;
-			
-		}
-	});
-	
-})(jQuery);
- 
\ No newline at end of file
diff --git a/moksha/widgetbrowser/widgetbrowser/static/ui.dialog.js b/moksha/widgetbrowser/widgetbrowser/static/ui.dialog.js
deleted file mode 100644
index 7a907bd..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/ui.dialog.js
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * jQuery UI Dialog
- *
- * Copyright (c) 2008 Richard D. Worth (rdworth.org)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- * 
- * http://docs.jquery.com/UI/Dialog
- *
- * Depends:
- *   ui.base.js
- *   ui.draggable.js
- *   ui.resizable.js
- *
- * Revision: $Id: ui.dialog.js 5185 2008-04-03 15:39:51Z scott.gonzalez $
- */
-;(function($) {
-	
-	$.fn.extend({
-		dialog: function(options) {
-			var args = Array.prototype.slice.call(arguments, 1);
-
-			return this.each(function() {
-				if (typeof options == "string") {
-					var elem = $(this).is('.ui-dialog')
-						? this
-						: $(this).parents(".ui-dialog:first").find(".ui-dialog-content")[0];
-					var dialog = elem ? $.data(elem, "dialog") : {};
-					if (dialog[options])
-						dialog[options].apply(dialog, args);
-				// INIT with optional options
-				} else if (!$(this).is(".ui-dialog-content"))
-					new $.ui.dialog(this, options);
-			});
-		}
-	});
-
-	$.ui.dialog = function(el, options) {
-		
-		this.options = options = $.extend({}, $.ui.dialog.defaults, options);
-		this.element = el;
-		var self = this; //Do bindings
-
-		$.data(this.element, "dialog", this);
-
-		$(el).bind("remove", function() {
-			self.destroy();
-		});
-		
-		$(el).bind("setData.dialog", function(event, key, value){
-			switch (key) {
-				case "draggable":
-					uiDialog.draggable(value ? 'enable' : 'disable');
-					break;
-				case "dragStart":
-					uiDialog.data('start.draggable', value);
-					break;
-				case "drag":
-					uiDialog.data('drag.draggable', value);
-					break;
-				case "dragStop":
-					uiDialog.data('stop.draggable', value);
-					break;
-				case "height":
-					uiDialog.height(value);
-					break;
-				case "maxHeight":
-				case "minHeight":
-				case "maxWidth":
-				case "minWidth":
-					uiDialog.data(key + ".resizable", value);
-					break;
-				case "position":
-					self.position(value);
-					break;
-				case "resizable":
-					uiDialog.resizable(value ? 'enable' : 'disable');
-					break;
-				case "resizeStart":
-					uiDialog.data('start.resizable', value);
-					break;
-				case "resize":
-					uiDialog.data('resize.resizable', value);
-					break;
-				case "resizeStop":
-					uiDialog.data('stop.resizable', value);
-					break;
-				case "title":
-					$(".ui-dialog-title", uiDialogTitlebar).text(value);
-					break;
-				case "width":
-					break;
-			}
-			options[key] = value;
-		}).bind("getData.dialog", function(event, key){
-			return options[key];
-		});
-
-		var uiDialogContent = $(el).addClass('ui-dialog-content');
-
-		if (!uiDialogContent.parent().length) {
-			uiDialogContent.appendTo('body');
-		}
-		uiDialogContent
-			.wrap(document.createElement('div'))
-			.wrap(document.createElement('div'));
-		var uiDialogContainer = uiDialogContent.parent().addClass('ui-dialog-container').css({position: 'relative'});
-		var uiDialog = this.uiDialog = uiDialogContainer.parent().hide()
-			.addClass('ui-dialog')
-			.css({position: 'absolute', width: options.width, height: options.height, overflow: 'hidden'}); 
-
-		var classNames = uiDialogContent.attr('className').split(' ');
-
-		// Add content classes to dialog, to inherit theme at top level of element
-		$.each(classNames, function(i, className) {
-			if (className != 'ui-dialog-content')
-				uiDialog.addClass(className);
-		});
-
-		if ($.fn.resizable) {
-			uiDialog.append('<div class="ui-resizable-n ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-s ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-e ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-w ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-ne ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-se ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-sw ui-resizable-handle"></div>')
-				.append('<div class="ui-resizable-nw ui-resizable-handle"></div>');
-			uiDialog.resizable({
-				maxWidth: options.maxWidth,
-				maxHeight: options.maxHeight,
-				minWidth: options.minWidth,
-				minHeight: options.minHeight,
-				start: options.resizeStart,
-				resize: options.resize,
-				stop: function(e, ui) {
-					options.resizeStop && options.resizeStop.apply(this, arguments);
-					$.ui.dialog.overlay.resize();
-				}
-			});
-			if (!options.resizable)
-				uiDialog.resizable('disable');
-		}
-
-		uiDialogContainer.prepend('<div class="ui-dialog-titlebar"></div>');
-		var uiDialogTitlebar = $('.ui-dialog-titlebar', uiDialogContainer);
-		var title = (options.title) ? options.title : (uiDialogContent.attr('title')) ? uiDialogContent.attr('title') : '';
-		uiDialogTitlebar.append('<span class="ui-dialog-title">' + title + '</span>');
-		uiDialogTitlebar.append('<a href="#" class="ui-dialog-titlebar-close"><span>X</span></a>');
-		this.uiDialogTitlebarClose = $('.ui-dialog-titlebar-close', uiDialogTitlebar)
-			.hover(function() { $(this).addClass('ui-dialog-titlebar-close-hover'); }, 
-			       function() { $(this).removeClass('ui-dialog-titlebar-close-hover'); })
-			.mousedown(function(ev) {
-				ev.stopPropagation();
-			})
-			.click(function() {
-				self.close();
-				return false;
-			})
-			.keydown(function(ev) {
-				var ESC = 27;
-				ev.keyCode && ev.keyCode == ESC && self.close(); 
-			});
-
-		var l = 0;
-		$.each(options.buttons, function() { l = 1; return false; });
-		if (l == 1) {
-			uiDialog.append('<div class="ui-dialog-buttonpane"></div>');
-			var uiDialogButtonPane = $('.ui-dialog-buttonpane', uiDialog);
-			$.each(options.buttons, function(name, value) {
-				var btn = $(document.createElement('button')).text(name).click(value);
-				uiDialogButtonPane.append(btn);
-			});
-		}
-
-		if ($.fn.draggable) {
-			uiDialog.draggable({
-				handle: '.ui-dialog-titlebar',
-				start: function(e, ui) {
-					self.activate();
-					options.dragStart && options.dragStart.apply(this, arguments);
-				},
-				drag: options.drag,
-				stop: function(e, ui) {
-					options.dragStop && options.dragStop.apply(this, arguments);
-					$.ui.dialog.overlay.resize();
-				}
-			});
-			if (!options.draggable)
-				uiDialog.draggable('disable')
-		}
-	
-		uiDialog.mousedown(function() {
-			self.activate();
-		});
-		uiDialogTitlebar.click(function() {
-			self.activate();
-		});
-		
-		options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe();
-
-		this.position = function(pos) {
-			var wnd = $(window), doc = $(document), top = doc.scrollTop(), left = doc.scrollLeft();
-			if (pos.constructor == Array) {
-				// [x, y]
-				top += pos[1];
-				left += pos[0];
-			} else {
-				switch (pos) {
-					case 'center':
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-						break;
-					case 'top':
-						top += 0;
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-						break;
-					case 'right':
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += (wnd.width()) - (uiDialog.width());
-						break;
-					case 'bottom':
-						top += (wnd.height()) - (uiDialog.height());
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-						break;
-					case 'left':
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += 0;
-						break;
-					default:
-						//center
-						top += (wnd.height() / 2) - (uiDialog.height() / 2);
-						left += (wnd.width() / 2) - (uiDialog.width() / 2);
-				}
-			}
-			top = top < doc.scrollTop() ? doc.scrollTop() : top;
-			uiDialog.css({top: top, left: left});
-		}
-		
-		this.open = function() {
-			this.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
-			uiDialog.appendTo('body');
-			this.position(options.position);
-			uiDialog.show();
-			self.moveToTop();
-			self.activate();
-			
-			// CALLBACK: open
-			var openEV = null;
-			var openUI = {
-				options: options
-			};
-			this.uiDialogTitlebarClose.focus();
-			$(this.element).triggerHandler("dialogopen", [openEV, openUI], options.open);
-		};
-
-		this.activate = function() {
-			// Move modeless dialogs to the top when they're activated.  Even
-			// if there is a modal dialog in the window, the modeless dialog
-			// should be on top because it must have been opened after the modal
-			// dialog.  Modal dialogs don't get moved to the top because that
-			// would make any modeless dialogs that it spawned unusable until
-			// the modal dialog is closed.
-			!options.modal && this.moveToTop();
-		};
-		
-		this.moveToTop = function() {
-			var maxZ = options.zIndex;
-			$('.ui-dialog:visible').each(function() {
-				maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10) || options.zIndex);
-			});
-			this.overlay && this.overlay.$el.css('z-index', ++maxZ);
-			uiDialog.css('z-index', ++maxZ);
-		};
-		
-		this.close = function() {
-			this.overlay && this.overlay.destroy();
-			uiDialog.hide();
-
-			// CALLBACK: close
-			var closeEV = null;
-			var closeUI = {
-				options: options
-			};
-			$(this.element).triggerHandler("dialogclose", [closeEV, closeUI], options.close);
-			$.ui.dialog.overlay.resize();
-		};
-
-		this.destroy = function() {
-			this.overlay && this.overlay.destroy();
-			uiDialog.hide();
-			$(el).unbind('.dialog').removeClass('ui-dialog-content').hide().appendTo('body');
-			uiDialog.remove();
-			$.removeData(this.element, "dialog");
-		};
-		
-		if (options.autoOpen) {
-			this.open();
-		};
-	};
-	
-	$.extend($.ui.dialog, {
-		defaults: {
-			autoOpen: true,
-			bgiframe: false,
-			buttons: [],
-			draggable: true,
-			height: 200,
-			minHeight: 100,
-			minWidth: 150,
-			modal: false,
-			overlay: {},
-			position: 'center',
-			resizable: true,
-			width: 300,
-			zIndex: 1000
-		},
-		
-		overlay: function(dialog) {
-			this.$el = $.ui.dialog.overlay.create(dialog);
-		}
-	});
-	
-	$.extend($.ui.dialog.overlay, {
-		instances: [],
-		events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
-			function(e) { return e + '.dialog-overlay'; }).join(' '),
-		create: function(dialog) {
-			if (this.instances.length === 0) {
-				// prevent use of anchors and inputs
-				$('a, :input').bind(this.events, function() {
-					// allow use of the element if inside a dialog and
-					// - there are no modal dialogs
-					// - there are modal dialogs, but we are in front of the
-					//   topmost modal dialog
-					var allow = false;
-					var $dialog = $(this).parents('.ui-dialog');
-					if ($dialog.length) {
-						var $overlays = $('.ui-dialog-overlay');
-						if ($overlays.length) {
-							var maxZ = parseInt($overlays.css('z-index'), 10);
-							$overlays.each(function() {
-								maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10));
-							});
-							allow = parseInt($dialog.css('z-index'), 10) > maxZ;
-						} else {
-							allow = true;
-						}
-					}
-					return allow;
-				});
-				
-				// allow closing by pressing the escape key
-				$(document).bind('keydown.dialog-overlay', function(e) {
-					var ESC = 27;
-					e.keyCode && e.keyCode == ESC && dialog.close(); 
-				});
-				
-				// handle window resize
-				$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
-			}
-			
-			var $el = $('<div/>').appendTo(document.body)
-				.addClass('ui-dialog-overlay').css($.extend({
-					borderWidth: 0, margin: 0, padding: 0,
-					position: 'absolute', top: 0, left: 0,
-					width: this.width(),
-					height: this.height()
-				}, dialog.options.overlay));
-			
-			dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe();
-			
-			this.instances.push($el);
-			return $el;
-		},
-		
-		destroy: function($el) {
-			this.instances.splice($.inArray(this.instances, $el), 1);
-			
-			if (this.instances.length === 0) {
-				$('a, :input').add([document, window]).unbind('.dialog-overlay');
-			}
-			
-			$el.remove();
-		},
-		
-		height: function() {
-			if ($.browser.msie && $.browser.version < 7) {
-				var scrollHeight = Math.max(
-					document.documentElement.scrollHeight,
-					document.body.scrollHeight
-				);
-				var offsetHeight = Math.max(
-					document.documentElement.offsetHeight,
-					document.body.offsetHeight
-				);
-				
-				if (scrollHeight < offsetHeight) {
-					return $(window).height() + 'px';
-				} else {
-					return scrollHeight + 'px';
-				}
-			} else {
-				return $(document).height() + 'px';
-			}
-		},
-		
-		width: function() {
-			if ($.browser.msie && $.browser.version < 7) {
-				var scrollWidth = Math.max(
-					document.documentElement.scrollWidth,
-					document.body.scrollWidth
-				);
-				var offsetWidth = Math.max(
-					document.documentElement.offsetWidth,
-					document.body.offsetWidth
-				);
-				
-				if (scrollWidth < offsetWidth) {
-					return $(window).width() + 'px';
-				} else {
-					return scrollWidth + 'px';
-				}
-			} else {
-				return $(document).width() + 'px';
-			}
-		},
-		
-		resize: function() {
-			/* If the dialog is draggable and the user drags it past the
-			 * right edge of the window, the document becomes wider so we
-			 * need to stretch the overlay.  If the user then drags the
-			 * dialog back to the left, the document will become narrower,
-			 * so we need to shrink the overlay to the appropriate size.
-			 * This is handled by shrinking the overlay before setting it
-			 * to the full document size.
-			 */
-			var $overlays = $([]);
-			$.each($.ui.dialog.overlay.instances, function() {
-				$overlays = $overlays.add(this);
-			});
-			
-			$overlays.css({
-				width: 0,
-				height: 0
-			}).css({
-				width: $.ui.dialog.overlay.width(),
-				height: $.ui.dialog.overlay.height()
-			});
-		}
-	});
-	
-	$.extend($.ui.dialog.overlay.prototype, {
-		destroy: function() {
-			$.ui.dialog.overlay.destroy(this.$el);
-		}
-	});
-
-})(jQuery);
diff --git a/moksha/widgetbrowser/widgetbrowser/static/ui.draggable.js b/moksha/widgetbrowser/widgetbrowser/static/ui.draggable.js
deleted file mode 100644
index ce209db..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/ui.draggable.js
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * jQuery UI Draggable
- *
- * Copyright (c) 2008 Paul Bakaus
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- * 
- * http://docs.jquery.com/UI/Draggables
- *
- * Depends:
- *   ui.base.js
- *
- * Revision: $Id: ui.draggable.js 5194 2008-04-04 12:30:10Z paul.bakaus $
- */
-;(function($) {
-
-	$.fn.extend({
-		draggable: function(options) {
-			var args = Array.prototype.slice.call(arguments, 1);
-			
-			return this.each(function() {
-				if (typeof options == "string") {
-					var drag = $.data(this, "draggable");
-					if(drag) drag[options].apply(drag, args);
-
-				} else if(!$.data(this, "draggable"))
-					new $.ui.draggable(this, options);
-			});
-		}
-	});
-	
-	$.ui.draggable = function(element, options) {
-		//Initialize needed constants
-		var self = this;
-		
-		this.element = $(element);
-		
-		$.data(element, "draggable", this);
-		this.element.addClass("ui-draggable");
-		
-		//Prepare the passed options
-		this.options = $.extend({}, options);
-		var o = this.options;
-		$.extend(o, {
-			helper: o.ghosting == true ? 'clone' : (o.helper || 'original'),
-			handle : o.handle ? ($(o.handle, element)[0] ? $(o.handle, element) : this.element) : this.element,
-			appendTo: o.appendTo || 'parent'		
-		});
-		
-		$(element).bind("setData.draggable", function(event, key, value){
-			self.options[key] = value;
-		}).bind("getData.draggable", function(event, key){
-			return self.options[key];
-		});
-		
-		//Initialize mouse events for interaction
-		$(o.handle).mouseInteraction({
-			executor: this,
-			delay: o.delay,
-			distance: o.distance || 1,
-			dragPrevention: o.cancel || o.cancel === '' ? o.cancel.toLowerCase().split(',') : ['input','textarea','button','select','option'],
-			start: this.start,
-			stop: this.stop,
-			drag: this.drag,
-			condition: function(e) { return !(e.target.className.indexOf("ui-resizable-handle") != -1 || this.options.disabled); }
-		});
-		
-		//Position the node
-		if(o.helper == 'original' && (this.element.css('position') == 'static' || this.element.css('position') == ''))
-			this.element.css('position', 'relative');
-			
-		//Prepare cursorAt
-		if(o.cursorAt && o.cursorAt.constructor == Array)
-			o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] };
-		
-	};
-	
-	$.extend($.ui.draggable.prototype, {
-		plugins: {},
-		ui: function(e) {
-			return {
-				helper: this.helper,
-				position: this.position,
-				absolutePosition: this.positionAbs,
-				instance: this,
-				options: this.options,
-				element: this.element				
-			};
-		},
-		propagate: function(n,e) {
-			$.ui.plugin.call(this, n, [e, this.ui()]);
-			return this.element.triggerHandler(n == "drag" ? n : "drag"+n, [e, this.ui()], this.options[n]);
-		},
-		destroy: function() {
-			if(!$.data(this.element[0], 'draggable')) return;
-			this.options.handle.removeMouseInteraction();
-			this.element
-				.removeClass("ui-draggable ui-draggable-disabled")
-				.removeData("draggable")
-				.unbind(".draggable");
-		},
-		enable: function() {
-			this.element.removeClass("ui-draggable-disabled");
-			this.options.disabled = false;
-		},
-		disable: function() {
-			this.element.addClass("ui-draggable-disabled");
-			this.options.disabled = true;
-		},
-		setContrains: function(minLeft,maxLeft,minTop,maxTop) {
-			this.minLeft = minLeft; this.maxLeft = maxLeft;
-			this.minTop = minTop; this.maxTop = maxTop;
-			this.constrainsSet = true;
-		},
-		checkConstrains: function() {
-			if(!this.constrainsSet) return;
-			if(this.position.left < this.minLeft) this.position.left = this.minLeft;
-			if(this.position.left > this.maxLeft - this.helperProportions.width) this.position.left = this.maxLeft - this.helperProportions.width;
-			if(this.position.top < this.minTop) this.position.top = this.minTop;
-			if(this.position.top > this.maxTop - this.helperProportions.height) this.position.top = this.maxTop - this.helperProportions.height;
-		},
-		recallOffset: function(e) {
-
-			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
-			var r = this.helper.css('position') == 'relative';
-
-			//Generate the original position
-			this.originalPosition = {
-				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
-				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
-			};
-			
-			//Generate a flexible offset that will later be subtracted from e.pageX/Y
-			this.offset = {left: this._pageX - this.originalPosition.left, top: this._pageY - this.originalPosition.top };
-			
-		},
-		start: function(e) {
-			var o = this.options;
-			if($.ui.ddmanager) $.ui.ddmanager.current = this;
-			
-			//Create and append the visible helper
-			this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e])) : (o.helper == 'clone' ? this.element.clone().appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)) : this.element);
-			if(this.helper[0] != this.element[0]) this.helper.css('position', 'absolute');
-			if(!this.helper.parents('body').length) this.helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
-			
-			
-			//Find out the next positioned parent
-			this.offsetParent = (function(cp) {
-				while(cp) {
-					if(cp.style && (/(absolute|relative|fixed)/).test($.css(cp,'position'))) return $(cp);
-					cp = cp.parentNode ? cp.parentNode : null;
-				}; return $("body");		
-			})(this.helper[0].parentNode);
-			
-			//Prepare variables for position generation
-			this.elementOffset = this.element.offset();
-			this.offsetParentOffset = this.offsetParent.offset();
-			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
-			this._pageX = e.pageX; this._pageY = e.pageY;
-			this.clickOffset = { left: e.pageX - this.elementOffset.left, top: e.pageY - this.elementOffset.top };
-			var r = this.helper.css('position') == 'relative';
-
-			//Generate the original position
-			this.originalPosition = {
-				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
-				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
-			};
-			
-			//If we have a fixed element, we must subtract the scroll offset again
-			if(this.element.css('position') == 'fixed') {
-				this.originalPosition.top -= this.offsetParent[0] == document.body ? $(document).scrollTop() : this.offsetParent[0].scrollTop;
-				this.originalPosition.left -= this.offsetParent[0] == document.body ? $(document).scrollLeft() : this.offsetParent[0].scrollLeft;
-			}
-			
-			//Generate a flexible offset that will later be subtracted from e.pageX/Y
-			this.offset = {left: e.pageX - this.originalPosition.left, top: e.pageY - this.originalPosition.top };
-			
-			//Substract margins
-			if(this.element[0] != this.helper[0]) {
-				this.offset.left += parseInt(this.element.css('marginLeft'),10) || 0;
-				this.offset.top += parseInt(this.element.css('marginTop'),10) || 0;
-			}
-			
-			//Call plugins and callbacks
-			this.propagate("start", e);
-
-			this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };
-			if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e);
-			
-			//If we have something in cursorAt, we'll use it
-			if(o.cursorAt) {
-				if(o.cursorAt.top != undefined || o.cursorAt.bottom != undefined) {
-					this.offset.top -= this.clickOffset.top - (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
-					this.clickOffset.top = (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
-				}
-				if(o.cursorAt.left != undefined || o.cursorAt.right != undefined) {
-					this.offset.left -= this.clickOffset.left - (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
-					this.clickOffset.left = (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
-				}
-			}
-
-			return false;
-
-		},
-		clear: function() {
-			if($.ui.ddmanager) $.ui.ddmanager.current = null;
-			this.helper = null;
-		},
-		stop: function(e) {
-
-			//If we are using droppables, inform the manager about the drop
-			if ($.ui.ddmanager && !this.options.dropBehaviour)
-				$.ui.ddmanager.drop(this, e);
-				
-			//Call plugins and trigger callbacks
-			this.propagate("stop", e);
-			
-			if(this.cancelHelperRemoval) return false;			
-			if(this.options.helper != 'original') this.helper.remove();
-			this.clear();
-
-			return false;
-		},
-		drag: function(e) {
-
-			//Compute the helpers position
-			this.position = { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left };
-			this.positionAbs = { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top };
-
-			//Call plugins and callbacks
-			this.checkConstrains();			
-			this.position = this.propagate("drag", e) || this.position;
-			this.checkConstrains();
-			
-			$(this.helper).css({ left: this.position.left+'px', top: this.position.top+'px' }); // Stick the helper to the cursor
-			if($.ui.ddmanager) $.ui.ddmanager.drag(this, e);
-			return false;
-			
-		}
-	});
-	
-/*
- * Draggable Extensions
- */
-	 
-	$.ui.plugin.add("draggable", "cursor", {
-		start: function(e, ui) {
-			var t = $('body');
-			if (t.css("cursor")) ui.options._cursor = t.css("cursor");
-			t.css("cursor", ui.options.cursor);
-		},
-		stop: function(e, ui) {
-			if (ui.options._cursor) $('body').css("cursor", ui.options._cursor);
-		}
-	});
-
-	$.ui.plugin.add("draggable", "zIndex", {
-		start: function(e, ui) {
-			var t = $(ui.helper);
-			if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex");
-			t.css('zIndex', ui.options.zIndex);
-		},
-		stop: function(e, ui) {
-			if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex);
-		}
-	});
-
-	$.ui.plugin.add("draggable", "opacity", {
-		start: function(e, ui) {
-			var t = $(ui.helper);
-			if(t.css("opacity")) ui.options._opacity = t.css("opacity");
-			t.css('opacity', ui.options.opacity);
-		},
-		stop: function(e, ui) {
-			if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity);
-		}
-	});
-
-
-	$.ui.plugin.add("draggable", "revert", {
-		stop: function(e, ui) {
-			var self = ui.instance, helper = $(self.helper);
-			self.cancelHelperRemoval = true;
-			
-			$(ui.helper).animate({ left: self.originalPosition.left, top: self.originalPosition.top }, parseInt(ui.options.revert, 10) || 500, function() {
-				if(ui.options.helper != 'original') helper.remove();
-				if (!helper) self.clear();
-			});
-		}
-	});
-
-	$.ui.plugin.add("draggable", "iframeFix", {
-		start: function(e, ui) {
-
-			var o = ui.options;
-			if(ui.instance.slowMode) return; // Make clones on top of iframes (only if we are not in slowMode)
-			
-			if(o.iframeFix.constructor == Array) {
-				for(var i=0;i<o.iframeFix.length;i++) {
-					var co = $(o.iframeFix[i]).offset({ border: false });
-					$('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width", $(o.iframeFix[i])[0].offsetWidth+"px").css("height", $(o.iframeFix[i])[0].offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
-				}		
-			} else {
-				$("iframe").each(function() {					
-					var co = $(this).offset({ border: false });
-					$('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width", this.offsetWidth+"px").css("height", this.offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
-				});							
-			}
-
-		},
-		stop: function(e, ui) {
-			if(ui.options.iframeFix) $("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers	
-		}
-	});
-	
-	$.ui.plugin.add("draggable", "containment", {
-		start: function(e, ui) {
-
-			var o = ui.options;
-			var self = ui.instance;
-			if((o.containment.left != undefined || o.containment.constructor == Array) && !o._containment) return;
-			if(!o._containment) o._containment = o.containment;
-
-			if(o._containment == 'parent') o._containment = this[0].parentNode;
-			if(o._containment == 'document') {
-				o.containment = [
-					0,
-					0,
-					$(document).width(),
-					($(document).height() || document.body.parentNode.scrollHeight)
-				];
-			} else { //I'm a node, so compute top/left/right/bottom
-
-				var ce = $(o._containment)[0];
-				var co = $(o._containment).offset();
-
-				o.containment = [
-					co.left,
-					co.top,
-					co.left+(ce.offsetWidth || ce.scrollWidth),
-					co.top+(ce.offsetHeight || ce.scrollHeight)
-				];
-			}
-			
-			var c = o.containment;
-			ui.instance.setContrains(
-				c[0] - (self.offset.left - self.clickOffset.left), //min left
-				c[2] - (self.offset.left - self.clickOffset.left), //max left
-				c[1] - (self.offset.top - self.clickOffset.top), //min top
-				c[3] - (self.offset.top - self.clickOffset.top) //max top
-			);
-
-		}
-	});
-
-	$.ui.plugin.add("draggable", "grid", {
-		drag: function(e, ui) {
-			var o = ui.options;
-			var newLeft = ui.instance.originalPosition.left + Math.round((e.pageX - ui.instance._pageX) / o.grid[0]) * o.grid[0];
-			var newTop = ui.instance.originalPosition.top + Math.round((e.pageY - ui.instance._pageY) / o.grid[1]) * o.grid[1];
-			
-			ui.instance.position.left = newLeft;
-			ui.instance.position.top = newTop;
-
-		}
-	});
-
-	$.ui.plugin.add("draggable", "axis", {
-		drag: function(e, ui) {
-			var o = ui.options;
-			if(o.constraint) o.axis = o.constraint; //Legacy check
-			switch (o.axis) {
-				case 'x' : ui.instance.position.top = ui.instance.originalPosition.top; break;
-				case 'y' : ui.instance.position.left = ui.instance.originalPosition.left; break;
-			}
-		}
-	});
-
-	$.ui.plugin.add("draggable", "scroll", {
-		start: function(e, ui) {
-			var o = ui.options;
-			o.scrollSensitivity	= o.scrollSensitivity || 20;
-			o.scrollSpeed		= o.scrollSpeed || 20;
-
-			ui.instance.overflowY = function(el) {
-				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode);
-				return $(document);
-			}(this);
-			ui.instance.overflowX = function(el) {
-				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode);
-				return $(document);
-			}(this);
-		},
-		drag: function(e, ui) {
-			
-			var o = ui.options;
-			var i = ui.instance;
-
-			if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') {
-				if(i.overflowY[0].offsetHeight - (ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
-					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed;
-				if((ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
-					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;				
-			} else {
-				//$(document.body).append('<p>'+(e.pageY - $(document).scrollTop())+'</p>');
-				if(e.pageY - $(document).scrollTop() < o.scrollSensitivity)
-					$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
-				if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity)
-					$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
-			}
-			
-			if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') {
-				if(i.overflowX[0].offsetWidth - (ui.position.left - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
-					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed;
-				if((ui.position.top - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
-					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;				
-			} else {
-				if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity)
-					$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
-				if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
-					$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
-			}
-			
-			ui.instance.recallOffset(e);
-
-		}
-	});
-	
-	$.ui.plugin.add("draggable", "snap", {
-		start: function(e, ui) {
-			
-			ui.instance.snapElements = [];
-			$(ui.options.snap === true ? '.ui-draggable' : ui.options.snap).each(function() {
-				var $t = $(this); var $o = $t.offset();
-				if(this != ui.instance.element[0]) ui.instance.snapElements.push({
-					item: this,
-					width: $t.outerWidth(),
-					height: $t.outerHeight(),
-					top: $o.top,
-					left: $o.left
-				});
-			});
-			
-		},
-		drag: function(e, ui) {
-
-			var d = ui.options.snapTolerance || 20;
-			var x1 = ui.absolutePosition.left, x2 = x1 + ui.instance.helperProportions.width,
-			    y1 = ui.absolutePosition.top, y2 = y1 + ui.instance.helperProportions.height;
-
-			for (var i = ui.instance.snapElements.length - 1; i >= 0; i--){
-
-				var l = ui.instance.snapElements[i].left, r = l + ui.instance.snapElements[i].width, 
-				    t = ui.instance.snapElements[i].top,  b = t + ui.instance.snapElements[i].height;
-
-				//Yes, I know, this is insane ;)
-				if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) continue;
-
-				if(ui.options.snapMode != 'inner') {
-					var ts = Math.abs(t - y2) <= 20;
-					var bs = Math.abs(b - y1) <= 20;
-					var ls = Math.abs(l - x2) <= 20;
-					var rs = Math.abs(r - x1) <= 20;
-					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
-					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top;
-					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
-					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left;
-				}
-				
-				if(ui.options.snapMode != 'outer') {
-					var ts = Math.abs(t - y1) <= 20;
-					var bs = Math.abs(b - y2) <= 20;
-					var ls = Math.abs(l - x1) <= 20;
-					var rs = Math.abs(r - x2) <= 20;
-					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top;
-					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
-					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left;
-					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
-				}
-
-			};
-		}
-	});
-	
-	$.ui.plugin.add("draggable", "connectToSortable", {
-		start: function(e,ui) {
-			ui.instance.sortable = $.data($(ui.options.connectToSortable)[0], 'sortable');
-			ui.instance.sortableOffset = ui.instance.sortable.element.offset();
-			ui.instance.sortableOuterWidth = ui.instance.sortable.element.outerWidth();
-			ui.instance.sortableOuterHeight = ui.instance.sortable.element.outerHeight();
-			if(ui.instance.sortable.options.revert) ui.instance.sortable.shouldRevert = true;
-		},
-		stop: function(e,ui) {
-			//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
-			var inst = ui.instance.sortable;
-			if(inst.isOver) {
-				inst.isOver = 0;
-				ui.instance.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
-				inst.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
-				if(inst.shouldRevert) inst.options.revert = true; //revert here
-				inst.stop(e);
-				inst.options.helper = "original";
-			}
-		},
-		drag: function(e,ui) {
-			//This is handy: We reuse the intersectsWith method for checking if the current draggable helper
-			//intersects with the sortable container
-			var inst = ui.instance.sortable;
-			ui.instance.position.absolute = ui.absolutePosition; //Sorry, this is an ugly API fix
-			
-			if(inst.intersectsWith.call(ui.instance, {
-				left: ui.instance.sortableOffset.left, top: ui.instance.sortableOffset.top,
-				width: ui.instance.sortableOuterWidth, height: ui.instance.sortableOuterHeight
-			})) {
-				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
-				if(!inst.isOver) {
-					inst.isOver = 1;
-					
-					//Cache the width/height of the new helper
-					var height = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerHeight() : $(inst.options.items, inst.element).innerHeight();
-					var width = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerWidth() : $(inst.options.items, inst.element).innerWidth();
-
-					//Now we fake the start of dragging for the sortable instance,
-					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
-					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
-					inst.currentItem = $(this).clone().appendTo(inst.element);
-					inst.options.helper = function() { return ui.helper[0]; };
-					inst.start(e);
-					
-					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
-					inst.clickOffset.top = ui.instance.clickOffset.top;
-					inst.clickOffset.left = ui.instance.clickOffset.left;
-					inst.offset.left -= ui.absolutePosition.left - inst.position.absolute.left;
-					inst.offset.top -= ui.absolutePosition.top - inst.position.absolute.top;
-					
-					//Do a nifty little helper animation: Animate it to the portlet's size (just takes the first 'li' element in the sortable now)
-					inst.helperProportions = { width:  width, height: height}; //We have to reset the helper proportions, because we are doing our animation there
-					ui.helper.animate({ height: height, width: width}, 500);
-					ui.instance.propagate("toSortable", e);
-				
-				}
-
-				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
-				if(inst.currentItem) inst.drag(e);
-				
-			} else {
-				
-				//If it doesn't intersect with the sortable, and it intersected before,
-				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
-				if(inst.isOver) {
-					inst.isOver = 0;
-					inst.cancelHelperRemoval = true;
-					inst.options.revert = false; //No revert here
-					inst.stop(e);
-					inst.options.helper = "original";
-					
-					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
-					inst.currentItem.remove();
-					inst.placeholder.remove();
-					
-					ui.helper.animate({ height: this.innerHeight(), width: this.innerWidth() }, 500);
-					ui.instance.propagate("fromSortable", e);
-				}
-				
-			};
-		}
-	})
-
-	//TODO: wrapHelper
-
-})(jQuery);
-
diff --git a/moksha/widgetbrowser/widgetbrowser/static/ui.resizable.js b/moksha/widgetbrowser/widgetbrowser/static/ui.resizable.js
deleted file mode 100644
index 409195e..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/ui.resizable.js
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * jQuery UI Resizable
- *
- * Copyright (c) 2008 Paul Bakaus
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- * 
- * http://docs.jquery.com/UI/Resizables
- *
- * Depends:
- *   ui.base.js
- *
- * Revision: $Id: ui.resizable.js 5205 2008-04-06 16:12:50Z braeker $
- */
-;(function($) {
-	
-	$.fn.extend({
-		resizable: function(options, data) {
-			var args = Array.prototype.slice.call(arguments, 1);
-			
-			return this.each(function() {
-				if (typeof options == "string") {
-					var resize = $.data(this, "resizable");
-					if (resize) resize[options].apply(resize, args);
-	
-				} else if(!$(this).is(".ui-resizable"))
-					new $.ui.resizable(this, options);
-			});
-		}
-	});
-
-	$.ui.resizable = function(element, options) {
-		//Initialize needed constants
-		var self = this;
-		
-		this.element = $(element);
-		
-		$.data(element, "resizable", this);
-		
-		// simulate .ui-resizable { position: relative; }
-		var elpos = this.element.css('position');
-		this.element.addClass("ui-resizable").css({ position: /static/.test(elpos) ? 'relative' : elpos });
-		
-		//Prepare the passed options
-		this.options = $.extend({
-			preventDefault: true,
-			transparent: false,
-			minWidth: 10,
-			minHeight: 10,
-			aspectRatio: false,
-			disableSelection: true,
-			preserveCursor: true,
-			autohide: false,
-			knobHandles: false
-		}, options);
-		
-		this.options._aspectRatio = !!(this.options.aspectRatio);
-		
-		// force proxy if helper is enabled
-		this.options.proxy = this.options.proxy || this.options.ghost ? 'proxy' : null; 
-		
-		// force proxy if animation is enabled
-		this.options.proxy = this.options.proxy || this.options.animate ? 'proxy' : null; 
-		
-		// if knobHandles equals true set to ui-resizable-knob-handle
-		this.options.knobHandles = this.options.knobHandles === true ? 'ui-resizable-knob-handle' : this.options.knobHandles;
-		
-		$(element).bind("setData.resizable", function(event, key, value){
-			self.options[key] = value;
-		}).bind("getData.resizable", function(event, key){
-			return self.options[key];
-		});
-	
-		var o = this.options;
-	
-		//Default Theme
-		var aBorder = '1px solid #DEDEDE';
-	
-		o.defaultTheme = {
-			'ui-resizable': { display: 'block' },
-			'ui-resizable-handle': { position: 'absolute', background: '#F2F2F2', fontSize: '0.1px' },
-			'ui-resizable-n': { cursor: 'n-resize', height: '4px', left: '0px', right: '0px', borderTop: aBorder },
-			'ui-resizable-s': { cursor: 's-resize', height: '4px', left: '0px', right: '0px', borderBottom: aBorder },
-			'ui-resizable-e': { cursor: 'e-resize', width: '4px', top: '0px', bottom: '0px', borderRight: aBorder },
-			'ui-resizable-w': { cursor: 'w-resize', width: '4px', top: '0px', bottom: '0px', borderLeft: aBorder },
-			'ui-resizable-se': { cursor: 'se-resize', width: '4px', height: '4px', borderRight: aBorder, borderBottom: aBorder },
-			'ui-resizable-sw': { cursor: 'sw-resize', width: '4px', height: '4px', borderBottom: aBorder, borderLeft: aBorder },
-			'ui-resizable-ne': { cursor: 'ne-resize', width: '4px', height: '4px', borderRight: aBorder, borderTop: aBorder },
-			'ui-resizable-nw': { cursor: 'nw-resize', width: '4px', height: '4px', borderLeft: aBorder, borderTop: aBorder }
-		};
-		
-		o.knobTheme = {
-			'ui-resizable-handle': { background: '#F2F2F2', border: '1px solid #808080', height: '8px', width: '8px' },
-			'ui-resizable-n': { cursor: 'n-resize', top: '-4px', left: '45%' },
-			'ui-resizable-s': { cursor: 's-resize', bottom: '-4px', left: '45%' },
-			'ui-resizable-e': { cursor: 'e-resize', right: '-4px', top: '45%' },
-			'ui-resizable-w': { cursor: 'w-resize', left: '-4px', top: '45%' },
-			'ui-resizable-se': { cursor: 'se-resize', right: '-4px', bottom: '-4px' },
-			'ui-resizable-sw': { cursor: 'sw-resize', left: '-4px', bottom: '-4px' },
-			'ui-resizable-nw': { cursor: 'nw-resize', left: '-4px', top: '-4px' },
-			'ui-resizable-ne': { cursor: 'ne-resize', right: '-4px', top: '-4px' }
-		};
-	
-		//Position the node
-		if(!o.proxy && (this.element.css('position') == 'static' || this.element.css('position') === ''))
-			this.element.css('position', 'relative');
-	
-		o._nodeName = element.nodeName;
-	
-		//Wrap the element if it cannot hold child nodes
-		if(o._nodeName.match(/textarea|input|select|button|img/i)) {
-			var el = this.element;
-			
-			//Opera fixing relative position
-			if (/relative/.test(el.css('position')) && $.browser.opera)
-				el.css({ position: 'relative', top: 'auto', left: 'auto' });
-			
-			//Create a wrapper element and set the wrapper to the new current internal element
-			el.wrap(
-				$('<div class="ui-wrapper"	style="overflow: hidden;"></div>').css( {
-					position: el.css('position'),
-					width: el.outerWidth(),
-					height: el.outerHeight(),
-					top: el.css('top'),
-					left: el.css('left')
-				})
-			);
-			
-			var oel = this.element; element = element.parentNode; this.element = $(element);
-	
-			//Move margins to the wrapper
-			this.element.css({ marginLeft: oel.css("marginLeft"), marginTop: oel.css("marginTop"),
-				marginRight: oel.css("marginRight"), marginBottom: oel.css("marginBottom")
-			});
-	
-			oel.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
-	
-			//Prevent Safari textarea resize
-			if ($.browser.safari && o.preventDefault) oel.css('resize', 'none');
-	
-			o.proportionallyResize = oel.css({ position: 'static', zoom: 1, display: 'block' });
-			
-			// avoid IE jump
-			this.element.css({ margin: oel.css('margin') });
-			
-			// fix handlers offset
-			this._proportionallyResize();
-		}
-	
-		if(!o.handles) o.handles = !$('.ui-resizable-handle', element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' };
-		if(o.handles.constructor == String) {
-	
-			if(o.handles == 'all') o.handles = 'n,e,s,w,se,sw,ne,nw';
-	
-			var n = o.handles.split(","); o.handles = {};
-	
-			o.zIndex = o.zIndex || 1000;
-			
-			// insertions are applied when don't have theme loaded
-			var insertionsDefault = {
-				handle: 'position: absolute; display: none; overflow:hidden;',
-				n: 'top: 0pt; width:100%;',
-				e: 'right: 0pt; height:100%;',
-				s: 'bottom: 0pt; width:100%;',
-				w: 'left: 0pt; height:100%;',
-				se: 'bottom: 0pt; right: 0px;',
-				sw: 'bottom: 0pt; left: 0px;',
-				ne: 'top: 0pt; right: 0px;',
-				nw: 'top: 0pt; left: 0px;'
-			};
-	
-			for(var i = 0; i < n.length; i++) {
-				var handle = jQuery.trim(n[i]), dt = o.defaultTheme, hname = 'ui-resizable-'+handle, loadDefault = !$.ui.css(hname) && !o.knobHandles, userKnobClass = $.ui.css('ui-resizable-knob-handle'), 
-							allDefTheme = $.extend(dt[hname], dt['ui-resizable-handle']), allKnobTheme = $.extend(o.knobTheme[hname], !userKnobClass ? o.knobTheme['ui-resizable-handle'] : {});
-				
-				// increase zIndex of sw, se, ne, nw axis
-				var applyZIndex = /sw|se|ne|nw/.test(handle) ? { zIndex: ++o.zIndex } : {};
-				
-				var defCss = (loadDefault ? insertionsDefault[handle] : ''), 
-					axis = $(['<div class="ui-resizable-handle ', hname, '" style="', defCss, insertionsDefault.handle, '"></div>'].join('')).css( applyZIndex );
-				o.handles[handle] = '.ui-resizable-'+handle;
-				
-				this.element.append(
-					//Theme detection, if not loaded, load o.defaultTheme
-					axis.css( loadDefault ? allDefTheme : {} )
-						// Load the knobHandle css, fix width, height, top, left...
-						.css( o.knobHandles ? allKnobTheme : {} ).addClass(o.knobHandles ? 'ui-resizable-knob-handle' : '').addClass(o.knobHandles)
-				);
-			}
-			
-			if (o.knobHandles) this.element.addClass('ui-resizable-knob').css( !$.ui.css('ui-resizable-knob') ? { /*border: '1px #fff dashed'*/ } : {} );
-		}
-	
-		this._renderAxis = function(target) {
-			target = target || this.element;
-	
-			for(var i in o.handles) {
-				if(o.handles[i].constructor == String) 
-					o.handles[i] = $(o.handles[i], element).show();
-	
-				if (o.transparent)
-					o.handles[i].css({opacity:0});
-	
-				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
-				if (this.element.is('.ui-wrapper') && 
-					o._nodeName.match(/textarea|input|select|button/i)) {
-	
-					var axis = $(o.handles[i], element), padWrapper = 0;
-	
-					//Checking the correct pad and border
-					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
-	
-					//The padding type i have to apply...
-					var padPos = [ 'padding', 
-						/ne|nw|n/.test(i) ? 'Top' :
-						/se|sw|s/.test(i) ? 'Bottom' : 
-						/^e$/.test(i) ? 'Right' : 'Left' ].join(""); 
-	
-					if (!o.transparent)
-						target.css(padPos, padWrapper);
-	
-					this._proportionallyResize();
-				}
-				if(!$(o.handles[i]).length) continue;
-			}
-		};
-			
-		this._renderAxis(this.element);
-		o._handles = $('.ui-resizable-handle', self.element);
-		
-		if (o.disableSelection)
-			o._handles.each(function(i, e) { $.ui.disableSelection(e); });
-		
-		//Matching axis name
-		o._handles.mouseover(function() {
-			if (!o.resizing) {
-				if (this.className) 
-					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
-				//Axis, default = se
-				self.axis = o.axis = axis && axis[1] ? axis[1] : 'se';
-			}
-		});
-				
-		//If we want to auto hide the elements
-		if (o.autohide) {
-			o._handles.hide();
-			$(self.element).addClass("ui-resizable-autohide").hover(function() {
-				$(this).removeClass("ui-resizable-autohide");
-				o._handles.show();
-			},
-			function(){
-				if (!o.resizing) {
-					$(this).addClass("ui-resizable-autohide");
-					o._handles.hide();
-				}
-			});
-		}
-	
-		//Initialize mouse events for interaction
-		this.element.mouseInteraction({
-			executor: this,
-			delay: 0,
-			distance: 0,
-			dragPrevention: ['input','textarea','button','select','option'],
-			start: this.start,
-			stop: this.stop,
-			drag: this.drag,
-			condition: function(e) {
-				if(this.disabled) return false;
-				for(var i in this.options.handles) {
-					if($(this.options.handles[i])[0] == e.target) return true;
-				}
-				return false;
-			}
-		});
-	};
-
-	$.extend($.ui.resizable.prototype, {
-		plugins: {},
-		ui: function() {
-			return {
-				instance: this,
-				axis: this.options.axis,
-				options: this.options
-			};
-		},
-		_renderProxy: function() {
-			var el = this.element, o = this.options;
-			this.elementOffset = el.offset();
-	
-			if(o.proxy) {
-				this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
-	
-				// fix ie6 offset
-				var ie6 = $.browser.msie && $.browser.version  < 7, ie6offset = (ie6 ? 1 : 0),
-				pxyoffset = ( ie6 ? 2 : -1 );
-	
-				this.helper.addClass(o.proxy).css({
-					width: el.outerWidth() + pxyoffset,
-					height: el.outerHeight() + pxyoffset,
-					position: 'absolute',
-					left: this.elementOffset.left - ie6offset +'px',
-					top: this.elementOffset.top - ie6offset +'px',
-					zIndex: ++o.zIndex
-				});
-				
-				this.helper.appendTo("body");
-	
-				if (o.disableSelection)
-					$.ui.disableSelection(this.helper.get(0));
-	
-			} else {
-				this.helper = el; 
-			}
-		},
-		propagate: function(n,e) {
-			$.ui.plugin.call(this, n, [e, this.ui()]);
-			this.element.triggerHandler(n == "resize" ? n : ["resize", n].join(""), [e, this.ui()], this.options[n]);
-		},
-		destroy: function() {
-			var el = this.element, wrapped = el.children(".ui-resizable").get(0),
-			
-			_destroy = function(exp) {
-				$(exp).removeClass("ui-resizable ui-resizable-disabled")
-					.removeMouseInteraction().removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
-			};
-			
-			_destroy(el);
-			
-			if (el.is('.ui-wrapper') && wrapped) {
-		  		el.parent().append(
-					$(wrapped).css({
-			  		position: el.css('position'),
-			  		width: el.outerWidth(),
-			  		height: el.outerHeight(),
-			  		top: el.css('top'),
-			  		left: el.css('left')
-		  		})
-				).end().remove();
-				
-				_destroy(wrapped);
-	  		}
-		},
-		enable: function() {
-			this.element.removeClass("ui-resizable-disabled");
-			this.disabled = false;
-		},
-		disable: function() {
-			this.element.addClass("ui-resizable-disabled");
-			this.disabled = true;
-		},
-		start: function(e) {
-			var o = this.options, iniPos = this.element.position(), el = this.element, 
-				num = function(v) { return parseInt(v, 10) || 0; }, ie6 = $.browser.msie && $.browser.version < 7;
-			o.resizing = true;
-			o.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
-	
-			// bugfix #1749
-			if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
-				
-				// sOffset decides if document scrollOffset will be added to the top/left of the resizable element
-				var sOffset = $.browser.msie && !o.containment && (/absolute/).test(el.css('position')) && !(/relative/).test(el.parent().css('position'));
-				var dscrollt = sOffset ? o.documentScroll.top : 0, dscrolll = sOffset ? o.documentScroll.left : 0;
-				
-				el.css({ position: 'absolute', top: (iniPos.top + dscrollt), left: (iniPos.left + dscrolll) });
-			}
-			
-			//Opera fixing relative position
-			if (/relative/.test(el.css('position')) && $.browser.opera)
-				el.css({ position: 'relative', top: 'auto', left: 'auto' });
-	
-			this._renderProxy();
-	
-			var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
-			
-			//Store needed variables
-			this.offset = this.helper.offset();
-			this.position = { left: curleft, top: curtop };
-			this.size = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-			this.originalSize = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-			this.originalPosition = { left: curleft, top: curtop };
-			this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
-			this.originalMousePosition = { left: e.pageX, top: e.pageY };
-			
-			//Aspect Ratio
-			o.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.height / this.originalSize.width)||1);
-	
-			if (o.preserveCursor)
-				$('body').css('cursor', this.axis + '-resize');
-				
-			this.propagate("start", e); 	
-			return false;
-		},
-		stop: function(e) {
-			this.options.resizing = false;
-			var o = this.options, num = function(v) { return parseInt(v, 10) || 0; }, self = this;
-	
-			if(o.proxy) {
-				var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
-							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
-								soffsetw = ista ? 0 : self.sizeDiff.width;
-			
-				var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
-						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
-							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top);
-				
-				if (!o.animate)
-					this.element.css($.extend(style, { top: top, left: left }));
-				
-				if (o.proxy && !o.animate) this._proportionallyResize();
-				this.helper.remove();
-			}
-
-			if (o.preserveCursor)
-			$('body').css('cursor', 'auto');
-	
-			this.propagate("stop", e);	
-			return false;
-		},
-		drag: function(e) {
-			//Increase performance, avoid regex
-			var el = this.helper, o = this.options, props = {},
-				self = this, smp = this.originalMousePosition, a = this.axis;
-
-			var dx = (e.pageX-smp.left)||0, dy = (e.pageY-smp.top)||0;
-			var trigger = this.change[a];
-			if (!trigger) return false;
-		 
-			// Calculate the attrs that will be change
-			var data = trigger.apply(this, [e, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
-		 
-			if (o._aspectRatio || e.shiftKey)
-				data = this._updateRatio(data, e);
-			
-			data = this._respectSize(data, e);
-			
-			this.propagate("resize", e);
-			
-			el.css({
-				top: this.position.top + "px", left: this.position.left + "px", 
-				width: this.size.width + "px", height: this.size.height + "px"
-			});
-			
-			if (!o.proxy && o.proportionallyResize)
-				this._proportionallyResize();
-			
-			this._updateCache(data);
-			
-			return false;
-		},
-		
-		_updateCache: function(data) {
-			var o = this.options;
-			this.offset = this.helper.offset();
-			if (data.left) this.position.left = data.left;
-			if (data.top) this.position.top = data.top;
-			if (data.height) this.size.height = data.height;
-			if (data.width) this.size.width = data.width;
-		},
-		
-		_updateRatio: function(data, e) {
-			var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
-			
-			if (data.height) data.width = Math.round(csize.height / o.aspectRatio);
-			else if (data.width) data.height = Math.round(csize.width * o.aspectRatio);
-			
-			if (a == 'sw') {
-				data.left = cpos.left + (csize.width - data.width);
-				data.top = null;
-			}
-			if (a == 'nw') { 
-				data.top = cpos.top + (csize.height - data.height);
-				data.left = cpos.left + (csize.width - data.width);
-			}
-			
-			return data;
-		},
-		
-		_respectSize: function(data, e) {
-			
-			var el = this.helper, o = this.options, pRatio = o._aspectRatio || e.shiftKey,  a = this.axis, 
-					ismaxw = data.width && o.maxWidth && o.maxWidth < data.width, ismaxh = data.height && o.maxHeight && o.maxHeight < data.height,
-						isminw = data.width && o.minWidth && o.minWidth > data.width, isminh = data.height && o.minHeight && o.minHeight > data.height;
-			
-			if (isminw) data.width = o.minWidth;
-			if (isminh) data.height = o.minHeight;
-			if (ismaxw) data.width = o.maxWidth;
-			if (ismaxh) data.height = o.maxHeight;
-			
-			var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
-			var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
-			
-			if (isminw && cw) data.left = dw - o.minWidth;
-			if (ismaxw && cw) data.left = dw - o.maxWidth;
-			if (isminh && ch)	data.top = dh - o.minHeight;
-			if (ismaxh && ch)	data.top = dh - o.maxHeight;
-			
-			// fixing jump error on top/left - bug #2330
-			var isNotwh = !data.width && !data.height;
-			if (isNotwh && !data.left && data.top) data.top = null;
-			else if (isNotwh && !data.top && data.left) data.left = null;
-			
-			return data;
-		},
-		
-		_proportionallyResize: function() {
-			var o = this.options;
-			if (!o.proportionallyResize) return;
-			var prel = o.proportionallyResize, el = this.helper || this.element;
-		 
-			if (!o.borderDif) {
-				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
-					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
-				 
-				o.borderDif = $.map(b, function(v, i) {
-					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
-					return border + padding; 
-				});
-			}
-			prel.css({
-				height: (el.height() - o.borderDif[0] - o.borderDif[2]) + "px",
-				width: (el.width() - o.borderDif[1] - o.borderDif[3]) + "px"
-			});
-		},
-		
-		change: {
-			e: function(e, dx, dy) {
-				return { width: this.originalSize.width + dx };
-			},
-			w: function(e, dx, dy) {
-				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-				return { left: sp.left + dx, width: cs.width - dx };
-			},
-			n: function(e, dx, dy) {
-				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-				return { top: sp.top + dy, height: cs.height - dy };
-			},
-			s: function(e, dx, dy) {
-				return { height: this.originalSize.height + dy };
-			},
-			se: function(e, dx, dy) {
-				return $.extend(this.change.s.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
-			},
-			sw: function(e, dx, dy) {
-				return $.extend(this.change.s.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
-			},
-			ne: function(e, dx, dy) {
-				return $.extend(this.change.n.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
-			},
-			nw: function(e, dx, dy) {
-				return $.extend(this.change.n.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
-			}
-		}
-	});
-
-/*
- * Resizable Extensions
- */
-
-	$.ui.plugin.add("resizable", "containment", {
-		
-		start: function(e, ui) {
-			var o = ui.options, self = ui.instance, el = self.element;
-			var oc = o.containment,	ce = (oc instanceof jQuery) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
-			if (!ce) return;
-			
-			if (/document/.test(oc) || oc == document) {
-				self.containerOffset = { left: 0, top: 0 };
-
-				self.parentData = { 
-					element: $(document), left: 0, top: 0, width: $(document).width(),
-					height: $(document).height() || document.body.parentNode.scrollHeight
-				};
-			}
-			
-			// i'm a node, so compute top, left, right, bottom
-			else{
-				self.containerOffset = $(ce).offset(), self.containerSize = { height: $(ce).innerHeight(), width: $(ce).innerWidth() };
-			
-				var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width, 
-							width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
-			
-				self.parentData = { 
-					element: ce, left: co.left, top: co.top, width: width, height: height
-				};
-			}
-		},
-		
-		resize: function(e, ui) {
-			var o = ui.options, self = ui.instance, ps = self.containerSize, 
-						co = self.containerOffset, cs = self.size, cp = self.position,
-							pRatio = o._aspectRatio || e.shiftKey;
-			
-			if (cp.left < (o.proxy ? co.left : 0)) {
-				self.size.width = self.size.width + (o.proxy ? (self.position.left - co.left) : self.position.left);
-				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
-				self.position.left = o.proxy ? co.left : 0;
-			}
-			
-			if (cp.top < (o.proxy ? co.top : 0)) {
-				self.size.height = self.size.height + (o.proxy ? (self.position.top - co.top) : self.position.top);
-				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
-				self.position.top = o.proxy ? co.top : 0;
-			}
-			
-			var woset = (o.proxy ? self.offset.left - co.left : self.position.left) + self.sizeDiff.width, 
-						hoset = (o.proxy ? self.offset.top - co.top : self.position.top) + self.sizeDiff.height;
-			
-			if (woset + self.size.width >= self.parentData.width) {
-				self.size.width = self.parentData.width - woset;
-				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
-			}
-			
-			if (hoset + self.size.height >= self.parentData.height) {
-				self.size.height = self.parentData.height - hoset;
-				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
-			}
-		}
-	});
-	
-	$.ui.plugin.add("resizable", "grid", {
-		
-		resize: function(e, ui) {
-			var o = ui.options, self =  ui.instance, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || e.shiftKey;
-			o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
-			var ox = Math.round((cs.width - os.width) / o.grid[0]) * o.grid[0], oy = Math.round((cs.height - os.height) / o.grid[1]) * o.grid[1];
-			
-			if (/^(se|s|e)$/.test(a)) {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-			}
-			else if (/^(ne)$/.test(a)) {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-				self.position.top = op.top - oy;
-			}
-			else if (/^(sw)$/.test(a)) {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-				self.position.left = op.left - ox;
-			}
-			else {
-				self.size.width = os.width + ox;
-				self.size.height = os.height + oy;
-				self.position.top = op.top - oy;
-				self.position.left = op.left - ox;
-			}
-		}
-		
-	});
-	
-	$.ui.plugin.add("resizable", "animate", {
-		
-		stop: function(e, ui) {
-			var o = ui.options, self =  ui.instance;
-
-			var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
-							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
-								soffsetw = ista ? 0 : self.sizeDiff.width;
-			
-			var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
-						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
-							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top); 
-			
-			self.element.animate(
-				$.extend(style, { top: top, left: left }),
-				{ 
-					duration: o.animateDuration || "slow", 
-					easing: o.animateEasing || "swing", 
-					step: function() {
-						if (pr) pr.css({ width: self.element.css('width'), height: self.element.css('height') });
-					}
-				}
-			);
-		}
-		
-	});
-	
-	$.ui.plugin.add("resizable", "ghost", {
-		
-		start: function(e, ui) {
-			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize, cs = self.size;
-			
-			if (!pr) self.ghost = self.element.clone();
-			else self.ghost = pr.clone();
-			
-			self.ghost.css(
-				{ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }
-			)
-			.addClass('ui-resizable-ghost').addClass(typeof o.ghost == 'string' ? o.ghost : '');
-			
-			self.ghost.appendTo(self.helper);
-			
-		},
-		
-		resize: function(e, ui){
-			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
-			
-			if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
-			
-		},
-		
-		stop: function(e, ui){
-			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
-			if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
-		}
-		
-	});
-
-})(jQuery);
diff --git a/moksha/widgetbrowser/widgetbrowser/static/ui.tabs.css b/moksha/widgetbrowser/widgetbrowser/static/ui.tabs.css
deleted file mode 100644
index 0eabf94..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/ui.tabs.css
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Caution! Ensure accessibility in print and other media types... */
- at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
-    .ui-tabs-hide {
-        display: none;
-    }
-}
-
-/* Hide useless elements in print layouts... */
- at media print {
-    .ui-tabs-nav {
-        display: none;
-    }
-}
-
-/* Skin */
-.ui-tabs-nav {
-    list-style: none;
-    margin: 0 !important;
-    padding: 0 0 0 4px;
-}
-.ui-tabs-nav li {
-    list-style-image: none !important;
-    margin: 0 !important;
-    padding: 0 0 0 4px;
-}
-
-.ui-tabs-panel {
-    border-top: #94ADA7 solid 1px;
-    padding-top: 5px;
-    clear: left;
-}
-
-/* IE6 hack */
-* html .ui-tabs-panel {
-    margin-top: -1.2em;
-}
-
-.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
-    display: block;
-    clear: both;
-    content: " ";
-}
-.ui-tabs-nav li {
-    float: left;
-    margin: 0 0 0 1px;
-    min-width: 84px; /* be nice to Opera */
-}
-.ui-tabs-nav a, .ui-tabs-nav a span {
-    display: block;
-    padding: 0 10px;
-    background: url(tab.png) no-repeat;
-}
-.ui-tabs-nav a {
-    position: relative;
-    top: 1px;
-    z-index: 2;
-    padding-left: 0;
-    color: #27537a;
-    font-size: 12px;
-    font-weight: bold;
-    line-height: 1.2;
-    text-align: center;
-    text-decoration: none;
-    white-space: nowrap; /* required in IE 6 */    
-}
-.ui-tabs-nav .ui-tabs-selected a {
-    color: #000;
-}
-.ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active {
-    background-position: 100% -150px;
-    outline: 0; /* prevent dotted border in Firefox */
-}
-.ui-tabs-nav a, .ui-tabs-nav .ui-tabs-disabled a:hover, .ui-tabs-nav .ui-tabs-disabled a:focus, .ui-tabs-nav .ui-tabs-disabled a:active {
-    background-position: 100% -100px;
-}
-.ui-tabs-nav a span {
-    width: 64px; /* IE 6 treats width as min-width */
-    min-width: 64px;
-    height: 18px; /* IE 6 treats height as min-height */
-    min-height: 18px;
-    padding-top: 6px;
-    padding-right: 0;
-}
-*>.ui-tabs-nav a span { /* hide from IE 6 */
-    width: auto;
-    height: auto;
-}
-.ui-tabs-nav .ui-tabs-selected a span {
-    padding-top: 7px;
-}
-.ui-tabs-nav .ui-tabs-selected a span, .ui-tabs-nav a:hover span, .ui-tabs-nav a:focus span, .ui-tabs-nav a:active span {
-    background-position: 0 -50px;
-}
-.ui-tabs-nav a span, .ui-tabs-nav .ui-tabs-disabled a:hover span, .ui-tabs-nav .ui-tabs-disabled a:focus span, .ui-tabs-nav .ui-tabs-disabled a:active span {
-    background-position: 0 0;
-}
-.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited, .ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
-    cursor: text;
-}
-.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active { /* @ Opera, we need to be explicit again here now... */
-    cursor: pointer;
-}
-.ui-tabs-nav .ui-tabs-disabled {
-    opacity: .4;
-}
-.ui-tabs-container {
-    border-top: 1px solid #97a5b0;
-    padding: 1em 8px;
-    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
-}
-.ui-tabs-loading em {
-    padding: 0 0 0 20px;
-    background: url(loading.gif) no-repeat 0 50%;
-}
diff --git a/moksha/widgetbrowser/widgetbrowser/static/ui.tabs.js b/moksha/widgetbrowser/widgetbrowser/static/ui.tabs.js
deleted file mode 100644
index f595c10..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/ui.tabs.js
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * jQuery UI Tabs
- *
- * Copyright (c) 2007 Klaus Hartl (stilbuero.de)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * http://docs.jquery.com/UI/Tabs
- *
- * Depends:
- *   ui.base.js
- *
- * Revision: $Id: ui.tabs.js 5149 2008-03-31 10:51:18Z rdworth $
- */
-;(function($) {
-
-    // tabs API methods
-    $.fn.tabs = function() {
-        var method = typeof arguments[0] == 'string' && arguments[0];
-        var args = method && Array.prototype.slice.call(arguments, 1) || arguments;
-
-        return method == 'length' ?
-            $.data(this[0], 'tabs').$tabs.length :
-            this.each(function() {
-                if (method) {
-                    var tabs = $.data(this, 'tabs');
-                    if (tabs) tabs[method].apply(tabs, args);
-                } else
-                    new $.ui.tabs(this, args[0] || {});
-            });
-    };
-
-    // tabs class
-    $.ui.tabs = function(el, options) {
-        var self = this;
-        
-        this.options = $.extend({}, $.ui.tabs.defaults, options);
-        this.element = el;
-
-        // doesn't extend with null
-        if (options.selected === null)
-            this.options.selected = null;
-
-        this.options.event += '.tabs'; // namespace event
-
-        $(el).bind('setData.tabs', function(event, key, value) {
-            if ((/^selected/).test(key))
-                self.select(value);
-            else {
-                self.options[key] = value;
-                self.tabify();
-            }
-        }).bind('getData.tabs', function(event, key) {
-            return self.options[key];
-        });
-
-        // save instance for later
-        $.data(el, 'tabs', this);
-
-        // create tabs
-        this.tabify(true);
-    };
-    
-    $.ui.tabs.defaults = {
-        // basic setup
-        selected: 0,
-        unselect: false,
-        event: 'click',
-        disabled: [],
-        cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
-        // TODO history: false,
-
-        // Ajax
-        spinner: 'Loading&#8230;',
-        cache: false,
-        idPrefix: 'ui-tabs-',
-        ajaxOptions: {},
-
-        // animations
-        fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
-
-        // templates
-        tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>',
-        panelTemplate: '<div></div>',
-
-        // CSS classes
-        navClass: 'ui-tabs-nav',
-        selectedClass: 'ui-tabs-selected',
-        unselectClass: 'ui-tabs-unselect',
-        disabledClass: 'ui-tabs-disabled',
-        panelClass: 'ui-tabs-panel',
-        hideClass: 'ui-tabs-hide',
-        loadingClass: 'ui-tabs-loading'
-    };
-
-    // instance methods
-    $.extend($.ui.tabs.prototype, {
-        tabId: function(a) {
-            return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
-                || this.options.idPrefix + $.data(a);
-        },
-        ui: function(tab, panel) {
-            return {
-                instance: this,
-                options: this.options,
-                tab: tab,
-                panel: panel
-            };
-        },
-        tabify: function(init) {
-
-            this.$lis = $('li:has(a[href])', this.element);
-            this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
-            this.$panels = $([]);
-
-            var self = this, o = this.options;
-
-            this.$tabs.each(function(i, a) {
-                // inline tab
-                if (a.hash && a.hash.replace('#', '')) // Safari 2 reports '#' for an empty hash
-                    self.$panels = self.$panels.add(a.hash);
-                // remote tab
-                else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#"
-                    $.data(a, 'href.tabs', a.href); // required for restore on destroy
-
-                    var _cls = a.getAttribute('class');
-                    var use_iframe = _cls && (_cls.indexOf('use_iframe') > -1)? true: false;
-                    if (!use_iframe) {
-                        $.data(a, 'load.tabs', a.href); // mutable
-                    } else {
-                        $.data(a, 'load.iframe_src', a.href); // mutable
-                    }
-
-
-                    var id = self.tabId(a);
-                    a.href = '#' + id;
-                    var $panel = $('#' + id);
-                    var panelTemplate = use_iframe? '<div><iframe></iframe></div>': o.panelTemplate;
-                    if (!$panel.length) {
-                        $panel = $(panelTemplate).attr('id', id).addClass(o.panelClass)
-                            .insertAfter( self.$panels[i - 1] || self.element );
-                        $panel.data('destroy.tabs', true);
-                    }
-                    self.$panels = self.$panels.add( $panel );
-                }
-                // invalid tab href
-                else
-                    o.disabled.push(i + 1);
-            });
-
-            if (init) {
-
-                // attach necessary classes for styling if not present
-                $(this.element).hasClass(o.navClass) || $(this.element).addClass(o.navClass);
-                this.$panels.each(function() {
-                    var $this = $(this);
-                    $this.hasClass(o.panelClass) || $this.addClass(o.panelClass);
-                });
-
-                // Try to retrieve selected tab:
-                // 1. from fragment identifier in url if present
-                // 2. from cookie
-                // 3. from selected class attribute on <li>
-                // 4. otherwise use given "selected" option
-                // 5. check if tab is disabled
-                this.$tabs.each(function(i, a) {
-                    if (location.hash) {
-                        if (a.hash == location.hash) {
-                            o.selected = i;
-                            // prevent page scroll to fragment
-                            //if (($.browser.msie || $.browser.opera) && !o.remote) {
-                            if ($.browser.msie || $.browser.opera) {
-                                var $toShow = $(location.hash), toShowId = $toShow.attr('id');
-                                $toShow.attr('id', '');
-                                setTimeout(function() {
-                                    $toShow.attr('id', toShowId); // restore id
-                                }, 500);
-                            }
-                            scrollTo(0, 0);
-                            return false; // break
-                        }
-                    } else if (o.cookie) {
-                        var index = parseInt($.cookie('ui-tabs' + $.data(self.element)),10);
-                        if (index && self.$tabs[index]) {
-                            o.selected = index;
-                            return false; // break
-                        }
-                    } else if ( self.$lis.eq(i).hasClass(o.selectedClass) ) {
-                        o.selected = i;
-                        return false; // break
-                    }
-                });
-
-                // highlight selected tab
-                this.$panels.addClass(o.hideClass);
-                this.$lis.removeClass(o.selectedClass);
-                if (o.selected !== null) {
-                    this.$panels.eq(o.selected).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before
-                    this.$lis.eq(o.selected).addClass(o.selectedClass);
-                }
-
-                // load if remote tab
-                var href = o.selected !== null && $.data(this.$tabs[o.selected], 'load.tabs');
-                if (href)
-                    this.load(o.selected);
-
-                // Take disabling tabs via class attribute from HTML
-                // into account and update option properly...
-                o.disabled = $.unique(o.disabled.concat(
-                    $.map(this.$lis.filter('.' + o.disabledClass),
-                        function(n, i) { return self.$lis.index(n); } )
-                )).sort();
-                
-                // clean up to avoid memory leaks in certain versions of IE 6
-                $(window).bind('unload', function() {
-                    self.$tabs.unbind('.tabs');
-                    self.$lis = self.$tabs = self.$panels = null;
-                });
-
-            }
-
-            // disable tabs
-            for (var i = 0, li; li = this.$lis[i]; i++)
-                $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass(o.selectedClass) ? 'addClass' : 'removeClass'](o.disabledClass);
-
-            // reset cache if switching from cached to not cached
-            if (o.cache === false)
-                this.$tabs.removeData('cache.tabs');
-            
-            // set up animations
-            var hideFx, showFx, baseFx = { 'min-width': 0, duration: 1 }, baseDuration = 'normal';
-            if (o.fx && o.fx.constructor == Array)
-                hideFx = o.fx[0] || baseFx, showFx = o.fx[1] || baseFx;
-            else
-                hideFx = showFx = o.fx || baseFx;
-
-            // reset some styles to maintain print style sheets etc.
-            var resetCSS = { display: '', overflow: '', height: '' };
-            if (!$.browser.msie) // not in IE to prevent ClearType font issue
-                resetCSS.opacity = '';
-
-            // Hide a tab, animation prevents browser scrolling to fragment,
-            // $show is optional.
-            function hideTab(clicked, $hide, $show) {
-                $hide.animate(hideFx, hideFx.duration || baseDuration, function() { //
-                    $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
-                    if ($.browser.msie && hideFx.opacity)
-                        $hide[0].style.filter = '';
-                    if ($show)
-                        showTab(clicked, $show, $hide);
-                });
-            }
-
-            // Show a tab, animation prevents browser scrolling to fragment,
-            // $hide is optional.
-            function showTab(clicked, $show, $hide) {
-                if (showFx === baseFx)
-                    $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels
-                $show.animate(showFx, showFx.duration || baseDuration, function() {
-                    $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
-                    if ($.browser.msie && showFx.opacity)
-                        $show[0].style.filter = '';
-
-                    // callback
-                    $(self.element).triggerHandler('tabsshow', [self.ui(clicked, $show[0])], o.show);
-
-                });
-            }
-
-            // switch a tab
-            function switchTab(clicked, $li, $hide, $show) {
-                /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
-                    $.ajaxHistory.update(clicked.hash);
-                }*/
-                $li.addClass(o.selectedClass)
-                    .siblings().removeClass(o.selectedClass);
-                hideTab(clicked, $hide, $show);
-            }
-
-            // attach tab event handler, unbind to avoid duplicates from former tabifying...
-            this.$tabs.unbind('.tabs').bind(o.event, function() {
-
-                //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
-                var $li = $(this).parents('li:eq(0)'),
-                    $hide = self.$panels.filter(':visible'),
-                    $show = $(this.hash);
-
-                // If tab is already selected and not unselectable or tab disabled or 
-                // or is already loading or click callback returns false stop here.
-                // Check if click handler returns false last so that it is not executed
-                // for a disabled or loading tab!
-                if (($li.hasClass(o.selectedClass) && !o.unselect)
-                    || $li.hasClass(o.disabledClass) 
-                    || $(this).hasClass(o.loadingClass)
-                    || $(self.element).triggerHandler('tabsselect', [self.ui(this, $show[0])], o.select) === false
-                    ) {
-                    this.blur();
-                    return false;
-                }
-
-                self.options.selected = self.$tabs.index(this);
-
-                // if tab may be closed
-                if (o.unselect) {
-                    if ($li.hasClass(o.selectedClass)) {
-                        self.options.selected = null;
-                        $li.removeClass(o.selectedClass);
-                        self.$panels.stop();
-                        hideTab(this, $hide);
-                        this.blur();
-                        return false;
-                    } else if (!$hide.length) {
-                        self.$panels.stop();
-                        var a = this;
-                        self.load(self.$tabs.index(this), function() {
-                            $li.addClass(o.selectedClass).addClass(o.unselectClass);
-                            showTab(a, $show);
-                        });
-                        this.blur();
-                        return false;
-                    }
-                }
-
-                if (o.cookie)
-                    $.cookie('ui-tabs' + $.data(self.element), self.options.selected, o.cookie);
-
-                // stop possibly running animations
-                self.$panels.stop();
-
-                // show new tab
-                if ($show.length) {
-
-                    // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
-                    /*if ($.browser.msie && o.bookmarkable) {
-                        var showId = this.hash.replace('#', '');
-                        $show.attr('id', '');
-                        setTimeout(function() {
-                            $show.attr('id', showId); // restore id
-                        }, 0);
-                    }*/
-
-                    var a = this;
-                    self.load(self.$tabs.index(this), $hide.length ? 
-                        function() {
-                            switchTab(a, $li, $hide, $show);
-                        } :
-                        function() {
-                            $li.addClass(o.selectedClass);
-                            showTab(a, $show);
-                        }
-                    );
-
-                    // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
-                    /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
-                    var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
-                    setTimeout(function() {
-                        scrollTo(scrollX, scrollY);
-                    }, 0);*/
-
-                } else
-                    throw 'jQuery UI Tabs: Mismatching fragment identifier.';
-
-                // Prevent IE from keeping other link focussed when using the back button
-                // and remove dotted border from clicked link. This is controlled in modern
-                // browsers via CSS, also blur removes focus from address bar in Firefox
-                // which can become a usability and annoying problem with tabsRotate.
-                if ($.browser.msie)
-                    this.blur();
-
-                //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE
-                return false;
-
-            });
-
-            // disable click if event is configured to something else
-            if (!(/^click/).test(o.event))
-                this.$tabs.bind('click.tabs', function() { return false; });
-
-        },
-        add: function(url, label, index) {
-            if (index == undefined) 
-                index = this.$tabs.length; // append by default
-
-            var o = this.options;
-            var $li = $(o.tabTemplate.replace(/#\{href\}/, url).replace(/#\{label\}/, label));
-            $li.data('destroy.tabs', true);
-
-            var id = url.indexOf('#') == 0 ? url.replace('#', '') : this.tabId( $('a:first-child', $li)[0] );
-
-            // try to find an existing element before creating a new one
-            var $panel = $('#' + id);
-            if (!$panel.length) {
-                $panel = $(o.panelTemplate).attr('id', id)
-                    .addClass(o.panelClass).addClass(o.hideClass);
-                $panel.data('destroy.tabs', true);
-            }
-            if (index >= this.$lis.length) {
-                $li.appendTo(this.element);
-                $panel.appendTo(this.element.parentNode);
-            } else {
-                $li.insertBefore(this.$lis[index]);
-                $panel.insertBefore(this.$panels[index]);
-            }
-            
-            o.disabled = $.map(o.disabled,
-                function(n, i) { return n >= index ? ++n : n });
-                
-            this.tabify();
-
-            if (this.$tabs.length == 1) {
-                 $li.addClass(o.selectedClass);
-                 $panel.removeClass(o.hideClass);
-                 var href = $.data(this.$tabs[0], 'load.tabs');
-                 if (href)
-                     this.load(index, href);
-            }
-
-            // callback
-            $(this.element).triggerHandler('tabsadd',
-                [this.ui(this.$tabs[index], this.$panels[index])], o.add
-            );
-        },
-        remove: function(index) {
-            var o = this.options, $li = this.$lis.eq(index).remove(),
-                $panel = this.$panels.eq(index).remove();
-
-            // If selected tab was removed focus tab to the right or
-            // in case the last tab was removed the tab to the left.
-            if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1)
-                this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));
-
-            o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
-                function(n, i) { return n >= index ? --n : n });
-
-            this.tabify();
-
-            // callback
-            $(this.element).triggerHandler('tabsremove',
-                [this.ui($li.find('a')[0], $panel[0])], o.remove
-            );
-        },
-        enable: function(index) {
-            var o = this.options;
-            if ($.inArray(index, o.disabled) == -1)
-                return;
-                
-            var $li = this.$lis.eq(index).removeClass(o.disabledClass);
-            if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2...
-                $li.css('display', 'inline-block');
-                setTimeout(function() {
-                    $li.css('display', 'block');
-                }, 0);
-            }
-
-            o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
-
-            // callback
-            $(this.element).triggerHandler('tabsenable',
-                [this.ui(this.$tabs[index], this.$panels[index])], o.enable
-            );
-
-        },
-        disable: function(index) {
-            var self = this, o = this.options;
-            if (index != o.selected) { // cannot disable already selected tab
-                this.$lis.eq(index).addClass(o.disabledClass);
-
-                o.disabled.push(index);
-                o.disabled.sort();
-
-                // callback
-                $(this.element).triggerHandler('tabsdisable',
-                    [this.ui(this.$tabs[index], this.$panels[index])], o.disable
-                );
-            }
-        },
-        select: function(index) {
-            if (typeof index == 'string')
-                index = this.$tabs.index( this.$tabs.filter('[href$=' + index + ']')[0] );
-            this.$tabs.eq(index).trigger(this.options.event);
-        },
-        load: function(index, callback) { // callback is for internal usage only
-            
-            var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
-                    bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
-
-            callback = callback || function() {};
-            
-            // no remote or from cache - just finish with callback
-            if (!url || ($.data(a, 'cache.tabs') && !bypassCache)) {
-                callback();
-                return;
-            }
-
-            // load remote from here on
-            if (o.spinner) {
-                var $span = $('span', a);
-                $span.data('label.tabs', $span.html()).html('<em>' + o.spinner + '</em>');
-            }
-            var finish = function() {
-                self.$tabs.filter('.' + o.loadingClass).each(function() {
-                    $(this).removeClass(o.loadingClass);
-                    if (o.spinner) {
-                        var $span = $('span', this);
-                        $span.html($span.data('label.tabs')).removeData('label.tabs');
-                    }
-                });
-                self.xhr = null;
-            };
-            var ajaxOptions = $.extend({}, o.ajaxOptions, {
-                url: url,
-                success: function(r, s) {
-                    $(a.hash).html(r);
-                    finish();
-                    
-                    // This callback is required because the switch has to take
-                    // place after loading has completed.
-                    callback();
-
-                    if (o.cache)
-                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
-
-                    // callback
-                    $(self.element).triggerHandler('tabsload',
-                        [self.ui(self.$tabs[index], self.$panels[index])], o.load
-                    );
-
-                    o.ajaxOptions.success && o.ajaxOptions.success(r, s);
-                }
-            });
-            if (this.xhr) {
-                // terminate pending requests from other tabs and restore tab label
-                this.xhr.abort();
-                finish();
-            }
-            $a.addClass(o.loadingClass);
-            setTimeout(function() { // timeout is again required in IE, "wait" for id being restored
-                self.xhr = $.ajax(ajaxOptions);
-            }, 0);
-
-        },
-        url: function(index, url) {
-            this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
-        },
-        destroy: function() {
-            var o = this.options;
-            $(this.element).unbind('.tabs')
-                .removeClass(o.navClass).removeData('tabs');
-            this.$tabs.each(function() {
-                var href = $.data(this, 'href.tabs');
-                if (href)
-                    this.href = href;
-                var $this = $(this).unbind('.tabs');
-                $.each(['href', 'load', 'cache'], function(i, prefix) {
-                      $this.removeData(prefix + '.tabs');
-                });
-            });
-            this.$lis.add(this.$panels).each(function() {
-                if ($.data(this, 'destroy.tabs'))
-                    $(this).remove();
-                else
-                    $(this).removeClass([o.selectedClass, o.unselectClass,
-                        o.disabledClass, o.panelClass, o.hideClass].join(' '));
-            });
-        }
-    });
-
-/*
- * Tabs Extensions
- */
-
-    /*
-     * Rotate
-     */
-    $.extend($.ui.tabs.prototype, {
-        rotation: null,
-        rotate: function(ms, continuing) {
-            
-            continuing = continuing || false;
-            
-            var self = this, t = this.options.selected;
-            
-            function start() {
-                self.rotation = setInterval(function() {
-                    t = ++t < self.$tabs.length ? t : 0;
-                    self.select(t);
-                }, ms);    
-            }
-            
-            function stop(e) {
-                if (!e || e.clientX) { // only in case of a true click
-                    clearInterval(self.rotation);
-                }
-            }
-            
-            // start interval
-            if (ms) {
-                start();
-                if (!continuing)
-                    this.$tabs.bind(this.options.event, stop);
-                else
-                    this.$tabs.bind(this.options.event, function() {
-                        stop();
-                        t = self.options.selected;
-                        start();
-                    });
-            }
-            // stop interval
-            else {
-                stop();
-                this.$tabs.unbind(this.options.event, stop);
-            }
-        }
-    });
-
-})(jQuery);
diff --git a/moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.css b/moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.css
deleted file mode 100644
index 21a046d..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.css
+++ /dev/null
@@ -1,9 +0,0 @@
-.widgetbrowser iframe {
-    width: 100%;
-    border: 0;
-}
-div.small iframe { height: 50px; }
-div.medium iframe { height: 150px; }
-div.large iframe { height: 300px; }
-div.x-large iframe { height: 500px; }
-
diff --git a/moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.js b/moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.js
deleted file mode 100644
index c0b78e6..0000000
--- a/moksha/widgetbrowser/widgetbrowser/static/widgetbrowser.js
+++ /dev/null
@@ -1,13 +0,0 @@
-jQuery(function() {
-    jQuery('.widgetbrowser > ul').tabs({
-        selected: null,
-        unselect: true,
-        select: function (ui) {
-            var url = jQuery.data(ui.tab, 'load.iframe_src');
-            var iframe = jQuery('iframe', ui.panel);
-            if (url && !iframe.attr('src')) {
-                iframe.attr('src', url);
-            }
-        }
-    })
-});
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/__init__.py b/moksha/widgetbrowser/widgetbrowser/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/home.html b/moksha/widgetbrowser/widgetbrowser/templates/home.html
deleted file mode 100644
index 012ce08..0000000
--- a/moksha/widgetbrowser/widgetbrowser/templates/home.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<?python
-from widgetbrowser import widgets
-?>
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-    <style>
-        .ui-tabs-panel {
-            border-bottom: solid 1px #94ada7;
-            padding-left: 1.5em;
-        }
-        .ui-tabs-panel iframe {
-            width: 100%;
-            border: 0;
-            min-height: 500px;
-        }
-        #home {
-            min-height: 450px;
-        }
-    </style>
-  </head>
-  <body class="flora">
-    <div id="main">
-        <ul>
-            <li><a href="#home"><span>Home</span></a></li>
-            <li><a href="#terminal" class="use_iframe"><span>Terminal</span></a></li>
-            <li><a href="${url('/widgets/')}" class="use_iframe"><span>Widgets</span></a></li>
-        </ul>
-        <div id="home">
-            <h1>Welcome to Toscawidgets' Browser</h1>
-            <p>
-            </p>
-        </div>
-        <div id="terminal">
-            ${widgets.repl(prefix=url('_repl/'))}
-        </div>
-    </div>
-    <div id="footer">
-    <p>&copy; 2008. Alberto Valverde González</p>
-    </div>
-    <script type="text/javascript">
-        //<![CDATA[
-        jQuery(function () {
-            jQuery('#main > ul').tabs({
-                select: function (ui) {
-                    var url = jQuery.data(ui.tab, 'load.iframe_src');
-                    var iframe = jQuery('iframe', ui.panel);
-                    if (url && !iframe.attr('src')) {
-                        iframe.attr('src', url);
-                    }
-                }
-            });
-        });
-        //]]>
-    </script>
-  </body>
-</html>
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/list_widgets.html b/moksha/widgetbrowser/widgetbrowser/templates/list_widgets.html
deleted file mode 100644
index 2ef5dfe..0000000
--- a/moksha/widgetbrowser/widgetbrowser/templates/list_widgets.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser: Installed widgets</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body id="widgets">
-    <ul>
-        <li py:for="path, url in widgets">
-            <a href="$url">$path</a>
-        </li>
-    </ul>
-  </body>
-</html>
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/show_widget.html b/moksha/widgetbrowser/widgetbrowser/templates/show_widget.html
deleted file mode 100644
index b75e063..0000000
--- a/moksha/widgetbrowser/widgetbrowser/templates/show_widget.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser: ${widget_name}</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body id="widget_browser">
-    <form py:if="interactive" method="GET">
-      <label for="display_args">Display arguments:</label>
-      <input id="display_args" name="_disp" type="text" size="50" value="${_disp}" />
-      <input type="submit" value="Display" />
-    </form>
-    <div py:replace="widget_output" />
-  </body>
-</html>
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/validation_result.html b/moksha/widgetbrowser/widgetbrowser/templates/validation_result.html
deleted file mode 100644
index e43da7b..0000000
--- a/moksha/widgetbrowser/widgetbrowser/templates/validation_result.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <head>
-    <title>WidgetBrowser: ${widget_name}</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body id="widget_browser">
-    <h1 class="title">Validated data:</h1>
-    ${Markup(value)}
-    <a href="">Back</a>
-  </body>
-</html>
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html b/moksha/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html
deleted file mode 100644
index 7edb374..0000000
--- a/moksha/widgetbrowser/widgetbrowser/templates/widget_browser_tabs.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<div xmlns:py="http://genshi.edgewall.org/"
-     class="widgetbrowser ${size}">
-  <ul>
-    <li py:for="text, url in tabs">
-      <a href="${url}" class="${text == 'Demo' and 'use_iframe' or None}">
-        <span>${text}</span>
-      </a>
-    </li>
-  </ul>
-</div>
-
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/widget_index.html b/moksha/widgetbrowser/widgetbrowser/templates/widget_index.html
deleted file mode 100644
index 4759c25..0000000
--- a/moksha/widgetbrowser/widgetbrowser/templates/widget_index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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"
-      xmlns:py="http://genshi.edgewall.org/">
-  <?python
-      from widgetbrowser.widgets import WidgetBrowserTabs
-      from widgetbrowser.util import widget_path
-      browser = WidgetBrowserTabs(size='x-large')
-  ?>
-  <head>
-    <title>WidgetBrowser: ${widget_path(widget)}</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-  </head>
-  <body>
-    <h1>${widget_path(widget)}</h1>
-    <p><a href="javascript:history.back()">Back</a></p>
-    ${browser(widget)}
-  </body>
-</html>
diff --git a/moksha/widgetbrowser/widgetbrowser/templates/widget_parameters.html b/moksha/widgetbrowser/widgetbrowser/templates/widget_parameters.html
deleted file mode 100644
index c95c195..0000000
--- a/moksha/widgetbrowser/widgetbrowser/templates/widget_parameters.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<div xmlns:py="http://genshi.edgewall.org/" class="widget_params">
-  <div py:if="parameters.local" class="widget_params local_params">
-    <h3>This widget's</h3>
-    <dl>
-        <py:for each="k in sorted(parameters.local)">
-            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
-            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
-        </py:for>
-    </dl>
-  </div>
-  <div py:if="parameters.inherited" class="widget_param inherited_params">
-    <h3>Inherited</h3>
-    <dl>
-        <py:for each="k in sorted(parameters.inherited)">
-            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
-            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
-        </py:for>
-    </dl>
-  </div>
-</div>
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/__init__.py b/moksha/widgetbrowser/widgetbrowser/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.html b/moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.html
deleted file mode 100644
index 7c9c42c..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.html
+++ /dev/null
@@ -1 +0,0 @@
-Dummy template $value
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak b/moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak
deleted file mode 100644
index 1774ce6..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/dummy_m_template.mak
+++ /dev/null
@@ -1 +0,0 @@
-Dummy template $value mako version
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/dummy_template.html b/moksha/widgetbrowser/widgetbrowser/tests/dummy_template.html
deleted file mode 100644
index 7c9c42c..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/dummy_template.html
+++ /dev/null
@@ -1 +0,0 @@
-Dummy template $value
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/test_app.txt b/moksha/widgetbrowser/widgetbrowser/tests/test_app.txt
deleted file mode 100644
index bacbc39..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/test_app.txt
+++ /dev/null
@@ -1,50 +0,0 @@
->>> from widgetbrowser import WidgetBrowser
->>> from webtest import TestApp
-
->>> app = TestApp(WidgetBrowser())
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo')
->>> assert 'default' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/')
->>> assert 'Demo' in r
-
->>> r = app.get('/os.open/demo', status=404)
-
-Test that code isn't executed if not allowed
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo?_disp="foo"')
->>> assert 'default' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/template')
->>> assert '$value' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/source')
->>> assert 'class' in r
->>> assert 'TestWidget' in r
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/parameters')
->>> assert 'Inherited' in r
-
-Test posting:
-
->>> r = app.post('/widgetbrowser.tests.widgets.TestWidget/demo', {'some_key':'foo'})
->>> assert 'some_key' in r
-
-# the following is just to test the failed validation code-path
->>> r = app.post('/widgetbrowser.tests.widgets.TestWidget/demo', {'break':'y'})
->>> assert 'some_key' not in r
-
-Test unimplemented methods:
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/foobarize', status=501)
-
-Test custom controller
-
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/test')
->>> assert 'Testing TestWidget' in r
-
-Now with code execution
-
->>> app = TestApp(WidgetBrowser(interactive=True))
->>> r = app.get('/widgetbrowser.tests.widgets.TestWidget/demo?_disp="foo"')
->>> assert 'foo' in r
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py b/moksha/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py
deleted file mode 100644
index fc2d10a..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/test_sphinx_ext.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import os
-import shutil
-from unittest import TestCase
-from pkg_resources import resource_filename
-import sphinx
-
-doc_dir = resource_filename('widgetbrowser.tests', 'testdocs')
-
-class TestSphinxExt(TestCase):
-    def setUp(self):
-        self.dest_dir = os.tempnam()
-        if not os.path.isdir(self.dest_dir):
-            os.makedirs(self.dest_dir)
-
-    def tearDown(self):
-        try:
-            shutil.rmtree(self.dest_dir)
-        except OSError:
-            pass
-
-    def test_generate(self):
-        out = sphinx.main(['sphinx-build', doc_dir, self.dest_dir])
-        self.failUnless(not out, out)
-        html = open(os.path.join(self.dest_dir, 'index.html')).read()
-        self.failUnless('widgetbrowser' in html)
-        self.failUnless('x-large' in html)
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/testdocs/conf.py b/moksha/widgetbrowser/widgetbrowser/tests/testdocs/conf.py
deleted file mode 100644
index 4bd428a..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/testdocs/conf.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# TestDocs documentation build configuration file, created by
-# sphinx-quickstart on Fri May  9 09:56:10 2008.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# The contents of this file are pickled, so don't put values in the namespace
-# that aren't pickleable (module imports are okay, they're removed automatically).
-#
-# All configuration values have a default value; values that are commented out
-# serve to show the default value.
-
-import sys, os
-
-# If your extensions are in another directory, add it here. If the directory
-# is relative to the documentation root, use os.path.abspath to make it
-# absolute, like shown here.
-#sys.path.append(os.path.abspath('some/directory'))
-
-# General configuration
-# ---------------------
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['widgetbrowser.sphinx_ext']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = []
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General substitutions.
-project = 'TestDocs'
-copyright = '2008, Alberto'
-
-# The default replacements for |version| and |release|, also used in various
-# other places throughout the built documents.
-#
-# The short X.Y version.
-version = '0.1'
-# The full version, including alpha/beta/rc tags.
-release = '0.1'
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%B %d, %Y'
-
-# List of documents that shouldn't be included in the build.
-#unused_docs = []
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-
-# Options for HTML output
-# -----------------------
-
-# The style sheet to use for HTML and HTML Help pages. A file of that name
-# must exist either in Sphinx' static/ path, or in one of the custom paths
-# given in html_static_path.
-html_style = 'default.css'
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# The name of an image file (within the static path) to place at the top of
-# the sidebar.
-#html_logo = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_use_modindex = True
-
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.
-#html_use_opensearch = False
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'TestDocsdoc'
-
-
-# Options for LaTeX output
-# ------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, document class [howto/manual]).
-latex_documents = [
-  ('index', 'TestDocs.tex', 'TestDocs Documentation', 'Alberto', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_use_modindex = True
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/testdocs/index.rst b/moksha/widgetbrowser/widgetbrowser/tests/testdocs/index.rst
deleted file mode 100644
index 6f70ced..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/testdocs/index.rst
+++ /dev/null
@@ -1,12 +0,0 @@
-.. TestDocs documentation master file, created by sphinx-quickstart on Fri May  9 09:56:10 2008.
-   You can adapt this file completely to your liking, but it should at least
-   contain the root `toctree` directive.
-
-Testing the `widgetbroser` directive
-====================================
-
-Test an existing widget
------------------------
-.. widgetbrowser:: widgetbrowser.tests.widgets.TestWidget
-   :tabs: source, demo, parameters, template
-   :size: x-large
diff --git a/moksha/widgetbrowser/widgetbrowser/tests/widgets.py b/moksha/widgetbrowser/widgetbrowser/tests/widgets.py
deleted file mode 100644
index 149139d..0000000
--- a/moksha/widgetbrowser/widgetbrowser/tests/widgets.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from tw.api import Widget
-from widgetbrowser import WidgetBrowser
-from formencode.api import Invalid
-
-class TestWidget(Widget):
-    template = "$value"
-    default = "default"
-
-    def validate(self, value, *args, **kw):
-        if 'break' in value.keys():
-            raise Invalid("Validation failed", value, None)
-        return value
-
- at WidgetBrowser.register_controller(TestWidget, 'test')
-def test_controller(request, response):
-    response.headers['Content-Type'] = 'text/plain'
-    return "Testing " + request.widget.__class__.__name__
-
-class TestWidgetExternalTemplate(Widget):
-    template = "toscawidgets:widgetbrowser.tests.dummy_template"
-    default = "default"
-
-class TestWidgetMultipleExternalTemplate(Widget):
-    template = "toscawidgets:widgetbrowser.tests.dummy_m_template"
-    default = "default"
diff --git a/moksha/widgetbrowser/widgetbrowser/util.py b/moksha/widgetbrowser/widgetbrowser/util.py
deleted file mode 100644
index 648cd8c..0000000
--- a/moksha/widgetbrowser/widgetbrowser/util.py
+++ /dev/null
@@ -1,242 +0,0 @@
-import logging
-import os
-import errno
-import sys
-import pprint
-
-from pkg_resources import EntryPoint, iter_entry_points, resource_string
-
-import tw
-from tw.api import Widget, WidgetType
-from tw.core import view
-
-log = logging.getLogger(__name__)
-
-def import_widget(path):
-    """Import a widget given a dotted or entry point notation path.
-
-    Can import both widget instances or classes.
-
-       >>> import_widget('tw.core.base.Widget')
-       <class 'tw.core.base.Widget'>
-       >>> import_widget('tw.core.base:Widget')
-       <class 'tw.core.base.Widget'>
-       >>> import_widget('os.popen')
-
-    """
-    if ':' not in path:
-        parts = path.split('.')
-        path = '.'.join(parts[:-1]) + ':' + parts[-1]
-    widget = EntryPoint.parse("x="+path).load(False)
-    if not isinstance(widget, (WidgetType, Widget)):
-        widget = None
-    return widget
-
-
-def widget_path(widget):
-    """Returns the path of a widget instance or subclass
-
-    >>> from tw.api import Widget
-    >>> widget_path(Widget)
-    'tw.core.base.Widget'
-    >>> widget_path(Widget())
-    'tw.core.base.Widget'
-    """
-    if not isinstance(widget, (WidgetType, Widget)):
-        raise TypeError("Only widgets are allowed")
-    if isinstance(widget, Widget):
-        widget = widget.__class__
-    return '.'.join([widget.__module__, widget.__name__])
-
-def format_code(code, format='python'):
-    """Formats a chunk of code as html. If pygments is installed it will
-    pygmentize it.
-    
-    >>> code = "from __future__ import teletransportation"
-    >>> '<pre' in format_code(code)
-    True
-    """
-    try:
-        from pygments import highlight, formatters, lexers
-    except ImportError:
-        log.info("Pygments is not available to colorize")
-        return '<pre>' + code + '</pre>'
-    lexer = lexers.get_lexer_by_name(format)
-    formatter = formatters.get_formatter_by_name('html')
-    return highlight(code, lexer, formatter)
-
-#TODO: Memoize this function
-def widget_template(widget, extension='.html'):
-    """Returns the template of a widget as a string.
-
-    Loads external templates if needed.
-
-    >>> from widgetbrowser.tests.widgets import *
-    >>> widget_template(TestWidgetExternalTemplate())
-    'Dummy template $value\\n'
-
-    If more than one is available, it will use the extension to disambiguate.
-
-    >>> from widgetbrowser.tests.widgets import TestWidgetExternalTemplate
-    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.html')
-    'Dummy template $value\\n'
-    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.mak')
-    'Dummy template $value mako version\\n'
-    """
-    template = widget.template
-    if template and not view._is_inline_template(template):
-        # Template seems to refer to a file, look it up
-        parts = template.split('.')
-        possible_extensions = set(".html .mak .mako".split())
-        possible_extensions.remove(extension)
-        possible_extensions = [extension] + list(possible_extensions)
-        for ext in possible_extensions:
-            try:
-                return resource_string('.'.join(parts[:-1]), parts[-1]+ext)
-            except IOError, e:
-                if e.errno not in (0, errno.ENOENT):
-                    raise
-        return None
-    return template
-
-def pretty_print(obj):
-    """Pretty prints an object returning pygmentized code if possible."""
-    return format_code(pprint.pformat(obj), 'python')
-
-def display_widget(widget, argstr='', ctx=None):
-    """Displays a widget with optional arguments as a string.
-    
-
-    .. warning:: IT IS VERY UNSAFE TO EXECUTE UNTRUSTED CODE
-
-    Example::
-
-        >>> from tw.api import Widget
-        >>> class TestWidget(Widget):
-        ...     params = ['param']
-        ...     template = "$value-$param"
-        >>> display_widget(TestWidget())
-        u'None-None'
-        >>> display_widget(TestWidget(), '"hello", param=2')
-        u'hello-2'
-    """
-    ctx = ctx or {}
-    ctx['_w'] = widget
-    code = "_o = _w(%s)" % argstr
-    exec code in ctx
-    return ctx['_o']
-
-def widget_url(widget, action='', prefix=None):
-    """Returns the URL of the controller to perform `action` on `widget`.
-
-    If no `prefix` is passed the it will be tried to be fetched from
-    `tw.framework.request_local` where the :class:`WidgetBrowser` leaves it
-    on every request.
-
-    Example::
-
-        >>> from tw.core.base import Widget
-        >>> widget_url(Widget)
-        '/tw.core.base.Widget/'
-        >>> widget_url(Widget())
-        '/tw.core.base.Widget/'
-
-    You can also pass the `path` of the widget::
-
-        >>> widget_url('tw.api.Widget')
-        '/tw.api.Widget/'
-        >>> widget_url('tw.api.Widget', 'show')
-        '/tw.api.Widget/show'
-        >>> widget_url('tw.api.Widget', 'show', prefix='/widget')
-        '/widget/tw.api.Widget/show'
-
-    .. note::
-
-        You can pass any path the widget can be imported from when passing a
-        string but if you pass a widget instance or subclass then the real
-        module where it is defined will be generated.
-    """
-    if isinstance(widget, (Widget, WidgetType)):
-        widgeturi = widget_path(widget)
-    else:
-        widgeturi = widget
-        if import_widget(widgeturi) is None:
-            return
-    if prefix is None:
-        prefix = getattr(tw.framework.request_local, 'browser_prefix', '')
-    return '/'.join([prefix.rstrip('/'), widgeturi, action])
-
-def all_widgets():
-    """Iterates over all the Widget subclasses in the modules
-    that are declared as `toscawidgets.widgets` entrypoints
-
-    >>> len(list(all_widgets())) > 0
-    True
-    """
-    seen = set()
-    for ep in iter_entry_points('toscawidgets.widgets'):
-        try:
-            mod = ep.load(False)
-        except ImportError, e:
-            log.error("Could not load %r: %s", ep, e)
-            continue
-        for name in dir(mod):
-            obj = getattr(mod, name)
-            if isinstance(obj, WidgetType) and obj not in seen:
-                seen.add(obj)
-                yield obj
-
-class WidgetParameters(object):
-    """Wraps a widget and provides information on it's parameters.
-
-    Example::
-
-        >>> from tw.core.base import Widget
-        >>> params = WidgetParameters(Widget)
-        >>> len(params.all) > 0
-        True
-        >>> params.all - params.local == params.inherited
-        True
-    """
-    def __init__(self, widget):
-        if isinstance(widget, Widget):
-            widget = widget.__class__
-        self.widget = widget
-        self.all = widget.params
-        self.inherited = set()
-        for b in self.widget.__mro__:
-            if b is self.widget:
-                continue
-            self.inherited.update(getattr(b, 'params', set()))
-        self.local = self.all - self.inherited
-
-    def get_default(self, name, default=None):
-        """Returns a string representation of a parameter default value.
-
-        Example::
-
-            >>> from tw.core.base import Widget
-            >>> params = WidgetParameters(Widget)
-            >>> type(params.get_default('id'))
-            <type 'str'>
-        """
-        return repr(getattr(self.widget, name, default))
-
-    def get_doc(self, name, default='Undocumented'):
-        """Returns parameters's doc. If it is not documented it will return
-        ``default``
-
-        Example::
-
-            >>> from tw.core.base import Widget
-            >>> params = WidgetParameters(Widget)
-            >>> type(params.get_doc('id'))
-            <type 'str'>
-        """
-        return getattr(self.widget, name + '__doc', default)
-        
-def build_docs(src, dst):
-    import sphinx
-    if not os.path.exists(dst):
-        os.mkdir(dst)
-    return sphinx.main(['sphinx-build', src, dst])
diff --git a/moksha/widgetbrowser/widgetbrowser/widgets.py b/moksha/widgetbrowser/widgetbrowser/widgets.py
deleted file mode 100644
index b40fdea..0000000
--- a/moksha/widgetbrowser/widgetbrowser/widgets.py
+++ /dev/null
@@ -1,71 +0,0 @@
-from tw.api import Widget, JSLink, CSSLink, js_function
-from widgetbrowser import util
-import string
-
-__all__ = ['WidgetBrowserTabs']
-
-mod = 'widgetbrowser'
-flora_all_css = CSSLink(modname=mod, filename="static/themes/flora/flora.all.css")
-tabs_css = CSSLink(modname=mod, filename="static/ui.tabs.css")
-wb_css = CSSLink(modname=mod, filename="static/widgetbrowser.css")
-pygments_css = CSSLink(modname=mod, filename="static/pygments.css")
-httprepl_css = CSSLink(modname=mod, filename="static/httprepl.css")
-jquery_js = JSLink(modname=mod, filename="static/jquery.js")
-# Do not pull jquery as an automatic dependency since Sphinx already includes
-# it
-ui_base_js = JSLink(modname=mod, filename="static/ui.base.js",
-                    location="bodybottom")
-ui_tabs_js = JSLink(modname=mod, filename="static/ui.tabs.js",
-                    location="bodybottom",
-                    javascript=[ui_base_js])
-ui_dragabble_js = JSLink(modname=mod, filename="static/ui.draggable.js",
-                         location="bodybottom")
-ui_resizable_js = JSLink(modname=mod, filename="static/ui.resizable.js",
-                         location="bodybottom")
-ui_dialog_js = JSLink(modname=mod, filename="static/ui.dialog.js",
-                      location="bodybottom",
-                      javascript=[ui_base_js, ui_dragabble_js, ui_resizable_js])
-widgetbrowser_js = JSLink(modname=mod, filename="static/widgetbrowser.js",
-                          javascript=[ui_tabs_js],
-                          css=[tabs_css, wb_css, pygments_css],
-                          location="bodybottom")
-
-httprepl_js = JSLink(modname=mod, filename='static/httprepl.js',
-                     javascript=[ui_dialog_js],
-                     css=[httprepl_css],
-                     location="bodybottom")
-
-class WidgetBrowserTabs(Widget):
-    template = "genshi:widgetbrowser.templates.widget_browser_tabs"
-    params = ["tabs", "prefix", "size", "in_sphinx"]
-    in_sphinx = False
-    javascript = [widgetbrowser_js]
-    size = "small"
-    tabs = ['demo', 'demo_source', 'source', 'template', 'parameters']
-    prefix = None
-     
-    def update_params(self, d):
-        super(WidgetBrowserTabs, self).update_params(d)
-        d.tabs = [(string.capwords(t.replace('_', ' ')), util.widget_url(d.value, t, prefix=d.prefix))
-                  for t in d.tabs]
-        if not d.in_sphinx:
-            # Not displayed inside Sphinx, include jquery and pygments
-            jquery_js.inject()
-            pygments_css.inject()
-
-
-class WidgetRepl(Widget):
-    template = '<div id="$id" class="$css_class"></div>'
-    params = ["prefix"]
-    prefix = '/_repl/' # show nicely in the browser tabs
-    include_dynamic_js_calls = True
-    javascript = [jquery_js, httprepl_js]
-    css = [flora_all_css]
-    def update_params(self, d):
-        super(WidgetRepl, self).update_params(d)
-        assert d.id, "This widget needs an id"
-        config = dict(prefix=d.prefix)
-        call = js_function('HTTPRepl.render')('#'+d.id, config)
-        self.add_call("jQuery(function () {%s});" %  call)
-
-repl = WidgetRepl("widgetrepl")
diff --git a/moksha/widgetbrowser/widgetbrowser/wsgiapp.py b/moksha/widgetbrowser/widgetbrowser/wsgiapp.py
deleted file mode 100644
index d2dbedd..0000000
--- a/moksha/widgetbrowser/widgetbrowser/wsgiapp.py
+++ /dev/null
@@ -1,251 +0,0 @@
-import sys
-import weakref
-import os
-import inspect
-import logging
-from pkg_resources import resource_filename
-from genshi.core import Markup
-from genshi.template import TemplateLoader, Context
-from webob import Request, Response, exc
-import tw
-from tw.api import Widget, WidgetType, make_middleware
-from widgetbrowser import util, widgets, repl
-
-try:
-    from formencode import Invalid
-    have_formencode = True
-except ImportError:
-    have_formencode = False
-
-from moksha.lib.helpers import cache_rendered
-
-__all__ = ['WidgetBrowser']
-
-log = logging.getLogger(__name__)
-
-def asbool(v):
-    if isinstance(v, basestring):
-        return v.lower().startswith('t') or v == '1' or v == 'on'
-    elif isinstance(v, bool):
-        return v
-    return False
-
-class WidgetBrowser(object):
-    """A widget browser WSGI app.
-
-    Parameters:
-
-      * `template_dirs`: A list of directories that shall be searched for
-        temlates used by the widget browser.
-      * `interactive`: Enable code execution. This is needed to for the REPL and
-        to override display arguments via the web interface. This is a BIG
-        SECURITY HOLE, enable only in a controlled environment.
-      * `docs_dir`: A directory where sphinx sources live.
-    """
-    def __init__(self, global_conf={}, template_dirs=None, interactive=False,
-                 docs_dir=None, full_stack=True):
-        if isinstance(template_dirs, basestring):
-            template_dirs = template_dirs.split()
-        template_dirs = template_dirs or []
-        template_dirs.append(resource_filename('widgetbrowser', 'templates'))
-        self.loader = TemplateLoader(template_dirs)
-        self.interactive = asbool(interactive)
-        if self.interactive:
-            self.http_repl = repl.WidgetReplApp(globals(), weakref.proxy(self))
-            self.context = self.http_repl.repl.locals
-        else:
-            self.context = None
-            self.http_repl = exc.HTTPForbidden("Interactive mode is disabled")
-        if docs_dir:
-            from paste.cascade import Cascade
-            dest_dir = os.path.abspath(os.path.join(docs_dir, '.build'))
-            log.info('Building docs...')
-            try:
-                util.build_docs(docs_dir, dest_dir)
-            except Exception, e:
-                log.warning('Skipping building docs: %s' % str(e))
-            self.built_docs = dest_dir
-            self.app = Cascade([self.docs_app, self.app])
-        if asbool(full_stack):
-            self.app = make_middleware(self.app, {
-                'toscawidgets.framework.default_view': 'genshi',
-                }, stack_registry = True)
-        self._default_controllers = dict(demo=self.show_demo,
-                                         index=self.show_index,
-                                         template=self.show_template,
-                                         parameters=self.show_parameters,
-                                         source=self.show_source,
-                                         demo_source=self.show_demo_source)
-
-
-    def docs_app(self, environ, start_response):
-        """Registers widgetbrowser_js as resources before serving static html
-        files so it is injected into the page"""
-        from paste.urlparser import StaticURLParser
-        app = StaticURLParser(self.built_docs)
-        resources = widgets.widgetbrowser_js.retrieve_resources()
-        tw.framework.register_resources(resources)
-        return app(environ, start_response)
-
-    _widget_controllers = {}
-    @classmethod
-    def register_controller(cls, widget, action):
-        """Registers function to act as a demo controller for a widget"""
-        def _register(controller):
-            cls._widget_controllers[(widget,action)] = controller
-            return controller
-        return _register
-
-    def lookup_controller(self, widget_cls, action):
-        try:
-            return self._widget_controllers[(widget_cls, action)]
-        except KeyError:
-            return self._default_controllers[action]
-
-    def lookup_widget_action(self, path_info):
-        try:
-            widget_path, action = path_info.strip('/').split('/')
-        except ValueError:
-            widget_path, action = path_info, 'index'
-        if widget_path:
-            try:
-                widget = util.import_widget(widget_path.strip('/'))
-            except (ImportError, ValueError):
-                widget = None
-            if widget:
-                return widget, action
-        raise LookupError(path_info)
-
-    def render(self, template, ns):
-        ns.pop('self',None)
-        stream = self.loader.load(template).generate(Context(**ns))
-        return stream.render(method='xhtml', doctype='xhtml')
-
-    def __call__(self, environ, start_response):
-        return self.app(environ, start_response)
-
-    @cache_rendered
-    def app(self, environ, start_response):
-        req = Request(environ)
-        resp = Response(request=req, content_type='text/html; charset=utf-8')
-        # Leave the interactive flag in tw.framework so demo controllers can know
-        # if it is safe to enable advanced/unsecure features.
-        tw.framework.request_local.interactive = self.interactive
-        tw.framework.request_local.browser_prefix = req.script_name
-
-        # Lookup widget XXX: Yuck!
-        if req.path_info == '/':
-            controller = self.home
-        elif req.path_info.startswith('/_repl') and self.http_repl:
-            req.path_info_pop()
-            return self.http_repl(environ, start_response)
-        elif req.path_info.startswith('/widgets'):
-            controller = self.widgets
-        else:
-            try:
-                widget, action = self.lookup_widget_action(req.path_info)
-            except LookupError:
-                resp = exc.HTTPNotFound('No widget at %s' % req.path_info)
-                return resp(environ, start_response)
-                
-
-            # Lookup controller
-            try:
-                controller = self.lookup_controller(widget, action)
-            except LookupError:
-                resp = exc.HTTPNotImplemented()
-                return resp(environ, start_response)
-                
-            # If it's a widget class instantiate it with no arguments 
-            if isinstance(widget, WidgetType):
-                widget = widget('test_widget')
-            req.widget = widget
-
-        # Call controller and handle output 
-        output = controller(req, resp)
-        if isinstance(output, str):
-            resp.body = output
-        elif isinstance(output, unicode):
-            resp.body = output.encode('utf-8')
-        elif output:
-            resp = output
-
-        return resp(environ, start_response)
-
-
-    def show_template(self, req, resp):
-        widget = req.widget
-        if getattr(widget, 'demo_for', None):
-            widget = req.widget.demo_for()
-        template = util.widget_template(widget)
-        if template:
-            return util.format_code(template, 'html')
-        else:
-            resp.content_type = "text/plain"
-            return widget.__class__.__name__ + ' has no template.'
-
-    def show_source(self, req, resp):
-        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
-        source = inspect.getsource(cls)
-        return util.format_code(source, 'python')
-
-    def show_demo_source(self, req, resp):
-        widget = req.widget
-        source = inspect.getsource(widget.__class__)
-        return util.format_code(source, 'python')
-
-    def show_parameters(self, req, resp):
-        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
-        parameters = util.WidgetParameters(cls)
-        return self.render('widget_parameters.html', locals())
-
-
-    def show_index(self, req, resp):
-        widget = req.widget
-        return self.render('widget_index.html', locals())
-
-    @cache_rendered
-    def show_demo(self, req, resp):
-        widget = req.widget
-        widget_name = widget.__class__.__name__
-        interactive = self.interactive
-        if have_formencode and req.method.upper() == "POST":
-            # A widget submission, try to validate.
-            try:
-                value = widget.validate(req.POST)
-                value = util.pretty_print(value)
-                return self.render('validation_result.html', locals())
-            except Invalid, error:
-                pass
-
-        if self.interactive:
-            _disp = req.GET.get('_disp', '')
-        else:
-            _disp = ''
-
-        widget_output = util.display_widget(widget, _disp, self.context)
-
-        # Wrap non-genshi things, like Mako based widgets, in a Genshi Markup object
-        if not callable(widget_output):
-            widget_output = Markup(widget_output)
-
-        # Inject moksha's global resources so we can get things like
-        # Orbited/Stomp/jQuery/etc.
-        from moksha.api.widgets.global_resources import global_resources
-        global_resources.register_resources()
-
-        return self.render('show_widget.html', locals())
-
-    def widgets(self, req, resp):
-        widgets = [(util.widget_path(w), util.widget_url(w))
-                       for w in util.all_widgets()]
-        widgets.sort()
-        return self.render('list_widgets.html', locals())
-
-    def home(self, req, resp):
-        widgets.jquery_js.inject()
-        widgets.tabs_css.inject()
-        widgets.ui_tabs_js.inject()
-        def url(s):
-            return req.script_name + s
-        return self.render('home.html', locals())


commit ab3334dc6d2eedad9e7a35e43b0e1984e6a6e087
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:39:06 2009 -0400

    Handle our new widgetbrowser location

diff --git a/docs/conf.py b/docs/conf.py
index 2a70ec7..55bc70b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -162,8 +162,12 @@ code_path = test_path = os.path.dirname(os.path.abspath(__file__)) + os.path.sep
 try:
     import widgetbrowser
     extensions.append("widgetbrowser.sphinx_ext")
-except:
-    print "Unable to import the `widgetbrowser`.  Try doing `cd moksha/widgetbrowser; python setup.py develop` to install it."
+except ImportError:
+    try:
+        from moksha.apps import widgetbrowser
+        extensions.append("moksha.apps.widgetbrowser.sphinx_ext")
+    except ImportError:
+        print "Unable to import the `widgetbrowser`"
 
 #
 # example configuration for intersphinx: refer to the python standard library.


commit 1820a46c91d0c03ed39bd8e091f6f7eb4ab23127
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:11:47 2009 -0400

    Mark the demo app as being deprecated

diff --git a/moksha/apps/demo/DEPRECATED b/moksha/apps/demo/DEPRECATED
new file mode 100644
index 0000000..e69de29


commit 4fb0a9b65e0df0ba1b6b4932f3a1203b7403abe9
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 23:10:16 2009 -0400

    Get our widgetbrowser working in the new moksha.docs app

diff --git a/moksha/apps/docs/MANIFEST.in b/moksha/apps/docs/MANIFEST.in
new file mode 100644
index 0000000..2d731e7
--- /dev/null
+++ b/moksha/apps/docs/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include moksha *.html *.js *.png *.gif *.css *.jpg *.jpeg
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py b/moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py
index 31ccd04..c61ab19 100644
--- a/moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py
@@ -22,7 +22,7 @@ def widgetbrowser_directive(dirname, arguments, options, content, lineno,
         prb = nodes.problematic(block_text, block_text, msg)
         return [msg, prb]
     tabs = options.get('tabs') or widget_tabs.tabs
-    prefix = os.environ.get('TW_BROWSER_PREFIX')
+    prefix = os.environ.get('TW_BROWSER_PREFIX', '/apps/docs')
     size = options.get('size')
     html = widget_tabs(widget, tabs=tabs, prefix=prefix, size=size)
     node = nodes.raw('', html, format='html')
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html
index 012ce08..92b48db 100644
--- a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <?python
-from widgetbrowser import widgets
+from moksha.apps.widgetbrowser import widgets
 ?>
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
       xmlns:py="http://genshi.edgewall.org/">
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html
index 4759c25..76ee215 100644
--- a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html
@@ -2,8 +2,8 @@
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
       xmlns:py="http://genshi.edgewall.org/">
   <?python
-      from widgetbrowser.widgets import WidgetBrowserTabs
-      from widgetbrowser.util import widget_path
+      from moksha.apps.widgetbrowser.widgets import WidgetBrowserTabs
+      from moksha.apps.widgetbrowser.util import widget_path
       browser = WidgetBrowserTabs(size='x-large')
   ?>
   <head>
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py b/moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py
index ca6a094..e374368 100644
--- a/moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py
@@ -4,7 +4,8 @@ import string
 
 __all__ = ['WidgetBrowserTabs']
 
-mod = 'widgetbrowser'
+mod = __name__
+#mod = 'widgetbrowser'
 flora_all_css = CSSLink(modname=mod, filename="static/themes/flora/flora.all.css")
 tabs_css = CSSLink(modname=mod, filename="static/ui.tabs.css")
 wb_css = CSSLink(modname=mod, filename="static/widgetbrowser.css")
@@ -36,7 +37,7 @@ httprepl_js = JSLink(modname=mod, filename='static/httprepl.js',
                      location="bodybottom")
 
 class WidgetBrowserTabs(Widget):
-    template = "genshi:widgetbrowser.templates.widget_browser_tabs"
+    template = "genshi:moksha.apps.widgetbrowser.templates.widget_browser_tabs"
     params = ["tabs", "prefix", "size", "in_sphinx"]
     in_sphinx = False
     javascript = [widgetbrowser_js]
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py b/moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py
index bfa5d4f..a1069cb 100644
--- a/moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py
@@ -58,12 +58,12 @@ class WidgetBrowser(object):
             self.http_repl = exc.HTTPForbidden("Interactive mode is disabled")
         if docs_dir:
             from paste.cascade import Cascade
-            dest_dir = os.path.abspath(os.path.join(docs_dir, '.build'))
-            log.info('Building docs...')
-            try:
-                util.build_docs(docs_dir, dest_dir)
-            except Exception, e:
-                log.warning('Skipping building docs: %s' % str(e))
+            dest_dir = os.path.abspath(os.path.join(docs_dir))
+            #log.info('Building docs...')
+            #try:
+            #    util.build_docs(docs_dir, dest_dir)
+            #except Exception, e:
+            #    log.warning('Skipping building docs: %s' % str(e))
             self.built_docs = dest_dir
             self.app = Cascade([self.docs_app, self.app])
         if asbool(full_stack):
@@ -124,7 +124,7 @@ class WidgetBrowser(object):
     def __call__(self, environ, start_response):
         return self.app(environ, start_response)
 
-    @cache_rendered
+    #@cache_rendered
     def app(self, environ, start_response):
         req = Request(environ)
         resp = Response(request=req, content_type='text/html; charset=utf-8')
diff --git a/moksha/apps/docs/pavement.py b/moksha/apps/docs/pavement.py
index 941b49a..b031509 100644
--- a/moksha/apps/docs/pavement.py
+++ b/moksha/apps/docs/pavement.py
@@ -19,6 +19,7 @@ options(
         author_email="lmacken at redhat.com",
         packages=find_packages(),
         package_data=find_package_data(),
+        include_package_data=True,
         install_requires=["Moksha"],
         namespace_packages=['moksha'],
         entry_points={


commit 34b110678b4526a51ae5c312070c7af404234ded
Author: Luke Macken <lmacken at redhat.com>
Date:   Sat Aug 8 22:26:23 2009 -0400

    Integrate the ToscaWidget WidgetBrowser into our moksha.docs app

diff --git a/moksha/apps/docs/moksha/apps/docs.py b/moksha/apps/docs/moksha/apps/docs.py
index 175db7f..0e6912c 100644
--- a/moksha/apps/docs/moksha/apps/docs.py
+++ b/moksha/apps/docs/moksha/apps/docs.py
@@ -39,14 +39,14 @@ import os
 from tg import config
 from tg.controllers import WSGIAppController
 from pkg_resources import resource_filename
-from widgetbrowser import WidgetBrowser
+from moksha.apps.widgetbrowser import WidgetBrowser
 
 os.environ['TW_BROWSER_PREFIX'] = '/apps/docs'
 
 docs = WSGIAppController(
             WidgetBrowser(
                 template_dirs=[
-                    resource_filename('moksha','templates/widget_browser')],
+                    resource_filename('moksha.apps.widgetbrowser','templates')],
                 docs_dir=config.get('docs_dir', 'docs'),
                 full_stack=False,
                 interactive=False))
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/__init__.py b/moksha/apps/docs/moksha/apps/widgetbrowser/__init__.py
new file mode 100644
index 0000000..c037ed3
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/__init__.py
@@ -0,0 +1,2 @@
+from wsgiapp import WidgetBrowser
+from util import widget_url
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/command.py b/moksha/apps/docs/moksha/apps/widgetbrowser/command.py
new file mode 100644
index 0000000..c32907e
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/command.py
@@ -0,0 +1,54 @@
+from wsgiref.simple_server import make_server
+from optparse import OptionParser
+
+from moksha.apps.widgetbrowser.wsgiapp import WidgetBrowser
+
+
+_parser = OptionParser(usage = "%prog [OPTIONS] [widget_url]")
+_parser.add_option("-i", "--interactive",
+                   dest="interactive",
+                   action="store_true",
+                   default=False)
+_parser.add_option("-b", "--browser",
+                   dest="browser",
+                   action="store_true",
+                   default=False)
+_parser.add_option("-d", "--docs",
+                   dest="docs",
+                   default=None)
+_parser.add_option("-p", "--port",
+                   dest="port",
+                   default=8000)
+
+def browser_command(argv=None):
+    """Command line interface to launch the widgetbrowser"""
+    opts, args = _parser.parse_args(argv)
+
+    # Only allow passing display arguments in debug mode 
+    if args:
+        widget_url = args[0] + '/'
+    else:
+        widget_url = ''
+    app = WidgetBrowser(interactive=opts.interactive, docs_dir=opts.docs)
+    if opts.interactive:
+        try:
+            from weberror.evalexception import EvalException
+            app = EvalException(app)
+        except ImportError:
+            raise ImportError("You need to install WebError for interactive "
+                              "debugging")
+    url = "http://127.0.0.1:%s/" % opts.port
+    if opts.browser:
+        import webbrowser
+        webbrowser.open(url + widget_url)
+    server = make_server('127.0.0.1', int(opts.port), app)
+    print "Server started at " + url
+    try:
+        server.serve_forever()
+    except (KeyboardInterrupt, SystemExit):
+        pass
+
+if __name__ == '__main__':
+    import sys
+    sys.exit(browser_command(sys.argv))
+
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/repl.py b/moksha/apps/docs/moksha/apps/widgetbrowser/repl.py
new file mode 100644
index 0000000..3897f4d
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/repl.py
@@ -0,0 +1,305 @@
+"""
+Robert Brewer was the original author of the module this module has heavily
+inspired from.  http://www.aminus.net/wiki/HTTPREPL
+"""
+import warnings
+from itertools import count
+import codeop
+import inspect
+import os
+import re
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+import sys
+import traceback
+
+from webob import Request, Response, exc
+
+try:
+    from formencode import Invalid
+    have_formencode = True
+except ImportError:
+    have_formencode = False
+
+from genshi.util import LRUCache
+import tw
+from tw.api import make_middleware, Widget
+
+from moksha.apps.widgetbrowser import util, widgets
+
+class HTTPREPL:
+    
+    def __init__(self, locals=None):
+        self.locals = {}
+        if locals:
+            self.locals.update(locals)
+        self.buffer = []
+    
+    def push(self, line):
+        """Push 'line' and return exec results (None if more input needed)."""
+        if line == "help":
+            return "Type help(object) for help about object."
+        if line == "help()":
+            return "You cannot call help() without an argument."
+        
+        self.buffer.append(line)
+        source = "\n".join(self.buffer)
+        
+        try:
+            code = codeop.compile_command(source, "<HTTP input>", 'single')
+        except (OverflowError, SyntaxError, ValueError):
+            self.buffer = []
+            return traceback.format_exc()
+        
+        if code is None:
+            # More lines needed.
+            return None
+        
+        self.buffer = []
+        return self.execute(code)
+    
+    def execute(self, code):
+        """Execute the given code in self.locals and return any stdout/sterr."""
+        out = StringIO()
+        oldout = sys.stdout
+        olderr = sys.stderr
+        sys.stdout = sys.stderr = out
+        try:
+            try:
+                exec code in self.locals
+            except:
+                result = traceback.format_exc()
+            else:
+                result = out.getvalue()
+        finally:
+            # FormEncode will break if _ is left in __builtins__ and it tries
+            # to use it as a translator
+            __builtins__.pop('_', None)
+            sys.stdout = oldout
+            sys.stderr = olderr
+        out.close()
+        return result
+    
+    def dir(self, line):
+        """Examine a partial line and provide attr list of final expr."""
+        line = re.split(r"\s", line)[-1].strip()
+        # Support lines like "thing.attr" as "thing.", because the browser
+        # may not finish calculating the partial line until after the user
+        # has clicked on a few more keys.
+        line = ".".join(line.split(".")[:-1])
+        try:
+            result = eval("dir(%s)" % line, {}, self.locals)
+        except:
+            return []
+        return result
+    
+    def doc(self, line):
+        """Examine a partial line and provide sig+doc of final expr."""
+        line = re.split(r"\s", line)[-1].strip()
+        # Support lines like "func(text" as "func(", because the browser
+        # may not finish calculating the partial line until after the user
+        # has clicked on a few more keys.
+        line = "(".join(line.split("(")[:-1])
+        try:
+            result = eval(line, {}, self.locals)
+            try:
+                if isinstance(result, type):
+                    func = result.__init__
+                else:
+                    func = result
+                args, varargs, varkw, defaults = inspect.getargspec(func)
+            except TypeError:
+                if callable(result):
+                    doc = getattr(result, "__doc__", "") or ""
+                    return "%s\n\n%s" % (line, doc)
+                return None
+        except:
+            return None
+        
+        if args and args[0] == 'self':
+            args.pop(0)
+        missing = object()
+        defaults = defaults or []
+        defaults = ([missing] * (len(args) - len(defaults))) + list(defaults)
+        arglist = []
+        for a, d in zip(args, defaults):
+            if d is missing:
+                arglist.append(a)
+            else:
+                arglist.append("%s=%s" % (a, d))
+        if varargs:
+            arglist.append("*%s" % varargs)
+        if varkw:
+            arglist.append("**%s" % varkw)
+        doc = getattr(result, "__doc__", "") or ""
+        return "%s(%s)\n%s" % (line, ", ".join(arglist), doc)
+
+
+class DeferredDisplay(object):
+    """Wraps a widget and the args passed to display/render so we can defer
+    its display to another request.
+    
+    .. note::
+        The JS code is dependent on the output of __repr__ since it parses it
+        to know a widget is being displayed so it can open an overlay.
+    """
+    _counter = count(0)
+    def __init__(self, widget, value, **kw):
+        self.id = self._counter.next()
+        self.value = value
+        self.widget = widget
+        self.kw = kw
+
+    def display(self):
+        """
+        Displays the widget as it was intended to be displayed when it was
+        wrapped.
+        """
+        return self.widget.display(self.value, **self.kw)
+
+    __call__ = display
+
+    def __repr__(self):
+        data = (self.id, self.widget.__class__)
+        return self.__class__.__name__ + repr(data)
+
+
+class WidgetReplApp(object):
+    def __init__(self, locals=None, widget_browser=None, max_dialogs=10):
+        self.repl = HTTPREPL(locals)
+        warnings.warn("\n"*2 + "*"*79 + "\n"
+                      "DISCLAIMER:\n"
+                      "Running this app poses a significant security threat "
+                      "if accessible to an \nattacker. Make sure the server is "
+                      "bound to the loopback interface or behind\na firewall "
+                      "and that there are no local untrusted users.\n" + "*"*79)
+        if widget_browser:
+            self.widget_browser = widget_browser
+            self.displayed_widgets = LRUCache(max_dialogs)
+            self.setup_tw()
+
+    def setup_tw(repl_app):
+        # Stack TW's middleware configured with dummy default_view to signal
+        # that a widget is being displayed so we can wrap and register its
+        # output.
+        conf = {'toscawidgets.framework.default_view' : 'tw_repl',
+                'toscawidgets.middleware.inject_resources' : True}
+        repl_app.app = make_middleware(repl_app.app, conf)
+        # monkey-patch display and render to hijack output
+        def wrap(f):
+            if f.func_name == 'wrapper':
+                return f
+            def wrapper(self, value=None, **kw):
+                if self.displays_on == 'tw_repl':
+                    o = DeferredDisplay(self, value, **kw)
+                    repl_app.displayed_widgets[o.id] = o
+                else:
+                    o = f(self, value, **kw)
+                return o
+            return wrapper
+        Widget.display = wrap(Widget.display)
+        Widget.render = wrap(Widget.render)
+
+    def __call__(self, environ, start_response):
+        assert not environ['wsgi.multiprocess'], "Cannot run in a multiprocess"\
+                                                 " environment"
+        return self.app(environ, start_response)
+
+    def app(self, environ, start_response):
+        """Main dispatcher. pops PATH_INFO and delegates to exposed methods."""
+        req = Request(environ.copy())
+        resp = Response(request=req, content_type='text/html; charset=UTF8')
+        first_part = req.path_info_pop() or 'index'
+        method = getattr(self, first_part, None)
+        if getattr(method, 'exposed', False):
+            output = method(req, resp)
+            if isinstance(output, unicode):
+                resp.body = output.encode('utf-8')
+            elif isinstance(output, str):
+                resp.body = output
+            elif output:
+                resp = output
+        else:
+            resp = exc.HTTPNotImplemented()
+        return resp(environ, start_response)
+        
+    def index(self, req, resp):
+        """Return an HTTP-based Read-Eval-Print-Loop terminal."""
+        # Override default_view so resources display properly
+        tw.framework.default_view = 'toscawidgets'
+        tpl = '<html><head><title>"%(title)s</title></head>' \
+              '<body class="flora">%(repl)s</body></html>'
+        prefix = req.script_name + '/'
+        return tpl % {'title': 'WidgetBrowser Terminal',
+                      'repl': widgets.repl(prefix=req.script_name + '/')}
+    index.exposed = True
+    
+    def push(self, req, resp):
+        """Push 'line' and return exec results as a bare response."""
+        line = req.params['line']
+        result = self.repl.push(line)
+        if result is None:
+            # More input lines needed.
+            resp.status_int = 204
+        return result
+    push.exposed = True
+    
+    def dir(self, req, resp):
+        """Push 'line' and return result of eval on the final expr."""
+        line = req.params['line']
+        result = self.repl.dir(line)
+        if not result:
+            resp.status_int = 204
+            return
+        return repr(result)
+    dir.exposed = True
+    
+    def doc(self, req, resp):
+        """Push 'line' and return result of getargspec on the final expr."""
+        line = req.params['line']
+        result = self.repl.doc(line)
+        if not result:
+            resp.status_int = 204
+        return result
+    doc.exposed = True
+    
+    def enrich_namespace(self, ns, request):
+        
+        _disp = request.GET.get('_disp', '')
+        
+        if not "_disp" in ns:
+            ns["_disp"]=_disp
+        if not "interactive" in ns:
+            ns["interactive"]=True
+        return ns
+    
+    def widget_output(self, req, resp):
+        try:
+            key = int(req.path_info.strip('/'))
+            dd = self.displayed_widgets[key]
+        except KeyError:
+            resp.status_int = 404
+            return "There's now widget output at this URL. Maybe it has "\
+                   "expired? Try increasing the 'max_dialogs' parameter"
+
+        widget = dd.widget
+        widget_name = widget.__class__.__name__
+        render = self.widget_browser.render
+        if have_formencode and req.method.upper() == "POST":
+            # A widget submission, try to validate.
+            try:
+                value = widget.validate(req.POST)
+                value = util.pretty_print(value)
+                return render('validation_result.html', locals())
+            except Invalid, error:
+                pass
+        # Override default_view because WidgetBrowser renders on Genshi, not
+        # 'tw_repl', this is needed so widget and resources display properly
+        tw.framework.default_view = 'genshi'
+        widget_output = dd.display()
+        return render('show_widget.html', self.enrich_namespace(locals(),request=req))
+    widget_output.exposed = True
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py b/moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py
new file mode 100644
index 0000000..31ccd04
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/sphinx_ext.py
@@ -0,0 +1,43 @@
+import os
+from docutils import nodes, utils
+from docutils.parsers.rst import directives
+
+from moksha.apps.widgetbrowser import util, widgets
+
+widget_tabs = widgets.WidgetBrowserTabs(in_sphinx=True)
+
+def widgetbrowser_directive(dirname, arguments, options, content, lineno,
+                            content_offset, block_text, state, state_machine):
+    """Processes the `widgetbrowser` reStructuredText directive.
+    
+    When generating the URL for the widget it peeks into os.environ for the
+    'TW_BROWSER_PREFIX' environment variable.
+    """
+    widget_path = arguments[0]
+    widget = util.import_widget(widget_path)
+    if not widget:
+        reporter = state.document.reporter
+        msg = reporter.warning(
+            'No widget found at %r' % widget_path, line=lineno)
+        prb = nodes.problematic(block_text, block_text, msg)
+        return [msg, prb]
+    tabs = options.get('tabs') or widget_tabs.tabs
+    prefix = os.environ.get('TW_BROWSER_PREFIX')
+    size = options.get('size')
+    html = widget_tabs(widget, tabs=tabs, prefix=prefix, size=size)
+    node = nodes.raw('', html, format='html')
+    return [node]
+
+
+def _get_tabs(arg):
+    if arg is None:
+        return []
+    return [s.strip() for s in arg.split(',')]
+    
+def _get_size(arg):
+    return arg or "small"
+
+def setup(app):
+    browser_options = {'tabs': _get_tabs, 'size':_get_size}
+    app.add_directive('widgetbrowser', widgetbrowser_directive, 1, (1, 0, 1),
+                      **browser_options)
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.css
new file mode 100644
index 0000000..6eda851
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.css
@@ -0,0 +1,78 @@
+.httprepl .output pre {
+    font: 10pt monospace;
+    margin: 0;
+    padding: 1px;
+    border: 1px solid #E0E0FF;
+    background-color: #F8F8FF;
+    
+    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
+    white-space: -pre-wrap; /* Opera 4 - 6 */
+    white-space: -o-pre-wrap; /* Opera 7 */
+    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
+                            http://www.w3.org/TR/css3-text/#white-space */
+    word-wrap: break-word; /* IE 5.5+ */
+}
+
+.httprepl .output pre.stdin {
+    border: none;
+    background-color: transparent;
+}
+
+form {
+    font: 10pt monospace;
+    margin: 0;
+}
+
+.httprepl .input {
+    font: 10pt monospace;
+    width: 95%;
+    border-top: none;
+    border-right: 1px dotted #E0E0FF;
+    border-bottom: none;
+    border-left: 1px dotted #E0E0FF;
+}
+
+.httprepl .tipbar {
+    position: fixed;
+    top: 10px;
+    
+    /* See http://annevankesteren.nl/test/examples/ie/position-fixed.html */
+    _position:absolute;
+    _top:expression(eval(document.body.scrollTop) + 10);
+    
+    right: 10px;
+    
+    max-width: 50%;
+    max-height: 80%;
+    /* See http://www.svendtofte.com/code/max_width_in_ie/ */
+    width: expression(document.body.clientWidth / 2);
+    height: expression(document.body.clientHeight * 0.8);
+    
+    border: 2px outset #DDCCBB;
+    background-color: #FFEEDD;
+    font: 9pt monospace;
+    
+    margin: 0;
+    padding: 4px;
+    
+    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
+    white-space: -pre-wrap; /* Opera 4 - 6 */
+    white-space: -o-pre-wrap; /* Opera 7 */
+    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation)
+                            http://www.w3.org/TR/css3-text/#white-space */
+    word-wrap: break-word; /* IE 5.5+ */
+    
+    display: none;
+    overflow: auto;
+}
+
+.httprepl .tipbar a {
+    padding: 4px;
+    text-decoration: none;
+    color: #666666;
+}
+
+.widget-dialog  {
+    background: #fff;
+    z-index: 9999;
+}
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.js
new file mode 100644
index 0000000..a85f1ef
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/httprepl.js
@@ -0,0 +1,432 @@
+var HTTPRepl = (function ($) {
+    function http() {
+        var h;
+        if (typeof(XMLHttpRequest) != "undefined") {
+            h = new XMLHttpRequest();
+        } else {
+            try { h = new ActiveXObject("Msxml2.XMLHTTP"); }
+            catch (e) {
+                try { h = new ActiveXObject("Microsoft.XMLHTTP"); }
+                catch (E) { alert("Your browser is not supported."); }
+            }
+        }
+        return h
+    }
+
+
+    //                           HISTORY NAVIGATION                           //
+
+    function use_history(elem) {
+        var content = get_text(elem);
+        // Strip the leading prompt
+        if (elem.className == 'stdin') content = content.substr(4);
+        input.value = content;
+        input.focus();
+    }
+
+    function history_hook() {
+        use_history(this);
+    }
+
+    var current_history = undefined;
+
+    function prev_history() {
+        if (current_history == undefined) {
+            var prev = output.lastChild;
+        } else {
+            var prev = current_history.previousSibling;
+        }
+        while (prev != null && prev.className != 'stdin') {
+            prev = prev.previousSibling;
+        }
+        if (prev != null) {
+            current_history = prev;
+            use_history(prev);
+        }
+    }
+
+    function next_history() {
+        if (current_history == undefined) return;
+        
+        var next = current_history.nextSibling;
+        while (next != null && next.className != 'stdin') {
+            next = next.nextSibling;
+        }
+        if (next != null) {
+            current_history = next;
+            use_history(next);
+        }
+    }
+
+
+    //                            CODE COMPLETION                            //
+
+    current_range = undefined;
+
+    function partial_line() {
+        if (document.selection) {
+            // Internet Explorer
+            current_range = document.selection.createRange();
+            var end = current_range.getBookmark().charCodeAt(2) - 2;
+        } else {
+            var end = input.selectionEnd;
+        }
+        return input.value.substring(0, end);
+    }
+
+    function insert_text(newtext) {
+        if (document.selection) {
+            // Internet Explorer
+            current_range.text = newtext;
+            current_range.select();
+        } else {
+            var start = input.selectionStart;
+            input.value = input.value.substring(0, start) + newtext + input.value.substr(input.selectionEnd);
+            var end = start + newtext.length;
+            input.setSelectionRange(end, end);
+        }
+    }
+
+    function clear_tips() {
+        tipbar.style.display = '';
+        while (tipbar.hasChildNodes()) {
+            tipbar.removeChild(tipbar.lastChild);
+        }
+    }
+
+    function show_tips() {
+        tipbar.style.display = 'block';
+    }
+
+    var intip = false;
+
+    function use_tip() {
+        insert_text(get_text(this));
+        clear_tips();
+        intip = true;
+        input.focus();
+    }
+
+    function dir() {
+        var data = partial_line();
+        
+        clear_tips();
+        
+        var h = http();
+        h.onreadystatechange = function() {
+            if (h.readyState == 4) {
+                try {
+                    var status = h.status;
+                } catch(e) {
+                    var status = "NO HTTP RESPONSE";
+                }
+                switch (status) {
+                    case 200:
+                        var tips = eval(h.responseText);
+                        for (var i=0; i < tips.length; i++) {
+                            var tiplink = document.createElement("a");
+                            tiplink.onclick = use_tip;
+                            tiplink.href = "javascript:void(0)";
+                            set_text(tiplink, tips[i]);
+                            tipbar.appendChild(tiplink);
+                            tipbar.appendChild(document.createElement("br"));
+                        }
+                        show_tips()
+                        input.focus();
+                        break;
+                    // Internet Explorer might return 1223 for 204
+                    case 1223:
+                    case 204:
+                        // No tips available
+                        break;
+                    case 12029:
+                        // Internet Explorer client could not connect to server
+                        status = "NO HTTP RESPONSE";
+                    case 403:
+                        stdout_write("Interactive mode is disabled", false);
+                        break;
+                    default:
+                        stdout_write(status + "\n" + h.responseText, false);
+                }
+            }
+        }
+        h.open("GET", prefix + "dir?line=" + escape(data), true);
+        h.send(null);
+    }
+
+    function doc() {
+        var data = partial_line();
+        
+        clear_tips();
+        
+        var h = http();
+        h.onreadystatechange = function() {
+            if (h.readyState == 4) {
+                try {
+                    var status = h.status;
+                } catch(e) {
+                    var status = "NO HTTP RESPONSE";
+                }
+                switch (status) {
+                    case 200:
+                        tipbar.appendChild(document.createTextNode(h.responseText));
+                        show_tips();
+                        input.focus();
+                        break;
+                    // Internet Explorer might return 1223 for 204
+                    case 1223:
+                    case 403:
+                        stdout_write("Interactive mode is disabled", false);
+                        break;
+                    case 204:
+                        // No tips available
+                        break;
+                    case 12029:
+                        // Internet Explorer client could not connect to server
+                        status = "NO HTTP RESPONSE";
+                    default:
+                        stdout_write(status + "\n" + h.responseText, false);
+                }
+            }
+        }
+        h.open("GET", prefix + "doc?line=" + escape(data), true);
+        h.send(null);
+    }
+
+    //                           COMMAND EXECUTION                           //
+
+    function get_text(elem) {
+        if (elem.innerText != undefined) {
+            // Internet Explorer
+            return elem.innerText;
+        } else {
+            // Mozilla
+            return elem.textContent;
+        }
+    }
+
+    function set_text(elem, newvalue) {
+        if (elem.innerText != undefined) {
+            // Internet Explorer
+            elem.innerText = newvalue;
+        } else {
+            // Mozilla
+            elem.textContent = newvalue;
+        }
+    }
+
+    function get_prompt() {
+        return get_text(prompt_);
+    }
+
+    function set_prompt(newvalue) {
+        set_text(prompt_, newvalue);
+    }
+
+    function stdout_write(content, stdin) {
+        current_history = undefined;
+        if (content == "") return;
+        
+        var block = document.createElement("pre");
+        block.ondblclick = history_hook;
+        if (stdin) {
+            content = get_prompt() + content;
+            block.className = 'stdin';
+        }
+        if (block.innerText != undefined) {
+            // Internet Explorer quirkiness
+            block.innerText = content;
+        } else {
+            block.appendChild(document.createTextNode(content));
+        }
+        output.appendChild(block);
+    }
+
+    whitespace = /^\s+$/;
+
+    function push() {
+        var data = input.value;
+        // Uncomment to treat a line with only whitespace like a blank line
+        // if (whitespace.test(data)) data = "";
+        
+        input.value = "";
+        
+        var h = http();
+        h.onreadystatechange = function() {
+            if (h.readyState == 4) {
+                stdout_write(data, true);
+                try {
+                    var status = h.status;
+                } catch(e) {
+                    var status = "NO HTTP RESPONSE";
+                }
+                switch (status) {
+                    case 200:
+                        set_prompt(">>> ");
+                        var response = h.responseText;
+                        if (!handle_widget_output(response)) {
+                            stdout_write(response, false);
+                        }
+                        break;
+                    // Internet Explorer might return 1223 for 204
+                    case 1223:
+                    case 204:
+                        set_prompt("... ");
+                        // input.value *should* be blank, but just in case...
+                        input.value = "    " + input.value;
+                        break;
+                    case 403:
+                        stdout_write("Interactive mode is disabled", false);
+                        break;
+                    case 12029:
+                        // Internet Explorer client could not connect to server
+                        status = "NO HTTP RESPONSE";
+                    default:
+                        stdout_write(status + "\n" + h.responseText, false);
+                }
+                input.focus();
+            }
+        }
+        h.open("POST", prefix + "push", true);
+        h.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+        h.send("line=" + escape(data));
+    }
+
+
+    function escape(data) {
+        data = data.replace(/%/gi, "%25");
+        data = data.replace(/&/gi, "%26");
+        data = data.replace(/[+]/gi, "%2B");
+        data = data.replace(/;/gi, "%3B");
+        return data;
+    }
+
+
+    //                                 SETUP                                 //
+
+    function mapKeys(key_code) {
+        if (intip) {
+            intip = false;
+            // Trap the bubbling keyup event from a tiplink. This means that,
+            // if you actually click a tiplink instead of tab and hit 'enter',
+            // you have to hit 'enter' twice to push the line. :(
+            if (key_code == 13) return;
+        }
+        switch(key_code) {
+            case 8:    // backspace
+                clear_tips();
+                break;
+            case 13:   // enter
+                clear_tips();
+                push();
+                break;
+            case 38:   // up arrow
+                prev_history();
+                break;
+            case 40:   // down arrow
+                next_history();
+                break;
+            case 48:  // close paren "("
+                clear_tips();
+                break;
+            case 57:  // open paren "("
+                doc();
+                break;
+            case 190:  // period "."
+                dir();
+                break;
+        }
+    }
+
+    function trapKeys(e) {
+        if (!e) var e = window.event;
+        mapKeys(e.keyCode);
+    }
+
+    //                   WIDGET DIALOGS                                      //
+
+    var new_id = (function make_counter(value) {
+        var state = {value: value || 0};
+        function next() {
+            state.value ++;
+            return 'widget-dialog-' + state.value;
+        }
+        return next;
+    })();
+
+    function open_dialog(config) {
+        var c = $.extend({}, {height:450, width:600}, config);
+        var iframe = $('<iframe><iframe>');
+        iframe.attr({id: new_id(), 'class': 'widget-dialog'});
+        function setSize(size) {
+            var attr = {
+                height: Math.max(0, Math.round(size.height-60)),
+                width: Math.max(0, Math.round(size.width-40))
+            }
+            iframe.attr(attr);
+        }
+        function onResizeStart(event, data) {
+            // Hide the iframe so it doesn't captute mouse events while dragging
+            // the resize handlers
+            iframe.hide();
+        }
+        function onResizeStop(event, data) {
+            setSize(data.instance.size);
+            iframe.show();
+        }
+        function onClose() {
+            iframe.remove();
+            input.focus();
+        }
+        iframe.appendTo(httprepl).dialog(config)
+              .bind('dialogclose', onClose)
+              .trigger('setData.dialog', ['resizeStart', onResizeStart])
+              .trigger('setData.dialog', ['resizeStop', onResizeStop])
+              .attr('src', config.url)
+              .dialog('open');
+        setSize(c);
+    }
+
+    var displayed_widget = /DeferredDisplay\((\d+)[^']*'([^']+)'/;
+
+    function handle_widget_output(response) {
+        var match = displayed_widget(response);
+        if (match) {
+            var config = {
+                url: prefix + 'widget_output/' + match[1],
+                height: 500,
+                width: 750,
+                title: match[2]
+            }
+            open_dialog(config);
+            return true;
+        }
+        return false;
+    }
+    var httprepl = $(''
+        +'<div class="httprepl">' 
+        +  '<div class="output"></div>'
+        +  '<form action="" class="terminal">'
+        +    '<div class="tipbar"></div>'
+        +    '<nobr>'
+        +      '<span class="prompt">&gt;&gt;&gt; </span>'
+        +      '<input type="text" class="input" size=60" />'
+        +    '</nobr>'
+        +  '</form>'
+        +'</div>'
+    );
+    var prefix = '';
+    var input = $('.input', httprepl)[0];
+    input.onkeyup = trapKeys;
+    var output = $('.output', httprepl)[0];
+    var tipbar = $('.tipbar', httprepl)[0];
+    var prompt_ = $('.prompt', httprepl)[0];
+    $('form', httprepl).submit(function() { return false });
+
+    return {
+        render: function(el, config) {
+            prefix = config.prefix || '';
+            httprepl.appendTo($(el));
+        }
+    }
+})(jQuery);
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/jquery.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/jquery.js
new file mode 100644
index 0000000..ea64073
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/jquery.js
@@ -0,0 +1,3436 @@
+(function(){
+/*
+ * jQuery 1.2.4a - New Wave Javascript
+ *
+ * Copyright (c) 2008 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-04-08 13:40:03 -0300 (ter, 08 abr 2008) $
+ * $Rev: 5214 $
+ */
+
+// Map over jQuery in case of overwrite
+if ( window.jQuery )
+	var _jQuery = window.jQuery;
+
+var jQuery = window.jQuery = function( selector, context ) {
+	// The jQuery object is actually just the init constructor 'enhanced'
+	return new jQuery.prototype.init( selector, context );
+};
+
+// Map over the $ in case of overwrite
+if ( window.$ )
+	var _$ = window.$;
+	
+// Map the jQuery namespace to the '$' one
+window.$ = jQuery;
+
+// A simple way to check for HTML strings or ID strings
+// (both of which we optimize for)
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+
+// Is it a simple selector
+var isSimple = /^.[^:#\[\.]*$/;
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		// Make sure that a selection was provided
+		selector = selector || document;
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// Handle HTML strings
+		} else if ( typeof selector == "string" ) {
+			// Are we dealing with HTML string or an ID?
+			var match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] )
+					selector = jQuery.clean( [ match[1] ], context );
+
+				// HANDLE: $("#id")
+				else {
+					var elem = document.getElementById( match[3] );
+
+					// Make sure an element was located
+					if ( elem )
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id != match[3] )
+							return jQuery().find( selector );
+
+						// Otherwise, we inject the element directly into the jQuery object
+						else {
+							this[0] = elem;
+							this.length = 1;
+							return this;
+						}
+
+					else
+						selector = [];
+				}
+
+			// HANDLE: $(expr, [context])
+			// (which is just equivalent to: $(content).find(expr)
+			} else
+				return new jQuery( context ).find( selector );
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) )
+			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
+
+		return this.setArray(
+			// HANDLE: $(array)
+			selector.constructor == Array && selector ||
+
+			// HANDLE: $(arraylike)
+			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
+			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
+
+			// HANDLE: $(*)
+			[ selector ] );
+	},
+	
+	// The current version of jQuery being used
+	jquery: "1.2.4a",
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+	
+	// The number of elements contained in the matched element set
+	length: 0,
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == undefined ?
+
+			// Return a 'clean' array
+			jQuery.makeArray( this ) :
+
+			// Return just the object
+			this[ num ];
+	},
+	
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery( elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+	
+	// Force the current matched set of elements to become
+	// the specified array of elements (destroying the stack in the process)
+	// You should use pushStack() in order to do this, but maintain the stack
+	setArray: function( elems ) {
+		// Resetting the length to 0, then using the native Array push
+		// is a super-fast way to populate an object with array-like properties
+		this.length = 0;
+		Array.prototype.push.apply( this, elems );
+		
+		return this;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	// Determine the position of an element within 
+	// the matched set of elements
+	index: function( elem ) {
+		var ret = -1;
+
+		// Locate the position of the desired element
+		this.each(function(i){
+			if ( this == elem )
+				ret = i;
+		});
+
+		return ret;
+	},
+
+	attr: function( name, value, type ) {
+		var options = name;
+		
+		// Look for the case where we're accessing a style value
+		if ( name.constructor == String )
+			if ( value == undefined )
+				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
+
+			else {
+				options = {};
+				options[ name ] = value;
+			}
+		
+		// Check to see if we're setting style values
+		return this.each(function(i){
+			// Set all the styles
+			for ( name in options )
+				jQuery.attr(
+					type ?
+						this.style :
+						this,
+					name, jQuery.prop( this, options[ name ], type, i, name )
+				);
+		});
+	},
+
+	css: function( key, value ) {
+		// ignore negative width and height values
+		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+			value = undefined;
+		return this.attr( key, value, "curCSS" );
+	},
+
+	text: function( text ) {
+		if ( typeof text != "object" && text != null )
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+		var ret = "";
+
+		jQuery.each( text || this, function(){
+			jQuery.each( this.childNodes, function(){
+				if ( this.nodeType != 8 )
+					ret += this.nodeType != 1 ?
+						this.nodeValue :
+						jQuery.fn.text( [ this ] );
+			});
+		});
+
+		return ret;
+	},
+
+	wrapAll: function( html ) {
+		if ( this[0] )
+			// The elements to wrap the target around
+			jQuery( html, this[0].ownerDocument )
+				.clone()
+				.insertBefore( this[0] )
+				.map(function(){
+					var elem = this;
+
+					while ( elem.firstChild )
+						elem = elem.firstChild;
+
+					return elem;
+				})
+				.append(this);
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		return this.each(function(){
+			jQuery( this ).contents().wrapAll( html );
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function(){
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, false, function(elem){
+			if (this.nodeType == 1)
+				this.appendChild( elem );
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, true, function(elem){
+			if (this.nodeType == 1)
+				this.insertBefore( elem, this.firstChild );
+		});
+	},
+	
+	before: function() {
+		return this.domManip(arguments, false, false, function(elem){
+			this.parentNode.insertBefore( elem, this );
+		});
+	},
+
+	after: function() {
+		return this.domManip(arguments, false, true, function(elem){
+			this.parentNode.insertBefore( elem, this.nextSibling );
+		});
+	},
+
+	end: function() {
+		return this.prevObject || jQuery( [] );
+	},
+
+	find: function( selector ) {
+		var elems = jQuery.map(this, function(elem){
+			return jQuery.find( selector, elem );
+		});
+
+		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
+			jQuery.unique( elems ) :
+			elems );
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function(){
+			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to 
+				// attributes in IE that are actually only stored 
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var clone = this.cloneNode(true),
+					container = document.createElement("div");
+				container.appendChild(clone);
+				return jQuery.clean([container.innerHTML])[0];
+			} else
+				return this.cloneNode(true);
+		});
+
+		// Need to set the expando to null on the cloned set if it exists
+		// removeData doesn't work here, IE removes it from the original as well
+		// this is primarily for IE but the data expando shouldn't be copied over in any browser
+		var clone = ret.find("*").andSelf().each(function(){
+			if ( this[ expando ] != undefined )
+				this[ expando ] = null;
+		});
+		
+		// Copy the events from the original to the clone
+		if ( events === true )
+			this.find("*").andSelf().each(function(i){
+				if (this.nodeType == 3)
+					return;
+				var events = jQuery.data( this, "events" );
+
+				for ( var type in events )
+					for ( var handler in events[ type ] )
+						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+			});
+
+		// Return the cloned set
+		return ret;
+	},
+
+	filter: function( selector ) {
+		return this.pushStack(
+			jQuery.isFunction( selector ) &&
+			jQuery.grep(this, function(elem, i){
+				return selector.call( elem, i );
+			}) ||
+
+			jQuery.multiFilter( selector, this ) );
+	},
+
+	not: function( selector ) {
+		if ( selector.constructor == String )
+			// test special case where just one selector is passed in
+			if ( isSimple.test( selector ) )
+				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
+			else
+				selector = jQuery.multiFilter( selector, this );
+
+		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+		return this.filter(function() {
+			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+		});
+	},
+
+	add: function( selector ) {
+		return !selector ? this : this.pushStack( jQuery.merge( 
+			this.get(),
+			selector.constructor == String ? 
+				jQuery( selector ).get() :
+				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
+					selector : [selector] ) );
+	},
+
+	is: function( selector ) {
+		return selector ?
+			jQuery.multiFilter( selector, this ).length > 0 :
+			false;
+	},
+
+	hasClass: function( selector ) {
+		return this.is( "." + selector );
+	},
+	
+	val: function( value ) {
+		if ( value == undefined ) {
+
+			if ( this.length ) {
+				var elem = this[0];
+
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type == "select-one";
+					
+					// Nothing was selected
+					if ( index < 0 )
+						return null;
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						if ( option.selected ) {
+							// Get the specifc value for the option
+							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
+							
+							// We don't need an array for one selects
+							if ( one )
+								return value;
+							
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+					
+					return values;
+					
+				// Everything else, we just grab the value
+				} else
+					return (this[0].value || "").replace(/\r/g, "");
+
+			}
+
+			return undefined;
+		}
+
+		return this.each(function(){
+			if ( this.nodeType != 1 )
+				return;
+
+			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
+				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+					jQuery.inArray(this.name, value) >= 0);
+
+			else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = value.constructor == Array ?
+					value :
+					[ value ];
+
+				jQuery( "option", this ).each(function(){
+					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+						jQuery.inArray( this.text, values ) >= 0);
+				});
+
+				if ( !values.length )
+					this.selectedIndex = -1;
+
+			} else
+				this.value = value;
+		});
+	},
+	
+	html: function( value ) {
+		return value == undefined ?
+			(this.length ?
+				this[0].innerHTML :
+				null) :
+			this.empty().append( value );
+	},
+
+	replaceWith: function( value ) {
+		return this.after( value ).remove();
+	},
+
+	eq: function( i ) {
+		return this.slice( i, i + 1 );
+	},
+
+	slice: function() {
+		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function(elem, i){
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	},
+
+	data: function( key, value ){
+		var parts = key.split(".");
+		parts[1] = parts[1] ? "." + parts[1] : "";
+
+		if ( value == null ) {
+			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+			
+			if ( data == undefined && this.length )
+				data = jQuery.data( this[0], key );
+
+			return data == null && parts[1] ?
+				this.data( parts[0] ) :
+				data;
+		} else
+			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+				jQuery.data( this, key, value );
+			});
+	},
+
+	removeData: function( key ){
+		return this.each(function(){
+			jQuery.removeData( this, key );
+		});
+	},
+	
+	domManip: function( args, table, reverse, callback ) {
+		var clone = this.length > 1, elems; 
+
+		return this.each(function(){
+			if ( !elems ) {
+				elems = jQuery.clean( args, this.ownerDocument );
+
+				if ( reverse )
+					elems.reverse();
+			}
+
+			var obj = this;
+
+			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
+				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
+
+			var scripts = jQuery( [] );
+
+			jQuery.each(elems, function(){
+				var elem = clone ?
+					jQuery( this ).clone( true )[0] :
+					this;
+
+				// execute all scripts after the elements have been injected
+				if ( jQuery.nodeName( elem, "script" ) ) {
+					scripts = scripts.add( elem );
+				} else {
+					// Remove any inner scripts for later evaluation
+					if ( elem.nodeType == 1 )
+						scripts = scripts.add( jQuery( "script", elem ).remove() );
+
+					// Inject the elements into the document
+					callback.call( obj, elem );
+				}
+			});
+
+			scripts.each( evalScript );
+		});
+	}
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.prototype.init.prototype = jQuery.prototype;
+
+function evalScript( i, elem ) {
+	if ( elem.src )
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+
+	else
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+	if ( elem.parentNode )
+		elem.parentNode.removeChild( elem );
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+	// copy reference to target object
+	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+	// Handle a deep copy situation
+	if ( target.constructor == Boolean ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target != "object" && typeof target != "function" )
+		target = {};
+
+	// extend jQuery itself if only one argument is passed
+	if ( length == 1 ) {
+		target = this;
+		i = 0;
+	}
+
+	for ( ; i < length; i++ )
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null )
+			// Extend the base object
+			for ( var name in options ) {
+				// Prevent never-ending loop
+				if ( target === options[ name ] )
+					continue;
+
+				// Recurse if we're merging object values
+				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
+					target[ name ] = jQuery.extend( deep, target[ name ], options[ name ] );
+
+				// Don't bring in undefined values
+				else if ( options[ name ] != undefined )
+					target[ name ] = options[ name ];
+
+			}
+
+	// Return the modified object
+	return target;
+};
+
+var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
+
+// exclude the following css properties to add px
+var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep )
+			window.jQuery = _jQuery;
+
+		return jQuery;
+	},
+
+	// See test/unit/core.js for details concerning this function.
+	isFunction: function( fn ) {
+		return !!fn && typeof fn != "string" && !fn.nodeName && 
+			fn.constructor != Array && /function/i.test( fn + "" );
+	},
+	
+	// check if an element is in a (or is an) XML document
+	isXMLDoc: function( elem ) {
+		return elem.documentElement && !elem.body ||
+			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+	},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		data = jQuery.trim( data );
+
+		if ( data ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+			if ( jQuery.browser.msie )
+				script.text = data;
+			else
+				script.appendChild( document.createTextNode( data ) );
+
+			head.appendChild( script );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+	},
+	
+	cache: {},
+	
+	data: function( elem, name, data ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// Compute a unique ID for the element
+		if ( !id ) 
+			id = elem[ expando ] = ++uuid;
+
+		// Only generate the data cache if we're
+		// trying to access or manipulate it
+		if ( name && !jQuery.cache[ id ] )
+			jQuery.cache[ id ] = {};
+		
+		// Prevent overriding the named cache with undefined values
+		if ( data != undefined )
+			jQuery.cache[ id ][ name ] = data;
+		
+		// Return the named cache data, or the ID for the element	
+		return name ?
+			jQuery.cache[ id ][ name ] :
+			id;
+	},
+	
+	removeData: function( elem, name ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// If we want to remove a specific section of the element's data
+		if ( name ) {
+			if ( jQuery.cache[ id ] ) {
+				// Remove the section of cache data
+				delete jQuery.cache[ id ][ name ];
+
+				// If we've removed all the data, remove the element's cache
+				name = "";
+
+				for ( name in jQuery.cache[ id ] )
+					break;
+
+				if ( !name )
+					jQuery.removeData( elem );
+			}
+
+		// Otherwise, we want to remove all of the element's data
+		} else {
+			// Clean up the element expando
+			try {
+				delete elem[ expando ];
+			} catch(e){
+				// IE has trouble directly removing the expando
+				// but it's ok with using removeAttribute
+				if ( elem.removeAttribute )
+					elem.removeAttribute( expando );
+			}
+
+			// Completely remove the data cache
+			delete jQuery.cache[ id ];
+		}
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		if ( args ) {
+			if ( object.length == undefined ) {
+				for ( var name in object )
+					if ( callback.apply( object[ name ], args ) === false )
+						break;
+			} else
+				for ( var i = 0, length = object.length; i < length; i++ )
+					if ( callback.apply( object[ i ], args ) === false )
+						break;
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( object.length == undefined ) {
+				for ( var name in object )
+					if ( callback.call( object[ name ], name, object[ name ] ) === false )
+						break;
+			} else
+				for ( var i = 0, length = object.length, value = object[0]; 
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+		}
+
+		return object;
+	},
+	
+	prop: function( elem, value, type, i, name ) {
+			// Handle executable functions
+			if ( jQuery.isFunction( value ) )
+				value = value.call( elem, i );
+				
+			// Handle passing in a number to a CSS property
+			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
+				value + "px" :
+				value;
+	},
+
+	className: {
+		// internal only, use addClass("class")
+		add: function( elem, classNames ) {
+			jQuery.each((classNames || "").split(/\s+/), function(i, className){
+				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+					elem.className += (elem.className ? " " : "") + className;
+			});
+		},
+
+		// internal only, use removeClass("class")
+		remove: function( elem, classNames ) {
+			if (elem.nodeType == 1)
+				elem.className = classNames != undefined ?
+					jQuery.grep(elem.className.split(/\s+/), function(className){
+						return !jQuery.className.has( classNames, className );	
+					}).join(" ") :
+					"";
+		},
+
+		// internal only, use is(".class")
+		has: function( elem, className ) {
+			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( var name in options )
+			elem.style[ name ] = old[ name ];
+	},
+
+	css: function( elem, name, force ) {
+		if ( name == "width" || name == "height" ) {
+			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+		
+			function getWH() {
+				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+				var padding = 0, border = 0;
+				jQuery.each( which, function() {
+					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+				});
+				val -= Math.round(padding + border);
+			}
+		
+			if ( jQuery(elem).is(":visible") )
+				getWH();
+			else
+				jQuery.swap( elem, props, getWH );
+			
+			return Math.max(0, val);
+		}
+		
+		return jQuery.curCSS( elem, name, force );
+	},
+
+	curCSS: function( elem, name, force ) {
+		var ret;
+
+		// A helper method for determining if an element's values are broken
+		function color( elem ) {
+			if ( !jQuery.browser.safari )
+				return false;
+
+			var ret = document.defaultView.getComputedStyle( elem, null );
+			return !ret || ret.getPropertyValue("color") == "";
+		}
+
+		// We need to handle opacity special in IE
+		if ( name == "opacity" && jQuery.browser.msie ) {
+			ret = jQuery.attr( elem.style, "opacity" );
+
+			return ret == "" ?
+				"1" :
+				ret;
+		}
+		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
+		if ( jQuery.browser.opera && name == "display" ) {
+			var save = elem.style.outline;
+			elem.style.outline = "0 solid black";
+			elem.style.outline = save;
+		}
+		
+		// Make sure we're using the right name for getting the float value
+		if ( name.match( /float/i ) )
+			name = styleFloat;
+
+		if ( !force && elem.style && elem.style[ name ] )
+			ret = elem.style[ name ];
+
+		else if ( document.defaultView && document.defaultView.getComputedStyle ) {
+
+			// Only "float" is needed here
+			if ( name.match( /float/i ) )
+				name = "float";
+
+			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+			var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
+
+			if ( getComputedStyle && !color( elem ) )
+				ret = getComputedStyle.getPropertyValue( name );
+
+			// If the element isn't reporting its values properly in Safari
+			// then some display: none elements are involved
+			else {
+				var swap = [], stack = [];
+
+				// Locate all of the parent display: none elements
+				for ( var a = elem; a && color(a); a = a.parentNode )
+					stack.unshift(a);
+
+				// Go through and make them visible, but in reverse
+				// (It would be better if we knew the exact display type that they had)
+				for ( var i = 0; i < stack.length; i++ )
+					if ( color( stack[ i ] ) ) {
+						swap[ i ] = stack[ i ].style.display;
+						stack[ i ].style.display = "block";
+					}
+
+				// Since we flip the display style, we have to handle that
+				// one special, otherwise get the value
+				ret = name == "display" && swap[ stack.length - 1 ] != null ?
+					"none" :
+					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
+
+				// Finally, revert the display styles back
+				for ( var i = 0; i < swap.length; i++ )
+					if ( swap[ i ] != null )
+						stack[ i ].style.display = swap[ i ];
+			}
+
+			// We should always get a number back from opacity
+			if ( name == "opacity" && ret == "" )
+				ret = "1";
+
+		} else if ( elem.currentStyle ) {
+			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+			// From the awesome hack by Dean Edwards
+			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+			// If we're not dealing with a regular pixel number
+			// but a number that has a weird ending, we need to convert it to pixels
+			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+				// Remember the original values
+				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
+
+				// Put in the new values to get a computed value out
+				elem.runtimeStyle.left = elem.currentStyle.left;
+				elem.style.left = ret || 0;
+				ret = elem.style.pixelLeft + "px";
+
+				// Revert the changed values
+				elem.style.left = style;
+				elem.runtimeStyle.left = runtimeStyle;
+			}
+		}
+
+		return ret;
+	},
+	
+	clean: function( elems, context ) {
+		var ret = [];
+		context = context || document;
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if (typeof context.createElement == 'undefined') 
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+		jQuery.each(elems, function(i, elem){
+			if ( !elem )
+				return;
+
+			if ( elem.constructor == Number )
+				elem = elem.toString();
+			
+			// Convert html string into DOM nodes
+			if ( typeof elem == "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+						all :
+						front + "></" + tag + ">";
+				});
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
+
+				var wrap =
+					// option or optgroup
+					!tags.indexOf("<opt") &&
+					[ 1, "<select multiple='multiple'>", "</select>" ] ||
+					
+					!tags.indexOf("<leg") &&
+					[ 1, "<fieldset>", "</fieldset>" ] ||
+					
+					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+					[ 1, "<table>", "</table>" ] ||
+					
+					!tags.indexOf("<tr") &&
+					[ 2, "<table><tbody>", "</tbody></table>" ] ||
+					
+				 	// <thead> matched above
+					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+					
+					!tags.indexOf("<col") &&
+					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+					// IE can't serialize <link> and <script> tags normally
+					jQuery.browser.msie &&
+					[ 1, "div<div>", "</div>" ] ||
+					
+					[ 0, "", "" ];
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+				
+				// Move to the right depth
+				while ( wrap[0]-- )
+					div = div.lastChild;
+				
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( jQuery.browser.msie ) {
+					
+					// String was a <table>, *may* have spurious <tbody>
+					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
+						div.firstChild && div.firstChild.childNodes :
+						
+						// String was a bare <thead> or <tfoot>
+						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+							div.childNodes :
+							[];
+				
+					for ( var j = tbody.length - 1; j >= 0 ; --j )
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+					
+					// IE completely kills leading whitespace when innerHTML is used	
+					if ( /^\s/.test( elem ) )	
+						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+				
+				}
+				
+				elem = jQuery.makeArray( div.childNodes );
+			}
+
+			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
+				return;
+
+			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
+				ret.push( elem );
+
+			else
+				ret = jQuery.merge( ret, elem );
+
+		});
+
+		return ret;
+	},
+	
+	attr: function( elem, name, value ) {
+		// don't set attributes on text and comment nodes
+		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+			return undefined;
+
+		var fix = jQuery.isXMLDoc( elem ) ?
+			{} :
+			jQuery.props;
+
+		// Safari mis-reports the default selected property of a hidden option
+		// Accessing the parent's selectedIndex property fixes it
+		if ( name == "selected" && jQuery.browser.safari )
+			elem.parentNode.selectedIndex;
+		
+		// Certain attributes only work when accessed via the old DOM 0 way
+		if ( fix[ name ] ) {
+			if ( value != undefined )
+				elem[ fix[ name ] ] = value;
+
+			return elem[ fix[ name ] ];
+
+		} else if ( jQuery.browser.msie && name == "style" )
+			return jQuery.attr( elem.style, "cssText", value );
+
+		else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
+			return elem.getAttributeNode( name ).nodeValue;
+
+		// IE elem.getAttribute passes even for style
+		else if ( elem.tagName ) {
+
+			if ( value != undefined ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+					throw "type property can't be changed";
+
+				// convert the value to a string (all browsers do this but IE) see #1070
+				elem.setAttribute( name, "" + value );
+			}
+
+			if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) ) 
+				return elem.getAttribute( name, 2 );
+
+			return elem.getAttribute( name );
+
+		// elem is actually elem.style ... set the style
+		} else {
+			// IE actually uses filters for opacity
+			if ( name == "opacity" && jQuery.browser.msie ) {
+				if ( value != undefined ) {
+					// IE has trouble with opacity if it does not have layout
+					// Force it by setting the zoom level
+					elem.zoom = 1; 
+	
+					// Set the alpha filter to set the opacity
+					elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+						(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+				}
+	
+				return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+					(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
+					"";
+			}
+
+			name = name.replace(/-([a-z])/ig, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			if ( value != undefined )
+				elem[ name ] = value;
+
+			return elem[ name ];
+		}
+	},
+	
+	trim: function( text ) {
+		return (text || "").replace( /^\s+|\s+$/g, "" );
+	},
+
+	makeArray: function( array ) {
+		var ret = [];
+
+		// Need to use typeof to fight Safari childNodes crashes
+		if ( array.constructor != Array )
+			for ( var i = 0, length = array.length; i < length; i++ )
+				ret.push( array[ i ] );
+		else
+			ret = array.slice( 0 );
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		for ( var i = 0, length = array.length; i < length; i++ )
+			if ( array[ i ] == elem )
+				return i;
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		// We have to loop this way because IE & Opera overwrite the length
+		// expando of getElementsByTagName
+
+		// Also, we need to make sure that the correct elements are being returned
+		// (IE returns comment nodes in a '*' query)
+		if ( jQuery.browser.msie ) {
+			for ( var i = 0; second[ i ]; i++ )
+				if ( second[ i ].nodeType != 8 )
+					first.push( second[ i ] );
+
+		} else
+			for ( var i = 0; second[ i ]; i++ )
+				first.push( second[ i ] );
+
+		return first;
+	},
+
+	unique: function( array ) {
+		var ret = [], done = {};
+
+		try {
+
+			for ( var i = 0, length = array.length; i < length; i++ ) {
+				var id = jQuery.data( array[ i ] );
+
+				if ( !done[ id ] ) {
+					done[ id ] = true;
+					ret.push( array[ i ] );
+				}
+			}
+
+		} catch( e ) {
+			ret = array;
+		}
+
+		return ret;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [];
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ )
+			if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
+				ret.push( elems[ i ] );
+
+		return ret;
+	},
+
+	map: function( elems, callback ) {
+		var ret = [];
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			var value = callback( elems[ i ], i );
+
+			if ( value !== null && value != undefined ) {
+				if ( value.constructor != Array )
+					value = [ value ];
+
+				ret = ret.concat( value );
+			}
+		}
+
+		return ret;
+	}
+});
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
+	safari: /webkit/.test( userAgent ),
+	opera: /opera/.test( userAgent ),
+	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+var styleFloat = jQuery.browser.msie ?
+	"styleFloat" :
+	"cssFloat";
+	
+jQuery.extend({
+	// Check to see if the W3C box model is being used
+	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
+	
+	props: {
+		"for": "htmlFor",
+		"class": "className",
+		"float": styleFloat,
+		cssFloat: styleFloat,
+		styleFloat: styleFloat,
+		innerHTML: "innerHTML",
+		className: "className",
+		value: "value",
+		disabled: "disabled",
+		checked: "checked",
+		readonly: "readOnly",
+		selected: "selected",
+		maxlength: "maxLength",
+		selectedIndex: "selectedIndex",
+		defaultValue: "defaultValue",
+		tagName: "tagName",
+		nodeName: "nodeName"
+	}
+});
+
+jQuery.each({
+	parent: function(elem){return elem.parentNode;},
+	parents: function(elem){return jQuery.dir(elem,"parentNode");},
+	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+	children: function(elem){return jQuery.sibling(elem.firstChild);},
+	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = jQuery.map( this, fn );
+
+		if ( selector && typeof selector == "string" )
+			ret = jQuery.multiFilter( selector, ret );
+
+		return this.pushStack( jQuery.unique( ret ) );
+	};
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function(name, original){
+	jQuery.fn[ name ] = function() {
+		var args = arguments;
+
+		return this.each(function(){
+			for ( var i = 0, length = args.length; i < length; i++ )
+				jQuery( args[ i ] )[ original ]( this );
+		});
+	};
+});
+
+jQuery.each({
+	removeAttr: function( name ) {
+		jQuery.attr( this, name, "" );
+		if (this.nodeType == 1) 
+			this.removeAttribute( name );
+	},
+
+	addClass: function( classNames ) {
+		jQuery.className.add( this, classNames );
+	},
+
+	removeClass: function( classNames ) {
+		jQuery.className.remove( this, classNames );
+	},
+
+	toggleClass: function( classNames ) {
+		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
+	},
+
+	remove: function( selector ) {
+		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
+			// Prevent memory leaks
+			jQuery( "*", this ).add(this).each(function(){
+				jQuery.event.remove(this);
+				jQuery.removeData(this);
+			});
+			if (this.parentNode)
+				this.parentNode.removeChild( this );
+		}
+	},
+
+	empty: function() {
+		// Remove element nodes and prevent memory leaks
+		jQuery( ">*", this ).remove();
+		
+		// Remove any remaining nodes
+		while ( this.firstChild )
+			this.removeChild( this.firstChild );
+	}
+}, function(name, fn){
+	jQuery.fn[ name ] = function(){
+		return this.each( fn, arguments );
+	};
+});
+
+jQuery.each([ "Height", "Width" ], function(i, name){
+	var type = name.toLowerCase();
+	
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		return this[0] == window ?
+			// Opera reports document.body.client[Width/Height] properly in both quirks and standards
+			jQuery.browser.opera && document.body[ "client" + name ] || 
+			
+			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
+			jQuery.browser.safari && window[ "inner" + name ] ||
+			
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
+		
+			// Get document width or height
+			this[0] == document ?
+				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+				Math.max( 
+					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), 
+					Math.max(document.body["offset" + name], document.documentElement["offset" + name]) 
+				) :
+
+				// Get or set width or height on the element
+				size == undefined ?
+					// Get width or height on the element
+					(this.length ? jQuery.css( this[0], type ) : null) :
+
+					// Set the width or height on the element (default to pixels if value is unitless)
+					this.css( type, size.constructor == String ? size : size + "px" );
+	};
+});
+
+var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
+		"(?:[\\w*_-]|\\\\.)" :
+		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
+	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
+	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
+	quickClass = new RegExp("^([#.]?)(" + chars + "*)");
+
+jQuery.extend({
+	expr: {
+		"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
+		"#": function(a,i,m){return a.getAttribute("id")==m[2];},
+		":": {
+			// Position Checks
+			lt: function(a,i,m){return i<m[3]-0;},
+			gt: function(a,i,m){return i>m[3]-0;},
+			nth: function(a,i,m){return m[3]-0==i;},
+			eq: function(a,i,m){return m[3]-0==i;},
+			first: function(a,i){return i==0;},
+			last: function(a,i,m,r){return i==r.length-1;},
+			even: function(a,i){return i%2==0;},
+			odd: function(a,i){return i%2;},
+
+			// Child Checks
+			"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
+			"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
+			"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
+
+			// Parent Checks
+			parent: function(a){return a.firstChild;},
+			empty: function(a){return !a.firstChild;},
+
+			// Text Check
+			contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
+
+			// Visibility
+			visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
+			hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
+
+			// Form attributes
+			enabled: function(a){return !a.disabled;},
+			disabled: function(a){return a.disabled;},
+			checked: function(a){return a.checked;},
+			selected: function(a){return a.selected||jQuery.attr(a,"selected");},
+
+			// Form elements
+			text: function(a){return "text"==a.type;},
+			radio: function(a){return "radio"==a.type;},
+			checkbox: function(a){return "checkbox"==a.type;},
+			file: function(a){return "file"==a.type;},
+			password: function(a){return "password"==a.type;},
+			submit: function(a){return "submit"==a.type;},
+			image: function(a){return "image"==a.type;},
+			reset: function(a){return "reset"==a.type;},
+			button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
+			input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
+
+			// :has()
+			has: function(a,i,m){return jQuery.find(m[3],a).length;},
+
+			// :header
+			header: function(a){return /h\d/i.test(a.nodeName);},
+
+			// :animated
+			animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
+		}
+	},
+	
+	// The regular expressions that power the parsing engine
+	parse: [
+		// Match: [@value='test'], [@foo]
+		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
+
+		// Match: :contains('foo')
+		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
+
+		// Match: :even, :last-chlid, #id, .class
+		new RegExp("^([:.#]*)(" + chars + "+)")
+	],
+
+	multiFilter: function( expr, elems, not ) {
+		var old, cur = [];
+
+		while ( expr && expr != old ) {
+			old = expr;
+			var f = jQuery.filter( expr, elems, not );
+			expr = f.t.replace(/^\s*,\s*/, "" );
+			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
+		}
+
+		return cur;
+	},
+
+	find: function( t, context ) {
+		// Quickly handle non-string expressions
+		if ( typeof t != "string" )
+			return [ t ];
+
+		// check to make sure context is a DOM element or a document
+		if ( context && context.nodeType != 1 && context.nodeType != 9)
+			return [ ];
+
+		// Set the correct context (if none is provided)
+		context = context || document;
+
+		// Initialize the search
+		var ret = [context], done = [], last, nodeName;
+
+		// Continue while a selector expression exists, and while
+		// we're no longer looping upon ourselves
+		while ( t && last != t ) {
+			var r = [];
+			last = t;
+
+			t = jQuery.trim(t);
+
+			var foundToken = false;
+
+			// An attempt at speeding up child selectors that
+			// point to a specific element tag
+			var re = quickChild;
+			var m = re.exec(t);
+
+			if ( m ) {
+				nodeName = m[1].toUpperCase();
+
+				// Perform our own iteration and filter
+				for ( var i = 0; ret[i]; i++ )
+					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
+						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
+							r.push( c );
+
+				ret = r;
+				t = t.replace( re, "" );
+				if ( t.indexOf(" ") == 0 ) continue;
+				foundToken = true;
+			} else {
+				re = /^([>+~])\s*(\w*)/i;
+
+				if ( (m = re.exec(t)) != null ) {
+					r = [];
+
+					var merge = {};
+					nodeName = m[2].toUpperCase();
+					m = m[1];
+
+					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
+						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
+						for ( ; n; n = n.nextSibling )
+							if ( n.nodeType == 1 ) {
+								var id = jQuery.data(n);
+
+								if ( m == "~" && merge[id] ) break;
+								
+								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
+									if ( m == "~" ) merge[id] = true;
+									r.push( n );
+								}
+								
+								if ( m == "+" ) break;
+							}
+					}
+
+					ret = r;
+
+					// And remove the token
+					t = jQuery.trim( t.replace( re, "" ) );
+					foundToken = true;
+				}
+			}
+
+			// See if there's still an expression, and that we haven't already
+			// matched a token
+			if ( t && !foundToken ) {
+				// Handle multiple expressions
+				if ( !t.indexOf(",") ) {
+					// Clean the result set
+					if ( context == ret[0] ) ret.shift();
+
+					// Merge the result sets
+					done = jQuery.merge( done, ret );
+
+					// Reset the context
+					r = ret = [context];
+
+					// Touch up the selector string
+					t = " " + t.substr(1,t.length);
+
+				} else {
+					// Optimize for the case nodeName#idName
+					var re2 = quickID;
+					var m = re2.exec(t);
+					
+					// Re-organize the results, so that they're consistent
+					if ( m ) {
+						m = [ 0, m[2], m[3], m[1] ];
+
+					} else {
+						// Otherwise, do a traditional filter check for
+						// ID, class, and element selectors
+						re2 = quickClass;
+						m = re2.exec(t);
+					}
+
+					m[2] = m[2].replace(/\\/g, "");
+
+					var elem = ret[ret.length-1];
+
+					// Try to do a global search by ID, where we can
+					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
+						// Optimization for HTML document case
+						var oid = elem.getElementById(m[2]);
+						
+						// Do a quick check for the existence of the actual ID attribute
+						// to avoid selecting by the name attribute in IE
+						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
+						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
+							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
+
+						// Do a quick check for node name (where applicable) so
+						// that div#foo searches will be really fast
+						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
+					} else {
+						// We need to find all descendant elements
+						for ( var i = 0; ret[i]; i++ ) {
+							// Grab the tag name being searched for
+							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
+
+							// Handle IE7 being really dumb about <object>s
+							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
+								tag = "param";
+
+							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
+						}
+
+						// It's faster to filter by class and be done with it
+						if ( m[1] == "." )
+							r = jQuery.classFilter( r, m[2] );
+
+						// Same with ID filtering
+						if ( m[1] == "#" ) {
+							var tmp = [];
+
+							// Try to find the element with the ID
+							for ( var i = 0; r[i]; i++ )
+								if ( r[i].getAttribute("id") == m[2] ) {
+									tmp = [ r[i] ];
+									break;
+								}
+
+							r = tmp;
+						}
+
+						ret = r;
+					}
+
+					t = t.replace( re2, "" );
+				}
+
+			}
+
+			// If a selector string still exists
+			if ( t ) {
+				// Attempt to filter it
+				var val = jQuery.filter(t,r);
+				ret = r = val.r;
+				t = jQuery.trim(val.t);
+			}
+		}
+
+		// An error occurred with the selector;
+		// just return an empty set instead
+		if ( t )
+			ret = [];
+
+		// Remove the root context
+		if ( ret && context == ret[0] )
+			ret.shift();
+
+		// And combine the results
+		done = jQuery.merge( done, ret );
+
+		return done;
+	},
+
+	classFilter: function(r,m,not){
+		m = " " + m + " ";
+		var tmp = [];
+		for ( var i = 0; r[i]; i++ ) {
+			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
+			if ( !not && pass || not && !pass )
+				tmp.push( r[i] );
+		}
+		return tmp;
+	},
+
+	filter: function(t,r,not) {
+		var last;
+
+		// Look for common filter expressions
+		while ( t && t != last ) {
+			last = t;
+
+			var p = jQuery.parse, m;
+
+			for ( var i = 0; p[i]; i++ ) {
+				m = p[i].exec( t );
+
+				if ( m ) {
+					// Remove what we just matched
+					t = t.substring( m[0].length );
+
+					m[2] = m[2].replace(/\\/g, "");
+					break;
+				}
+			}
+
+			if ( !m )
+				break;
+
+			// :not() is a special case that can be optimized by
+			// keeping it out of the expression list
+			if ( m[1] == ":" && m[2] == "not" )
+				// optimize if only one selector found (most common case)
+				r = isSimple.test( m[3] ) ?
+					jQuery.filter(m[3], r, true).r :
+					jQuery( r ).not( m[3] );
+
+			// We can get a big speed boost by filtering by class here
+			else if ( m[1] == "." )
+				r = jQuery.classFilter(r, m[2], not);
+
+			else if ( m[1] == "[" ) {
+				var tmp = [], type = m[3];
+				
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
+					
+					if ( z == null || /href|src|selected/.test(m[2]) )
+						z = jQuery.attr(a,m[2]) || '';
+
+					if ( (type == "" && !!z ||
+						 type == "=" && z == m[5] ||
+						 type == "!=" && z != m[5] ||
+						 type == "^=" && z && !z.indexOf(m[5]) ||
+						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
+						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
+							tmp.push( a );
+				}
+				
+				r = tmp;
+
+			// We can get a speed boost by handling nth-child here
+			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
+				var merge = {}, tmp = [],
+					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
+						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
+					// calculate the numbers (first)n+(last) including if they are negative
+					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
+ 
+				// loop through all the elements left in the jQuery object
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
+
+					if ( !merge[id] ) {
+						var c = 1;
+
+						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
+							if ( n.nodeType == 1 )
+								n.nodeIndex = c++;
+
+						merge[id] = true;
+					}
+
+					var add = false;
+
+					if ( first == 0 ) {
+						if ( node.nodeIndex == last )
+							add = true;
+					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
+						add = true;
+
+					if ( add ^ not )
+						tmp.push( node );
+				}
+
+				r = tmp;
+
+			// Otherwise, find the expression to execute
+			} else {
+				var fn = jQuery.expr[ m[1] ];
+				if ( typeof fn == "object" )
+					fn = fn[ m[2] ];
+
+				if ( typeof fn == "string" )
+					fn = eval("false||function(a,i){return " + fn + ";}");
+
+				// Execute it against the current filter
+				r = jQuery.grep( r, function(elem, i){
+					return fn(elem, i, m, r);
+				}, not );
+			}
+		}
+
+		// Return an array of filtered elements (r)
+		// and the modified expression string (t)
+		return { r: r, t: t };
+	},
+
+	dir: function( elem, dir ){
+		var matched = [];
+		var cur = elem[dir];
+		while ( cur && cur != document ) {
+			if ( cur.nodeType == 1 )
+				matched.push( cur );
+			cur = cur[dir];
+		}
+		return matched;
+	},
+	
+	nth: function(cur,result,dir,elem){
+		result = result || 1;
+		var num = 0;
+
+		for ( ; cur; cur = cur[dir] )
+			if ( cur.nodeType == 1 && ++num == result )
+				break;
+
+		return cur;
+	},
+	
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType == 1 && (!elem || n != elem) )
+				r.push( n );
+		}
+
+		return r;
+	}
+});
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code orignated from 
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function(elem, types, handler, data) {
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( jQuery.browser.msie && elem.setInterval != undefined )
+			elem = window;
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid )
+			handler.guid = this.guid++;
+			
+		// if data is passed, bind to handler 
+		if( data != undefined ) { 
+			// Create temporary function pointer to original handler 
+			var fn = handler; 
+
+			// Create unique handler function, wrapped around original handler 
+			handler = function() { 
+				// Pass arguments and context to original handler 
+				return fn.apply(this, arguments); 
+			};
+
+			// Store data in unique handler 
+			handler.data = data;
+
+			// Set the guid of unique handler to the same of original handler, so it can be removed 
+			handler.guid = fn.guid;
+		}
+
+		// Init the element's event structure
+		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+				// returned undefined or false
+				var val;
+
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				if ( typeof jQuery == "undefined" || jQuery.event.triggered )
+					return val;
+		
+				val = jQuery.event.handle.apply(arguments.callee.elem, arguments);
+		
+				return val;
+			});
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native
+		// event in IE.
+		handle.elem = elem;
+			
+			// Handle multiple events seperated by a space
+			// jQuery(...).bind("mouseover mouseout", fn);
+			jQuery.each(types.split(/\s+/), function(index, type) {
+				// Namespaced event handlers
+				var parts = type.split(".");
+				type = parts[0];
+				handler.type = parts[1];
+
+				// Get the current list of functions bound to this event
+				var handlers = events[type];
+
+				// Init the event handler queue
+				if (!handlers) {
+					handlers = events[type] = {};
+		
+					// Check for a special event handler
+					// Only use addEventListener/attachEvent if the special
+					// events handler returns false
+					if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
+						// Bind the global event handler to the element
+						if (elem.addEventListener)
+							elem.addEventListener(type, handle, false);
+						else if (elem.attachEvent)
+							elem.attachEvent("on" + type, handle);
+					}
+				}
+
+				// Add the function to the element's handler list
+				handlers[handler.guid] = handler;
+
+				// Keep track of which events have been used, for global triggering
+				jQuery.event.global[type] = true;
+			});
+		
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	guid: 1,
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function(elem, types, handler) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		var events = jQuery.data(elem, "events"), ret, index;
+
+		if ( events ) {
+			// Unbind all events for the element
+			if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
+				for ( var type in events )
+					this.remove( elem, type + (types || "") );
+			else {
+				// types is actually an event object here
+				if ( types.type ) {
+					handler = types.handler;
+					types = types.type;
+				}
+				
+				// Handle multiple events seperated by a space
+				// jQuery(...).unbind("mouseover mouseout", fn);
+				jQuery.each(types.split(/\s+/), function(index, type){
+					// Namespaced event handlers
+					var parts = type.split(".");
+					type = parts[0];
+					
+					if ( events[type] ) {
+						// remove the given handler for the given type
+						if ( handler )
+							delete events[type][handler.guid];
+			
+						// remove all handlers for the given type
+						else
+							for ( handler in events[type] )
+								// Handle the removal of namespaced events
+								if ( !parts[1] || events[type][handler].type == parts[1] )
+									delete events[type][handler];
+
+						// remove generic event handler if no more handlers exist
+						for ( ret in events[type] ) break;
+						if ( !ret ) {
+							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
+								if (elem.removeEventListener)
+									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+								else if (elem.detachEvent)
+									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+							}
+							ret = null;
+							delete events[type];
+						}
+					}
+				});
+			}
+
+			// Remove the expando if it's no longer used
+			for ( ret in events ) break;
+			if ( !ret ) {
+				var handle = jQuery.data( elem, "handle" );
+				if ( handle ) handle.elem = null;
+				jQuery.removeData( elem, "events" );
+				jQuery.removeData( elem, "handle" );
+			}
+		}
+	},
+
+	trigger: function(type, data, elem, donative, extra) {
+		// Clone the incoming data, if any
+		data = jQuery.makeArray(data || []);
+
+		if ( type.indexOf("!") >= 0 ) {
+			type = type.slice(0, -1);
+			var exclusive = true;
+		}
+
+		// Handle a global trigger
+		if ( !elem ) {
+			// Only trigger if we've ever bound an event for it
+			if ( this.global[type] )
+				jQuery("*").add([window, document]).trigger(type, data);
+
+		// Handle triggering a single element
+		} else {
+			// don't do events on text and comment nodes
+			if ( elem.nodeType == 3 || elem.nodeType == 8 )
+				return undefined;
+
+			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
+				// Check to see if we need to provide a fake event, or not
+				event = !data[0] || !data[0].preventDefault;
+			
+			// Pass along a fake event
+			if ( event )
+				data.unshift( this.fix({ type: type, target: elem }) );
+
+			// Enforce the right trigger type
+			data[0].type = type;
+			if ( exclusive )
+				data[0].exclusive = true;
+
+			// Trigger the event
+			if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
+				val = jQuery.data(elem, "handle").apply( elem, data );
+
+			// Handle triggering native .onfoo handlers
+			if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+				val = false;
+
+			// Extra functions don't get the custom event object
+			if ( event )
+				data.shift();
+
+			// Handle triggering of extra function
+			if ( extra && jQuery.isFunction( extra ) ) {
+				// call the extra function and tack the current return value on the end for possible inspection
+				ret = extra.apply( elem, val == null ? data : data.concat( val ) );
+				// if anything is returned, give it precedence and have it overwrite the previous value
+				if (ret !== undefined)
+					val = ret;
+			}
+
+			// Trigger the native events (except for clicks on links)
+			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+				this.triggered = true;
+				try {
+					elem[ type ]();
+				// prevent IE from throwing an error for some hidden elements
+				} catch (e) {}
+			}
+
+			this.triggered = false;
+		}
+
+		return val;
+	},
+
+	handle: function(event) {
+		// returned undefined or false
+		var val;
+
+		// Empty object is for triggered events with no data
+		event = jQuery.event.fix( event || window.event || {} ); 
+
+		// Namespaced event handlers
+		var parts = event.type.split(".");
+		event.type = parts[0];
+
+		var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
+		args.unshift( event );
+
+		for ( var j in handlers ) {
+			var handler = handlers[j];
+			// Pass in a reference to the handler function itself
+			// So that we can later remove it
+			args[0].handler = handler;
+			args[0].data = handler.data;
+
+			// Filter the functions by class
+			if ( !parts[1] && !event.exclusive || handler.type == parts[1] ) {
+				var ret = handler.apply( this, args );
+
+				if ( val !== false )
+					val = ret;
+
+				if ( ret === false ) {
+					event.preventDefault();
+					event.stopPropagation();
+				}
+			}
+		}
+
+		// Clean up added properties in IE to prevent memory leak
+		if (jQuery.browser.msie)
+			event.target = event.preventDefault = event.stopPropagation =
+				event.handler = event.data = null;
+
+		return val;
+	},
+
+	fix: function(event) {
+		// store a copy of the original event object 
+		// and clone to set read-only properties
+		var originalEvent = event;
+		event = jQuery.extend({}, originalEvent);
+		
+		// add preventDefault and stopPropagation since 
+		// they will not work on the clone
+		event.preventDefault = function() {
+			// if preventDefault exists run it on the original event
+			if (originalEvent.preventDefault)
+				originalEvent.preventDefault();
+			// otherwise set the returnValue property of the original event to false (IE)
+			originalEvent.returnValue = false;
+		};
+		event.stopPropagation = function() {
+			// if stopPropagation exists run it on the original event
+			if (originalEvent.stopPropagation)
+				originalEvent.stopPropagation();
+			// otherwise set the cancelBubble property of the original event to true (IE)
+			originalEvent.cancelBubble = true;
+		};
+		
+		// Fix target property, if necessary
+		if ( !event.target )
+			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+				
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType == 3 )
+			event.target = originalEvent.target.parentNode;
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement )
+			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement, body = document.body;
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+		}
+			
+		// Add which for key events
+		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+			event.which = event.charCode || event.keyCode;
+		
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey )
+			event.metaKey = event.ctrlKey;
+
+		// Add which for click: 1 == left; 2 == middle; 3 == right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button )
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+			
+		return event;
+	},
+	
+	special: {
+		ready: {
+			setup: function() {
+				// Make sure the ready event is setup
+				bindReady();
+				return;
+			},
+			
+			teardown: function() { return; }
+		},
+		
+		mouseenter: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+		
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+			
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseenter
+				arguments[0].type = "mouseenter";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		},
+	
+		mouseleave: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+		
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+			
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseleave
+				arguments[0].type = "mouseleave";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		}
+	}
+};
+
+jQuery.fn.extend({
+	bind: function( type, data, fn ) {
+		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+			jQuery.event.add( this, type, fn || data, fn && data );
+		});
+	},
+	
+	one: function( type, data, fn ) {
+		return this.each(function(){
+			jQuery.event.add( this, type, function(event) {
+				jQuery(this).unbind(event);
+				return (fn || data).apply( this, arguments);
+			}, fn && data);
+		});
+	},
+
+	unbind: function( type, fn ) {
+		return this.each(function(){
+			jQuery.event.remove( this, type, fn );
+		});
+	},
+
+	trigger: function( type, data, fn ) {
+		return this.each(function(){
+			jQuery.event.trigger( type, data, this, true, fn );
+		});
+	},
+
+	triggerHandler: function( type, data, fn ) {
+		if ( this[0] )
+			return jQuery.event.trigger( type, data, this[0], false, fn );
+		return undefined;
+	},
+
+	toggle: function() {
+		// Save reference to arguments for access in closure
+		var args = arguments;
+
+		return this.click(function(event) {
+			// Figure out which function to execute
+			this.lastToggle = 0 == this.lastToggle ? 1 : 0;
+			
+			// Make sure that clicks stop
+			event.preventDefault();
+			
+			// and execute the function
+			return args[this.lastToggle].apply( this, arguments ) || false;
+		});
+	},
+
+	hover: function(fnOver, fnOut) {
+		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
+	},
+	
+	ready: function(fn) {
+		// Attach the listeners
+		bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady )
+			// Execute the function immediately
+			fn.call( document, jQuery );
+			
+		// Otherwise, remember the function for later
+		else
+			// Add the function to the wait list
+			jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
+	
+		return this;
+	}
+});
+
+jQuery.extend({
+	isReady: false,
+	readyList: [],
+	// Handle when the DOM is ready
+	ready: function() {
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.isReady ) {
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+			
+			// If there are functions bound, to execute
+			if ( jQuery.readyList ) {
+				// Execute all of them
+				jQuery.each( jQuery.readyList, function(){
+					this.apply( document );
+				});
+				
+				// Reset the list of functions
+				jQuery.readyList = null;
+			}
+		
+			// Trigger any bound ready events
+			jQuery(document).triggerHandler("ready");
+		}
+	}
+});
+
+var readyBound = false;
+
+function bindReady(){
+	if ( readyBound ) return;
+	readyBound = true;
+
+	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
+	if ( document.addEventListener && !jQuery.browser.opera)
+		// Use the handy event callback
+		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
+	
+	// If IE is used and is not in a frame
+	// Continually check to see if the document is ready
+	if ( jQuery.browser.msie && window == top ) (function(){
+		if (jQuery.isReady) return;
+		try {
+			// If IE is used, use the trick by Diego Perini
+			// http://javascript.nwbox.com/IEContentLoaded/
+			document.documentElement.doScroll("left");
+		} catch( error ) {
+			setTimeout( arguments.callee, 0 );
+			return;
+		}
+		// and execute any waiting functions
+		jQuery.ready();
+	})();
+
+	if ( jQuery.browser.opera )
+		document.addEventListener( "DOMContentLoaded", function () {
+			if (jQuery.isReady) return;
+			for (var i = 0; i < document.styleSheets.length; i++)
+				if (document.styleSheets[i].disabled) {
+					setTimeout( arguments.callee, 0 );
+					return;
+				}
+			// and execute any waiting functions
+			jQuery.ready();
+		}, false);
+
+	if ( jQuery.browser.safari ) {
+		var numStyles;
+		(function(){
+			if (jQuery.isReady) return;
+			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			if ( numStyles === undefined )
+				numStyles = jQuery("style, link[rel=stylesheet]").length;
+			if ( document.styleSheets.length != numStyles ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			// and execute any waiting functions
+			jQuery.ready();
+		})();
+	}
+
+	// A fallback to window.onload, that will always work
+	jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
+	"submit,keydown,keypress,keyup,error").split(","), function(i, name){
+	
+	// Handle event binding
+	jQuery.fn[name] = function(fn){
+		return fn ? this.bind(name, fn) : this.trigger(name);
+	};
+});
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event, elem) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+	// Traverse up the tree
+	while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
+	// Return true if we actually just moused on to a sub-element
+	return parent == elem;
+};
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery(window).bind("unload", function() {
+	jQuery("*").add(document).unbind();
+});
+jQuery.fn.extend({
+	load: function( url, params, callback ) {
+		if ( jQuery.isFunction( url ) )
+			return this.bind("load", url);
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		callback = callback || function(){};
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params )
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else {
+				params = jQuery.param( params );
+				type = "POST";
+			}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function(res, status){
+				// If successful, inject the HTML into all the matched elements
+				if ( status == "success" || status == "notmodified" )
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div/>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+
+				self.each( callback, [res.responseText, status, res] );
+			}
+		});
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+	serializeArray: function() {
+		return this.map(function(){
+			return jQuery.nodeName(this, "form") ?
+				jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled && 
+				(this.checked || /select|textarea/i.test(this.nodeName) || 
+					/text|hidden|password/i.test(this.type));
+		})
+		.map(function(i, elem){
+			var val = jQuery(this).val();
+			return val == null ? null :
+				val.constructor == Array ?
+					jQuery.map( val, function(val, i){
+						return {name: elem.name, value: val};
+					}) :
+					{name: elem.name, value: val};
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+	jQuery.fn[o] = function(f){
+		return this.bind(o, f);
+	};
+});
+
+var jsc = (new Date).getTime();
+
+jQuery.extend({
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was ommited
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = null;
+		}
+		
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		global: true,
+		type: "GET",
+		timeout: 0,
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		data: null,
+		username: null,
+		password: null,
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			script: "text/javascript, application/javascript",
+			json: "application/json, text/javascript",
+			text: "text/plain",
+			_default: "*/*"
+		}
+	},
+	
+	// Last-Modified header cache for next request
+	lastModified: {},
+
+	ajax: function( s ) {
+		var jsonp, jsre = /=\?(&|$)/g, status, data;
+
+		// Extend the settings, but re-extend 's' so that it can be
+		// checked again later (in the test suite, specifically)
+		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data != "string" )
+			s.data = jQuery.param(s.data);
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType == "jsonp" ) {
+			if ( s.type.toLowerCase() == "get" ) {
+				if ( !s.url.match(jsre) )
+					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+			} else if ( !s.data || !s.data.match(jsre) )
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+			jsonp = "jsonp" + jsc++;
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data )
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			window[ jsonp ] = function(tmp){
+				data = tmp;
+				success();
+				complete();
+				// Garbage collect
+				window[ jsonp ] = undefined;
+				try{ delete window[ jsonp ]; } catch(e){}
+				if ( head )
+					head.removeChild( script );
+			};
+		}
+
+		if ( s.dataType == "script" && s.cache == null )
+			s.cache = false;
+
+		if ( s.cache === false && s.type.toLowerCase() == "get" ) {
+			var ts = (new Date()).getTime();
+			// try replacing _= if it is there
+			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for get requests
+		if ( s.data && s.type.toLowerCase() == "get" ) {
+			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+			// IE likes to send both get and post data, prevent this
+			s.data = null;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && ! jQuery.active++ )
+			jQuery.event.trigger( "ajaxStart" );
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get" ) {
+			var head = document.getElementsByTagName("head")[0];
+			var script = document.createElement("script");
+			script.src = s.url;
+			if (s.scriptCharset)
+				script.charset = s.scriptCharset;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function(){
+					if ( !done && (!this.readyState || 
+							this.readyState == "loaded" || this.readyState == "complete") ) {
+						done = true;
+						success();
+						complete();
+						head.removeChild( script );
+					}
+				};
+			}
+
+			head.appendChild(script);
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object; Microsoft failed to properly
+		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+		var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+
+		// Open the socket
+		xml.open(s.type, s.url, s.async, s.username, s.password);
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set the correct header, if data is being sent
+			if ( s.data )
+				xml.setRequestHeader("Content-Type", s.contentType);
+
+			// Set the If-Modified-Since header, if ifModified mode.
+			if ( s.ifModified )
+				xml.setRequestHeader("If-Modified-Since",
+					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+			// Set the Accepts header for the server, depending on the dataType
+			xml.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+				s.accepts[ s.dataType ] + ", */*" :
+				s.accepts._default );
+		} catch(e){}
+
+		// Allow custom headers/mimetypes
+		if ( s.beforeSend )
+			s.beforeSend(xml);
+			
+		if ( s.global )
+			jQuery.event.trigger("ajaxSend", [xml, s]);
+
+		// Wait for a response to come back
+		var onreadystatechange = function(isTimeout){
+			// The transfer is complete and the data is available, or the request timed out
+			if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
+				requestDone = true;
+				
+				// clear poll interval
+				if (ival) {
+					clearInterval(ival);
+					ival = null;
+				}
+				
+				status = isTimeout == "timeout" && "timeout" ||
+					!jQuery.httpSuccess( xml ) && "error" ||
+					s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
+					"success";
+
+				if ( status == "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xml, s.dataType );
+					} catch(e) {
+						status = "parsererror";
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status == "success" ) {
+					// Cache Last-Modified header, if ifModified mode.
+					var modRes;
+					try {
+						modRes = xml.getResponseHeader("Last-Modified");
+					} catch(e) {} // swallow exception thrown by FF if header is not available
+	
+					if ( s.ifModified && modRes )
+						jQuery.lastModified[s.url] = modRes;
+
+					// JSONP handles its own success callback
+					if ( !jsonp )
+						success();	
+				} else
+					jQuery.handleError(s, xml, status);
+
+				// Fire the complete handlers
+				complete();
+
+				// Stop memory leaks
+				if ( s.async )
+					xml = null;
+			}
+		};
+		
+		if ( s.async ) {
+			// don't attach the handler to the request, just poll it instead
+			var ival = setInterval(onreadystatechange, 13); 
+
+			// Timeout checker
+			if ( s.timeout > 0 )
+				setTimeout(function(){
+					// Check to see if the request is still happening
+					if ( xml ) {
+						// Cancel the request
+						xml.abort();
+	
+						if( !requestDone )
+							onreadystatechange( "timeout" );
+					}
+				}, s.timeout);
+		}
+			
+		// Send the data
+		try {
+			xml.send(s.data);
+		} catch(e) {
+			jQuery.handleError(s, xml, null, e);
+		}
+		
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async )
+			onreadystatechange();
+
+		function success(){
+			// If a local callback was specified, fire it and pass it the data
+			if ( s.success )
+				s.success( data, status );
+
+			// Fire the global callback
+			if ( s.global )
+				jQuery.event.trigger( "ajaxSuccess", [xml, s] );
+		}
+
+		function complete(){
+			// Process result
+			if ( s.complete )
+				s.complete(xml, status);
+
+			// The request was completed
+			if ( s.global )
+				jQuery.event.trigger( "ajaxComplete", [xml, s] );
+
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+		}
+		
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xml;
+	},
+
+	handleError: function( s, xml, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) s.error( xml, status, e );
+
+		// Fire the global callback
+		if ( s.global )
+			jQuery.event.trigger( "ajaxError", [xml, s, e] );
+	},
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( r ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !r.status && location.protocol == "file:" ||
+				( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
+				jQuery.browser.safari && r.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xml, url ) {
+		try {
+			var xmlRes = xml.getResponseHeader("Last-Modified");
+
+			// Firefox always returns 200. check Last-Modified date
+			return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
+				jQuery.browser.safari && xml.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	httpData: function( r, type ) {
+		var ct = r.getResponseHeader("content-type");
+		var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
+		var data = xml ? r.responseXML : r.responseText;
+
+		if ( xml && data.documentElement.tagName == "parsererror" )
+			throw "parsererror";
+
+		// If the type is "script", eval it in global context
+		if ( type == "script" )
+			jQuery.globalEval( data );
+
+		// Get the JavaScript object, if JSON is used.
+		if ( type == "json" )
+			data = eval("(" + data + ")");
+
+		return data;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a ) {
+		var s = [];
+
+		// If an array was passed in, assume that it is an array
+		// of form elements
+		if ( a.constructor == Array || a.jquery )
+			// Serialize the form elements
+			jQuery.each( a, function(){
+				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
+			});
+
+		// Otherwise, assume that it's an object of key/value pairs
+		else
+			// Serialize the key/values
+			for ( var j in a )
+				// If the value is an array then the key names need to be repeated
+				if ( a[j] && a[j].constructor == Array )
+					jQuery.each( a[j], function(){
+						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
+					});
+				else
+					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
+
+		// Return the resulting serialization
+		return s.join("&").replace(/%20/g, "+");
+	}
+
+});
+jQuery.fn.extend({
+	show: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "show", width: "show", opacity: "show"
+			}, speed, callback) :
+			
+			this.filter(":hidden").each(function(){
+				this.style.display = this.oldblock || "";
+				if ( jQuery.css(this,"display") == "none" ) {
+					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
+					this.style.display = elem.css("display");
+					// handle an edge condition where css is - div { display:none; } or similar
+					if (this.style.display == "none")
+						this.style.display = "block";
+					elem.remove();
+				}
+			}).end();
+	},
+	
+	hide: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "hide", width: "hide", opacity: "hide"
+			}, speed, callback) :
+			
+			this.filter(":visible").each(function(){
+				this.oldblock = this.oldblock || jQuery.css(this,"display");
+				this.style.display = "none";
+			}).end();
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+	
+	toggle: function( fn, fn2 ){
+		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+			this._toggle( fn, fn2 ) :
+			fn ?
+				this.animate({
+					height: "toggle", width: "toggle", opacity: "toggle"
+				}, fn, fn2) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+				});
+	},
+	
+	slideDown: function(speed,callback){
+		return this.animate({height: "show"}, speed, callback);
+	},
+	
+	slideUp: function(speed,callback){
+		return this.animate({height: "hide"}, speed, callback);
+	},
+
+	slideToggle: function(speed, callback){
+		return this.animate({height: "toggle"}, speed, callback);
+	},
+	
+	fadeIn: function(speed, callback){
+		return this.animate({opacity: "show"}, speed, callback);
+	},
+	
+	fadeOut: function(speed, callback){
+		return this.animate({opacity: "hide"}, speed, callback);
+	},
+	
+	fadeTo: function(speed,to,callback){
+		return this.animate({opacity: to}, speed, callback);
+	},
+	
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		return this[ optall.queue === false ? "each" : "queue" ](function(){
+			if ( this.nodeType != 1)
+				return false;
+
+			var opt = jQuery.extend({}, optall);
+			var hidden = jQuery(this).is(":hidden"), self = this;
+			
+			for ( var p in prop ) {
+				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+					return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
+
+				if ( p == "height" || p == "width" ) {
+					// Store display property
+					opt.display = jQuery.css(this, "display");
+
+					// Make sure that nothing sneaks out
+					opt.overflow = this.style.overflow;
+				}
+			}
+
+			if ( opt.overflow != null )
+				this.style.overflow = "hidden";
+
+			opt.curAnim = jQuery.extend({}, prop);
+			
+			jQuery.each( prop, function(name, val){
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( /toggle|show|hide/.test(val) )
+					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+				else {
+					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+						start = e.cur(true) || 0;
+
+					if ( parts ) {
+						var end = parseFloat(parts[2]),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit != "px" ) {
+							self.style[ name ] = (end || 1) + unit;
+							start = ((end || 1) / e.cur(true)) * start;
+							self.style[ name ] = start + unit;
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] )
+							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+						e.custom( start, end, unit );
+					} else
+						e.custom( start, val, "" );
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+	
+	queue: function(type, fn){
+		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
+			fn = type;
+			type = "fx";
+		}
+
+		if ( !type || (typeof type == "string" && !fn) )
+			return queue( this[0], type );
+
+		return this.each(function(){
+			if ( fn.constructor == Array )
+				queue(this, type, fn);
+			else {
+				queue(this, type).push( fn );
+			
+				if ( queue(this, type).length == 1 )
+					fn.apply(this);
+			}
+		});
+	},
+
+	stop: function(clearQueue, gotoEnd){
+		var timers = jQuery.timers;
+
+		if (clearQueue)
+			this.queue([]);
+
+		this.each(function(){
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- )
+				if ( timers[i].elem == this ) {
+					if (gotoEnd)
+						// force the next step to be the last
+						timers[i](true);
+					timers.splice(i, 1);
+				}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if (!gotoEnd)
+			this.dequeue();
+
+		return this;
+	}
+
+});
+
+var queue = function( elem, type, array ) {
+	if ( !elem )
+		return undefined;
+
+	type = type || "fx";
+
+	var q = jQuery.data( elem, type + "queue" );
+
+	if ( !q || array )
+		q = jQuery.data( elem, type + "queue", 
+			array ? jQuery.makeArray(array) : [] );
+
+	return q;
+};
+
+jQuery.fn.dequeue = function(type){
+	type = type || "fx";
+
+	return this.each(function(){
+		var q = queue(this, type);
+
+		q.shift();
+
+		if ( q.length )
+			q[0].apply( this );
+	});
+};
+
+jQuery.extend({
+	
+	speed: function(speed, easing, fn) {
+		var opt = speed && speed.constructor == Object ? speed : {
+			complete: fn || !fn && easing || 
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && easing.constructor != Function && easing
+		};
+
+		opt.duration = (opt.duration && opt.duration.constructor == Number ? 
+			opt.duration : 
+			{ slow: 600, fast: 200 }[opt.duration]) || 400;
+	
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function(){
+			if ( opt.queue !== false )
+				jQuery(this).dequeue();
+			if ( jQuery.isFunction( opt.old ) )
+				opt.old.apply( this );
+		};
+	
+		return opt;
+	},
+	
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+	
+	timers: [],
+	timerId: null,
+
+	fx: function( elem, options, prop ){
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig )
+			options.orig = {};
+	}
+
+});
+
+jQuery.fx.prototype = {
+
+	// Simple function for setting a style value
+	update: function(){
+		if ( this.options.step )
+			this.options.step.apply( this.elem, [ this.now, this ] );
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+		// Set display property to block for height/width animations
+		if ( this.prop == "height" || this.prop == "width" )
+			this.elem.style.display = "block";
+	},
+
+	// Get the current size
+	cur: function(force){
+		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
+			return this.elem[ this.prop ];
+
+		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function(from, to, unit){
+		this.startTime = (new Date()).getTime();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+		this.update();
+
+		var self = this;
+		function t(gotoEnd){
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		jQuery.timers.push(t);
+
+		if ( jQuery.timerId == null ) {
+			jQuery.timerId = setInterval(function(){
+				var timers = jQuery.timers;
+				
+				for ( var i = 0; i < timers.length; i++ )
+					if ( !timers[i]() )
+						timers.splice(i--, 1);
+
+				if ( !timers.length ) {
+					clearInterval( jQuery.timerId );
+					jQuery.timerId = null;
+				}
+			}, 13);
+		}
+	},
+
+	// Simple 'show' function
+	show: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		this.custom(0, this.cur());
+
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		if ( this.prop == "width" || this.prop == "height" )
+			this.elem.style[this.prop] = "1px";
+		
+		// Start by showing the element
+		jQuery(this.elem).show();
+	},
+
+	// Simple 'hide' function
+	hide: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function(gotoEnd){
+		var t = (new Date()).getTime();
+
+		if ( gotoEnd || t > this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			var done = true;
+			for ( var i in this.options.curAnim )
+				if ( this.options.curAnim[i] !== true )
+					done = false;
+
+			if ( done ) {
+				if ( this.options.display != null ) {
+					// Reset the overflow
+					this.elem.style.overflow = this.options.overflow;
+				
+					// Reset the display
+					this.elem.style.display = this.options.display;
+					if ( jQuery.css(this.elem, "display") == "none" )
+						this.elem.style.display = "block";
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide )
+					this.elem.style.display = "none";
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show )
+					for ( var p in this.options.curAnim )
+						jQuery.attr(this.elem.style, p, this.options.orig[p]);
+			}
+
+			// If a callback was provided, execute it
+			if ( done && jQuery.isFunction( this.options.complete ) )
+				// Execute the complete function
+				this.options.complete.apply( this.elem );
+
+			return false;
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+
+};
+
+jQuery.fx.step = {
+	scrollLeft: function(fx){
+		fx.elem.scrollLeft = fx.now;
+	},
+
+	scrollTop: function(fx){
+		fx.elem.scrollTop = fx.now;
+	},
+
+	opacity: function(fx){
+		jQuery.attr(fx.elem.style, "opacity", fx.now);
+	},
+
+	_default: function(fx){
+		fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+	}
+};
+// The Offset Method
+// Originally By Brandon Aaron, part of the Dimension Plugin
+// http://jquery.com/plugins/project/dimensions
+jQuery.fn.offset = function() {
+	var left = 0, top = 0, elem = this[0], results;
+	
+	if ( elem ) with ( jQuery.browser ) {
+		var parent       = elem.parentNode, 
+		    offsetChild  = elem,
+		    offsetParent = elem.offsetParent, 
+		    doc          = elem.ownerDocument,
+		    safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
+		    fixed        = jQuery.css(elem, "position") == "fixed";
+	
+		// Use getBoundingClientRect if available
+		if ( elem.getBoundingClientRect ) {
+			var box = elem.getBoundingClientRect();
+		
+			// Add the document scroll offsets
+			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+		
+			// IE adds the HTML element's border, by default it is medium which is 2px
+			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
+			// IE 7 standards mode, the border is always 2px
+			// This border/offset is typically represented by the clientLeft and clientTop properties
+			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
+			// Therefore this method will be off by 2px in IE while in quirksmode
+			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
+	
+		// Otherwise loop through the offsetParents and parentNodes
+		} else {
+		
+			// Initial element offsets
+			add( elem.offsetLeft, elem.offsetTop );
+			
+			// Get parent offsets
+			while ( offsetParent ) {
+				// Add offsetParent offsets
+				add( offsetParent.offsetLeft, offsetParent.offsetTop );
+			
+				// Mozilla and Safari > 2 does not include the border on offset parents
+				// However Mozilla adds the border for table or table cells
+				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
+					border( offsetParent );
+					
+				// Add the document scroll offsets if position is fixed on any offsetParent
+				if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
+					fixed = true;
+			
+				// Set offsetChild to previous offsetParent unless it is the body element
+				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
+				// Get next offsetParent
+				offsetParent = offsetParent.offsetParent;
+			}
+		
+			// Get parent scroll offsets
+			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
+				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
+				if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
+					// Subtract parent scroll offsets
+					add( -parent.scrollLeft, -parent.scrollTop );
+			
+				// Mozilla does not add the border for a parent that has overflow != visible
+				if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
+					border( parent );
+			
+				// Get next parent
+				parent = parent.parentNode;
+			}
+		
+			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
+			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
+			if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) || 
+				(mozilla && jQuery.css(offsetChild, "position") != "absolute") )
+					add( -doc.body.offsetLeft, -doc.body.offsetTop );
+			
+			// Add the document scroll offsets if position is fixed
+			if ( fixed )
+				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+		}
+
+		// Return an object with top and left properties
+		results = { top: top, left: left };
+	}
+
+	function border(elem) {
+		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
+	}
+
+	function add(l, t) {
+		left += parseInt(l) || 0;
+		top += parseInt(t) || 0;
+	}
+
+	return results;
+};
+
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each(["Height", "Width"], function(i, name){
+
+	var tl = name == "Height" ? "Top"    : "Left",  // top or left
+		br = name == "Height" ? "Bottom" : "Right"; // bottom or right
+	
+	// innerHeight and innerWidth
+	jQuery.fn["inner" + name] = function(){
+		return this[ name.toLowerCase() ]() + 
+			num(this, "padding" + tl) + 
+			num(this, "padding" + br);
+	};
+	
+	// outerHeight and outerWidth
+	jQuery.fn["outer" + name] = function(margin) {
+		return this["inner" + name]() + 
+			num(this, "border" + tl + "Width") +
+			num(this, "border" + br + "Width") +
+			(!!margin ? 
+				num(this, "margin" + tl) + num(this, "margin" + br) : 0);
+	};
+	
+});
+
+function num(elem, prop) {
+	elem = elem.jquery ? elem[0] : elem;
+	return elem && parseInt( jQuery.curCSS(elem, prop, true) ) || 0;
+}})();
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/loading.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/loading.gif
new file mode 100644
index 0000000..85b99d4
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/loading.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/pygments.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/pygments.css
new file mode 100644
index 0000000..a55a324
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/pygments.css
@@ -0,0 +1,59 @@
+.c { color: #408090; font-style: italic } /* Comment */
+.err { border: 1px solid #FF0000 } /* Error */
+.k { color: #007020; font-weight: bold } /* Keyword */
+.o { color: #666666 } /* Operator */
+.cm { color: #408090; font-style: italic } /* Comment.Multiline */
+.cp { color: #007020 } /* Comment.Preproc */
+.c1 { color: #408090; font-style: italic } /* Comment.Single */
+.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
+.gd { color: #A00000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #FF0000 } /* Generic.Error */
+.gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.gi { color: #00A000 } /* Generic.Inserted */
+.go { color: #303030 } /* Generic.Output */
+.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.gs { font-weight: bold } /* Generic.Strong */
+.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.gt { color: #0040D0 } /* Generic.Traceback */
+.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.kp { color: #007020 } /* Keyword.Pseudo */
+.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.kt { color: #902000 } /* Keyword.Type */
+.m { color: #208050 } /* Literal.Number */
+.s { color: #4070a0 } /* Literal.String */
+.na { color: #4070a0 } /* Name.Attribute */
+.nb { color: #007020 } /* Name.Builtin */
+.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.no { color: #60add5 } /* Name.Constant */
+.nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.ne { color: #007020 } /* Name.Exception */
+.nf { color: #06287e } /* Name.Function */
+.nl { color: #002070; font-weight: bold } /* Name.Label */
+.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.nt { color: #062873; font-weight: bold } /* Name.Tag */
+.nv { color: #bb60d5 } /* Name.Variable */
+.ow { color: #007020; font-weight: bold } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mf { color: #208050 } /* Literal.Number.Float */
+.mh { color: #208050 } /* Literal.Number.Hex */
+.mi { color: #208050 } /* Literal.Number.Integer */
+.mo { color: #208050 } /* Literal.Number.Oct */
+.sb { color: #4070a0 } /* Literal.String.Backtick */
+.sc { color: #4070a0 } /* Literal.String.Char */
+.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.s2 { color: #4070a0 } /* Literal.String.Double */
+.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.sh { color: #4070a0 } /* Literal.String.Heredoc */
+.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.sx { color: #c65d09 } /* Literal.String.Other */
+.sr { color: #235388 } /* Literal.String.Regex */
+.s1 { color: #4070a0 } /* Literal.String.Single */
+.ss { color: #517918 } /* Literal.String.Symbol */
+.bp { color: #007020 } /* Name.Builtin.Pseudo */
+.vc { color: #bb60d5 } /* Name.Variable.Class */
+.vg { color: #bb60d5 } /* Name.Variable.Global */
+.vi { color: #bb60d5 } /* Name.Variable.Instance */
+.il { color: #208050 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/tab.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/tab.png
new file mode 100644
index 0000000..413c755
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/tab.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.accordion.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.accordion.css
new file mode 100644
index 0000000..f45ed75
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.accordion.css
@@ -0,0 +1,12 @@
+ul.ui-accordion { margin: 0; padding: 0; list-style-type: none; }
+ul.ui-accordion li { margin: 0; margin-bottom: 2px; padding: 0; background-image: url(i/accordion-left.png); background-repeat: no-repeat; }
+ul.ui-accordion li a.ui-accordion-header { display: block; padding-left: 5px; margin-right: 3px; height: 28px; background-image: url(i/accordion-middle.png); color: #000; text-decoration: none; line-height: 28px; }
+ul.ui-accordion li .ui-accordion-right { display: block; background-image: url(i/accordion-right.png); position: absolute; top: 0px; right: 0px; height: 28px; width: 3px;  }
+
+ul.ui-accordion li:hover { background-image: url(i/accordion-left-over.png); }
+ul.ui-accordion li:hover a.ui-accordion-header { background-image: url(i/accordion-middle-over.png); }
+ul.ui-accordion li:hover .ui-accordion-right { background-image: url(i/accordion-right-over.png); }
+
+ul.ui-accordion li.active { background-image: url(i/accordion-left-act.png); }
+ul.ui-accordion li.active a.ui-accordion-header { background-image: url(i/accordion-middle-act.png); }
+ul.ui-accordion li.active .ui-accordion-right { background-image: url(i/accordion-right-act.png); }
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.all.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.all.css
new file mode 100644
index 0000000..3de5386
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.all.css
@@ -0,0 +1,9 @@
+ at import "flora.css";
+ at import "flora.shadow.css";
+ at import "flora.resizable.css";
+ at import "flora.slider.css";
+ at import "flora.accordion.css";
+ at import "flora.tabs.css";
+ at import "flora.dialog.css";
+ at import "flora.tablesorter.css";
+ at import "flora.datepicker.css";
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.calendar.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.calendar.css
new file mode 100644
index 0000000..dedcf0c
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.calendar.css
@@ -0,0 +1,167 @@
+/* Main Style Sheet for jQuery Calendar */
+#calendar_div, .calendar_inline {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 14px;
+	padding: 0;
+	margin: 0;
+	background: #ddd;
+}
+#calendar_div {
+	display: none;
+	border: 1px solid #FF9900;
+	z-index: 10; /*must have*/ 
+}
+#calendar_div, .calendar_control, .calendar_links, .calendar_header, .calendar {
+	width: 185px;
+}
+.calendar_inline {
+	float: left;
+	display: block;
+	border: 0;
+}
+.calendar_dialog {
+	padding: 5px !important;
+	border: 4px ridge #ddd !important;
+}
+button.calendar_trigger {
+	width: 25px;
+}
+img.calendar_trigger {
+	margin: 2px;
+	vertical-align: middle;
+}
+.calendar_prompt {
+	float: left;
+	width: 181px;
+	padding: 2px;
+	background: #ddd;
+	color: #000;
+}
+* html .calendar_prompt {
+	width: 185px;
+}
+.calendar_control, .calendar_links, .calendar_header, .calendar {
+	clear: both;
+	float: left;
+	color: #fff;
+}
+.calendar_control {
+	background: #FF9900;
+}
+.calendar_links {
+	background: #E0F4D7;
+}
+.calendar_control, .calendar_links {
+	font-weight: bold;
+	font-size: 80%;
+	letter-spacing: 1px;
+}
+.calendar_links label { /* disabled links */
+	padding: 2px 5px;
+	color: #888;
+}
+.calendar_clear, .calendar_prev {
+	float: left;
+}
+.calendar_current {
+	float: left;
+	width: 35%;
+	text-align: center;
+}
+.calendar_close, .calendar_next {
+	float: right;
+}
+.calendar_header {
+	background: #83C948;
+	text-align: center;
+	font-weight: bold;
+}
+.calendar_header select {
+	background: #83C948;
+	color: #000;
+	border: 0px;
+	font-weight: bold;
+}
+.calendar {
+	background: #ccc;
+	text-align: center;
+	font-size: 100%;
+}
+.calendar a {
+	display: block;
+	width: 100%;
+}
+.calendar .calendar_titleRow {
+	background: #B1DB87;
+	color: #000 !important;
+}
+.calendar .calendar_daysRow {
+	background: #FFF;
+	color: #666;
+}
+.calendar .calendar_daysCell {
+	color: #000;
+	border: 1px solid #ddd;
+}
+#calendar .calendar_daysCell a{
+	display: block;
+}
+.calendar .calendar_weekEndCell {
+	background: #E0F4D7;
+}
+.calendar .calendar_daysCellOver {
+	background: #fff;
+	border: 1px solid #777;
+}
+.calendar .calendar_unselectable {
+	color: #888;
+}
+.calendar_today {
+	background: #ccc !important;
+}
+.calendar_currentDay {
+	background: #999 !important;
+}
+
+/* ________ CALENDAR LINKS _______
+
+** Reset link properties and then override them with !important */
+#calendar_div a, .calendar_inline a {
+	cursor: pointer;
+	margin: 0;
+	padding: 0;
+	background: none;
+	color: #000;
+}
+.calendar_inline .calendar_links a {
+	padding: 0 5px !important;
+}
+.calendar_control a, .calendar_links a {
+	padding: 2px 5px !important;
+	color: #000 !important;
+}
+.calendar_titleRow a {
+	color: #000 !important;
+}
+.calendar_control a:hover {
+	/*background: #fdd !important;*/
+	color: #333 !important;
+}
+.calendar_links a:hover, .calendar_titleRow a:hover {
+	background: #FFF !important;
+	color: #333 !important;
+}
+
+/* ___________ IE6 IFRAME FIX ________ */
+
+.calendar_cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 193px; /*must have to match width and borders*/
+    height: 200px; /*must have to match maximum height*/ 
+}
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.css
new file mode 100644
index 0000000..761217d
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.css
@@ -0,0 +1,2 @@
+.ui-wrapper { border: 1px solid #50A029; }
+.ui-wrapper input, .ui-wrapper textarea { border: 0; }
\ No newline at end of file
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.datepicker.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.datepicker.css
new file mode 100644
index 0000000..34ea650
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.datepicker.css
@@ -0,0 +1,179 @@
+/* Main Flora Style Sheet for jQuery UI Datepicker */
+#datepicker_div, .datepicker_inline {
+	font-family: Arial,Helvetica,sans-serif;
+	font-size: 14px;
+	padding: 0;
+	margin: 0;
+	background: #DDD;
+	width: 185px;
+}
+#datepicker_div {
+	display: none;
+	border: 1px solid #FF9900;
+	z-index: 10;
+}
+.datepicker_inline {
+	float: left;
+	display: block;
+	border: 0;
+}
+.datepicker_dialog {
+	padding: 5px !important;
+	border: 4px ridge #DDD !important;
+}
+button.datepicker_trigger {
+	width: 25px;
+}
+img.datepicker_trigger {
+	margin: 2px;
+	vertical-align: middle;
+}
+.datepicker_prompt {
+	float: left;
+	padding: 2px;
+	background: #DDD;
+	color: #000;
+}
+*html .datepicker_prompt {
+	width: 185px;
+}
+.datepicker_control, .datepicker_links, .datepicker_header, .datepicker {
+	clear: both;
+	float: left;
+	width: 100%;
+	color: #FFF;
+}
+.datepicker_control {
+	background: #FF9900;
+	padding: 2px 0px;
+}
+.datepicker_links {
+	background: #E0F4D7;
+	padding: 2px 0px;
+}
+.datepicker_control, .datepicker_links {
+	font-weight: bold;
+	font-size: 80%;
+	letter-spacing: 1px;
+}
+.datepicker_links label {
+	padding: 2px 5px;
+	color: #888;
+}
+.datepicker_clear, .datepicker_prev {
+	float: left;
+	width: 34%;
+}
+.datepicker_current {
+	float: left;
+	width: 30%;
+	text-align: center;
+}
+.datepicker_close, .datepicker_next {
+	float: right;
+	width: 34%;
+	text-align: right;
+}
+.datepicker_header {
+	padding: 1px 0 3px;
+	background: #83C948;
+	text-align: center;
+	font-weight: bold;
+	height: 1.3em;
+}
+.datepicker_header select {
+	background: #83C948;
+	color: #000;
+	border: 0px;
+	font-weight: bold;
+}
+.datepicker {
+	background: #CCC;
+	text-align: center;
+	font-size: 100%;
+}
+.datepicker a {
+	display: block;
+	width: 100%;
+}
+.datepicker .datepicker_titleRow {
+	background: #B1DB87;
+	color: #000;
+}
+.datepicker .datepicker_daysRow {
+	background: #FFF;
+	color: #666;
+}
+.datepicker_weekCol {
+	background: #B1DB87;
+	color: #000;
+}
+.datepicker .datepicker_daysCell {
+	color: #000;
+	border: 1px solid #DDD;
+}
+#datepicker .datepicker_daysCell a {
+	display: block;
+}
+.datepicker .datepicker_weekEndCell {
+	background: #E0F4D7;
+}
+.datepicker .datepicker_daysCellOver {
+	background: #FFF;
+	border: 1px solid #777;
+}
+.datepicker .datepicker_unselectable {
+	color: #888;
+}
+.datepicker_today {
+	background: #B1DB87 !important;
+}
+.datepicker_currentDay {
+	background: #83C948 !important;
+}
+#datepicker_div a, .datepicker_inline a {
+	cursor: pointer;
+	margin: 0;
+	padding: 0;
+	background: none;
+	color: #000;
+}
+.datepicker_inline .datepicker_links a {
+	padding: 0 5px !important;
+}
+.datepicker_control a, .datepicker_links a {
+	padding: 2px 5px !important;
+	color: #000 !important;
+}
+.datepicker_titleRow a {
+	color: #000 !important;
+}
+.datepicker_control a:hover {
+	background: #FDD !important;
+	color: #333 !important;
+}
+.datepicker_links a:hover, .datepicker_titleRow a:hover {
+	background: #FFF !important;
+	color: #333 !important;
+}
+.datepicker_multi .datepicker {
+	border: 1px solid #83C948;
+}
+.datepicker_oneMonth {
+	float: left;
+	width: 185px;
+}
+.datepicker_newRow {
+	clear: left;
+}
+.datepicker_cover {
+	display: none;
+	display/**/: block;
+	position: absolute;
+	z-index: -1;
+	filter: mask();
+	top: -4px;
+	left: -4px;
+	width: 193px;
+	height: 200px;
+}
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.dialog.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.dialog.css
new file mode 100644
index 0000000..efef1c4
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.dialog.css
@@ -0,0 +1,95 @@
+/* This file skins dialog */
+
+.flora .ui-dialog,
+.flora.ui-dialog {
+	background-color: #e6f7d4;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar,
+.flora.ui-dialog .ui-dialog-titlebar {
+	border-bottom: 1px solid #d8d2aa;
+	background: #ff9900 url(i/dialog-title.gif) repeat-x;
+	padding: 0px;
+	height: 28px;
+	_height: 29px;
+}
+
+.flora .ui-dialog.ui-draggable .ui-dialog-titlebar,
+.flora.ui-dialog.ui-draggable .ui-dialog-titlebar {
+	cursor: move;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar-close,
+.flora.ui-dialog .ui-dialog-titlebar-close {
+	width: 16px;
+	height: 16px;
+	background: url(i/dialog-titlebar-close.png) no-repeat;
+	position:absolute;
+	top: 6px;
+	right: 7px;
+	cursor: default;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar-close span,
+.flora.ui-dialog .ui-dialog-titlebar-close span {
+	display: none;
+}
+
+.flora .ui-dialog .ui-dialog-titlebar-close-hover,
+.flora.ui-dialog .ui-dialog-titlebar-close-hover {
+	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
+}
+
+.flora .ui-dialog .ui-dialog-title,
+.flora.ui-dialog .ui-dialog-title {
+	margin-left: 5px;
+	color: white;
+	font-weight: bold;
+	position: relative;
+	top: 7px;
+	left: 4px;
+}
+
+.flora .ui-dialog .ui-dialog-content,
+.flora.ui-dialog .ui-dialog-content {
+	margin: 1.2em;
+}
+
+.flora .ui-dialog .ui-dialog-buttonpane,
+.flora.ui-dialog .ui-dialog-buttonpane {
+	position: absolute;
+	bottom: 8px;
+	right: 12px;
+	width: 100%;
+	text-align: right;
+}
+
+.flora .ui-dialog .ui-dialog-buttonpane button,
+.flora.ui-dialog .ui-dialog-buttonpane button {
+	margin: 6px;
+}
+
+/* Dialog handle styles */
+.flora .ui-dialog .ui-resizable-n,
+.flora.ui-dialog .ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/dialog-n.gif) repeat scroll center top; }
+
+.flora .ui-dialog .ui-resizable-s,
+.flora.ui-dialog .ui-resizable-s { cursor: s-resize; height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/dialog-s.gif) repeat scroll center top; }
+
+.flora .ui-dialog .ui-resizable-e,
+.flora.ui-dialog .ui-resizable-e { cursor: e-resize; width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-e.gif) repeat scroll right center; }
+
+.flora .ui-dialog .ui-resizable-w,
+.flora.ui-dialog .ui-resizable-w { cursor: w-resize; width: 7px; left: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-w.gif) repeat scroll right center; }
+
+.flora .ui-dialog .ui-resizable-se,
+.flora.ui-dialog .ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/dialog-se.gif); }
+
+.flora .ui-dialog .ui-resizable-sw,
+.flora.ui-dialog .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/dialog-sw.gif); }
+
+.flora .ui-dialog .ui-resizable-nw,
+.flora.ui-dialog .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/dialog-nw.gif); }
+
+.flora .ui-dialog .ui-resizable-ne,
+.flora.ui-dialog .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/dialog-ne.gif); }
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.menu.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.menu.css
new file mode 100644
index 0000000..6d2dd21
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.menu.css
@@ -0,0 +1,8 @@
+.ui-menu-toolbar {z-index:500; list-style:none;}
+.ui-menu-toolbar-button {float:left; padding:4px 20px; cursor:pointer;}
+.ui-menu-toolbar-button:hover {}
+.ui-menu-toolbar-button a {text-decoration:none;}
+.ui-menu-items {display:none; padding:0; z-index:500; list-style:none; padding:1px 4px; min-width:80px; *width:80px;}
+.ui-menu-item a { text-decoration:none;}
+.ui-menu-item-parent { background: url('i/menu-submenu.gif') no-repeat center right; }
+.ui-menu-item-disabled {}
\ No newline at end of file
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.resizable.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.resizable.css
new file mode 100644
index 0000000..5e30c0c
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.resizable.css
@@ -0,0 +1,20 @@
+/* This file skins resizables */
+
+.ui-resizable { position: relative; }
+
+/* Global handle styles */
+.ui-resizable-handle { position: absolute; display: none; font-size: 0.1px; }
+.ui-resizable .ui-resizable-handle { display: block; }
+body .ui-resizable-disabled .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
+body .ui-resizable-autohide .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */
+
+.ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/resizable-n.gif) repeat scroll center top; }
+.ui-resizable-s { cursor: s-resize; height: 6px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/resizable-s.gif) repeat scroll center top; }
+
+.ui-resizable-e { cursor: e-resize; width: 6px; right: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-e.gif) repeat scroll right center; }
+.ui-resizable-w { cursor: w-resize; width: 6px; left: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-w.gif) repeat scroll right center; }
+
+.ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/resizable-se.gif); }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/resizable-sw.gif); }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: 0px; top: 0px; background: transparent url(i/resizable-nw.gif); }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: 0px; top: 0px; background: transparent url(i/resizable-ne.gif); }
\ No newline at end of file
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.slider.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.slider.css
new file mode 100644
index 0000000..94827b3
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.slider.css
@@ -0,0 +1,11 @@
+/* This file skins sliders */
+
+.ui-slider { width: 200px; height: 23px; position: relative; background-repeat: no-repeat; background-position: center center; }
+.ui-slider-handle { position: absolute; z-index: 1; height: 23px; width: 12px; top: 0px; left: 0px; background-image: url(i/slider-handle.gif);  }
+.ui-slider-handle-active { border: 1px dotted black;  }
+.ui-slider-disabled .ui-slider-handle { opacity: 0.5; filter: alpha(opacity=50); }
+.ui-slider-range { position: absolute; background: #50A029; opacity: 0.3; filter: alpha(opacity=30); width: 100%; height: 100%; }
+
+/* Default slider backgrounds */
+.ui-slider, .ui-slider-1 { background-image: url(i/slider-bg-1.png); }
+.ui-slider-2 { background-image: url(i/slider-bg-2.png); }
\ No newline at end of file
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tablesorter.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tablesorter.css
new file mode 100644
index 0000000..7d805a7
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tablesorter.css
@@ -0,0 +1,40 @@
+/* This file skins tableSorter */
+
+table.tablesorter {
+	font-family:arial;
+	background-color: #CDCDCD;
+	margin:10px 0pt 15px;
+	font-size: 8pt;
+	width: 100%;
+	text-align: left;
+}
+table.tablesorter thead tr th, table.tablesorter tfoot tr th {
+	background-color: #B1DB87;
+	border: 1px solid #FFF;
+	font-size: 8pt;
+	padding: 4px;
+}
+table.tablesorter thead tr .header {
+	background-image: url(i/bg.gif);
+	background-repeat: no-repeat;
+	background-position: center right;
+	cursor: pointer;
+}
+table.tablesorter tbody td {
+	color: #3D3D3D;
+	padding: 4px;
+	background-color: #FFF;
+	vertical-align: top;
+}
+table.tablesorter tbody tr.odd td {
+	background-color:#E0F4D7;
+}
+table.tablesorter thead tr .headerSortUp {
+	background-image: url(i/asc.gif);
+}
+table.tablesorter thead tr .headerSortDown {
+	background-image: url(i/desc.gif);
+}
+table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
+background-color: #83C948;
+}
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tabs.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tabs.css
new file mode 100644
index 0000000..c79a17e
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.tabs.css
@@ -0,0 +1,105 @@
+ at import "flora.css";
+
+/* Caution! Ensure accessibility in print and other media types... */
+ at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
+    .ui-tabs-hide {
+        display: none;
+    }
+}
+
+/* Hide useless elements in print layouts... */
+ at media print {
+    .ui-tabs-nav {
+        display: none;
+    }
+}
+
+/* Skin */
+.ui-tabs-nav, .ui-tabs-panel {
+    font-family: "Trebuchet MS", Trebuchet, Verdana, Helvetica, Arial, sans-serif;
+    font-size: 12px;
+}
+.ui-tabs-nav {
+    list-style: none;
+    margin: 0;
+    padding: 0 0 0 3px;
+}
+.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
+    display: block;
+    clear: both;
+    content: " ";
+}
+.ui-tabs-nav li {
+    float: left;
+    margin: 0 0 0 2px;
+    font-weight: bold;
+}
+.ui-tabs-nav a, .ui-tabs-nav a span {
+    float: left; /* fixes dir=ltr problem and other quirks IE */
+    padding: 0 12px;
+    background: url(i/tabs.png) no-repeat;
+}
+.ui-tabs-nav a {
+    margin: 5px 0 0; /* position: relative makes opacity fail for disabled tab in IE */
+    padding-left: 0;
+    background-position: 100% 0;
+    text-decoration: none;
+    white-space: nowrap; /* @ IE 6 */
+    outline: 0; /* @ Firefox, prevent dotted border after click */    
+}
+.ui-tabs-nav a:link, .ui-tabs-nav a:visited {
+    color: #fff;
+}
+.ui-tabs-nav .ui-tabs-selected a {
+    position: relative;
+    top: 1px;
+    z-index: 2;
+    margin-top: 0;
+    background-position: 100% -23px;
+}
+.ui-tabs-nav a span {
+    padding-top: 1px;
+    padding-right: 0;
+    height: 20px;
+    background-position: 0 0;
+    line-height: 20px;
+}
+.ui-tabs-nav .ui-tabs-selected a span {
+    padding-top: 0;
+    height: 27px;
+    background-position: 0 -23px;
+    line-height: 27px;
+}
+.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited,
+.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
+    cursor: text;
+}
+.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active,
+.ui-tabs-nav .ui-tabs-unselect a:hover, .ui-tabs-nav .ui-tabs-unselect a:focus, .ui-tabs-nav .ui-tabs-unselect a:active { /* @ Opera, we need to be explicit again here now... */
+    cursor: pointer;
+}
+.ui-tabs-disabled {
+    opacity: .4;
+    filter: alpha(opacity=40);
+}
+.ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited {
+    color: #000;
+}
+.ui-tabs-panel {
+    border: 1px solid #519e2d;
+    padding: 10px;
+    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
+}
+/*.ui-tabs-loading em {
+    padding: 0 0 0 20px;
+    background: url(loading.gif) no-repeat 0 50%;
+}*/
+
+/* Additional IE specific bug fixes... */
+* html .ui-tabs-nav { /* auto clear @ IE 6 & IE 7 Quirks Mode */
+    display: inline-block;
+}
+*:first-child+html .ui-tabs-nav  { /* auto clear @ IE 7 Standards Mode - do not group selectors, otherwise IE 6 will ignore complete rule (because of the unknown + combinator)... */
+    display: inline-block;
+}
+
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toasterLite.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toasterLite.css
new file mode 100644
index 0000000..6f2b55f
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toasterLite.css
@@ -0,0 +1,106 @@
+/* This file skins toasterLite */
+
+.flora .ui-toasterLite,
+.flora.ui-toasterLite {
+	background-color: #e6f7d4;
+	width: 100px;
+	display: block;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-titlebar,
+.flora.ui-toasterLite .ui-toasterLite-titlebar {
+	border-bottom: 1px solid #d8d2aa;
+	background: #ff9900 url(i/dialog-title.gif) repeat-x;
+	padding: 0px;
+	height: 28px;
+	z-index: 5;
+	position: relative;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-title,
+.flora.ui-toasterLite .ui-toasterLite-title {
+	margin-left: 5px;
+	color: white;
+	font-weight: bold;
+	position: relative;
+	top: 7px;
+	left: 4px;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-content,
+.flora.ui-toasterLite .ui-toasterLite-content {
+	margin: 1.2em;
+	padding-bottom: 12px;
+}
+
+/* Toaster handle styles */
+.flora .ui-toasterLite .ui-toasterLite-n,
+.flora.ui-toasterLite .ui-toasterLite-n { height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/toaster-n.gif) repeat scroll center top; z-index: 6; }
+
+.flora .ui-toasterLite .ui-toasterLite-s,
+.flora.ui-toasterLite .ui-toasterLite-s { height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/toaster-s.gif) repeat scroll center top; z-index: 1; }
+
+.flora .ui-toasterLite .ui-toasterLite-e,
+.flora.ui-toasterLite .ui-toasterLite-e { width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/toaster-e.gif) repeat scroll right center; }
+
+.flora .ui-toasterLite .ui-toasterLite-w,
+.flora.ui-toasterLite .ui-toasterLite-w { width: 7px; left: 0px; top: 0px; height: 100%; background: url(i/toaster-w.gif) repeat scroll right center; }
+
+.flora .ui-toasterLite .ui-toasterLite-se,
+.flora.ui-toasterLite .ui-toasterLite-se { width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/toaster-se.gif); z-index: 2; }
+
+.flora .ui-toasterLite .ui-toasterLite-sw,
+.flora.ui-toasterLite .ui-toasterLite-sw { width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/toaster-sw.gif); z-index: 2; }
+
+.flora .ui-toasterLite .ui-toasterLite-nw,
+.flora.ui-toasterLite .ui-toasterLite-nw { width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/toaster-nw.gif); z-index: 6; }
+
+.flora .ui-toasterLite .ui-toasterLite-ne,
+.flora.ui-toasterLite .ui-toasterLite-ne { width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/toaster-ne.gif); z-index: 6; }
+
+/* Global handle styles */
+.ui-toasterLite-corner { position: absolute; font-size: 0.1px; }
+
+.flora .ui-toasterLite-holder,
+.flora.ui-toasterLite-holder {
+  position: absolute;
+}
+.flora .ui-toasterLite-holder-pos-tr,
+.flora.ui-toasterLite-holder-pos-tr {
+  top: 10px;
+  right: 10px;
+}
+
+.flora .ui-toasterLite-holder-pos-tl,
+.flora.ui-toasterLite-holder-pos-tl {
+  top: 10px;
+  left: 10px;
+}
+
+.flora .ui-toasterLite-holder-pos-br,
+.flora.ui-toasterLite-holder-pos-br {
+  bottom: 10px;
+  right: 10px;
+}
+
+.flora .ui-toasterLite-holder-pos-bl,
+.flora.ui-toasterLite-holder-pos-bl {
+  bottom: 10px;
+  left: 10px;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-titlebar-close,
+.flora.ui-toasterLite .ui-toasterLite-titlebar-close {
+	width: 16px;
+	height: 16px;
+	background: url(i/dialog-titlebar-close.png) no-repeat;
+	position:absolute;
+	top: 6px;
+	right: 7px;
+	cursor: default;
+}
+
+.flora .ui-toasterLite .ui-toasterLite-titlebar-close-hover,
+.flora.ui-toasterLite .ui-toasterLite-titlebar-close-hover {
+	background: url(i/dialog-titlebar-close-hover.png) no-repeat;
+}
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toolbar.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toolbar.css
new file mode 100644
index 0000000..8ad0588
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/flora.toolbar.css
@@ -0,0 +1,241 @@
+/* light.toolbar.css
+ *
+ *  Written: 05/09/07 4:38:01 PM
+ *  Revision: 1.0.0
+ *
+ *
+ * Credits:
+ *  Miksago: Full Coding.
+ */
+
+.flora .ui-toolbar {
+  position:relative;
+  padding:0px;
+  margin:0px;
+}
+.flora .ui-toolbar ul {
+  background:#E6F7D4;
+  padding:0px;
+  margin:0px;
+}
+  .flora .ui-toolbar ul li {
+    list-style-type: none;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-horiz {
+    border-top:1px solid #5AB500;
+    background:#E6F7D4 url("i/toolbars-bot-bg.gif") repeat-x bottom left;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-horiz li {
+    display:inline;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert {
+    padding: 0.025em 0em;
+    border-left: 1px solid #111;
+    border-right: 1px solid #444;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert li {
+    display:block;
+  }
+  /* This hides the text on buttons in a icon only toolbar */
+  .flora .ui-toolbar ul.ui-toolbar-icons li .ui-toolbar-btn-desc {
+    display:none;
+  }
+  /* This hides the icon on buttons in a text only toolbar */
+  .flora .ui-toolbar ul.ui-toolbar-text li .ui-toolbar-btn-icon {
+    display:none;
+  }
+  /* This is just for icon sizes, not really needed, but it's there so if icon sizes are defined.. */
+  .flora .ui-toolbar ul li.ui-toolbar-btn-icon-sixteen .ui-toolbar-btn-icon {
+    width:16px; height:16px;
+    overflow:hidden;
+    padding:2px;
+    padding-left:16px;
+    background:no-repeat;
+    background-position:50% 50%;
+  }
+  
+/************************************************
+ * Factory Elements:
+ *  - These are different kinds of items that
+ *    can be in a toolbar.
+ *
+ *  Includes:
+ *    @ ui-toolbar-btn
+ *        toolbar buttons.
+ *    @ ui-toolbar-sep
+ *        toolbar separators.
+ *
+*/
+
+
+
+/************************************************
+ * UI-TOOLBAR-BTN
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-btn">
+ *      <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
+ *      <span class="ui-toolbar-btn-center">
+ *        <button><span>{{text}}</span></button>
+ *      </span>
+ *      <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
+ *    </li>
+ *
+ ************************************************/
+
+
+  .flora .ui-toolbar ul li.ui-toolbar-btn {
+    cursor:pointer;
+    white-space: nowrap;
+    position:relative;
+  }
+  .flora .ui-toolbar ul li .ui-toolbar-btn-left {
+    width:3px;
+    padding:5px 0px 1px 0;
+    position:absolute;
+    top:-3px;
+    bottom:0px;
+    left:-3px;
+    height:100%;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
+    width:3px; height:5px;
+    padding:0px 0px 0px 0px;
+    position:absolute;
+    bottom:0px;
+    left:0px;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center{
+    background:url("i/accordion-middle-over.png") repeat-x left top;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left {
+    background:url("i/accordion-left-over.png") no-repeat left top;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-left i,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-left i{
+    background:url("i/accordion-left-over.png") no-repeat left bottom;
+  }
+  .flora .ui-toolbar ul li .ui-toolbar-btn-center {
+    padding: 0.2em 0em;
+    line-height:2.2em;
+  }
+    .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-btn {
+      vertical-align: middle;
+      margin:0.3em 0.2em;
+    }
+    .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-btn {
+      margin:0.2em;
+      line-height:1.6em;
+      vertical-align: middle;
+    }
+      .flora .ui-toolbar ul li button {
+        vertical-align: middle;
+        background:transparent;
+        color:#000;
+        border:0px none;
+        cursor:pointer;
+        overflow:visible;
+        -moz-outline:0 none;
+        outline:0 none;
+        padding: 0.1em 0.1em;
+      }
+        .flora .ui-toolbar ul li.ui-toolbar-btn button span {
+          vertical-align: middle;
+        }
+        /* This hides the text on buttons in a icon only toolbar */
+        .flora .ui-toolbar ul.ui-toobar-iconOnly li.ui-toolbar-btn button span {
+          display:none;
+        }
+  
+  .flora .ui-toolbar ul li.ui-toolbar-btn-over .ui-toolbar-btn-center button,
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active .ui-toolbar-btn-center button {
+    background: url("i/accordion-middle-over.png") repeat-x left bottom;
+  }
+  .flora .ui-toolbar ul li.ui-toolbar-btn-active {
+    
+  }
+  
+  .flora .ui-toolbar ul li.ui-toolbar-btn-disabled {
+    opacity:0.2;
+  }
+
+/************************************************
+ * UI-TOOLBAR-BTN
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-sep">
+ *      <span>
+ *        &nbsp;
+ *      </span>
+ *    </li>
+ *
+ ************************************************/
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-sep {
+    border-left:1px solid #444;
+    border-right:1px solid #111;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-sep {
+    border-top:1px solid #111;
+    border-bottom:1px solid #444;
+  }
+
+/************************************************
+ * UI-TOOLBAR-SLIDER
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-slider">
+ *      <div class="ui-toolbar-slider-track ui-slider-track">
+ *        <div class="ui-slider-handle"></div>
+ *      </div>
+ *   </li>
+ *
+ ************************************************/
+
+.flora .ui-toolbar ul li.ui-toolbar-slider .ui-toolbar-slider-track {
+  height: 20px!important;
+}
+
+/************************************************
+ * UI-TOOLBAR-RADIOGRP
+ *
+ *  STRUCTURE:
+ *    <li class="ui-toolbar-radioGrp">
+ *      <ul class="DIRECTION">
+ *        <li class="ui-toolbar-btn">
+ *          <span class="ui-toolbar-btn-left"><i>&#160;</i></span>
+ *          <span class="ui-toolbar-btn-center">
+ *            <button><span>{{text}}</span></button>
+ *          </span>
+ *          <span class="ui-toolbar-btn-right"><i>&#160;</i></span>
+ *        </li>
+ *      </ul>
+ *    </li>
+ *      
+ *
+ ************************************************/
+
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp,
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul,
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul li{
+    display:inline;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-horiz li.ui-toolbar-radioGrp ul {
+    margin:0px;
+    padding:0px;
+  }
+
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp,
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul,
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul li{
+    display:block;
+  }
+  .flora .ui-toolbar ul.ui-toolbar-vert li.ui-toolbar-radioGrp ul {
+    margin:0px;
+    padding:0px;
+  }
+
+
+/* END OF FILE */
\ No newline at end of file
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-act.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-act.png
new file mode 100644
index 0000000..bf6ee99
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-act.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-over.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-over.png
new file mode 100644
index 0000000..66378e0
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left-over.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left.png
new file mode 100644
index 0000000..13344fc
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-left.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-act.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-act.png
new file mode 100644
index 0000000..cecf4f1
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-act.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-over.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-over.png
new file mode 100644
index 0000000..251ad11
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle-over.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle.png
new file mode 100644
index 0000000..5238fd4
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-middle.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-act.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-act.png
new file mode 100644
index 0000000..1fa4792
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-act.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-over.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-over.png
new file mode 100644
index 0000000..d676dad
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right-over.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right.png
new file mode 100644
index 0000000..543991a
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/accordion-right.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/asc.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/asc.gif
new file mode 100644
index 0000000..7415786
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/asc.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/bg.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/bg.gif
new file mode 100644
index 0000000..fac668f
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/bg.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/desc.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/desc.gif
new file mode 100644
index 0000000..3b30b3c
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/desc.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-e.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-e.gif
new file mode 100644
index 0000000..3b8b521
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-e.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-n.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-n.gif
new file mode 100644
index 0000000..70887b8
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-n.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-ne.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-ne.gif
new file mode 100644
index 0000000..ab9c38e
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-ne.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-nw.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-nw.gif
new file mode 100644
index 0000000..e934073
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-nw.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-s.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-s.gif
new file mode 100644
index 0000000..d5f6b99
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-s.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-se.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-se.gif
new file mode 100644
index 0000000..186a864
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-se.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-sw.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-sw.gif
new file mode 100644
index 0000000..025dfda
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-sw.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-title.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-title.gif
new file mode 100644
index 0000000..156c59b
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-title.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png
new file mode 100644
index 0000000..67c1303
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close-hover.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png
new file mode 100644
index 0000000..cec974c
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-titlebar-close.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-w.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-w.gif
new file mode 100644
index 0000000..931ff4a
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/dialog-w.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/menu-submenu.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/menu-submenu.gif
new file mode 100644
index 0000000..77647d8
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/menu-submenu.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-e.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-e.gif
new file mode 100644
index 0000000..7acf248
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-e.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-n.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-n.gif
new file mode 100644
index 0000000..59110f6
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-n.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-ne.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-ne.gif
new file mode 100644
index 0000000..515a3f8
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-ne.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-nw.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-nw.gif
new file mode 100644
index 0000000..665f318
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-nw.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-s.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-s.gif
new file mode 100644
index 0000000..da2fb35
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-s.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-se.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-se.gif
new file mode 100644
index 0000000..6c258ef
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-se.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-sw.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-sw.gif
new file mode 100644
index 0000000..2fd8de4
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-sw.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-w.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-w.gif
new file mode 100644
index 0000000..34b875b
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/resizable-w.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/shadow.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/shadow.png
new file mode 100644
index 0000000..4c58c7f
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/shadow.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-1.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-1.png
new file mode 100644
index 0000000..b7d806e
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-1.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-2.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-2.png
new file mode 100644
index 0000000..8b24cf0
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-bg-2.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-handle.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-handle.gif
new file mode 100644
index 0000000..9b89f26
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/slider-handle.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/tabs.png b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/tabs.png
new file mode 100644
index 0000000..8018e41
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/tabs.png differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-e.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-e.gif
new file mode 100644
index 0000000..55dcb2c
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-e.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-n.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-n.gif
new file mode 100644
index 0000000..b0fbeb9
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-n.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-ne.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-ne.gif
new file mode 100644
index 0000000..ab9c38e
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-ne.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-nw.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-nw.gif
new file mode 100644
index 0000000..e934073
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-nw.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-s.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-s.gif
new file mode 100644
index 0000000..15640e8
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-s.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-se.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-se.gif
new file mode 100644
index 0000000..fb7a7df
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-se.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-sw.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-sw.gif
new file mode 100644
index 0000000..ad1ae1c
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-sw.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-w.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-w.gif
new file mode 100644
index 0000000..8489de8
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toaster-w.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif
new file mode 100644
index 0000000..15640e8
Binary files /dev/null and b/moksha/apps/docs/moksha/apps/widgetbrowser/static/themes/flora/i/toolbars-bot-bg.gif differ
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.base.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.base.js
new file mode 100644
index 0000000..17115f0
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.base.js
@@ -0,0 +1,204 @@
+/*
+ * jQuery UI @VERSION
+ *
+ * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ *
+ * $Date: 2008-04-01 09:23:47 -0400 (Tue, 01 Apr 2008) $
+ * $Rev: 5174 $
+ */
+;(function($) {
+
+	//If the UI scope is not available, add it
+	$.ui = $.ui || {};
+	
+	//Add methods that are vital for all mouse interaction stuff (plugin registering)
+	$.extend($.ui, {
+		plugin: {
+			add: function(module, option, set) {
+				var proto = $.ui[module].prototype;
+				for(var i in set) {
+					proto.plugins[i] = proto.plugins[i] || [];
+					proto.plugins[i].push([option, set[i]]);
+				}
+			},
+			call: function(instance, name, arguments) {
+				var set = instance.plugins[name]; if(!set) return;
+				for (var i = 0; i < set.length; i++) {
+					if (instance.options[set[i][0]]) set[i][1].apply(instance.element, arguments);
+				}
+			}	
+		},
+		cssCache: {},
+		css: function(name) {
+			if ($.ui.cssCache[name]) return $.ui.cssCache[name];
+			var tmp = $('<div class="ui-resizable-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
+			
+			//if (!$.browser.safari)
+				//tmp.appendTo('body'); 
+			
+			//Opera and Safari set width and height to 0px instead of auto
+			//Safari returns rgba(0,0,0,0) when bgcolor is not set
+			$.ui.cssCache[name] = !!(
+				(!/auto|default/.test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 
+				!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
+			);
+			try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
+			return $.ui.cssCache[name];
+		},
+		disableSelection: function(e) {
+			e.unselectable = "on";
+			e.onselectstart = function() {	return false; };
+			if (e.style) e.style.MozUserSelect = "none";
+		},
+		enableSelection: function(e) {
+			e.unselectable = "off";
+			e.onselectstart = function() { return true; };
+			if (e.style) e.style.MozUserSelect = "";
+		},
+		hasScroll: function(e, a) {
+      		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;
+      		if (e[scroll] > 0) return true; e[scroll] = 1;
+      		has = e[scroll] > 0 ? true : false; e[scroll] = 0;
+      		return has; 
+    	}
+	});
+
+	/******* fn scope modifications ********/
+
+	$.each( ['Left', 'Top'], function(i, name) {
+		if(!$.fn['scroll'+name]) $.fn['scroll'+name] = function(v) {
+			return v != undefined ?
+				this.each(function() { this == window || this == document ? window.scrollTo(name == 'Left' ? v : $(window)['scrollLeft'](), name == 'Top'  ? v : $(window)['scrollTop']()) : this['scroll'+name] = v; }) :
+				this[0] == window || this[0] == document ? self[(name == 'Left' ? 'pageXOffset' : 'pageYOffset')] || $.boxModel && document.documentElement['scroll'+name] || document.body['scroll'+name] : this[0][ 'scroll' + name ];
+		};
+	});
+
+	var _remove = $.fn.remove;
+	$.fn.extend({
+		position: function() {
+			var offset       = this.offset();
+			var offsetParent = this.offsetParent();
+			var parentOffset = offsetParent.offset();
+
+			return {
+				top:  offset.top - num(this[0], 'marginTop')  - parentOffset.top - num(offsetParent, 'borderTopWidth'),
+				left: offset.left - num(this[0], 'marginLeft')  - parentOffset.left - num(offsetParent, 'borderLeftWidth')
+			};
+		},
+		offsetParent: function() {
+			var offsetParent = this[0].offsetParent;
+			while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
+				offsetParent = offsetParent.offsetParent;
+			return $(offsetParent);
+		},
+		mouseInteraction: function(o) {
+			return this.each(function() {
+				new $.ui.mouseInteraction(this, o);
+			});
+		},
+		removeMouseInteraction: function(o) {
+			return this.each(function() {
+				if($.data(this, "ui-mouse"))
+					$.data(this, "ui-mouse").destroy();
+			});
+		},
+		remove: function() {
+			jQuery("*", this).add(this).trigger("remove");
+			return _remove.apply(this, arguments );
+		}
+	});
+	
+	function num(el, prop) {
+		return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
+	};
+	
+	
+	/********** Mouse Interaction Plugin *********/
+	
+	$.ui.mouseInteraction = function(element, options) {
+	
+		var self = this;
+		this.element = element;
+
+		$.data(this.element, "ui-mouse", this);
+		this.options = $.extend({}, options);
+		
+		$(element).bind('mousedown.draggable', function() { return self.click.apply(self, arguments); });
+		if($.browser.msie) $(element).attr('unselectable', 'on'); //Prevent text selection in IE
+		
+		// prevent draggable-options-delay bug #2553
+		$(element).mouseup(function() {
+			if(self.timer) clearInterval(self.timer);
+		});
+	};
+	
+	$.extend($.ui.mouseInteraction.prototype, {
+		
+		destroy: function() { $(this.element).unbind('mousedown.draggable'); },
+		trigger: function() { return this.click.apply(this, arguments); },
+		click: function(e) {
+			
+			if(
+				   e.which != 1 //only left click starts dragging
+				|| $.inArray(e.target.nodeName.toLowerCase(), this.options.dragPrevention || []) != -1 // Prevent execution on defined elements
+				|| (this.options.condition && !this.options.condition.apply(this.options.executor || this, [e, this.element])) //Prevent execution on condition
+			) return true;
+				
+			var self = this;
+			var initialize = function() {
+				self._MP = { left: e.pageX, top: e.pageY }; // Store the click mouse position
+				$(document).bind('mouseup.draggable', function() { return self.stop.apply(self, arguments); });
+				$(document).bind('mousemove.draggable', function() { return self.drag.apply(self, arguments); });
+				
+				if(!self.initalized && Math.abs(self._MP.left-e.pageX) >= self.options.distance || Math.abs(self._MP.top-e.pageY) >= self.options.distance) {				
+					if(self.options.start) self.options.start.call(self.options.executor || self, e, self.element);
+					if(self.options.drag) self.options.drag.call(self.options.executor || self, e, this.element); //This is actually not correct, but expected
+					self.initialized = true;
+				}
+			};
+
+			if(this.options.delay) {
+				if(this.timer) clearInterval(this.timer);
+				this.timer = setTimeout(initialize, this.options.delay);
+			} else {
+				initialize();
+			}
+				
+			return false;
+			
+		},
+		stop: function(e) {			
+			
+			var o = this.options;
+			if(!this.initialized) return $(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
+
+			if(this.options.stop) this.options.stop.call(this.options.executor || this, e, this.element);
+			$(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
+			this.initialized = false;
+			return false;
+			
+		},
+		drag: function(e) {
+
+			var o = this.options;
+			if ($.browser.msie && !e.button) return this.stop.apply(this, [e]); // IE mouseup check
+			
+			if(!this.initialized && (Math.abs(this._MP.left-e.pageX) >= o.distance || Math.abs(this._MP.top-e.pageY) >= o.distance)) {				
+				if(this.options.start) this.options.start.call(this.options.executor || this, e, this.element);
+				this.initialized = true;
+			} else {
+				if(!this.initialized) return false;
+			}
+
+			if(o.drag) o.drag.call(this.options.executor || this, e, this.element);
+			return false;
+			
+		}
+	});
+	
+})(jQuery);
+ 
\ No newline at end of file
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.dialog.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.dialog.js
new file mode 100644
index 0000000..7a907bd
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.dialog.js
@@ -0,0 +1,459 @@
+/*
+ * jQuery UI Dialog
+ *
+ * Copyright (c) 2008 Richard D. Worth (rdworth.org)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *   ui.base.js
+ *   ui.draggable.js
+ *   ui.resizable.js
+ *
+ * Revision: $Id: ui.dialog.js 5185 2008-04-03 15:39:51Z scott.gonzalez $
+ */
+;(function($) {
+	
+	$.fn.extend({
+		dialog: function(options) {
+			var args = Array.prototype.slice.call(arguments, 1);
+
+			return this.each(function() {
+				if (typeof options == "string") {
+					var elem = $(this).is('.ui-dialog')
+						? this
+						: $(this).parents(".ui-dialog:first").find(".ui-dialog-content")[0];
+					var dialog = elem ? $.data(elem, "dialog") : {};
+					if (dialog[options])
+						dialog[options].apply(dialog, args);
+				// INIT with optional options
+				} else if (!$(this).is(".ui-dialog-content"))
+					new $.ui.dialog(this, options);
+			});
+		}
+	});
+
+	$.ui.dialog = function(el, options) {
+		
+		this.options = options = $.extend({}, $.ui.dialog.defaults, options);
+		this.element = el;
+		var self = this; //Do bindings
+
+		$.data(this.element, "dialog", this);
+
+		$(el).bind("remove", function() {
+			self.destroy();
+		});
+		
+		$(el).bind("setData.dialog", function(event, key, value){
+			switch (key) {
+				case "draggable":
+					uiDialog.draggable(value ? 'enable' : 'disable');
+					break;
+				case "dragStart":
+					uiDialog.data('start.draggable', value);
+					break;
+				case "drag":
+					uiDialog.data('drag.draggable', value);
+					break;
+				case "dragStop":
+					uiDialog.data('stop.draggable', value);
+					break;
+				case "height":
+					uiDialog.height(value);
+					break;
+				case "maxHeight":
+				case "minHeight":
+				case "maxWidth":
+				case "minWidth":
+					uiDialog.data(key + ".resizable", value);
+					break;
+				case "position":
+					self.position(value);
+					break;
+				case "resizable":
+					uiDialog.resizable(value ? 'enable' : 'disable');
+					break;
+				case "resizeStart":
+					uiDialog.data('start.resizable', value);
+					break;
+				case "resize":
+					uiDialog.data('resize.resizable', value);
+					break;
+				case "resizeStop":
+					uiDialog.data('stop.resizable', value);
+					break;
+				case "title":
+					$(".ui-dialog-title", uiDialogTitlebar).text(value);
+					break;
+				case "width":
+					break;
+			}
+			options[key] = value;
+		}).bind("getData.dialog", function(event, key){
+			return options[key];
+		});
+
+		var uiDialogContent = $(el).addClass('ui-dialog-content');
+
+		if (!uiDialogContent.parent().length) {
+			uiDialogContent.appendTo('body');
+		}
+		uiDialogContent
+			.wrap(document.createElement('div'))
+			.wrap(document.createElement('div'));
+		var uiDialogContainer = uiDialogContent.parent().addClass('ui-dialog-container').css({position: 'relative'});
+		var uiDialog = this.uiDialog = uiDialogContainer.parent().hide()
+			.addClass('ui-dialog')
+			.css({position: 'absolute', width: options.width, height: options.height, overflow: 'hidden'}); 
+
+		var classNames = uiDialogContent.attr('className').split(' ');
+
+		// Add content classes to dialog, to inherit theme at top level of element
+		$.each(classNames, function(i, className) {
+			if (className != 'ui-dialog-content')
+				uiDialog.addClass(className);
+		});
+
+		if ($.fn.resizable) {
+			uiDialog.append('<div class="ui-resizable-n ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-s ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-e ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-w ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-ne ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-se ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-sw ui-resizable-handle"></div>')
+				.append('<div class="ui-resizable-nw ui-resizable-handle"></div>');
+			uiDialog.resizable({
+				maxWidth: options.maxWidth,
+				maxHeight: options.maxHeight,
+				minWidth: options.minWidth,
+				minHeight: options.minHeight,
+				start: options.resizeStart,
+				resize: options.resize,
+				stop: function(e, ui) {
+					options.resizeStop && options.resizeStop.apply(this, arguments);
+					$.ui.dialog.overlay.resize();
+				}
+			});
+			if (!options.resizable)
+				uiDialog.resizable('disable');
+		}
+
+		uiDialogContainer.prepend('<div class="ui-dialog-titlebar"></div>');
+		var uiDialogTitlebar = $('.ui-dialog-titlebar', uiDialogContainer);
+		var title = (options.title) ? options.title : (uiDialogContent.attr('title')) ? uiDialogContent.attr('title') : '';
+		uiDialogTitlebar.append('<span class="ui-dialog-title">' + title + '</span>');
+		uiDialogTitlebar.append('<a href="#" class="ui-dialog-titlebar-close"><span>X</span></a>');
+		this.uiDialogTitlebarClose = $('.ui-dialog-titlebar-close', uiDialogTitlebar)
+			.hover(function() { $(this).addClass('ui-dialog-titlebar-close-hover'); }, 
+			       function() { $(this).removeClass('ui-dialog-titlebar-close-hover'); })
+			.mousedown(function(ev) {
+				ev.stopPropagation();
+			})
+			.click(function() {
+				self.close();
+				return false;
+			})
+			.keydown(function(ev) {
+				var ESC = 27;
+				ev.keyCode && ev.keyCode == ESC && self.close(); 
+			});
+
+		var l = 0;
+		$.each(options.buttons, function() { l = 1; return false; });
+		if (l == 1) {
+			uiDialog.append('<div class="ui-dialog-buttonpane"></div>');
+			var uiDialogButtonPane = $('.ui-dialog-buttonpane', uiDialog);
+			$.each(options.buttons, function(name, value) {
+				var btn = $(document.createElement('button')).text(name).click(value);
+				uiDialogButtonPane.append(btn);
+			});
+		}
+
+		if ($.fn.draggable) {
+			uiDialog.draggable({
+				handle: '.ui-dialog-titlebar',
+				start: function(e, ui) {
+					self.activate();
+					options.dragStart && options.dragStart.apply(this, arguments);
+				},
+				drag: options.drag,
+				stop: function(e, ui) {
+					options.dragStop && options.dragStop.apply(this, arguments);
+					$.ui.dialog.overlay.resize();
+				}
+			});
+			if (!options.draggable)
+				uiDialog.draggable('disable')
+		}
+	
+		uiDialog.mousedown(function() {
+			self.activate();
+		});
+		uiDialogTitlebar.click(function() {
+			self.activate();
+		});
+		
+		options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe();
+
+		this.position = function(pos) {
+			var wnd = $(window), doc = $(document), top = doc.scrollTop(), left = doc.scrollLeft();
+			if (pos.constructor == Array) {
+				// [x, y]
+				top += pos[1];
+				left += pos[0];
+			} else {
+				switch (pos) {
+					case 'center':
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+						break;
+					case 'top':
+						top += 0;
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+						break;
+					case 'right':
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += (wnd.width()) - (uiDialog.width());
+						break;
+					case 'bottom':
+						top += (wnd.height()) - (uiDialog.height());
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+						break;
+					case 'left':
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += 0;
+						break;
+					default:
+						//center
+						top += (wnd.height() / 2) - (uiDialog.height() / 2);
+						left += (wnd.width() / 2) - (uiDialog.width() / 2);
+				}
+			}
+			top = top < doc.scrollTop() ? doc.scrollTop() : top;
+			uiDialog.css({top: top, left: left});
+		}
+		
+		this.open = function() {
+			this.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
+			uiDialog.appendTo('body');
+			this.position(options.position);
+			uiDialog.show();
+			self.moveToTop();
+			self.activate();
+			
+			// CALLBACK: open
+			var openEV = null;
+			var openUI = {
+				options: options
+			};
+			this.uiDialogTitlebarClose.focus();
+			$(this.element).triggerHandler("dialogopen", [openEV, openUI], options.open);
+		};
+
+		this.activate = function() {
+			// Move modeless dialogs to the top when they're activated.  Even
+			// if there is a modal dialog in the window, the modeless dialog
+			// should be on top because it must have been opened after the modal
+			// dialog.  Modal dialogs don't get moved to the top because that
+			// would make any modeless dialogs that it spawned unusable until
+			// the modal dialog is closed.
+			!options.modal && this.moveToTop();
+		};
+		
+		this.moveToTop = function() {
+			var maxZ = options.zIndex;
+			$('.ui-dialog:visible').each(function() {
+				maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10) || options.zIndex);
+			});
+			this.overlay && this.overlay.$el.css('z-index', ++maxZ);
+			uiDialog.css('z-index', ++maxZ);
+		};
+		
+		this.close = function() {
+			this.overlay && this.overlay.destroy();
+			uiDialog.hide();
+
+			// CALLBACK: close
+			var closeEV = null;
+			var closeUI = {
+				options: options
+			};
+			$(this.element).triggerHandler("dialogclose", [closeEV, closeUI], options.close);
+			$.ui.dialog.overlay.resize();
+		};
+
+		this.destroy = function() {
+			this.overlay && this.overlay.destroy();
+			uiDialog.hide();
+			$(el).unbind('.dialog').removeClass('ui-dialog-content').hide().appendTo('body');
+			uiDialog.remove();
+			$.removeData(this.element, "dialog");
+		};
+		
+		if (options.autoOpen) {
+			this.open();
+		};
+	};
+	
+	$.extend($.ui.dialog, {
+		defaults: {
+			autoOpen: true,
+			bgiframe: false,
+			buttons: [],
+			draggable: true,
+			height: 200,
+			minHeight: 100,
+			minWidth: 150,
+			modal: false,
+			overlay: {},
+			position: 'center',
+			resizable: true,
+			width: 300,
+			zIndex: 1000
+		},
+		
+		overlay: function(dialog) {
+			this.$el = $.ui.dialog.overlay.create(dialog);
+		}
+	});
+	
+	$.extend($.ui.dialog.overlay, {
+		instances: [],
+		events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
+			function(e) { return e + '.dialog-overlay'; }).join(' '),
+		create: function(dialog) {
+			if (this.instances.length === 0) {
+				// prevent use of anchors and inputs
+				$('a, :input').bind(this.events, function() {
+					// allow use of the element if inside a dialog and
+					// - there are no modal dialogs
+					// - there are modal dialogs, but we are in front of the
+					//   topmost modal dialog
+					var allow = false;
+					var $dialog = $(this).parents('.ui-dialog');
+					if ($dialog.length) {
+						var $overlays = $('.ui-dialog-overlay');
+						if ($overlays.length) {
+							var maxZ = parseInt($overlays.css('z-index'), 10);
+							$overlays.each(function() {
+								maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10));
+							});
+							allow = parseInt($dialog.css('z-index'), 10) > maxZ;
+						} else {
+							allow = true;
+						}
+					}
+					return allow;
+				});
+				
+				// allow closing by pressing the escape key
+				$(document).bind('keydown.dialog-overlay', function(e) {
+					var ESC = 27;
+					e.keyCode && e.keyCode == ESC && dialog.close(); 
+				});
+				
+				// handle window resize
+				$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+			}
+			
+			var $el = $('<div/>').appendTo(document.body)
+				.addClass('ui-dialog-overlay').css($.extend({
+					borderWidth: 0, margin: 0, padding: 0,
+					position: 'absolute', top: 0, left: 0,
+					width: this.width(),
+					height: this.height()
+				}, dialog.options.overlay));
+			
+			dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe();
+			
+			this.instances.push($el);
+			return $el;
+		},
+		
+		destroy: function($el) {
+			this.instances.splice($.inArray(this.instances, $el), 1);
+			
+			if (this.instances.length === 0) {
+				$('a, :input').add([document, window]).unbind('.dialog-overlay');
+			}
+			
+			$el.remove();
+		},
+		
+		height: function() {
+			if ($.browser.msie && $.browser.version < 7) {
+				var scrollHeight = Math.max(
+					document.documentElement.scrollHeight,
+					document.body.scrollHeight
+				);
+				var offsetHeight = Math.max(
+					document.documentElement.offsetHeight,
+					document.body.offsetHeight
+				);
+				
+				if (scrollHeight < offsetHeight) {
+					return $(window).height() + 'px';
+				} else {
+					return scrollHeight + 'px';
+				}
+			} else {
+				return $(document).height() + 'px';
+			}
+		},
+		
+		width: function() {
+			if ($.browser.msie && $.browser.version < 7) {
+				var scrollWidth = Math.max(
+					document.documentElement.scrollWidth,
+					document.body.scrollWidth
+				);
+				var offsetWidth = Math.max(
+					document.documentElement.offsetWidth,
+					document.body.offsetWidth
+				);
+				
+				if (scrollWidth < offsetWidth) {
+					return $(window).width() + 'px';
+				} else {
+					return scrollWidth + 'px';
+				}
+			} else {
+				return $(document).width() + 'px';
+			}
+		},
+		
+		resize: function() {
+			/* If the dialog is draggable and the user drags it past the
+			 * right edge of the window, the document becomes wider so we
+			 * need to stretch the overlay.  If the user then drags the
+			 * dialog back to the left, the document will become narrower,
+			 * so we need to shrink the overlay to the appropriate size.
+			 * This is handled by shrinking the overlay before setting it
+			 * to the full document size.
+			 */
+			var $overlays = $([]);
+			$.each($.ui.dialog.overlay.instances, function() {
+				$overlays = $overlays.add(this);
+			});
+			
+			$overlays.css({
+				width: 0,
+				height: 0
+			}).css({
+				width: $.ui.dialog.overlay.width(),
+				height: $.ui.dialog.overlay.height()
+			});
+		}
+	});
+	
+	$.extend($.ui.dialog.overlay.prototype, {
+		destroy: function() {
+			$.ui.dialog.overlay.destroy(this.$el);
+		}
+	});
+
+})(jQuery);
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.draggable.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.draggable.js
new file mode 100644
index 0000000..ce209db
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.draggable.js
@@ -0,0 +1,572 @@
+/*
+ * jQuery UI Draggable
+ *
+ * Copyright (c) 2008 Paul Bakaus
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *   ui.base.js
+ *
+ * Revision: $Id: ui.draggable.js 5194 2008-04-04 12:30:10Z paul.bakaus $
+ */
+;(function($) {
+
+	$.fn.extend({
+		draggable: function(options) {
+			var args = Array.prototype.slice.call(arguments, 1);
+			
+			return this.each(function() {
+				if (typeof options == "string") {
+					var drag = $.data(this, "draggable");
+					if(drag) drag[options].apply(drag, args);
+
+				} else if(!$.data(this, "draggable"))
+					new $.ui.draggable(this, options);
+			});
+		}
+	});
+	
+	$.ui.draggable = function(element, options) {
+		//Initialize needed constants
+		var self = this;
+		
+		this.element = $(element);
+		
+		$.data(element, "draggable", this);
+		this.element.addClass("ui-draggable");
+		
+		//Prepare the passed options
+		this.options = $.extend({}, options);
+		var o = this.options;
+		$.extend(o, {
+			helper: o.ghosting == true ? 'clone' : (o.helper || 'original'),
+			handle : o.handle ? ($(o.handle, element)[0] ? $(o.handle, element) : this.element) : this.element,
+			appendTo: o.appendTo || 'parent'		
+		});
+		
+		$(element).bind("setData.draggable", function(event, key, value){
+			self.options[key] = value;
+		}).bind("getData.draggable", function(event, key){
+			return self.options[key];
+		});
+		
+		//Initialize mouse events for interaction
+		$(o.handle).mouseInteraction({
+			executor: this,
+			delay: o.delay,
+			distance: o.distance || 1,
+			dragPrevention: o.cancel || o.cancel === '' ? o.cancel.toLowerCase().split(',') : ['input','textarea','button','select','option'],
+			start: this.start,
+			stop: this.stop,
+			drag: this.drag,
+			condition: function(e) { return !(e.target.className.indexOf("ui-resizable-handle") != -1 || this.options.disabled); }
+		});
+		
+		//Position the node
+		if(o.helper == 'original' && (this.element.css('position') == 'static' || this.element.css('position') == ''))
+			this.element.css('position', 'relative');
+			
+		//Prepare cursorAt
+		if(o.cursorAt && o.cursorAt.constructor == Array)
+			o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] };
+		
+	};
+	
+	$.extend($.ui.draggable.prototype, {
+		plugins: {},
+		ui: function(e) {
+			return {
+				helper: this.helper,
+				position: this.position,
+				absolutePosition: this.positionAbs,
+				instance: this,
+				options: this.options,
+				element: this.element				
+			};
+		},
+		propagate: function(n,e) {
+			$.ui.plugin.call(this, n, [e, this.ui()]);
+			return this.element.triggerHandler(n == "drag" ? n : "drag"+n, [e, this.ui()], this.options[n]);
+		},
+		destroy: function() {
+			if(!$.data(this.element[0], 'draggable')) return;
+			this.options.handle.removeMouseInteraction();
+			this.element
+				.removeClass("ui-draggable ui-draggable-disabled")
+				.removeData("draggable")
+				.unbind(".draggable");
+		},
+		enable: function() {
+			this.element.removeClass("ui-draggable-disabled");
+			this.options.disabled = false;
+		},
+		disable: function() {
+			this.element.addClass("ui-draggable-disabled");
+			this.options.disabled = true;
+		},
+		setContrains: function(minLeft,maxLeft,minTop,maxTop) {
+			this.minLeft = minLeft; this.maxLeft = maxLeft;
+			this.minTop = minTop; this.maxTop = maxTop;
+			this.constrainsSet = true;
+		},
+		checkConstrains: function() {
+			if(!this.constrainsSet) return;
+			if(this.position.left < this.minLeft) this.position.left = this.minLeft;
+			if(this.position.left > this.maxLeft - this.helperProportions.width) this.position.left = this.maxLeft - this.helperProportions.width;
+			if(this.position.top < this.minTop) this.position.top = this.minTop;
+			if(this.position.top > this.maxTop - this.helperProportions.height) this.position.top = this.maxTop - this.helperProportions.height;
+		},
+		recallOffset: function(e) {
+
+			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
+			var r = this.helper.css('position') == 'relative';
+
+			//Generate the original position
+			this.originalPosition = {
+				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
+				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
+			};
+			
+			//Generate a flexible offset that will later be subtracted from e.pageX/Y
+			this.offset = {left: this._pageX - this.originalPosition.left, top: this._pageY - this.originalPosition.top };
+			
+		},
+		start: function(e) {
+			var o = this.options;
+			if($.ui.ddmanager) $.ui.ddmanager.current = this;
+			
+			//Create and append the visible helper
+			this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e])) : (o.helper == 'clone' ? this.element.clone().appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)) : this.element);
+			if(this.helper[0] != this.element[0]) this.helper.css('position', 'absolute');
+			if(!this.helper.parents('body').length) this.helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
+			
+			
+			//Find out the next positioned parent
+			this.offsetParent = (function(cp) {
+				while(cp) {
+					if(cp.style && (/(absolute|relative|fixed)/).test($.css(cp,'position'))) return $(cp);
+					cp = cp.parentNode ? cp.parentNode : null;
+				}; return $("body");		
+			})(this.helper[0].parentNode);
+			
+			//Prepare variables for position generation
+			this.elementOffset = this.element.offset();
+			this.offsetParentOffset = this.offsetParent.offset();
+			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
+			this._pageX = e.pageX; this._pageY = e.pageY;
+			this.clickOffset = { left: e.pageX - this.elementOffset.left, top: e.pageY - this.elementOffset.top };
+			var r = this.helper.css('position') == 'relative';
+
+			//Generate the original position
+			this.originalPosition = {
+				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
+				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
+			};
+			
+			//If we have a fixed element, we must subtract the scroll offset again
+			if(this.element.css('position') == 'fixed') {
+				this.originalPosition.top -= this.offsetParent[0] == document.body ? $(document).scrollTop() : this.offsetParent[0].scrollTop;
+				this.originalPosition.left -= this.offsetParent[0] == document.body ? $(document).scrollLeft() : this.offsetParent[0].scrollLeft;
+			}
+			
+			//Generate a flexible offset that will later be subtracted from e.pageX/Y
+			this.offset = {left: e.pageX - this.originalPosition.left, top: e.pageY - this.originalPosition.top };
+			
+			//Substract margins
+			if(this.element[0] != this.helper[0]) {
+				this.offset.left += parseInt(this.element.css('marginLeft'),10) || 0;
+				this.offset.top += parseInt(this.element.css('marginTop'),10) || 0;
+			}
+			
+			//Call plugins and callbacks
+			this.propagate("start", e);
+
+			this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };
+			if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e);
+			
+			//If we have something in cursorAt, we'll use it
+			if(o.cursorAt) {
+				if(o.cursorAt.top != undefined || o.cursorAt.bottom != undefined) {
+					this.offset.top -= this.clickOffset.top - (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
+					this.clickOffset.top = (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
+				}
+				if(o.cursorAt.left != undefined || o.cursorAt.right != undefined) {
+					this.offset.left -= this.clickOffset.left - (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
+					this.clickOffset.left = (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
+				}
+			}
+
+			return false;
+
+		},
+		clear: function() {
+			if($.ui.ddmanager) $.ui.ddmanager.current = null;
+			this.helper = null;
+		},
+		stop: function(e) {
+
+			//If we are using droppables, inform the manager about the drop
+			if ($.ui.ddmanager && !this.options.dropBehaviour)
+				$.ui.ddmanager.drop(this, e);
+				
+			//Call plugins and trigger callbacks
+			this.propagate("stop", e);
+			
+			if(this.cancelHelperRemoval) return false;			
+			if(this.options.helper != 'original') this.helper.remove();
+			this.clear();
+
+			return false;
+		},
+		drag: function(e) {
+
+			//Compute the helpers position
+			this.position = { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left };
+			this.positionAbs = { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top };
+
+			//Call plugins and callbacks
+			this.checkConstrains();			
+			this.position = this.propagate("drag", e) || this.position;
+			this.checkConstrains();
+			
+			$(this.helper).css({ left: this.position.left+'px', top: this.position.top+'px' }); // Stick the helper to the cursor
+			if($.ui.ddmanager) $.ui.ddmanager.drag(this, e);
+			return false;
+			
+		}
+	});
+	
+/*
+ * Draggable Extensions
+ */
+	 
+	$.ui.plugin.add("draggable", "cursor", {
+		start: function(e, ui) {
+			var t = $('body');
+			if (t.css("cursor")) ui.options._cursor = t.css("cursor");
+			t.css("cursor", ui.options.cursor);
+		},
+		stop: function(e, ui) {
+			if (ui.options._cursor) $('body').css("cursor", ui.options._cursor);
+		}
+	});
+
+	$.ui.plugin.add("draggable", "zIndex", {
+		start: function(e, ui) {
+			var t = $(ui.helper);
+			if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex");
+			t.css('zIndex', ui.options.zIndex);
+		},
+		stop: function(e, ui) {
+			if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex);
+		}
+	});
+
+	$.ui.plugin.add("draggable", "opacity", {
+		start: function(e, ui) {
+			var t = $(ui.helper);
+			if(t.css("opacity")) ui.options._opacity = t.css("opacity");
+			t.css('opacity', ui.options.opacity);
+		},
+		stop: function(e, ui) {
+			if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity);
+		}
+	});
+
+
+	$.ui.plugin.add("draggable", "revert", {
+		stop: function(e, ui) {
+			var self = ui.instance, helper = $(self.helper);
+			self.cancelHelperRemoval = true;
+			
+			$(ui.helper).animate({ left: self.originalPosition.left, top: self.originalPosition.top }, parseInt(ui.options.revert, 10) || 500, function() {
+				if(ui.options.helper != 'original') helper.remove();
+				if (!helper) self.clear();
+			});
+		}
+	});
+
+	$.ui.plugin.add("draggable", "iframeFix", {
+		start: function(e, ui) {
+
+			var o = ui.options;
+			if(ui.instance.slowMode) return; // Make clones on top of iframes (only if we are not in slowMode)
+			
+			if(o.iframeFix.constructor == Array) {
+				for(var i=0;i<o.iframeFix.length;i++) {
+					var co = $(o.iframeFix[i]).offset({ border: false });
+					$('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width", $(o.iframeFix[i])[0].offsetWidth+"px").css("height", $(o.iframeFix[i])[0].offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
+				}		
+			} else {
+				$("iframe").each(function() {					
+					var co = $(this).offset({ border: false });
+					$('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width", this.offsetWidth+"px").css("height", this.offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
+				});							
+			}
+
+		},
+		stop: function(e, ui) {
+			if(ui.options.iframeFix) $("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers	
+		}
+	});
+	
+	$.ui.plugin.add("draggable", "containment", {
+		start: function(e, ui) {
+
+			var o = ui.options;
+			var self = ui.instance;
+			if((o.containment.left != undefined || o.containment.constructor == Array) && !o._containment) return;
+			if(!o._containment) o._containment = o.containment;
+
+			if(o._containment == 'parent') o._containment = this[0].parentNode;
+			if(o._containment == 'document') {
+				o.containment = [
+					0,
+					0,
+					$(document).width(),
+					($(document).height() || document.body.parentNode.scrollHeight)
+				];
+			} else { //I'm a node, so compute top/left/right/bottom
+
+				var ce = $(o._containment)[0];
+				var co = $(o._containment).offset();
+
+				o.containment = [
+					co.left,
+					co.top,
+					co.left+(ce.offsetWidth || ce.scrollWidth),
+					co.top+(ce.offsetHeight || ce.scrollHeight)
+				];
+			}
+			
+			var c = o.containment;
+			ui.instance.setContrains(
+				c[0] - (self.offset.left - self.clickOffset.left), //min left
+				c[2] - (self.offset.left - self.clickOffset.left), //max left
+				c[1] - (self.offset.top - self.clickOffset.top), //min top
+				c[3] - (self.offset.top - self.clickOffset.top) //max top
+			);
+
+		}
+	});
+
+	$.ui.plugin.add("draggable", "grid", {
+		drag: function(e, ui) {
+			var o = ui.options;
+			var newLeft = ui.instance.originalPosition.left + Math.round((e.pageX - ui.instance._pageX) / o.grid[0]) * o.grid[0];
+			var newTop = ui.instance.originalPosition.top + Math.round((e.pageY - ui.instance._pageY) / o.grid[1]) * o.grid[1];
+			
+			ui.instance.position.left = newLeft;
+			ui.instance.position.top = newTop;
+
+		}
+	});
+
+	$.ui.plugin.add("draggable", "axis", {
+		drag: function(e, ui) {
+			var o = ui.options;
+			if(o.constraint) o.axis = o.constraint; //Legacy check
+			switch (o.axis) {
+				case 'x' : ui.instance.position.top = ui.instance.originalPosition.top; break;
+				case 'y' : ui.instance.position.left = ui.instance.originalPosition.left; break;
+			}
+		}
+	});
+
+	$.ui.plugin.add("draggable", "scroll", {
+		start: function(e, ui) {
+			var o = ui.options;
+			o.scrollSensitivity	= o.scrollSensitivity || 20;
+			o.scrollSpeed		= o.scrollSpeed || 20;
+
+			ui.instance.overflowY = function(el) {
+				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode);
+				return $(document);
+			}(this);
+			ui.instance.overflowX = function(el) {
+				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode);
+				return $(document);
+			}(this);
+		},
+		drag: function(e, ui) {
+			
+			var o = ui.options;
+			var i = ui.instance;
+
+			if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') {
+				if(i.overflowY[0].offsetHeight - (ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
+					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed;
+				if((ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
+					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;				
+			} else {
+				//$(document.body).append('<p>'+(e.pageY - $(document).scrollTop())+'</p>');
+				if(e.pageY - $(document).scrollTop() < o.scrollSensitivity)
+					$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+				if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+					$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+			}
+			
+			if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') {
+				if(i.overflowX[0].offsetWidth - (ui.position.left - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
+					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed;
+				if((ui.position.top - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
+					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;				
+			} else {
+				if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+					$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+				if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+					$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+			}
+			
+			ui.instance.recallOffset(e);
+
+		}
+	});
+	
+	$.ui.plugin.add("draggable", "snap", {
+		start: function(e, ui) {
+			
+			ui.instance.snapElements = [];
+			$(ui.options.snap === true ? '.ui-draggable' : ui.options.snap).each(function() {
+				var $t = $(this); var $o = $t.offset();
+				if(this != ui.instance.element[0]) ui.instance.snapElements.push({
+					item: this,
+					width: $t.outerWidth(),
+					height: $t.outerHeight(),
+					top: $o.top,
+					left: $o.left
+				});
+			});
+			
+		},
+		drag: function(e, ui) {
+
+			var d = ui.options.snapTolerance || 20;
+			var x1 = ui.absolutePosition.left, x2 = x1 + ui.instance.helperProportions.width,
+			    y1 = ui.absolutePosition.top, y2 = y1 + ui.instance.helperProportions.height;
+
+			for (var i = ui.instance.snapElements.length - 1; i >= 0; i--){
+
+				var l = ui.instance.snapElements[i].left, r = l + ui.instance.snapElements[i].width, 
+				    t = ui.instance.snapElements[i].top,  b = t + ui.instance.snapElements[i].height;
+
+				//Yes, I know, this is insane ;)
+				if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) continue;
+
+				if(ui.options.snapMode != 'inner') {
+					var ts = Math.abs(t - y2) <= 20;
+					var bs = Math.abs(b - y1) <= 20;
+					var ls = Math.abs(l - x2) <= 20;
+					var rs = Math.abs(r - x1) <= 20;
+					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
+					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top;
+					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
+					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left;
+				}
+				
+				if(ui.options.snapMode != 'outer') {
+					var ts = Math.abs(t - y1) <= 20;
+					var bs = Math.abs(b - y2) <= 20;
+					var ls = Math.abs(l - x1) <= 20;
+					var rs = Math.abs(r - x2) <= 20;
+					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top;
+					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
+					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left;
+					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
+				}
+
+			};
+		}
+	});
+	
+	$.ui.plugin.add("draggable", "connectToSortable", {
+		start: function(e,ui) {
+			ui.instance.sortable = $.data($(ui.options.connectToSortable)[0], 'sortable');
+			ui.instance.sortableOffset = ui.instance.sortable.element.offset();
+			ui.instance.sortableOuterWidth = ui.instance.sortable.element.outerWidth();
+			ui.instance.sortableOuterHeight = ui.instance.sortable.element.outerHeight();
+			if(ui.instance.sortable.options.revert) ui.instance.sortable.shouldRevert = true;
+		},
+		stop: function(e,ui) {
+			//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
+			var inst = ui.instance.sortable;
+			if(inst.isOver) {
+				inst.isOver = 0;
+				ui.instance.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
+				inst.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
+				if(inst.shouldRevert) inst.options.revert = true; //revert here
+				inst.stop(e);
+				inst.options.helper = "original";
+			}
+		},
+		drag: function(e,ui) {
+			//This is handy: We reuse the intersectsWith method for checking if the current draggable helper
+			//intersects with the sortable container
+			var inst = ui.instance.sortable;
+			ui.instance.position.absolute = ui.absolutePosition; //Sorry, this is an ugly API fix
+			
+			if(inst.intersectsWith.call(ui.instance, {
+				left: ui.instance.sortableOffset.left, top: ui.instance.sortableOffset.top,
+				width: ui.instance.sortableOuterWidth, height: ui.instance.sortableOuterHeight
+			})) {
+				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
+				if(!inst.isOver) {
+					inst.isOver = 1;
+					
+					//Cache the width/height of the new helper
+					var height = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerHeight() : $(inst.options.items, inst.element).innerHeight();
+					var width = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerWidth() : $(inst.options.items, inst.element).innerWidth();
+
+					//Now we fake the start of dragging for the sortable instance,
+					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
+					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
+					inst.currentItem = $(this).clone().appendTo(inst.element);
+					inst.options.helper = function() { return ui.helper[0]; };
+					inst.start(e);
+					
+					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
+					inst.clickOffset.top = ui.instance.clickOffset.top;
+					inst.clickOffset.left = ui.instance.clickOffset.left;
+					inst.offset.left -= ui.absolutePosition.left - inst.position.absolute.left;
+					inst.offset.top -= ui.absolutePosition.top - inst.position.absolute.top;
+					
+					//Do a nifty little helper animation: Animate it to the portlet's size (just takes the first 'li' element in the sortable now)
+					inst.helperProportions = { width:  width, height: height}; //We have to reset the helper proportions, because we are doing our animation there
+					ui.helper.animate({ height: height, width: width}, 500);
+					ui.instance.propagate("toSortable", e);
+				
+				}
+
+				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
+				if(inst.currentItem) inst.drag(e);
+				
+			} else {
+				
+				//If it doesn't intersect with the sortable, and it intersected before,
+				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
+				if(inst.isOver) {
+					inst.isOver = 0;
+					inst.cancelHelperRemoval = true;
+					inst.options.revert = false; //No revert here
+					inst.stop(e);
+					inst.options.helper = "original";
+					
+					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
+					inst.currentItem.remove();
+					inst.placeholder.remove();
+					
+					ui.helper.animate({ height: this.innerHeight(), width: this.innerWidth() }, 500);
+					ui.instance.propagate("fromSortable", e);
+				}
+				
+			};
+		}
+	})
+
+	//TODO: wrapHelper
+
+})(jQuery);
+
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.resizable.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.resizable.js
new file mode 100644
index 0000000..409195e
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.resizable.js
@@ -0,0 +1,710 @@
+/*
+ * jQuery UI Resizable
+ *
+ * Copyright (c) 2008 Paul Bakaus
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *   ui.base.js
+ *
+ * Revision: $Id: ui.resizable.js 5205 2008-04-06 16:12:50Z braeker $
+ */
+;(function($) {
+	
+	$.fn.extend({
+		resizable: function(options, data) {
+			var args = Array.prototype.slice.call(arguments, 1);
+			
+			return this.each(function() {
+				if (typeof options == "string") {
+					var resize = $.data(this, "resizable");
+					if (resize) resize[options].apply(resize, args);
+	
+				} else if(!$(this).is(".ui-resizable"))
+					new $.ui.resizable(this, options);
+			});
+		}
+	});
+
+	$.ui.resizable = function(element, options) {
+		//Initialize needed constants
+		var self = this;
+		
+		this.element = $(element);
+		
+		$.data(element, "resizable", this);
+		
+		// simulate .ui-resizable { position: relative; }
+		var elpos = this.element.css('position');
+		this.element.addClass("ui-resizable").css({ position: /static/.test(elpos) ? 'relative' : elpos });
+		
+		//Prepare the passed options
+		this.options = $.extend({
+			preventDefault: true,
+			transparent: false,
+			minWidth: 10,
+			minHeight: 10,
+			aspectRatio: false,
+			disableSelection: true,
+			preserveCursor: true,
+			autohide: false,
+			knobHandles: false
+		}, options);
+		
+		this.options._aspectRatio = !!(this.options.aspectRatio);
+		
+		// force proxy if helper is enabled
+		this.options.proxy = this.options.proxy || this.options.ghost ? 'proxy' : null; 
+		
+		// force proxy if animation is enabled
+		this.options.proxy = this.options.proxy || this.options.animate ? 'proxy' : null; 
+		
+		// if knobHandles equals true set to ui-resizable-knob-handle
+		this.options.knobHandles = this.options.knobHandles === true ? 'ui-resizable-knob-handle' : this.options.knobHandles;
+		
+		$(element).bind("setData.resizable", function(event, key, value){
+			self.options[key] = value;
+		}).bind("getData.resizable", function(event, key){
+			return self.options[key];
+		});
+	
+		var o = this.options;
+	
+		//Default Theme
+		var aBorder = '1px solid #DEDEDE';
+	
+		o.defaultTheme = {
+			'ui-resizable': { display: 'block' },
+			'ui-resizable-handle': { position: 'absolute', background: '#F2F2F2', fontSize: '0.1px' },
+			'ui-resizable-n': { cursor: 'n-resize', height: '4px', left: '0px', right: '0px', borderTop: aBorder },
+			'ui-resizable-s': { cursor: 's-resize', height: '4px', left: '0px', right: '0px', borderBottom: aBorder },
+			'ui-resizable-e': { cursor: 'e-resize', width: '4px', top: '0px', bottom: '0px', borderRight: aBorder },
+			'ui-resizable-w': { cursor: 'w-resize', width: '4px', top: '0px', bottom: '0px', borderLeft: aBorder },
+			'ui-resizable-se': { cursor: 'se-resize', width: '4px', height: '4px', borderRight: aBorder, borderBottom: aBorder },
+			'ui-resizable-sw': { cursor: 'sw-resize', width: '4px', height: '4px', borderBottom: aBorder, borderLeft: aBorder },
+			'ui-resizable-ne': { cursor: 'ne-resize', width: '4px', height: '4px', borderRight: aBorder, borderTop: aBorder },
+			'ui-resizable-nw': { cursor: 'nw-resize', width: '4px', height: '4px', borderLeft: aBorder, borderTop: aBorder }
+		};
+		
+		o.knobTheme = {
+			'ui-resizable-handle': { background: '#F2F2F2', border: '1px solid #808080', height: '8px', width: '8px' },
+			'ui-resizable-n': { cursor: 'n-resize', top: '-4px', left: '45%' },
+			'ui-resizable-s': { cursor: 's-resize', bottom: '-4px', left: '45%' },
+			'ui-resizable-e': { cursor: 'e-resize', right: '-4px', top: '45%' },
+			'ui-resizable-w': { cursor: 'w-resize', left: '-4px', top: '45%' },
+			'ui-resizable-se': { cursor: 'se-resize', right: '-4px', bottom: '-4px' },
+			'ui-resizable-sw': { cursor: 'sw-resize', left: '-4px', bottom: '-4px' },
+			'ui-resizable-nw': { cursor: 'nw-resize', left: '-4px', top: '-4px' },
+			'ui-resizable-ne': { cursor: 'ne-resize', right: '-4px', top: '-4px' }
+		};
+	
+		//Position the node
+		if(!o.proxy && (this.element.css('position') == 'static' || this.element.css('position') === ''))
+			this.element.css('position', 'relative');
+	
+		o._nodeName = element.nodeName;
+	
+		//Wrap the element if it cannot hold child nodes
+		if(o._nodeName.match(/textarea|input|select|button|img/i)) {
+			var el = this.element;
+			
+			//Opera fixing relative position
+			if (/relative/.test(el.css('position')) && $.browser.opera)
+				el.css({ position: 'relative', top: 'auto', left: 'auto' });
+			
+			//Create a wrapper element and set the wrapper to the new current internal element
+			el.wrap(
+				$('<div class="ui-wrapper"	style="overflow: hidden;"></div>').css( {
+					position: el.css('position'),
+					width: el.outerWidth(),
+					height: el.outerHeight(),
+					top: el.css('top'),
+					left: el.css('left')
+				})
+			);
+			
+			var oel = this.element; element = element.parentNode; this.element = $(element);
+	
+			//Move margins to the wrapper
+			this.element.css({ marginLeft: oel.css("marginLeft"), marginTop: oel.css("marginTop"),
+				marginRight: oel.css("marginRight"), marginBottom: oel.css("marginBottom")
+			});
+	
+			oel.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
+	
+			//Prevent Safari textarea resize
+			if ($.browser.safari && o.preventDefault) oel.css('resize', 'none');
+	
+			o.proportionallyResize = oel.css({ position: 'static', zoom: 1, display: 'block' });
+			
+			// avoid IE jump
+			this.element.css({ margin: oel.css('margin') });
+			
+			// fix handlers offset
+			this._proportionallyResize();
+		}
+	
+		if(!o.handles) o.handles = !$('.ui-resizable-handle', element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' };
+		if(o.handles.constructor == String) {
+	
+			if(o.handles == 'all') o.handles = 'n,e,s,w,se,sw,ne,nw';
+	
+			var n = o.handles.split(","); o.handles = {};
+	
+			o.zIndex = o.zIndex || 1000;
+			
+			// insertions are applied when don't have theme loaded
+			var insertionsDefault = {
+				handle: 'position: absolute; display: none; overflow:hidden;',
+				n: 'top: 0pt; width:100%;',
+				e: 'right: 0pt; height:100%;',
+				s: 'bottom: 0pt; width:100%;',
+				w: 'left: 0pt; height:100%;',
+				se: 'bottom: 0pt; right: 0px;',
+				sw: 'bottom: 0pt; left: 0px;',
+				ne: 'top: 0pt; right: 0px;',
+				nw: 'top: 0pt; left: 0px;'
+			};
+	
+			for(var i = 0; i < n.length; i++) {
+				var handle = jQuery.trim(n[i]), dt = o.defaultTheme, hname = 'ui-resizable-'+handle, loadDefault = !$.ui.css(hname) && !o.knobHandles, userKnobClass = $.ui.css('ui-resizable-knob-handle'), 
+							allDefTheme = $.extend(dt[hname], dt['ui-resizable-handle']), allKnobTheme = $.extend(o.knobTheme[hname], !userKnobClass ? o.knobTheme['ui-resizable-handle'] : {});
+				
+				// increase zIndex of sw, se, ne, nw axis
+				var applyZIndex = /sw|se|ne|nw/.test(handle) ? { zIndex: ++o.zIndex } : {};
+				
+				var defCss = (loadDefault ? insertionsDefault[handle] : ''), 
+					axis = $(['<div class="ui-resizable-handle ', hname, '" style="', defCss, insertionsDefault.handle, '"></div>'].join('')).css( applyZIndex );
+				o.handles[handle] = '.ui-resizable-'+handle;
+				
+				this.element.append(
+					//Theme detection, if not loaded, load o.defaultTheme
+					axis.css( loadDefault ? allDefTheme : {} )
+						// Load the knobHandle css, fix width, height, top, left...
+						.css( o.knobHandles ? allKnobTheme : {} ).addClass(o.knobHandles ? 'ui-resizable-knob-handle' : '').addClass(o.knobHandles)
+				);
+			}
+			
+			if (o.knobHandles) this.element.addClass('ui-resizable-knob').css( !$.ui.css('ui-resizable-knob') ? { /*border: '1px #fff dashed'*/ } : {} );
+		}
+	
+		this._renderAxis = function(target) {
+			target = target || this.element;
+	
+			for(var i in o.handles) {
+				if(o.handles[i].constructor == String) 
+					o.handles[i] = $(o.handles[i], element).show();
+	
+				if (o.transparent)
+					o.handles[i].css({opacity:0});
+	
+				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
+				if (this.element.is('.ui-wrapper') && 
+					o._nodeName.match(/textarea|input|select|button/i)) {
+	
+					var axis = $(o.handles[i], element), padWrapper = 0;
+	
+					//Checking the correct pad and border
+					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+	
+					//The padding type i have to apply...
+					var padPos = [ 'padding', 
+						/ne|nw|n/.test(i) ? 'Top' :
+						/se|sw|s/.test(i) ? 'Bottom' : 
+						/^e$/.test(i) ? 'Right' : 'Left' ].join(""); 
+	
+					if (!o.transparent)
+						target.css(padPos, padWrapper);
+	
+					this._proportionallyResize();
+				}
+				if(!$(o.handles[i]).length) continue;
+			}
+		};
+			
+		this._renderAxis(this.element);
+		o._handles = $('.ui-resizable-handle', self.element);
+		
+		if (o.disableSelection)
+			o._handles.each(function(i, e) { $.ui.disableSelection(e); });
+		
+		//Matching axis name
+		o._handles.mouseover(function() {
+			if (!o.resizing) {
+				if (this.className) 
+					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+				//Axis, default = se
+				self.axis = o.axis = axis && axis[1] ? axis[1] : 'se';
+			}
+		});
+				
+		//If we want to auto hide the elements
+		if (o.autohide) {
+			o._handles.hide();
+			$(self.element).addClass("ui-resizable-autohide").hover(function() {
+				$(this).removeClass("ui-resizable-autohide");
+				o._handles.show();
+			},
+			function(){
+				if (!o.resizing) {
+					$(this).addClass("ui-resizable-autohide");
+					o._handles.hide();
+				}
+			});
+		}
+	
+		//Initialize mouse events for interaction
+		this.element.mouseInteraction({
+			executor: this,
+			delay: 0,
+			distance: 0,
+			dragPrevention: ['input','textarea','button','select','option'],
+			start: this.start,
+			stop: this.stop,
+			drag: this.drag,
+			condition: function(e) {
+				if(this.disabled) return false;
+				for(var i in this.options.handles) {
+					if($(this.options.handles[i])[0] == e.target) return true;
+				}
+				return false;
+			}
+		});
+	};
+
+	$.extend($.ui.resizable.prototype, {
+		plugins: {},
+		ui: function() {
+			return {
+				instance: this,
+				axis: this.options.axis,
+				options: this.options
+			};
+		},
+		_renderProxy: function() {
+			var el = this.element, o = this.options;
+			this.elementOffset = el.offset();
+	
+			if(o.proxy) {
+				this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
+	
+				// fix ie6 offset
+				var ie6 = $.browser.msie && $.browser.version  < 7, ie6offset = (ie6 ? 1 : 0),
+				pxyoffset = ( ie6 ? 2 : -1 );
+	
+				this.helper.addClass(o.proxy).css({
+					width: el.outerWidth() + pxyoffset,
+					height: el.outerHeight() + pxyoffset,
+					position: 'absolute',
+					left: this.elementOffset.left - ie6offset +'px',
+					top: this.elementOffset.top - ie6offset +'px',
+					zIndex: ++o.zIndex
+				});
+				
+				this.helper.appendTo("body");
+	
+				if (o.disableSelection)
+					$.ui.disableSelection(this.helper.get(0));
+	
+			} else {
+				this.helper = el; 
+			}
+		},
+		propagate: function(n,e) {
+			$.ui.plugin.call(this, n, [e, this.ui()]);
+			this.element.triggerHandler(n == "resize" ? n : ["resize", n].join(""), [e, this.ui()], this.options[n]);
+		},
+		destroy: function() {
+			var el = this.element, wrapped = el.children(".ui-resizable").get(0),
+			
+			_destroy = function(exp) {
+				$(exp).removeClass("ui-resizable ui-resizable-disabled")
+					.removeMouseInteraction().removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
+			};
+			
+			_destroy(el);
+			
+			if (el.is('.ui-wrapper') && wrapped) {
+		  		el.parent().append(
+					$(wrapped).css({
+			  		position: el.css('position'),
+			  		width: el.outerWidth(),
+			  		height: el.outerHeight(),
+			  		top: el.css('top'),
+			  		left: el.css('left')
+		  		})
+				).end().remove();
+				
+				_destroy(wrapped);
+	  		}
+		},
+		enable: function() {
+			this.element.removeClass("ui-resizable-disabled");
+			this.disabled = false;
+		},
+		disable: function() {
+			this.element.addClass("ui-resizable-disabled");
+			this.disabled = true;
+		},
+		start: function(e) {
+			var o = this.options, iniPos = this.element.position(), el = this.element, 
+				num = function(v) { return parseInt(v, 10) || 0; }, ie6 = $.browser.msie && $.browser.version < 7;
+			o.resizing = true;
+			o.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
+	
+			// bugfix #1749
+			if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
+				
+				// sOffset decides if document scrollOffset will be added to the top/left of the resizable element
+				var sOffset = $.browser.msie && !o.containment && (/absolute/).test(el.css('position')) && !(/relative/).test(el.parent().css('position'));
+				var dscrollt = sOffset ? o.documentScroll.top : 0, dscrolll = sOffset ? o.documentScroll.left : 0;
+				
+				el.css({ position: 'absolute', top: (iniPos.top + dscrollt), left: (iniPos.left + dscrolll) });
+			}
+			
+			//Opera fixing relative position
+			if (/relative/.test(el.css('position')) && $.browser.opera)
+				el.css({ position: 'relative', top: 'auto', left: 'auto' });
+	
+			this._renderProxy();
+	
+			var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
+			
+			//Store needed variables
+			this.offset = this.helper.offset();
+			this.position = { left: curleft, top: curtop };
+			this.size = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+			this.originalSize = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+			this.originalPosition = { left: curleft, top: curtop };
+			this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
+			this.originalMousePosition = { left: e.pageX, top: e.pageY };
+			
+			//Aspect Ratio
+			o.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.height / this.originalSize.width)||1);
+	
+			if (o.preserveCursor)
+				$('body').css('cursor', this.axis + '-resize');
+				
+			this.propagate("start", e); 	
+			return false;
+		},
+		stop: function(e) {
+			this.options.resizing = false;
+			var o = this.options, num = function(v) { return parseInt(v, 10) || 0; }, self = this;
+	
+			if(o.proxy) {
+				var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
+							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+								soffsetw = ista ? 0 : self.sizeDiff.width;
+			
+				var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
+							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top);
+				
+				if (!o.animate)
+					this.element.css($.extend(style, { top: top, left: left }));
+				
+				if (o.proxy && !o.animate) this._proportionallyResize();
+				this.helper.remove();
+			}
+
+			if (o.preserveCursor)
+			$('body').css('cursor', 'auto');
+	
+			this.propagate("stop", e);	
+			return false;
+		},
+		drag: function(e) {
+			//Increase performance, avoid regex
+			var el = this.helper, o = this.options, props = {},
+				self = this, smp = this.originalMousePosition, a = this.axis;
+
+			var dx = (e.pageX-smp.left)||0, dy = (e.pageY-smp.top)||0;
+			var trigger = this.change[a];
+			if (!trigger) return false;
+		 
+			// Calculate the attrs that will be change
+			var data = trigger.apply(this, [e, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
+		 
+			if (o._aspectRatio || e.shiftKey)
+				data = this._updateRatio(data, e);
+			
+			data = this._respectSize(data, e);
+			
+			this.propagate("resize", e);
+			
+			el.css({
+				top: this.position.top + "px", left: this.position.left + "px", 
+				width: this.size.width + "px", height: this.size.height + "px"
+			});
+			
+			if (!o.proxy && o.proportionallyResize)
+				this._proportionallyResize();
+			
+			this._updateCache(data);
+			
+			return false;
+		},
+		
+		_updateCache: function(data) {
+			var o = this.options;
+			this.offset = this.helper.offset();
+			if (data.left) this.position.left = data.left;
+			if (data.top) this.position.top = data.top;
+			if (data.height) this.size.height = data.height;
+			if (data.width) this.size.width = data.width;
+		},
+		
+		_updateRatio: function(data, e) {
+			var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
+			
+			if (data.height) data.width = Math.round(csize.height / o.aspectRatio);
+			else if (data.width) data.height = Math.round(csize.width * o.aspectRatio);
+			
+			if (a == 'sw') {
+				data.left = cpos.left + (csize.width - data.width);
+				data.top = null;
+			}
+			if (a == 'nw') { 
+				data.top = cpos.top + (csize.height - data.height);
+				data.left = cpos.left + (csize.width - data.width);
+			}
+			
+			return data;
+		},
+		
+		_respectSize: function(data, e) {
+			
+			var el = this.helper, o = this.options, pRatio = o._aspectRatio || e.shiftKey,  a = this.axis, 
+					ismaxw = data.width && o.maxWidth && o.maxWidth < data.width, ismaxh = data.height && o.maxHeight && o.maxHeight < data.height,
+						isminw = data.width && o.minWidth && o.minWidth > data.width, isminh = data.height && o.minHeight && o.minHeight > data.height;
+			
+			if (isminw) data.width = o.minWidth;
+			if (isminh) data.height = o.minHeight;
+			if (ismaxw) data.width = o.maxWidth;
+			if (ismaxh) data.height = o.maxHeight;
+			
+			var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
+			var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+			
+			if (isminw && cw) data.left = dw - o.minWidth;
+			if (ismaxw && cw) data.left = dw - o.maxWidth;
+			if (isminh && ch)	data.top = dh - o.minHeight;
+			if (ismaxh && ch)	data.top = dh - o.maxHeight;
+			
+			// fixing jump error on top/left - bug #2330
+			var isNotwh = !data.width && !data.height;
+			if (isNotwh && !data.left && data.top) data.top = null;
+			else if (isNotwh && !data.top && data.left) data.left = null;
+			
+			return data;
+		},
+		
+		_proportionallyResize: function() {
+			var o = this.options;
+			if (!o.proportionallyResize) return;
+			var prel = o.proportionallyResize, el = this.helper || this.element;
+		 
+			if (!o.borderDif) {
+				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
+					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
+				 
+				o.borderDif = $.map(b, function(v, i) {
+					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
+					return border + padding; 
+				});
+			}
+			prel.css({
+				height: (el.height() - o.borderDif[0] - o.borderDif[2]) + "px",
+				width: (el.width() - o.borderDif[1] - o.borderDif[3]) + "px"
+			});
+		},
+		
+		change: {
+			e: function(e, dx, dy) {
+				return { width: this.originalSize.width + dx };
+			},
+			w: function(e, dx, dy) {
+				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+				return { left: sp.left + dx, width: cs.width - dx };
+			},
+			n: function(e, dx, dy) {
+				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+				return { top: sp.top + dy, height: cs.height - dy };
+			},
+			s: function(e, dx, dy) {
+				return { height: this.originalSize.height + dy };
+			},
+			se: function(e, dx, dy) {
+				return $.extend(this.change.s.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
+			},
+			sw: function(e, dx, dy) {
+				return $.extend(this.change.s.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
+			},
+			ne: function(e, dx, dy) {
+				return $.extend(this.change.n.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
+			},
+			nw: function(e, dx, dy) {
+				return $.extend(this.change.n.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
+			}
+		}
+	});
+
+/*
+ * Resizable Extensions
+ */
+
+	$.ui.plugin.add("resizable", "containment", {
+		
+		start: function(e, ui) {
+			var o = ui.options, self = ui.instance, el = self.element;
+			var oc = o.containment,	ce = (oc instanceof jQuery) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
+			if (!ce) return;
+			
+			if (/document/.test(oc) || oc == document) {
+				self.containerOffset = { left: 0, top: 0 };
+
+				self.parentData = { 
+					element: $(document), left: 0, top: 0, width: $(document).width(),
+					height: $(document).height() || document.body.parentNode.scrollHeight
+				};
+			}
+			
+			// i'm a node, so compute top, left, right, bottom
+			else{
+				self.containerOffset = $(ce).offset(), self.containerSize = { height: $(ce).innerHeight(), width: $(ce).innerWidth() };
+			
+				var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width, 
+							width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
+			
+				self.parentData = { 
+					element: ce, left: co.left, top: co.top, width: width, height: height
+				};
+			}
+		},
+		
+		resize: function(e, ui) {
+			var o = ui.options, self = ui.instance, ps = self.containerSize, 
+						co = self.containerOffset, cs = self.size, cp = self.position,
+							pRatio = o._aspectRatio || e.shiftKey;
+			
+			if (cp.left < (o.proxy ? co.left : 0)) {
+				self.size.width = self.size.width + (o.proxy ? (self.position.left - co.left) : self.position.left);
+				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
+				self.position.left = o.proxy ? co.left : 0;
+			}
+			
+			if (cp.top < (o.proxy ? co.top : 0)) {
+				self.size.height = self.size.height + (o.proxy ? (self.position.top - co.top) : self.position.top);
+				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
+				self.position.top = o.proxy ? co.top : 0;
+			}
+			
+			var woset = (o.proxy ? self.offset.left - co.left : self.position.left) + self.sizeDiff.width, 
+						hoset = (o.proxy ? self.offset.top - co.top : self.position.top) + self.sizeDiff.height;
+			
+			if (woset + self.size.width >= self.parentData.width) {
+				self.size.width = self.parentData.width - woset;
+				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
+			}
+			
+			if (hoset + self.size.height >= self.parentData.height) {
+				self.size.height = self.parentData.height - hoset;
+				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
+			}
+		}
+	});
+	
+	$.ui.plugin.add("resizable", "grid", {
+		
+		resize: function(e, ui) {
+			var o = ui.options, self =  ui.instance, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || e.shiftKey;
+			o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
+			var ox = Math.round((cs.width - os.width) / o.grid[0]) * o.grid[0], oy = Math.round((cs.height - os.height) / o.grid[1]) * o.grid[1];
+			
+			if (/^(se|s|e)$/.test(a)) {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+			}
+			else if (/^(ne)$/.test(a)) {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+				self.position.top = op.top - oy;
+			}
+			else if (/^(sw)$/.test(a)) {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+				self.position.left = op.left - ox;
+			}
+			else {
+				self.size.width = os.width + ox;
+				self.size.height = os.height + oy;
+				self.position.top = op.top - oy;
+				self.position.left = op.left - ox;
+			}
+		}
+		
+	});
+	
+	$.ui.plugin.add("resizable", "animate", {
+		
+		stop: function(e, ui) {
+			var o = ui.options, self =  ui.instance;
+
+			var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
+							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+								soffsetw = ista ? 0 : self.sizeDiff.width;
+			
+			var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
+							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top); 
+			
+			self.element.animate(
+				$.extend(style, { top: top, left: left }),
+				{ 
+					duration: o.animateDuration || "slow", 
+					easing: o.animateEasing || "swing", 
+					step: function() {
+						if (pr) pr.css({ width: self.element.css('width'), height: self.element.css('height') });
+					}
+				}
+			);
+		}
+		
+	});
+	
+	$.ui.plugin.add("resizable", "ghost", {
+		
+		start: function(e, ui) {
+			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize, cs = self.size;
+			
+			if (!pr) self.ghost = self.element.clone();
+			else self.ghost = pr.clone();
+			
+			self.ghost.css(
+				{ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }
+			)
+			.addClass('ui-resizable-ghost').addClass(typeof o.ghost == 'string' ? o.ghost : '');
+			
+			self.ghost.appendTo(self.helper);
+			
+		},
+		
+		resize: function(e, ui){
+			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
+			
+			if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
+			
+		},
+		
+		stop: function(e, ui){
+			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
+			if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
+		}
+		
+	});
+
+})(jQuery);
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.css
new file mode 100644
index 0000000..0eabf94
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.css
@@ -0,0 +1,114 @@
+/* Caution! Ensure accessibility in print and other media types... */
+ at media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
+    .ui-tabs-hide {
+        display: none;
+    }
+}
+
+/* Hide useless elements in print layouts... */
+ at media print {
+    .ui-tabs-nav {
+        display: none;
+    }
+}
+
+/* Skin */
+.ui-tabs-nav {
+    list-style: none;
+    margin: 0 !important;
+    padding: 0 0 0 4px;
+}
+.ui-tabs-nav li {
+    list-style-image: none !important;
+    margin: 0 !important;
+    padding: 0 0 0 4px;
+}
+
+.ui-tabs-panel {
+    border-top: #94ADA7 solid 1px;
+    padding-top: 5px;
+    clear: left;
+}
+
+/* IE6 hack */
+* html .ui-tabs-panel {
+    margin-top: -1.2em;
+}
+
+.ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
+    display: block;
+    clear: both;
+    content: " ";
+}
+.ui-tabs-nav li {
+    float: left;
+    margin: 0 0 0 1px;
+    min-width: 84px; /* be nice to Opera */
+}
+.ui-tabs-nav a, .ui-tabs-nav a span {
+    display: block;
+    padding: 0 10px;
+    background: url(tab.png) no-repeat;
+}
+.ui-tabs-nav a {
+    position: relative;
+    top: 1px;
+    z-index: 2;
+    padding-left: 0;
+    color: #27537a;
+    font-size: 12px;
+    font-weight: bold;
+    line-height: 1.2;
+    text-align: center;
+    text-decoration: none;
+    white-space: nowrap; /* required in IE 6 */    
+}
+.ui-tabs-nav .ui-tabs-selected a {
+    color: #000;
+}
+.ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active {
+    background-position: 100% -150px;
+    outline: 0; /* prevent dotted border in Firefox */
+}
+.ui-tabs-nav a, .ui-tabs-nav .ui-tabs-disabled a:hover, .ui-tabs-nav .ui-tabs-disabled a:focus, .ui-tabs-nav .ui-tabs-disabled a:active {
+    background-position: 100% -100px;
+}
+.ui-tabs-nav a span {
+    width: 64px; /* IE 6 treats width as min-width */
+    min-width: 64px;
+    height: 18px; /* IE 6 treats height as min-height */
+    min-height: 18px;
+    padding-top: 6px;
+    padding-right: 0;
+}
+*>.ui-tabs-nav a span { /* hide from IE 6 */
+    width: auto;
+    height: auto;
+}
+.ui-tabs-nav .ui-tabs-selected a span {
+    padding-top: 7px;
+}
+.ui-tabs-nav .ui-tabs-selected a span, .ui-tabs-nav a:hover span, .ui-tabs-nav a:focus span, .ui-tabs-nav a:active span {
+    background-position: 0 -50px;
+}
+.ui-tabs-nav a span, .ui-tabs-nav .ui-tabs-disabled a:hover span, .ui-tabs-nav .ui-tabs-disabled a:focus span, .ui-tabs-nav .ui-tabs-disabled a:active span {
+    background-position: 0 0;
+}
+.ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited, .ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
+    cursor: text;
+}
+.ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active { /* @ Opera, we need to be explicit again here now... */
+    cursor: pointer;
+}
+.ui-tabs-nav .ui-tabs-disabled {
+    opacity: .4;
+}
+.ui-tabs-container {
+    border-top: 1px solid #97a5b0;
+    padding: 1em 8px;
+    background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
+}
+.ui-tabs-loading em {
+    padding: 0 0 0 20px;
+    background: url(loading.gif) no-repeat 0 50%;
+}
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.js
new file mode 100644
index 0000000..f595c10
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/ui.tabs.js
@@ -0,0 +1,616 @@
+/*
+ * jQuery UI Tabs
+ *
+ * Copyright (c) 2007 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *   ui.base.js
+ *
+ * Revision: $Id: ui.tabs.js 5149 2008-03-31 10:51:18Z rdworth $
+ */
+;(function($) {
+
+    // tabs API methods
+    $.fn.tabs = function() {
+        var method = typeof arguments[0] == 'string' && arguments[0];
+        var args = method && Array.prototype.slice.call(arguments, 1) || arguments;
+
+        return method == 'length' ?
+            $.data(this[0], 'tabs').$tabs.length :
+            this.each(function() {
+                if (method) {
+                    var tabs = $.data(this, 'tabs');
+                    if (tabs) tabs[method].apply(tabs, args);
+                } else
+                    new $.ui.tabs(this, args[0] || {});
+            });
+    };
+
+    // tabs class
+    $.ui.tabs = function(el, options) {
+        var self = this;
+        
+        this.options = $.extend({}, $.ui.tabs.defaults, options);
+        this.element = el;
+
+        // doesn't extend with null
+        if (options.selected === null)
+            this.options.selected = null;
+
+        this.options.event += '.tabs'; // namespace event
+
+        $(el).bind('setData.tabs', function(event, key, value) {
+            if ((/^selected/).test(key))
+                self.select(value);
+            else {
+                self.options[key] = value;
+                self.tabify();
+            }
+        }).bind('getData.tabs', function(event, key) {
+            return self.options[key];
+        });
+
+        // save instance for later
+        $.data(el, 'tabs', this);
+
+        // create tabs
+        this.tabify(true);
+    };
+    
+    $.ui.tabs.defaults = {
+        // basic setup
+        selected: 0,
+        unselect: false,
+        event: 'click',
+        disabled: [],
+        cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+        // TODO history: false,
+
+        // Ajax
+        spinner: 'Loading&#8230;',
+        cache: false,
+        idPrefix: 'ui-tabs-',
+        ajaxOptions: {},
+
+        // animations
+        fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+
+        // templates
+        tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>',
+        panelTemplate: '<div></div>',
+
+        // CSS classes
+        navClass: 'ui-tabs-nav',
+        selectedClass: 'ui-tabs-selected',
+        unselectClass: 'ui-tabs-unselect',
+        disabledClass: 'ui-tabs-disabled',
+        panelClass: 'ui-tabs-panel',
+        hideClass: 'ui-tabs-hide',
+        loadingClass: 'ui-tabs-loading'
+    };
+
+    // instance methods
+    $.extend($.ui.tabs.prototype, {
+        tabId: function(a) {
+            return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
+                || this.options.idPrefix + $.data(a);
+        },
+        ui: function(tab, panel) {
+            return {
+                instance: this,
+                options: this.options,
+                tab: tab,
+                panel: panel
+            };
+        },
+        tabify: function(init) {
+
+            this.$lis = $('li:has(a[href])', this.element);
+            this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
+            this.$panels = $([]);
+
+            var self = this, o = this.options;
+
+            this.$tabs.each(function(i, a) {
+                // inline tab
+                if (a.hash && a.hash.replace('#', '')) // Safari 2 reports '#' for an empty hash
+                    self.$panels = self.$panels.add(a.hash);
+                // remote tab
+                else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#"
+                    $.data(a, 'href.tabs', a.href); // required for restore on destroy
+
+                    var _cls = a.getAttribute('class');
+                    var use_iframe = _cls && (_cls.indexOf('use_iframe') > -1)? true: false;
+                    if (!use_iframe) {
+                        $.data(a, 'load.tabs', a.href); // mutable
+                    } else {
+                        $.data(a, 'load.iframe_src', a.href); // mutable
+                    }
+
+
+                    var id = self.tabId(a);
+                    a.href = '#' + id;
+                    var $panel = $('#' + id);
+                    var panelTemplate = use_iframe? '<div><iframe></iframe></div>': o.panelTemplate;
+                    if (!$panel.length) {
+                        $panel = $(panelTemplate).attr('id', id).addClass(o.panelClass)
+                            .insertAfter( self.$panels[i - 1] || self.element );
+                        $panel.data('destroy.tabs', true);
+                    }
+                    self.$panels = self.$panels.add( $panel );
+                }
+                // invalid tab href
+                else
+                    o.disabled.push(i + 1);
+            });
+
+            if (init) {
+
+                // attach necessary classes for styling if not present
+                $(this.element).hasClass(o.navClass) || $(this.element).addClass(o.navClass);
+                this.$panels.each(function() {
+                    var $this = $(this);
+                    $this.hasClass(o.panelClass) || $this.addClass(o.panelClass);
+                });
+
+                // Try to retrieve selected tab:
+                // 1. from fragment identifier in url if present
+                // 2. from cookie
+                // 3. from selected class attribute on <li>
+                // 4. otherwise use given "selected" option
+                // 5. check if tab is disabled
+                this.$tabs.each(function(i, a) {
+                    if (location.hash) {
+                        if (a.hash == location.hash) {
+                            o.selected = i;
+                            // prevent page scroll to fragment
+                            //if (($.browser.msie || $.browser.opera) && !o.remote) {
+                            if ($.browser.msie || $.browser.opera) {
+                                var $toShow = $(location.hash), toShowId = $toShow.attr('id');
+                                $toShow.attr('id', '');
+                                setTimeout(function() {
+                                    $toShow.attr('id', toShowId); // restore id
+                                }, 500);
+                            }
+                            scrollTo(0, 0);
+                            return false; // break
+                        }
+                    } else if (o.cookie) {
+                        var index = parseInt($.cookie('ui-tabs' + $.data(self.element)),10);
+                        if (index && self.$tabs[index]) {
+                            o.selected = index;
+                            return false; // break
+                        }
+                    } else if ( self.$lis.eq(i).hasClass(o.selectedClass) ) {
+                        o.selected = i;
+                        return false; // break
+                    }
+                });
+
+                // highlight selected tab
+                this.$panels.addClass(o.hideClass);
+                this.$lis.removeClass(o.selectedClass);
+                if (o.selected !== null) {
+                    this.$panels.eq(o.selected).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before
+                    this.$lis.eq(o.selected).addClass(o.selectedClass);
+                }
+
+                // load if remote tab
+                var href = o.selected !== null && $.data(this.$tabs[o.selected], 'load.tabs');
+                if (href)
+                    this.load(o.selected);
+
+                // Take disabling tabs via class attribute from HTML
+                // into account and update option properly...
+                o.disabled = $.unique(o.disabled.concat(
+                    $.map(this.$lis.filter('.' + o.disabledClass),
+                        function(n, i) { return self.$lis.index(n); } )
+                )).sort();
+                
+                // clean up to avoid memory leaks in certain versions of IE 6
+                $(window).bind('unload', function() {
+                    self.$tabs.unbind('.tabs');
+                    self.$lis = self.$tabs = self.$panels = null;
+                });
+
+            }
+
+            // disable tabs
+            for (var i = 0, li; li = this.$lis[i]; i++)
+                $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass(o.selectedClass) ? 'addClass' : 'removeClass'](o.disabledClass);
+
+            // reset cache if switching from cached to not cached
+            if (o.cache === false)
+                this.$tabs.removeData('cache.tabs');
+            
+            // set up animations
+            var hideFx, showFx, baseFx = { 'min-width': 0, duration: 1 }, baseDuration = 'normal';
+            if (o.fx && o.fx.constructor == Array)
+                hideFx = o.fx[0] || baseFx, showFx = o.fx[1] || baseFx;
+            else
+                hideFx = showFx = o.fx || baseFx;
+
+            // reset some styles to maintain print style sheets etc.
+            var resetCSS = { display: '', overflow: '', height: '' };
+            if (!$.browser.msie) // not in IE to prevent ClearType font issue
+                resetCSS.opacity = '';
+
+            // Hide a tab, animation prevents browser scrolling to fragment,
+            // $show is optional.
+            function hideTab(clicked, $hide, $show) {
+                $hide.animate(hideFx, hideFx.duration || baseDuration, function() { //
+                    $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
+                    if ($.browser.msie && hideFx.opacity)
+                        $hide[0].style.filter = '';
+                    if ($show)
+                        showTab(clicked, $show, $hide);
+                });
+            }
+
+            // Show a tab, animation prevents browser scrolling to fragment,
+            // $hide is optional.
+            function showTab(clicked, $show, $hide) {
+                if (showFx === baseFx)
+                    $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels
+                $show.animate(showFx, showFx.duration || baseDuration, function() {
+                    $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
+                    if ($.browser.msie && showFx.opacity)
+                        $show[0].style.filter = '';
+
+                    // callback
+                    $(self.element).triggerHandler('tabsshow', [self.ui(clicked, $show[0])], o.show);
+
+                });
+            }
+
+            // switch a tab
+            function switchTab(clicked, $li, $hide, $show) {
+                /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
+                    $.ajaxHistory.update(clicked.hash);
+                }*/
+                $li.addClass(o.selectedClass)
+                    .siblings().removeClass(o.selectedClass);
+                hideTab(clicked, $hide, $show);
+            }
+
+            // attach tab event handler, unbind to avoid duplicates from former tabifying...
+            this.$tabs.unbind('.tabs').bind(o.event, function() {
+
+                //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
+                var $li = $(this).parents('li:eq(0)'),
+                    $hide = self.$panels.filter(':visible'),
+                    $show = $(this.hash);
+
+                // If tab is already selected and not unselectable or tab disabled or 
+                // or is already loading or click callback returns false stop here.
+                // Check if click handler returns false last so that it is not executed
+                // for a disabled or loading tab!
+                if (($li.hasClass(o.selectedClass) && !o.unselect)
+                    || $li.hasClass(o.disabledClass) 
+                    || $(this).hasClass(o.loadingClass)
+                    || $(self.element).triggerHandler('tabsselect', [self.ui(this, $show[0])], o.select) === false
+                    ) {
+                    this.blur();
+                    return false;
+                }
+
+                self.options.selected = self.$tabs.index(this);
+
+                // if tab may be closed
+                if (o.unselect) {
+                    if ($li.hasClass(o.selectedClass)) {
+                        self.options.selected = null;
+                        $li.removeClass(o.selectedClass);
+                        self.$panels.stop();
+                        hideTab(this, $hide);
+                        this.blur();
+                        return false;
+                    } else if (!$hide.length) {
+                        self.$panels.stop();
+                        var a = this;
+                        self.load(self.$tabs.index(this), function() {
+                            $li.addClass(o.selectedClass).addClass(o.unselectClass);
+                            showTab(a, $show);
+                        });
+                        this.blur();
+                        return false;
+                    }
+                }
+
+                if (o.cookie)
+                    $.cookie('ui-tabs' + $.data(self.element), self.options.selected, o.cookie);
+
+                // stop possibly running animations
+                self.$panels.stop();
+
+                // show new tab
+                if ($show.length) {
+
+                    // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
+                    /*if ($.browser.msie && o.bookmarkable) {
+                        var showId = this.hash.replace('#', '');
+                        $show.attr('id', '');
+                        setTimeout(function() {
+                            $show.attr('id', showId); // restore id
+                        }, 0);
+                    }*/
+
+                    var a = this;
+                    self.load(self.$tabs.index(this), $hide.length ? 
+                        function() {
+                            switchTab(a, $li, $hide, $show);
+                        } :
+                        function() {
+                            $li.addClass(o.selectedClass);
+                            showTab(a, $show);
+                        }
+                    );
+
+                    // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
+                    /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
+                    var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
+                    setTimeout(function() {
+                        scrollTo(scrollX, scrollY);
+                    }, 0);*/
+
+                } else
+                    throw 'jQuery UI Tabs: Mismatching fragment identifier.';
+
+                // Prevent IE from keeping other link focussed when using the back button
+                // and remove dotted border from clicked link. This is controlled in modern
+                // browsers via CSS, also blur removes focus from address bar in Firefox
+                // which can become a usability and annoying problem with tabsRotate.
+                if ($.browser.msie)
+                    this.blur();
+
+                //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE
+                return false;
+
+            });
+
+            // disable click if event is configured to something else
+            if (!(/^click/).test(o.event))
+                this.$tabs.bind('click.tabs', function() { return false; });
+
+        },
+        add: function(url, label, index) {
+            if (index == undefined) 
+                index = this.$tabs.length; // append by default
+
+            var o = this.options;
+            var $li = $(o.tabTemplate.replace(/#\{href\}/, url).replace(/#\{label\}/, label));
+            $li.data('destroy.tabs', true);
+
+            var id = url.indexOf('#') == 0 ? url.replace('#', '') : this.tabId( $('a:first-child', $li)[0] );
+
+            // try to find an existing element before creating a new one
+            var $panel = $('#' + id);
+            if (!$panel.length) {
+                $panel = $(o.panelTemplate).attr('id', id)
+                    .addClass(o.panelClass).addClass(o.hideClass);
+                $panel.data('destroy.tabs', true);
+            }
+            if (index >= this.$lis.length) {
+                $li.appendTo(this.element);
+                $panel.appendTo(this.element.parentNode);
+            } else {
+                $li.insertBefore(this.$lis[index]);
+                $panel.insertBefore(this.$panels[index]);
+            }
+            
+            o.disabled = $.map(o.disabled,
+                function(n, i) { return n >= index ? ++n : n });
+                
+            this.tabify();
+
+            if (this.$tabs.length == 1) {
+                 $li.addClass(o.selectedClass);
+                 $panel.removeClass(o.hideClass);
+                 var href = $.data(this.$tabs[0], 'load.tabs');
+                 if (href)
+                     this.load(index, href);
+            }
+
+            // callback
+            $(this.element).triggerHandler('tabsadd',
+                [this.ui(this.$tabs[index], this.$panels[index])], o.add
+            );
+        },
+        remove: function(index) {
+            var o = this.options, $li = this.$lis.eq(index).remove(),
+                $panel = this.$panels.eq(index).remove();
+
+            // If selected tab was removed focus tab to the right or
+            // in case the last tab was removed the tab to the left.
+            if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1)
+                this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));
+
+            o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
+                function(n, i) { return n >= index ? --n : n });
+
+            this.tabify();
+
+            // callback
+            $(this.element).triggerHandler('tabsremove',
+                [this.ui($li.find('a')[0], $panel[0])], o.remove
+            );
+        },
+        enable: function(index) {
+            var o = this.options;
+            if ($.inArray(index, o.disabled) == -1)
+                return;
+                
+            var $li = this.$lis.eq(index).removeClass(o.disabledClass);
+            if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2...
+                $li.css('display', 'inline-block');
+                setTimeout(function() {
+                    $li.css('display', 'block');
+                }, 0);
+            }
+
+            o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
+
+            // callback
+            $(this.element).triggerHandler('tabsenable',
+                [this.ui(this.$tabs[index], this.$panels[index])], o.enable
+            );
+
+        },
+        disable: function(index) {
+            var self = this, o = this.options;
+            if (index != o.selected) { // cannot disable already selected tab
+                this.$lis.eq(index).addClass(o.disabledClass);
+
+                o.disabled.push(index);
+                o.disabled.sort();
+
+                // callback
+                $(this.element).triggerHandler('tabsdisable',
+                    [this.ui(this.$tabs[index], this.$panels[index])], o.disable
+                );
+            }
+        },
+        select: function(index) {
+            if (typeof index == 'string')
+                index = this.$tabs.index( this.$tabs.filter('[href$=' + index + ']')[0] );
+            this.$tabs.eq(index).trigger(this.options.event);
+        },
+        load: function(index, callback) { // callback is for internal usage only
+            
+            var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
+                    bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
+
+            callback = callback || function() {};
+            
+            // no remote or from cache - just finish with callback
+            if (!url || ($.data(a, 'cache.tabs') && !bypassCache)) {
+                callback();
+                return;
+            }
+
+            // load remote from here on
+            if (o.spinner) {
+                var $span = $('span', a);
+                $span.data('label.tabs', $span.html()).html('<em>' + o.spinner + '</em>');
+            }
+            var finish = function() {
+                self.$tabs.filter('.' + o.loadingClass).each(function() {
+                    $(this).removeClass(o.loadingClass);
+                    if (o.spinner) {
+                        var $span = $('span', this);
+                        $span.html($span.data('label.tabs')).removeData('label.tabs');
+                    }
+                });
+                self.xhr = null;
+            };
+            var ajaxOptions = $.extend({}, o.ajaxOptions, {
+                url: url,
+                success: function(r, s) {
+                    $(a.hash).html(r);
+                    finish();
+                    
+                    // This callback is required because the switch has to take
+                    // place after loading has completed.
+                    callback();
+
+                    if (o.cache)
+                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
+
+                    // callback
+                    $(self.element).triggerHandler('tabsload',
+                        [self.ui(self.$tabs[index], self.$panels[index])], o.load
+                    );
+
+                    o.ajaxOptions.success && o.ajaxOptions.success(r, s);
+                }
+            });
+            if (this.xhr) {
+                // terminate pending requests from other tabs and restore tab label
+                this.xhr.abort();
+                finish();
+            }
+            $a.addClass(o.loadingClass);
+            setTimeout(function() { // timeout is again required in IE, "wait" for id being restored
+                self.xhr = $.ajax(ajaxOptions);
+            }, 0);
+
+        },
+        url: function(index, url) {
+            this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
+        },
+        destroy: function() {
+            var o = this.options;
+            $(this.element).unbind('.tabs')
+                .removeClass(o.navClass).removeData('tabs');
+            this.$tabs.each(function() {
+                var href = $.data(this, 'href.tabs');
+                if (href)
+                    this.href = href;
+                var $this = $(this).unbind('.tabs');
+                $.each(['href', 'load', 'cache'], function(i, prefix) {
+                      $this.removeData(prefix + '.tabs');
+                });
+            });
+            this.$lis.add(this.$panels).each(function() {
+                if ($.data(this, 'destroy.tabs'))
+                    $(this).remove();
+                else
+                    $(this).removeClass([o.selectedClass, o.unselectClass,
+                        o.disabledClass, o.panelClass, o.hideClass].join(' '));
+            });
+        }
+    });
+
+/*
+ * Tabs Extensions
+ */
+
+    /*
+     * Rotate
+     */
+    $.extend($.ui.tabs.prototype, {
+        rotation: null,
+        rotate: function(ms, continuing) {
+            
+            continuing = continuing || false;
+            
+            var self = this, t = this.options.selected;
+            
+            function start() {
+                self.rotation = setInterval(function() {
+                    t = ++t < self.$tabs.length ? t : 0;
+                    self.select(t);
+                }, ms);    
+            }
+            
+            function stop(e) {
+                if (!e || e.clientX) { // only in case of a true click
+                    clearInterval(self.rotation);
+                }
+            }
+            
+            // start interval
+            if (ms) {
+                start();
+                if (!continuing)
+                    this.$tabs.bind(this.options.event, stop);
+                else
+                    this.$tabs.bind(this.options.event, function() {
+                        stop();
+                        t = self.options.selected;
+                        start();
+                    });
+            }
+            // stop interval
+            else {
+                stop();
+                this.$tabs.unbind(this.options.event, stop);
+            }
+        }
+    });
+
+})(jQuery);
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.css b/moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.css
new file mode 100644
index 0000000..21a046d
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.css
@@ -0,0 +1,9 @@
+.widgetbrowser iframe {
+    width: 100%;
+    border: 0;
+}
+div.small iframe { height: 50px; }
+div.medium iframe { height: 150px; }
+div.large iframe { height: 300px; }
+div.x-large iframe { height: 500px; }
+
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.js b/moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.js
new file mode 100644
index 0000000..c0b78e6
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/static/widgetbrowser.js
@@ -0,0 +1,13 @@
+jQuery(function() {
+    jQuery('.widgetbrowser > ul').tabs({
+        selected: null,
+        unselect: true,
+        select: function (ui) {
+            var url = jQuery.data(ui.tab, 'load.iframe_src');
+            var iframe = jQuery('iframe', ui.panel);
+            if (url && !iframe.attr('src')) {
+                iframe.attr('src', url);
+            }
+        }
+    })
+});
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/__init__.py b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html
new file mode 100644
index 0000000..012ce08
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/home.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<?python
+from widgetbrowser import widgets
+?>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <style>
+        .ui-tabs-panel {
+            border-bottom: solid 1px #94ada7;
+            padding-left: 1.5em;
+        }
+        .ui-tabs-panel iframe {
+            width: 100%;
+            border: 0;
+            min-height: 500px;
+        }
+        #home {
+            min-height: 450px;
+        }
+    </style>
+  </head>
+  <body class="flora">
+    <div id="main">
+        <ul>
+            <li><a href="#home"><span>Home</span></a></li>
+            <li><a href="#terminal" class="use_iframe"><span>Terminal</span></a></li>
+            <li><a href="${url('/widgets/')}" class="use_iframe"><span>Widgets</span></a></li>
+        </ul>
+        <div id="home">
+            <h1>Welcome to Toscawidgets' Browser</h1>
+            <p>
+            </p>
+        </div>
+        <div id="terminal">
+            ${widgets.repl(prefix=url('_repl/'))}
+        </div>
+    </div>
+    <div id="footer">
+    <p>&copy; 2008. Alberto Valverde González</p>
+    </div>
+    <script type="text/javascript">
+        //<![CDATA[
+        jQuery(function () {
+            jQuery('#main > ul').tabs({
+                select: function (ui) {
+                    var url = jQuery.data(ui.tab, 'load.iframe_src');
+                    var iframe = jQuery('iframe', ui.panel);
+                    if (url && !iframe.attr('src')) {
+                        iframe.attr('src', url);
+                    }
+                }
+            });
+        });
+        //]]>
+    </script>
+  </body>
+</html>
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/list_widgets.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/list_widgets.html
new file mode 100644
index 0000000..2ef5dfe
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/list_widgets.html
@@ -0,0 +1,15 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser: Installed widgets</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body id="widgets">
+    <ul>
+        <li py:for="path, url in widgets">
+            <a href="$url">$path</a>
+        </li>
+    </ul>
+  </body>
+</html>
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/show_widget.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/show_widget.html
new file mode 100644
index 0000000..7f391dc
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/show_widget.html
@@ -0,0 +1,11 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser: ${widget_name}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body id="widget_browser">
+    <div py:replace="widget_output" />
+  </body>
+</html>
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/validation_result.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/validation_result.html
new file mode 100644
index 0000000..e43da7b
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/validation_result.html
@@ -0,0 +1,13 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>WidgetBrowser: ${widget_name}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body id="widget_browser">
+    <h1 class="title">Validated data:</h1>
+    ${Markup(value)}
+    <a href="">Back</a>
+  </body>
+</html>
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_browser_tabs.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_browser_tabs.html
new file mode 100644
index 0000000..7edb374
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_browser_tabs.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<div xmlns:py="http://genshi.edgewall.org/"
+     class="widgetbrowser ${size}">
+  <ul>
+    <li py:for="text, url in tabs">
+      <a href="${url}" class="${text == 'Demo' and 'use_iframe' or None}">
+        <span>${text}</span>
+      </a>
+    </li>
+  </ul>
+</div>
+
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html
new file mode 100644
index 0000000..4759c25
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_index.html
@@ -0,0 +1,18 @@
+<!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"
+      xmlns:py="http://genshi.edgewall.org/">
+  <?python
+      from widgetbrowser.widgets import WidgetBrowserTabs
+      from widgetbrowser.util import widget_path
+      browser = WidgetBrowserTabs(size='x-large')
+  ?>
+  <head>
+    <title>WidgetBrowser: ${widget_path(widget)}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  </head>
+  <body>
+    <h1>${widget_path(widget)}</h1>
+    <p><a href="javascript:history.back()">Back</a></p>
+    ${browser(widget)}
+  </body>
+</html>
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_parameters.html b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_parameters.html
new file mode 100644
index 0000000..c95c195
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/templates/widget_parameters.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<div xmlns:py="http://genshi.edgewall.org/" class="widget_params">
+  <div py:if="parameters.local" class="widget_params local_params">
+    <h3>This widget's</h3>
+    <dl>
+        <py:for each="k in sorted(parameters.local)">
+            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
+            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
+        </py:for>
+    </dl>
+  </div>
+  <div py:if="parameters.inherited" class="widget_param inherited_params">
+    <h3>Inherited</h3>
+    <dl>
+        <py:for each="k in sorted(parameters.inherited)">
+            <dt>${k} <span class="default_param">(default = ${parameters.get_default(k)})</span></dt>
+            <dd py:content="parameters.get_doc(k, 'Undocumented')" />
+        </py:for>
+    </dl>
+  </div>
+</div>
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/util.py b/moksha/apps/docs/moksha/apps/widgetbrowser/util.py
new file mode 100644
index 0000000..648cd8c
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/util.py
@@ -0,0 +1,242 @@
+import logging
+import os
+import errno
+import sys
+import pprint
+
+from pkg_resources import EntryPoint, iter_entry_points, resource_string
+
+import tw
+from tw.api import Widget, WidgetType
+from tw.core import view
+
+log = logging.getLogger(__name__)
+
+def import_widget(path):
+    """Import a widget given a dotted or entry point notation path.
+
+    Can import both widget instances or classes.
+
+       >>> import_widget('tw.core.base.Widget')
+       <class 'tw.core.base.Widget'>
+       >>> import_widget('tw.core.base:Widget')
+       <class 'tw.core.base.Widget'>
+       >>> import_widget('os.popen')
+
+    """
+    if ':' not in path:
+        parts = path.split('.')
+        path = '.'.join(parts[:-1]) + ':' + parts[-1]
+    widget = EntryPoint.parse("x="+path).load(False)
+    if not isinstance(widget, (WidgetType, Widget)):
+        widget = None
+    return widget
+
+
+def widget_path(widget):
+    """Returns the path of a widget instance or subclass
+
+    >>> from tw.api import Widget
+    >>> widget_path(Widget)
+    'tw.core.base.Widget'
+    >>> widget_path(Widget())
+    'tw.core.base.Widget'
+    """
+    if not isinstance(widget, (WidgetType, Widget)):
+        raise TypeError("Only widgets are allowed")
+    if isinstance(widget, Widget):
+        widget = widget.__class__
+    return '.'.join([widget.__module__, widget.__name__])
+
+def format_code(code, format='python'):
+    """Formats a chunk of code as html. If pygments is installed it will
+    pygmentize it.
+    
+    >>> code = "from __future__ import teletransportation"
+    >>> '<pre' in format_code(code)
+    True
+    """
+    try:
+        from pygments import highlight, formatters, lexers
+    except ImportError:
+        log.info("Pygments is not available to colorize")
+        return '<pre>' + code + '</pre>'
+    lexer = lexers.get_lexer_by_name(format)
+    formatter = formatters.get_formatter_by_name('html')
+    return highlight(code, lexer, formatter)
+
+#TODO: Memoize this function
+def widget_template(widget, extension='.html'):
+    """Returns the template of a widget as a string.
+
+    Loads external templates if needed.
+
+    >>> from widgetbrowser.tests.widgets import *
+    >>> widget_template(TestWidgetExternalTemplate())
+    'Dummy template $value\\n'
+
+    If more than one is available, it will use the extension to disambiguate.
+
+    >>> from widgetbrowser.tests.widgets import TestWidgetExternalTemplate
+    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.html')
+    'Dummy template $value\\n'
+    >>> widget_template(TestWidgetMultipleExternalTemplate(), '.mak')
+    'Dummy template $value mako version\\n'
+    """
+    template = widget.template
+    if template and not view._is_inline_template(template):
+        # Template seems to refer to a file, look it up
+        parts = template.split('.')
+        possible_extensions = set(".html .mak .mako".split())
+        possible_extensions.remove(extension)
+        possible_extensions = [extension] + list(possible_extensions)
+        for ext in possible_extensions:
+            try:
+                return resource_string('.'.join(parts[:-1]), parts[-1]+ext)
+            except IOError, e:
+                if e.errno not in (0, errno.ENOENT):
+                    raise
+        return None
+    return template
+
+def pretty_print(obj):
+    """Pretty prints an object returning pygmentized code if possible."""
+    return format_code(pprint.pformat(obj), 'python')
+
+def display_widget(widget, argstr='', ctx=None):
+    """Displays a widget with optional arguments as a string.
+    
+
+    .. warning:: IT IS VERY UNSAFE TO EXECUTE UNTRUSTED CODE
+
+    Example::
+
+        >>> from tw.api import Widget
+        >>> class TestWidget(Widget):
+        ...     params = ['param']
+        ...     template = "$value-$param"
+        >>> display_widget(TestWidget())
+        u'None-None'
+        >>> display_widget(TestWidget(), '"hello", param=2')
+        u'hello-2'
+    """
+    ctx = ctx or {}
+    ctx['_w'] = widget
+    code = "_o = _w(%s)" % argstr
+    exec code in ctx
+    return ctx['_o']
+
+def widget_url(widget, action='', prefix=None):
+    """Returns the URL of the controller to perform `action` on `widget`.
+
+    If no `prefix` is passed the it will be tried to be fetched from
+    `tw.framework.request_local` where the :class:`WidgetBrowser` leaves it
+    on every request.
+
+    Example::
+
+        >>> from tw.core.base import Widget
+        >>> widget_url(Widget)
+        '/tw.core.base.Widget/'
+        >>> widget_url(Widget())
+        '/tw.core.base.Widget/'
+
+    You can also pass the `path` of the widget::
+
+        >>> widget_url('tw.api.Widget')
+        '/tw.api.Widget/'
+        >>> widget_url('tw.api.Widget', 'show')
+        '/tw.api.Widget/show'
+        >>> widget_url('tw.api.Widget', 'show', prefix='/widget')
+        '/widget/tw.api.Widget/show'
+
+    .. note::
+
+        You can pass any path the widget can be imported from when passing a
+        string but if you pass a widget instance or subclass then the real
+        module where it is defined will be generated.
+    """
+    if isinstance(widget, (Widget, WidgetType)):
+        widgeturi = widget_path(widget)
+    else:
+        widgeturi = widget
+        if import_widget(widgeturi) is None:
+            return
+    if prefix is None:
+        prefix = getattr(tw.framework.request_local, 'browser_prefix', '')
+    return '/'.join([prefix.rstrip('/'), widgeturi, action])
+
+def all_widgets():
+    """Iterates over all the Widget subclasses in the modules
+    that are declared as `toscawidgets.widgets` entrypoints
+
+    >>> len(list(all_widgets())) > 0
+    True
+    """
+    seen = set()
+    for ep in iter_entry_points('toscawidgets.widgets'):
+        try:
+            mod = ep.load(False)
+        except ImportError, e:
+            log.error("Could not load %r: %s", ep, e)
+            continue
+        for name in dir(mod):
+            obj = getattr(mod, name)
+            if isinstance(obj, WidgetType) and obj not in seen:
+                seen.add(obj)
+                yield obj
+
+class WidgetParameters(object):
+    """Wraps a widget and provides information on it's parameters.
+
+    Example::
+
+        >>> from tw.core.base import Widget
+        >>> params = WidgetParameters(Widget)
+        >>> len(params.all) > 0
+        True
+        >>> params.all - params.local == params.inherited
+        True
+    """
+    def __init__(self, widget):
+        if isinstance(widget, Widget):
+            widget = widget.__class__
+        self.widget = widget
+        self.all = widget.params
+        self.inherited = set()
+        for b in self.widget.__mro__:
+            if b is self.widget:
+                continue
+            self.inherited.update(getattr(b, 'params', set()))
+        self.local = self.all - self.inherited
+
+    def get_default(self, name, default=None):
+        """Returns a string representation of a parameter default value.
+
+        Example::
+
+            >>> from tw.core.base import Widget
+            >>> params = WidgetParameters(Widget)
+            >>> type(params.get_default('id'))
+            <type 'str'>
+        """
+        return repr(getattr(self.widget, name, default))
+
+    def get_doc(self, name, default='Undocumented'):
+        """Returns parameters's doc. If it is not documented it will return
+        ``default``
+
+        Example::
+
+            >>> from tw.core.base import Widget
+            >>> params = WidgetParameters(Widget)
+            >>> type(params.get_doc('id'))
+            <type 'str'>
+        """
+        return getattr(self.widget, name + '__doc', default)
+        
+def build_docs(src, dst):
+    import sphinx
+    if not os.path.exists(dst):
+        os.mkdir(dst)
+    return sphinx.main(['sphinx-build', src, dst])
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py b/moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py
new file mode 100644
index 0000000..ca6a094
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/widgets.py
@@ -0,0 +1,71 @@
+from tw.api import Widget, JSLink, CSSLink, js_function
+from moksha.apps.widgetbrowser import util
+import string
+
+__all__ = ['WidgetBrowserTabs']
+
+mod = 'widgetbrowser'
+flora_all_css = CSSLink(modname=mod, filename="static/themes/flora/flora.all.css")
+tabs_css = CSSLink(modname=mod, filename="static/ui.tabs.css")
+wb_css = CSSLink(modname=mod, filename="static/widgetbrowser.css")
+pygments_css = CSSLink(modname=mod, filename="static/pygments.css")
+httprepl_css = CSSLink(modname=mod, filename="static/httprepl.css")
+jquery_js = JSLink(modname=mod, filename="static/jquery.js")
+# Do not pull jquery as an automatic dependency since Sphinx already includes
+# it
+ui_base_js = JSLink(modname=mod, filename="static/ui.base.js",
+                    location="bodybottom")
+ui_tabs_js = JSLink(modname=mod, filename="static/ui.tabs.js",
+                    location="bodybottom",
+                    javascript=[ui_base_js])
+ui_dragabble_js = JSLink(modname=mod, filename="static/ui.draggable.js",
+                         location="bodybottom")
+ui_resizable_js = JSLink(modname=mod, filename="static/ui.resizable.js",
+                         location="bodybottom")
+ui_dialog_js = JSLink(modname=mod, filename="static/ui.dialog.js",
+                      location="bodybottom",
+                      javascript=[ui_base_js, ui_dragabble_js, ui_resizable_js])
+widgetbrowser_js = JSLink(modname=mod, filename="static/widgetbrowser.js",
+                          javascript=[ui_tabs_js],
+                          css=[tabs_css, wb_css, pygments_css],
+                          location="bodybottom")
+
+httprepl_js = JSLink(modname=mod, filename='static/httprepl.js',
+                     javascript=[ui_dialog_js],
+                     css=[httprepl_css],
+                     location="bodybottom")
+
+class WidgetBrowserTabs(Widget):
+    template = "genshi:widgetbrowser.templates.widget_browser_tabs"
+    params = ["tabs", "prefix", "size", "in_sphinx"]
+    in_sphinx = False
+    javascript = [widgetbrowser_js]
+    size = "small"
+    tabs = ['demo', 'demo_source', 'source', 'template', 'parameters']
+    prefix = None
+     
+    def update_params(self, d):
+        super(WidgetBrowserTabs, self).update_params(d)
+        d.tabs = [(string.capwords(t.replace('_', ' ')), util.widget_url(d.value, t, prefix=d.prefix))
+                  for t in d.tabs]
+        if not d.in_sphinx:
+            # Not displayed inside Sphinx, include jquery and pygments
+            jquery_js.inject()
+            pygments_css.inject()
+
+
+class WidgetRepl(Widget):
+    template = '<div id="$id" class="$css_class"></div>'
+    params = ["prefix"]
+    prefix = '/_repl/' # show nicely in the browser tabs
+    include_dynamic_js_calls = True
+    javascript = [jquery_js, httprepl_js]
+    css = [flora_all_css]
+    def update_params(self, d):
+        super(WidgetRepl, self).update_params(d)
+        assert d.id, "This widget needs an id"
+        config = dict(prefix=d.prefix)
+        call = js_function('HTTPRepl.render')('#'+d.id, config)
+        self.add_call("jQuery(function () {%s});" %  call)
+
+repl = WidgetRepl("widgetrepl")
diff --git a/moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py b/moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py
new file mode 100644
index 0000000..bfa5d4f
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/widgetbrowser/wsgiapp.py
@@ -0,0 +1,251 @@
+import sys
+import weakref
+import os
+import inspect
+import logging
+from pkg_resources import resource_filename
+from genshi.core import Markup
+from genshi.template import TemplateLoader, Context
+from webob import Request, Response, exc
+import tw
+from tw.api import Widget, WidgetType, make_middleware
+from moksha.apps.widgetbrowser import util, widgets, repl
+
+try:
+    from formencode import Invalid
+    have_formencode = True
+except ImportError:
+    have_formencode = False
+
+from moksha.lib.helpers import cache_rendered
+
+__all__ = ['WidgetBrowser']
+
+log = logging.getLogger(__name__)
+
+def asbool(v):
+    if isinstance(v, basestring):
+        return v.lower().startswith('t') or v == '1' or v == 'on'
+    elif isinstance(v, bool):
+        return v
+    return False
+
+class WidgetBrowser(object):
+    """A widget browser WSGI app.
+
+    Parameters:
+
+      * `template_dirs`: A list of directories that shall be searched for
+        temlates used by the widget browser.
+      * `interactive`: Enable code execution. This is needed to for the REPL and
+        to override display arguments via the web interface. This is a BIG
+        SECURITY HOLE, enable only in a controlled environment.
+      * `docs_dir`: A directory where sphinx sources live.
+    """
+    def __init__(self, global_conf={}, template_dirs=None, interactive=False,
+                 docs_dir=None, full_stack=True):
+        if isinstance(template_dirs, basestring):
+            template_dirs = template_dirs.split()
+        template_dirs = template_dirs or []
+        template_dirs.append(resource_filename('moksha.apps.widgetbrowser', 'templates'))
+        self.loader = TemplateLoader(template_dirs)
+        self.interactive = asbool(interactive)
+        if self.interactive:
+            self.http_repl = repl.WidgetReplApp(globals(), weakref.proxy(self))
+            self.context = self.http_repl.repl.locals
+        else:
+            self.context = None
+            self.http_repl = exc.HTTPForbidden("Interactive mode is disabled")
+        if docs_dir:
+            from paste.cascade import Cascade
+            dest_dir = os.path.abspath(os.path.join(docs_dir, '.build'))
+            log.info('Building docs...')
+            try:
+                util.build_docs(docs_dir, dest_dir)
+            except Exception, e:
+                log.warning('Skipping building docs: %s' % str(e))
+            self.built_docs = dest_dir
+            self.app = Cascade([self.docs_app, self.app])
+        if asbool(full_stack):
+            self.app = make_middleware(self.app, {
+                'toscawidgets.framework.default_view': 'genshi',
+                }, stack_registry = True)
+        self._default_controllers = dict(demo=self.show_demo,
+                                         index=self.show_index,
+                                         template=self.show_template,
+                                         parameters=self.show_parameters,
+                                         source=self.show_source,
+                                         demo_source=self.show_demo_source)
+
+
+    def docs_app(self, environ, start_response):
+        """Registers widgetbrowser_js as resources before serving static html
+        files so it is injected into the page"""
+        from paste.urlparser import StaticURLParser
+        app = StaticURLParser(self.built_docs)
+        resources = widgets.widgetbrowser_js.retrieve_resources()
+        tw.framework.register_resources(resources)
+        return app(environ, start_response)
+
+    _widget_controllers = {}
+    @classmethod
+    def register_controller(cls, widget, action):
+        """Registers function to act as a demo controller for a widget"""
+        def _register(controller):
+            cls._widget_controllers[(widget,action)] = controller
+            return controller
+        return _register
+
+    def lookup_controller(self, widget_cls, action):
+        try:
+            return self._widget_controllers[(widget_cls, action)]
+        except KeyError:
+            return self._default_controllers[action]
+
+    def lookup_widget_action(self, path_info):
+        try:
+            widget_path, action = path_info.strip('/').split('/')
+        except ValueError:
+            widget_path, action = path_info, 'index'
+        if widget_path:
+            try:
+                widget = util.import_widget(widget_path.strip('/'))
+            except (ImportError, ValueError):
+                widget = None
+            if widget:
+                return widget, action
+        raise LookupError(path_info)
+
+    def render(self, template, ns):
+        ns.pop('self',None)
+        stream = self.loader.load(template).generate(Context(**ns))
+        return stream.render(method='xhtml', doctype='xhtml')
+
+    def __call__(self, environ, start_response):
+        return self.app(environ, start_response)
+
+    @cache_rendered
+    def app(self, environ, start_response):
+        req = Request(environ)
+        resp = Response(request=req, content_type='text/html; charset=utf-8')
+        # Leave the interactive flag in tw.framework so demo controllers can know
+        # if it is safe to enable advanced/unsecure features.
+        tw.framework.request_local.interactive = self.interactive
+        tw.framework.request_local.browser_prefix = req.script_name
+
+        # Lookup widget XXX: Yuck!
+        if req.path_info == '/':
+            controller = self.home
+        elif req.path_info.startswith('/_repl') and self.http_repl:
+            req.path_info_pop()
+            return self.http_repl(environ, start_response)
+        elif req.path_info.startswith('/widgets'):
+            controller = self.widgets
+        else:
+            try:
+                widget, action = self.lookup_widget_action(req.path_info)
+            except LookupError:
+                resp = exc.HTTPNotFound('No widget at %s' % req.path_info)
+                return resp(environ, start_response)
+                
+
+            # Lookup controller
+            try:
+                controller = self.lookup_controller(widget, action)
+            except LookupError:
+                resp = exc.HTTPNotImplemented()
+                return resp(environ, start_response)
+                
+            # If it's a widget class instantiate it with no arguments 
+            if isinstance(widget, WidgetType):
+                widget = widget('test_widget')
+            req.widget = widget
+
+        # Call controller and handle output 
+        output = controller(req, resp)
+        if isinstance(output, str):
+            resp.body = output
+        elif isinstance(output, unicode):
+            resp.body = output.encode('utf-8')
+        elif output:
+            resp = output
+
+        return resp(environ, start_response)
+
+
+    def show_template(self, req, resp):
+        widget = req.widget
+        if getattr(widget, 'demo_for', None):
+            widget = req.widget.demo_for()
+        template = util.widget_template(widget)
+        if template:
+            return util.format_code(template, 'html')
+        else:
+            resp.content_type = "text/plain"
+            return widget.__class__.__name__ + ' has no template.'
+
+    def show_source(self, req, resp):
+        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
+        source = inspect.getsource(cls)
+        return util.format_code(source, 'python')
+
+    def show_demo_source(self, req, resp):
+        widget = req.widget
+        source = inspect.getsource(widget.__class__)
+        return util.format_code(source, 'python')
+
+    def show_parameters(self, req, resp):
+        cls = getattr(req.widget, 'demo_for', req.widget.__class__)
+        parameters = util.WidgetParameters(cls)
+        return self.render('widget_parameters.html', locals())
+
+
+    def show_index(self, req, resp):
+        widget = req.widget
+        return self.render('widget_index.html', locals())
+
+    @cache_rendered
+    def show_demo(self, req, resp):
+        widget = req.widget
+        widget_name = widget.__class__.__name__
+        interactive = self.interactive
+        if have_formencode and req.method.upper() == "POST":
+            # A widget submission, try to validate.
+            try:
+                value = widget.validate(req.POST)
+                value = util.pretty_print(value)
+                return self.render('validation_result.html', locals())
+            except Invalid, error:
+                pass
+
+        if self.interactive:
+            _disp = req.GET.get('_disp', '')
+        else:
+            _disp = ''
+
+        widget_output = util.display_widget(widget, _disp, self.context)
+
+        # Wrap non-genshi things, like Mako based widgets, in a Genshi Markup object
+        if not callable(widget_output):
+            widget_output = Markup(widget_output)
+
+        # Inject moksha's global resources so we can get things like
+        # Orbited/Stomp/jQuery/etc.
+        from moksha.api.widgets.global_resources import global_resources
+        global_resources.register_resources()
+
+        return self.render('show_widget.html', locals())
+
+    def widgets(self, req, resp):
+        widgets = [(util.widget_path(w), util.widget_url(w))
+                       for w in util.all_widgets()]
+        widgets.sort()
+        return self.render('list_widgets.html', locals())
+
+    def home(self, req, resp):
+        widgets.jquery_js.inject()
+        widgets.tabs_css.inject()
+        widgets.ui_tabs_js.inject()
+        def url(s):
+            return req.script_name + s
+        return self.render('home.html', locals())
diff --git a/moksha/apps/docs/pavement.py b/moksha/apps/docs/pavement.py
index eca53f1..941b49a 100644
--- a/moksha/apps/docs/pavement.py
+++ b/moksha/apps/docs/pavement.py
@@ -12,7 +12,7 @@ options(
         release="1",
         url="http://moksha.fedorahosted.org",
         description="Moksha Docs App",
-        long_description="TODO.",
+        long_description="Moksha Sphinx docs and ToscaWidgets demos",
         license='AGPLv3',
         rpm_name='moksha-apps-docs',
         author="Luke Macken",
@@ -23,7 +23,7 @@ options(
         namespace_packages=['moksha'],
         entry_points={
             'moksha.application': (
-                'docs = moksha.apps.docs.docs:docs',
+                'docs = moksha.apps.docs:docs',
             ),
         }
     ),


commit 50055623471b7214226bc587e8381316a76d00a7
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:42:22 2009 -0400

    Improve Moksha's pavement.py
    
    - Add a `reinstall` task
    - Add the beginnings of a rebuild_apps task
    - Use the find_packages and find_package_data methods

diff --git a/pavement.py b/pavement.py
index 5a50f95..83c9ffa 100644
--- a/pavement.py
+++ b/pavement.py
@@ -20,6 +20,7 @@ import urllib2
 from urlparse import urlparse
 
 from paver.easy import *
+from paver.setuputils import find_packages, find_package_data
 import paver.misctasks
 import paver.virtual
 
@@ -45,6 +46,8 @@ options(
         name="Moksha",
         api="1"
     ),
+    package_data=find_package_data(),
+    packages=find_packages(exclude=['ez_setup']),
     build_top=path("build"),
     build_dir=lambda: options.build_top / "Moksha",
     license=Bunch(
@@ -170,3 +173,25 @@ def test():
     from os import system
     sh("nosetests")
     system("nosetests")
+
+ at task
+def reinstall():
+    # TODO: get the moksha version so we can fill it in below
+    sh('rm -fr dist/')
+    sh('python setup.py sdist --format=bztar')
+    sh('mv dist/* ~/rpmbuild/SOURCES/')
+    sh('cp moksha.spec ~/rpmbuild/SPECS/')
+    sh('rpmbuild -ba ~/rpmbuild/SPECS/moksha.spec') 
+    sh('sudo rpm -ivh --replacefiles --replacepkgs ~/rpmbuild/RPMS/noarch/moksha{,-docs}-0.3-1.noarch.rpm')
+    sh('sudo /sbin/service httpd restart')
+    sh('curl http://localhost/')
+
+ at task
+def reinstall_apps():
+# rebuild and install all apps?
+    import os
+    for app in os.listdir('moksha/apps'):
+        os.chdir('moksha/apps/' + app)
+        if os.path.isfile('pavement.py'):
+            sh('echo `pwd` ;paver rpm')
+        os.chdir('../../')


commit 812689fb75bc96a4f96b9c7fc2f68ed8b7c2c208
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:41:25 2009 -0400

    Remove `_` from moksha.__init__, as it causes circular deps

diff --git a/moksha/__init__.py b/moksha/__init__.py
index 748466d..bc23927 100644
--- a/moksha/__init__.py
+++ b/moksha/__init__.py
@@ -16,7 +16,6 @@ __import__('pkg_resources').declare_namespace(__name__)
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from pylons.i18n import ugettext as _
 from paste.registry import StackedObjectProxy
 
 # The central feed cache, used by the Feed widget.
diff --git a/moksha/controllers/root.py b/moksha/controllers/root.py
index 324d6f6..dcc5fc3 100644
--- a/moksha/controllers/root.py
+++ b/moksha/controllers/root.py
@@ -21,8 +21,8 @@ import pylons
 
 from tg import url
 from tg import expose, flash, tmpl_context, redirect
+from pylons.i18n import ugettext as _
 
-from moksha import _
 from moksha.lib.base import BaseController
 from moksha.controllers.error import ErrorController
 from moksha.controllers.apps import AppController


commit 4367c406502c9515c0fc7c119d423db6b3bef4da
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:40:56 2009 -0400

    Moksha spec file tweaks
    
    - 0.3 release
    - Rename the moksha-doc to moksha-docs
    - Don't ship anything under moksha/apps/, since each of
      those are self-contained and can be packaged seperately

diff --git a/moksha.spec b/moksha.spec
index 097438d..3131488 100644
--- a/moksha.spec
+++ b/moksha.spec
@@ -2,7 +2,7 @@
 %{!?pyver: %define pyver %(%{__python} -c "import sys ; print sys.version[:3]")}
 
 Name:           moksha 
-Version:        0.2
+Version:        0.3
 Release:        1%{?dist}
 Summary:        A flexable platform for creating live collaborative web applications
 Group:          Applications/Internet
@@ -49,12 +49,12 @@ external services. It is a unified framework build using the best available
 open source technologies such as TurboGears2, jQuery, AMQP, and Orbited.  More 
 information can be found on the Moksha Project Page at 
 
-%package doc
+%package docs
 Summary: Developer documentation for Moksha
 Group: Documentation
 Requires: %{name} = %{version}-%{release}
 
-%description doc 
+%description docs
 This package contains developer documentation for Moksha along with
 other supporting documentation
 
@@ -67,9 +67,13 @@ make -C docs html
 
 %install
 %{__rm} -rf %{buildroot}
+
 %{__python} setup.py install -O1 --skip-build \
     --install-data=%{_datadir} --root %{buildroot}
 
+# Wipe out moksha/apps because that is where other app packages install
+%{__rm} -fr %{buildroot}%{python_sitelib}/moksha/apps/*
+
 %{__mkdir_p} %{buildroot}%{_datadir}/%{name}/production/apache
 %{__mkdir_p} %{buildroot}%{_datadir}/%{name}/production/nginx
 %{__mkdir_p} %{buildroot}%{_datadir}/%{name}/production/rabbitmq
@@ -96,7 +100,7 @@ make -C docs html
 %attr(-,apache,apache) %dir %{_localstatedir}/cache/%{name}
 %{_bindir}/moksha-hub
 
-%files doc
+%files docs
 %defattr(-,root,root)
 %doc docs/_build/html 
 


commit e5be314e7b0f6ca835e9f645f30ff710d279ee7a
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:38:03 2009 -0400

    Declare our moksha namespace in moksha.__init__

diff --git a/moksha/__init__.py b/moksha/__init__.py
index 1387592..748466d 100644
--- a/moksha/__init__.py
+++ b/moksha/__init__.py
@@ -1,3 +1,5 @@
+__import__('pkg_resources').declare_namespace(__name__)
+
 # This file is part of Moksha.
 # Copyright (C) 2008-2009  Red Hat, Inc.
 # 


commit 66fd6d96dbecb581a13b79e70f63435a51cdf503
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:37:30 2009 -0400

    Update our manifest.in to include more static files

diff --git a/MANIFEST.in b/MANIFEST.in
index b6074d7..3c4a5b7 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,6 @@
 recursive-include docs *
 recursive-include production *
-recursive-include moksha *.mak
+recursive-include moksha *.mak *.html *.js *.css *.png *.jpg *.gif
 recursive-include moksha/public *
 
 include moksha.spec


commit fc0b679921395fc6b3f5d8e3869016216b04e0c3
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:36:50 2009 -0400

    Add a moksha menus app

diff --git a/moksha/apps/menus/moksha-menus.spec b/moksha/apps/menus/moksha-menus.spec
deleted file mode 100644
index aa0dfbc..0000000
--- a/moksha/apps/menus/moksha-menus.spec
+++ /dev/null
@@ -1,55 +0,0 @@
-%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%{!?pyver: %define pyver %(%{__python} -c "import sys ; print sys.version[:3]")}
-
-%global modname moksha.menus
-
-Name:           moksha-menus
-Version:        0.1
-Release:        1%{?dist}
-Summary:        A dynamic menu API for Moksha
-Group:          Applications/Internet
-License:        AGPLv3
-URL:            https://fedorahosted.org/moksha
-Source0:        moksha.menus-%{version}.tar.gz
-
-BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-BuildArch:      noarch
-
-BuildRequires: python-setuptools-devel
-BuildRequires: python-paver
-
-Requires: moksha
-
-%description
-TODO
-
-%prep
-%setup -q -n moksha.menus-%{version}
-
-%build
-paver bdist_egg
-
-%install
-%{__rm} -rf %{buildroot}
-%{__mkdir} -p %{buildroot}%{python_sitelib}
-PYTHONPATH=%{buildroot}%{python_sitelib} easy_install \
-    --prefix %{buildroot}%{_usr} --no-deps --always-unzip \
-    dist/*.egg
-
-# TODO: see if this is absolutely necessar!
-%{__rm} %{buildroot}%{python_sitelib}/easy-install.pth
-
-%{__rm} %{buildroot}%{python_sitelib}/site.py{,c}
-
-%clean
-%{__rm} -rf %{buildroot}
-
-
-%files 
-%defattr(-,root,root,-)
-#%doc README AUTHORS LICENSE COPYING
-%{python_sitelib}/%{modname}-%{version}-py%{pyver}.egg/
-
-%changelog
-* Thu Aug 06 2009 Luke Macken <lmacken at redhat.com> - 0.1-1
-- Initial package
diff --git a/moksha/apps/menus/pavement.py b/moksha/apps/menus/pavement.py
index 098ebca..5deae77 100644
--- a/moksha/apps/menus/pavement.py
+++ b/moksha/apps/menus/pavement.py
@@ -1,37 +1,33 @@
 from paver.easy import *
-from paver.setuputils import setup, find_package_data, find_packages
+from paver.setuputils import (setup, find_package_data, find_packages,
+                              install_distutils_tasks)
+from moksha.lib.paver_tasks import *
 
-setup(
-    name="moksha.menus",
-    version="0.1",
-    url="http://moksha.fedorahosted.org",
-    description="Moksha Menus App",
-    author="Luke Macken",
-    author_email="lmacken at redhat.com",
-    packages=find_packages(),
-    package_data=find_package_data(),
-    namespace_packages=['moksha'],
-    install_requires=["Moksha"],
-    entry_points="""
+install_distutils_tasks()
 
-    [moksha.menu]
-    default_menu = moksha.apps.menus:MokshaDefaultMenu
-
-    [moksha.application]
-    menu = moksha.apps.menus.controllers:MokshaMenuController
-
-    """,
+options(
+    setup=Bunch(
+        name="moksha.menus",
+        version="0.1",
+        release="1",
+        url="http://moksha.fedorahosted.org",
+        description="Moksha Menus App",
+        license="AGPLv3",
+        long_description="",
+        author="Luke Macken",
+        author_email="lmacken at redhat.com",
+        rpm_name='moksha-menus',
+        packages=find_packages(),
+        package_data=find_package_data(),
+        namespace_packages=['moksha'],
+        install_requires=["Moksha"],
+        entry_points={
+            'moksha.menu': (
+                'default_menu = moksha.apps.menus:MokshaDefaultMenu',
+            ),
+            'moksha.application': (
+                'menu = moksha.apps.menus.controllers:MokshaMenuController',
+            ),
+        }
+    ),
 )
-
- at task
-def rpm():
-    sh('rm -fr dist')
-    sh('paver sdist')
-    sh('mv dist/* ~/rpmbuild/SOURCES/')
-    sh('cp *.spec ~/rpmbuild/SPECS/')
-    sh('rpmbuild -ba ~/rpmbuild/SPECS/moksha-menus.spec')
-
- at task
- at needs(['rpm'])
-def reinstall():
-    sh('sudo rpm -ivh --replacefiles --replacepkgs ~/rpmbuild/RPMS/noarch/moksha-menus-0.1-1.noarch.rpm')


commit 9c433936f3e9a083faa98828c805ea5380c1568e
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:36:20 2009 -0400

    Add a moksha metrics app

diff --git a/moksha/apps/metrics/moksha/__init__.py b/moksha/apps/metrics/moksha/__init__.py
new file mode 100644
index 0000000..de40ea7
--- /dev/null
+++ b/moksha/apps/metrics/moksha/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/moksha/apps/metrics/moksha/apps/__init__.py b/moksha/apps/metrics/moksha/apps/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/metrics/moksha/apps/metrics/__init__.py b/moksha/apps/metrics/moksha/apps/metrics/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/metrics/moksha/apps/metrics/consumers/__init__.py b/moksha/apps/metrics/moksha/apps/metrics/consumers/__init__.py
new file mode 100644
index 0000000..e8f4382
--- /dev/null
+++ b/moksha/apps/metrics/moksha/apps/metrics/consumers/__init__.py
@@ -0,0 +1 @@
+from metrics_consumer import *
diff --git a/moksha/apps/metrics/moksha/apps/metrics/consumers/metrics_consumer.py b/moksha/apps/metrics/moksha/apps/metrics/consumers/metrics_consumer.py
new file mode 100644
index 0000000..58acdef
--- /dev/null
+++ b/moksha/apps/metrics/moksha/apps/metrics/consumers/metrics_consumer.py
@@ -0,0 +1,36 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import logging
+
+from orbited import json
+from moksha.api.hub import Consumer
+
+log = logging.getLogger('moksha.hub')
+
+class MokshaMessageMetricsConsumer(Consumer):
+    """
+    This consumer listens to all messages on the `moksha_message_metrics`
+    topic, and relays the messgae to the message['headers']['topic']
+    """
+    topic = 'moksha_message_metrics'
+
+    def consume(self, message):
+        topic = message['headers'].get('topic')
+        if topic:
+            self.send_message(topic, json.encode(message['body']))
+        else:
+            log.error('No `topic` specified in moksha_message_metrics message')
diff --git a/moksha/apps/metrics/moksha/apps/metrics/streams/__init__.py b/moksha/apps/metrics/moksha/apps/metrics/streams/__init__.py
new file mode 100644
index 0000000..a73e436
--- /dev/null
+++ b/moksha/apps/metrics/moksha/apps/metrics/streams/__init__.py
@@ -0,0 +1 @@
+from metrics_stream import *
diff --git a/moksha/apps/metrics/moksha/apps/metrics/streams/metrics_stream.py b/moksha/apps/metrics/moksha/apps/metrics/streams/metrics_stream.py
new file mode 100644
index 0000000..9461220
--- /dev/null
+++ b/moksha/apps/metrics/moksha/apps/metrics/streams/metrics_stream.py
@@ -0,0 +1,295 @@
+# -*- coding: utf-8 -*-
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import subprocess
+
+from moksha.lib.helpers import defaultdict
+from moksha.api.streams import PollingDataStream
+
+PID = 0
+NAME = -1
+MEM_TOTAL = -2
+
+class MokshaMetricsDataStream(PollingDataStream):
+    frequency = 3
+    procs = ('orbited', 'paster', 'moksha', 'httpd')
+    cpu_usage = defaultdict(list)
+    programs = None
+    pids = {}
+    count = 0
+
+    # Unless we are monitoring apache, only poll for pids once
+    poll_for_new_pids = False
+
+    def __init__(self):
+        self.programs = self._find_programs()
+        self.processors = self._find_processors()
+        super(MokshaMetricsDataStream, self).__init__()
+
+    def _find_programs(self):
+        programs = []
+        for program in self.mem():
+            for proc in self.procs:
+                if program[NAME].startswith(proc) or proc in program[NAME]:
+                    programs.append(program)
+                    for pid in program[PID].split(','):
+                        self.pids[int(pid)] = program[NAME]
+                    if proc == 'httpd':
+                        self.poll_for_new_pids = True
+        return programs
+
+    def _find_processors(self):
+        """ Find the number of processors """
+        processors = 0
+        for line in file('/proc/cpuinfo').readlines():
+            if line.startswith('processor'):
+                processors = int(line.split(':')[1])
+        return processors + 1
+
+    def poll(self):
+        i = 0
+        mem_data = {
+            'data': [],
+            'options': {
+                'xaxis': {'ticks': []},
+                'legend': {'position': 'nw', 'backgroundColor': 'null'}
+            }
+        }
+        cpu_data = {
+            'data': [],
+            'options': {
+                'xaxis': {'min': 0, 'max': 50},
+                'yaxis': {'min': 0, 'max': 100 * self.processors},
+                'legend': {
+                    'position': 'nw',
+                    'backgroundColor': 'null'
+                }
+            }
+        }
+
+        self.count += 1
+        if self.poll_for_new_pids and self.count % 10 == 0:
+            self.programs = self._find_programs()
+            self.count = 0
+
+        for program in self.programs:
+            for proc in self.procs:
+                if program[NAME].startswith(proc) or proc in program[NAME]:
+                    total_mem_usage = float(program[MEM_TOTAL].split()[0])
+                    mem_data['data'].append({
+                            'data': [[i, total_mem_usage]],
+                            'bars': {'show': 'true'},
+                            'label': program[NAME],
+                            })
+                    mem_data['options']['xaxis']['ticks'].append(
+                            [i + 0.5, program[NAME]])
+                    i += 1
+
+        self.send_message('moksha_mem_metrics', [mem_data])
+
+        # top only allows 20 pids to be specified at a time
+        # so make multiple calls if we have to
+        out = []
+        _pids = []
+        _pids.extend(self.pids.keys())
+        while _pids:
+            cmd = ['/usr/bin/top', '-b', '-n 1']
+            for pid in _pids[:20]:
+                cmd += ['-p %s' % pid]
+            p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+            stdout, stderr = p.communicate()
+            stdout = stdout.strip().split('\n')
+            for i, line in enumerate(stdout):
+                if line.lstrip().startswith('PID'):
+                    out += stdout[i+1:]
+                    break
+            _pids = _pids[20:]
+
+        # Determine the % CPU usage for each pid
+        pid_cpu = defaultdict(float)
+        for line in out:
+            splitline = line.split()
+            if not splitline: continue
+            pid = int(splitline[0])
+            cpu_usage = float(splitline[-4])
+            pid_cpu[self.pids[pid]] += cpu_usage
+
+        # Move everything to the left, and append the latest CPU usage.
+        for program, cpu_usage in pid_cpu.items():
+            for history in self.cpu_usage[program]:
+                history[0] -= 1
+
+            self.cpu_usage[program].append([50, cpu_usage])
+
+            # Only store 50 ticks worth of data
+            self.cpu_usage[program] = self.cpu_usage[program][-51:]
+
+        for program, history in self.cpu_usage.items():
+            cpu_data['data'].append({
+                'data': history,
+                'lines': {'show': 'true', 'fill': 'true'},
+                'label': program.split()[0],
+                })
+
+        self.send_message('moksha_cpu_metrics', [cpu_data])
+
+    def mem(self):
+        """
+        Returns a list of per-program memory usage.
+
+             Private  +  Shared   =  RAM used     Program
+
+           [["39.4 MiB", "10.3 MiB", "49.8 MiB",  "Xorg"],
+            ["42.2 MiB", "12.4 MiB", "54.6 MiB",  "nautilus"],
+            ["52.3 MiB", "10.8 MiB", "63.0 MiB",  "liferea-bin"]
+            ["171.6 MiB", "11.9 MiB", "183.5 MiB", "firefox-bin"]]
+
+        Taken from the ps_mem.py script written by Pádraig Brady.
+        http://www.pixelbeat.org/scripts/ps_mem.py
+        """
+        our_pid=os.getpid()
+        results = []
+        global have_pss
+        have_pss=0
+
+        def kernel_ver():
+            """ (major,minor,release) """
+            kv=open("/proc/sys/kernel/osrelease").readline().split(".")[:3]
+            for char in "-_":
+                kv[2]=kv[2].split(char)[0]
+            return (int(kv[0]), int(kv[1]), int(kv[2]))
+
+        kv=kernel_ver()
+
+        def getMemStats(pid):
+            """ return Private,Shared """
+            global have_pss
+            Private_lines=[]
+            Shared_lines=[]
+            Pss_lines=[]
+            pagesize=os.sysconf("SC_PAGE_SIZE")/1024 #KiB
+            Rss=int(open("/proc/"+str(pid)+"/statm").readline().split()[1])*pagesize
+            if os.path.exists("/proc/"+str(pid)+"/smaps"): #stat
+                for line in open("/proc/"+str(pid)+"/smaps").readlines(): #open
+                    if line.startswith("Shared"):
+                        Shared_lines.append(line)
+                    elif line.startswith("Private"):
+                        Private_lines.append(line)
+                    elif line.startswith("Pss"):
+                        have_pss=1
+                        Pss_lines.append(line)
+                Shared=sum([int(line.split()[1]) for line in Shared_lines])
+                Private=sum([int(line.split()[1]) for line in Private_lines])
+                #Note Shared + Private = Rss above
+                #The Rss in smaps includes video card mem etc.
+                if have_pss:
+                    pss_adjust=0.5 #add 0.5KiB as this average error due to trunctation
+                    Pss=sum([float(line.split()[1])+pss_adjust for line in Pss_lines])
+                    Shared = Pss - Private
+            elif (2,6,1) <= kv <= (2,6,9):
+                Shared=0 #lots of overestimation, but what can we do?
+                Private = Rss
+            else:
+                Shared=int(open("/proc/"+str(pid)+"/statm").readline().split()[2])*pagesize
+                Private = Rss - Shared
+            return (Private, Shared)
+
+        def getCmdName(pid):
+            cmd = file("/proc/%d/status" % pid).readline()[6:-1]
+            exe = os.path.basename(os.path.realpath("/proc/%d/exe" % pid))
+            if exe.startswith(cmd):
+                cmd=exe #show non truncated version
+                #Note because we show the non truncated name
+                #one can have separated programs as follows:
+                #584.0 KiB +   1.0 MiB =   1.6 MiB    mozilla-thunder (exe -> bash)
+                # 56.0 MiB +  22.2 MiB =  78.2 MiB    mozilla-thunderbird-bin
+            return cmd
+
+        cmds={}
+        shareds={}
+        count={}
+        pids = {}
+
+        for pid in os.listdir("/proc/"):
+            try:
+                pid = int(pid) #note Thread IDs not listed in /proc/ which is good
+                #if pid == our_pid: continue
+            except:
+                continue
+            try:
+                cmd = getCmdName(pid)
+            except Exception, e:
+                #permission denied or
+                #kernel threads don't have exe links or
+                #process gone
+                continue
+            try:
+                private, shared = getMemStats(pid)
+            except:
+                continue #process gone
+            if shareds.get(cmd):
+                if have_pss: #add shared portion of PSS together
+                    shareds[cmd]+=shared
+                elif shareds[cmd] < shared: #just take largest shared val
+                    shareds[cmd]=shared
+            else:
+                shareds[cmd]=shared
+            cmds[cmd]=cmds.setdefault(cmd,0)+private
+            if count.has_key(cmd):
+               count[cmd] += 1
+               pids[cmd] += ',%d' % pid
+            else:
+               count[cmd] = 1
+               pids[cmd] = str(pid)
+
+        #Add shared mem for each program
+        total=0
+        for cmd in cmds.keys():
+            cmds[cmd]=cmds[cmd]+shareds[cmd]
+            total+=cmds[cmd] #valid if PSS available
+
+        sort_list = cmds.items()
+        sort_list.sort(lambda x,y:cmp(x[1],y[1]))
+        sort_list=filter(lambda x:x[1],sort_list) #get rid of zero sized processes
+
+        #The following matches "du -h" output
+        def human(num, power="Ki"):
+            powers=["Ki","Mi","Gi","Ti"]
+            while num >= 1000: #4 digits
+                num /= 1024.0
+                power=powers[powers.index(power)+1]
+            return "%.1f %s" % (num,power)
+
+        def cmd_with_count(cmd, count):
+            if count>1:
+               return "%s (%u)" % (cmd, count)
+            else:
+               return cmd
+
+        for cmd in sort_list:
+            results.append([
+                "%s" % pids[cmd[0]],
+                "%sB" % human(cmd[1]-shareds[cmd[0]]),
+                "%sB" % human(shareds[cmd[0]]),
+                "%sB" % human(cmd[1]),
+                "%s" % cmd_with_count(cmd[0], count[cmd[0]])
+            ])
+        if have_pss:
+            results.append(["", "", "", "%sB" % human(total)])
+
+        return results
diff --git a/moksha/apps/metrics/moksha/apps/metrics/widgets/__init__.py b/moksha/apps/metrics/moksha/apps/metrics/widgets/__init__.py
new file mode 100644
index 0000000..e28912a
--- /dev/null
+++ b/moksha/apps/metrics/moksha/apps/metrics/widgets/__init__.py
@@ -0,0 +1 @@
+from metrics import *
diff --git a/moksha/apps/metrics/moksha/apps/metrics/widgets/metrics.py b/moksha/apps/metrics/moksha/apps/metrics/widgets/metrics.py
new file mode 100644
index 0000000..311e421
--- /dev/null
+++ b/moksha/apps/metrics/moksha/apps/metrics/widgets/metrics.py
@@ -0,0 +1,154 @@
+# -*- coding: utf-8 -*-
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+:mod:`moksha.widgets.metrics` -- Moksha Metrics
+===============================================
+
+This module contains Moksha-specific widgets and
+DataStreams that provide live statistics of
+Moksha's memory and CPU usage.
+
+.. moduleauthor:: Luke Macken <lmacken at redhat.com>
+"""
+
+from uuid import uuid4
+from tw.jquery.ui import ui_progressbar_js
+from tw.jquery.flot import flot_js, excanvas_js, flot_css
+
+from moksha.api.widgets.flot import LiveFlotWidget
+from moksha.api.widgets.buttons import buttons_css
+from moksha.widgets.jquery_ui_theme import ui_base_css
+
+class MokshaMemoryUsageWidget(LiveFlotWidget):
+    name = 'Memory Usage'
+    topic = 'moksha_mem_metrics'
+    container_options = {
+            'icon': 'chart.png', 'top': 400, 'left': 80, 'height': 310,
+            'iconize': False, 'minimize': False,
+            }
+
+
+class MokshaCPUUsageWidget(LiveFlotWidget):
+    name = 'CPU Usage'
+    topic = 'moksha_cpu_metrics'
+    container_options = {
+            'icon': 'chart.png', 'top': 80, 'left': 80, 'height': 310,
+            'iconize': False, 'minimize': False,
+            }
+
+
+class MokshaMessageMetricsWidget(LiveFlotWidget):
+    """ A Moksha Message Benchmarking Widget.
+
+    This widget will fire off a bunch of messages to a unique message topic.
+    The MokshaMessageMetricsConsumer, being run in the Moksha Hub, will
+    echo these messages back to the sender.  This widget will then graph
+    the round-trip results.
+
+    TODO:
+    - display the latency
+    """
+    name = 'Message Metrics'
+    template = """
+        Messages sent: <span id="metrics_msg_sent">0</span><br/>
+        <div id="metrics_sent_progress"></div>
+        Messages received: <span id="metrics_msg_recv">0</span><br/>
+        <div id="metrics_recv_progress"></div>
+        <br/>
+        <script>
+            var NUM_MESSAGES = 100;
+            var accum = 0.0;
+            var flot_data = [];
+            var x = 0;
+            var start_time = 0;
+
+            $('#metrics_sent_progress').progressbar({value: 0});
+            $('#metrics_recv_progress').progressbar({value: 0});
+
+            function run_message_metrics() {
+                $('#metrics_sent_progress').progressbar('option', 'value', 0);
+                $('#metrics_recv_progress').progressbar('option', 'value', 0);
+                $('#metrics_msg_sent').text("0");
+                $('#metrics_msg_recv').text("0");
+
+                flot_data = [];
+                x = 0;
+                accum = 0.0;
+
+                for (var i = 0; i < NUM_MESSAGES; i++) {
+                    var start = new Date();
+                    start_time = start.getTime();
+                    stomp.send(start.getTime() + '', 'moksha_message_metrics',
+                               {topic: '${topic}'});
+                    $('#metrics_sent_progress').progressbar('option', 'value', i+1)
+                    $('#metrics_msg_sent').text(i + 1 + '');
+                }
+                stomp.send('done', 'moksha_message_metrics',
+                           {topic: '${topic}'});
+            }
+
+        </script>
+        <div id="metrics_flot" style="width:390px;height:250px;" />
+        <div id="metrics_avg"></div>
+        <div id="metrics_msg_sec"></div>
+        <br/>
+        <center>
+          <a href="#" class="opaquebutton" onclick="run_message_metrics(); return false"><span>Send 100 Messages</span></a>
+        </center>
+    """
+    onmessage = """
+        if (json == 'done') {
+            avg = accum / (NUM_MESSAGES * 1.0);
+            $('#metrics_recv_progress').progressbar('option', 'value', x+1)
+            $.plot($('#metrics_flot'), [{data: flot_data, lines: {show: true}}]);
+            $('#metrics_avg').text('Average round trip: ' + avg + ' seconds.');
+            var start = new Date();
+            seconds = (start.getTime() - start_time) / 1000.0;
+            $('#metrics_msg_sec').text('Messages per second: ' + NUM_MESSAGES / seconds);
+        } else {
+            var now = new Date();
+            seconds = (now.getTime() - json) / 1000.0;
+            accum = accum + seconds;
+            flot_data.push([x, seconds]);
+            $('#metrics_recv_progress').progressbar('option', 'value', x+1)
+            $('#metrics_msg_recv').text(x + 1 + '');
+            x = x + 1;
+        }
+    """
+    javascript = [excanvas_js, flot_js, ui_progressbar_js]
+    css = [ui_base_css, flot_css, buttons_css]
+    container_options = {'icon': 'chart.png', 'left': 550, 'top': 80,
+                         'height': 500}
+
+    def update_params(self, d):
+        d.topic = str(uuid4())
+        super(MokshaMessageMetricsWidget, self).update_params(d)
+
+
+# @@ FIXME: We need to not insert two stomp widgets in this case...
+#class MokshaMetricsWidget(Widget):
+#    children = [MokshaCPUUsageWidget('moksha_cpu'),
+#                MokshaMemoryUsageWidget('moksha_mem')]
+#    template = """
+#        <center>${c.moksha_cpu.label}</center>
+#        ${c.moksha_cpu()}
+#        <br/>
+#        <center>${c.moksha_mem.label}</center>
+#        ${c.moksha_mem()}
+#    """
+#    engine_name = 'mako'
diff --git a/moksha/apps/metrics/pavement.py b/moksha/apps/metrics/pavement.py
new file mode 100644
index 0000000..fabed56
--- /dev/null
+++ b/moksha/apps/metrics/pavement.py
@@ -0,0 +1,44 @@
+from paver.easy import *
+from paver.setuputils import (setup, find_package_data, find_packages,
+                              install_distutils_tasks)
+from moksha.lib.paver_tasks import *
+
+install_distutils_tasks()
+
+options(
+    setup=Bunch(
+        name="moksha.metrics",
+        version="0.1",
+        release="1",
+        url="http://moksha.fedorahosted.org",
+        description="Moksha Metrics App",
+        long_description="",
+        author="Luke Macken",
+        author_email="lmacken at redhat.com",
+        license="AGPLv3",
+        rpm_name='moksha-metrics',
+        packages=find_packages(),
+        package_data=find_package_data(),
+        namespace_packages=['moksha'],
+        install_requires=["Moksha"],
+        entry_points={
+            'moksha.stream': (
+                'moksha_metrics = moksha.apps.metrics.streams:MokshaMetricsDataStream',
+            ),
+            'moksha.consumer': (
+                'moksha_message_metrics = moksha.apps.metrics.consumers:MokshaMessageMetricsConsumer',
+            ),
+            'moksha.widget': (
+                'MokshaMemoryUsageWidget = moksha.apps.metrics.widgets:MokshaMemoryUsageWidget',
+                'MokshaCPUUsageWidget = moksha.apps.metrics.widgets:MokshaCPUUsageWidget',
+                'MokshaMessageMetricsWidget = moksha.apps.metrics.widgets:MokshaMessageMetricsWidget',
+            ),
+            'moksha.global': (
+                'stomp_js = moksha.api.widgets.stomp:stomp_js',
+                'orbited = moksha.api.widgets.orbited:orbited_js',
+                'jquery_ui_draggable = tw.jquery.ui:ui_draggable_min_js',
+                'jquery_ui_resizable = tw.jquery.ui:ui_resizable_min_js',
+            ),
+        }
+    ),
+)


commit 6030a00e25e7ae88abb2852171b4becf4c5b4208
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:35:56 2009 -0400

    Add a moksha docs app

diff --git a/moksha/apps/docs/__init__.py b/moksha/apps/docs/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/moksha/apps/docs/docs.py b/moksha/apps/docs/docs.py
deleted file mode 100644
index 175db7f..0000000
--- a/moksha/apps/docs/docs.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""
-:mod:`moksha.apps.docs.docs` - Moksha Documentation & Widget Demo App
-=====================================================================
-
-This Moksha app integrates your Sphinx documentation with the ToscaWidgets
-WidgetBrowser.  This gives you the ability to write your documentation
-in reStructuredText, and easily expose it in your application via the 
-`/apps/docs` URL.  Since it integrates the ToscaWidgets WidgetBrowser,
-this also gives you the ability to create Widget demos and embed them
-in your documentation.
-
-.. seealso::
-
-    See the ToscaWidgets WidgetBrowser documentation for more information
-    http://toscawidgets.org/documentation/WidgetBrowser/widget_demo_howto.html
-
-.. moduleauthor:: Luke Macken <lmacken at redhat.com>
-
-"""
-
-import os
-
-from tg import config
-from tg.controllers import WSGIAppController
-from pkg_resources import resource_filename
-from widgetbrowser import WidgetBrowser
-
-os.environ['TW_BROWSER_PREFIX'] = '/apps/docs'
-
-docs = WSGIAppController(
-            WidgetBrowser(
-                template_dirs=[
-                    resource_filename('moksha','templates/widget_browser')],
-                docs_dir=config.get('docs_dir', 'docs'),
-                full_stack=False,
-                interactive=False))
diff --git a/moksha/apps/docs/moksha/__init__.py b/moksha/apps/docs/moksha/__init__.py
new file mode 100644
index 0000000..de40ea7
--- /dev/null
+++ b/moksha/apps/docs/moksha/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/moksha/apps/docs/moksha/apps/__init__.py b/moksha/apps/docs/moksha/apps/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/docs/moksha/apps/docs.py b/moksha/apps/docs/moksha/apps/docs.py
new file mode 100644
index 0000000..175db7f
--- /dev/null
+++ b/moksha/apps/docs/moksha/apps/docs.py
@@ -0,0 +1,52 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+:mod:`moksha.apps.docs.docs` - Moksha Documentation & Widget Demo App
+=====================================================================
+
+This Moksha app integrates your Sphinx documentation with the ToscaWidgets
+WidgetBrowser.  This gives you the ability to write your documentation
+in reStructuredText, and easily expose it in your application via the 
+`/apps/docs` URL.  Since it integrates the ToscaWidgets WidgetBrowser,
+this also gives you the ability to create Widget demos and embed them
+in your documentation.
+
+.. seealso::
+
+    See the ToscaWidgets WidgetBrowser documentation for more information
+    http://toscawidgets.org/documentation/WidgetBrowser/widget_demo_howto.html
+
+.. moduleauthor:: Luke Macken <lmacken at redhat.com>
+
+"""
+
+import os
+
+from tg import config
+from tg.controllers import WSGIAppController
+from pkg_resources import resource_filename
+from widgetbrowser import WidgetBrowser
+
+os.environ['TW_BROWSER_PREFIX'] = '/apps/docs'
+
+docs = WSGIAppController(
+            WidgetBrowser(
+                template_dirs=[
+                    resource_filename('moksha','templates/widget_browser')],
+                docs_dir=config.get('docs_dir', 'docs'),
+                full_stack=False,
+                interactive=False))
diff --git a/moksha/apps/docs/pavement.py b/moksha/apps/docs/pavement.py
index d34229d..eca53f1 100644
--- a/moksha/apps/docs/pavement.py
+++ b/moksha/apps/docs/pavement.py
@@ -1,19 +1,30 @@
 from paver.easy import *
-from paver.setuputils import setup
+from paver.setuputils import (setup, find_package_data, find_packages,
+                              install_distutils_tasks)
+from moksha.lib.paver_tasks import *
 
-setup(
-    name="moksha.docs",
-    version="1.0",
-    url="http://moksha.fedorahosted.org",
-    description="Moksha Docs App",
-    author="Luke Macken",
-    author_email="lmacken at redhat.com",
-    packages=[],
-    install_requires=["Moksha"],
-    entry_points="""
+install_distutils_tasks()
 
-    [moksha.application]
-    docs = moksha.apps.docs.docs:docs
-
-    """,
+options(
+    setup=Bunch(
+        name="moksha.docs",
+        version="1.0",
+        release="1",
+        url="http://moksha.fedorahosted.org",
+        description="Moksha Docs App",
+        long_description="TODO.",
+        license='AGPLv3',
+        rpm_name='moksha-apps-docs',
+        author="Luke Macken",
+        author_email="lmacken at redhat.com",
+        packages=find_packages(),
+        package_data=find_package_data(),
+        install_requires=["Moksha"],
+        namespace_packages=['moksha'],
+        entry_points={
+            'moksha.application': (
+                'docs = moksha.apps.docs.docs:docs',
+            ),
+        }
+    ),
 )


commit ad92631428000a0b5d1c0f1e4238cb8e8b9a07df
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Aug 7 14:27:52 2009 -0400

    Add a new moksha.lib.paver_tasks module with some useful paver tasks

diff --git a/moksha/lib/paver_tasks.py b/moksha/lib/paver_tasks.py
new file mode 100644
index 0000000..3ae9abb
--- /dev/null
+++ b/moksha/lib/paver_tasks.py
@@ -0,0 +1,66 @@
+import os
+from paver.easy import *
+
+ at task
+def rpm():
+    specfile = '%s.spec' % options.rpm_name
+    if not os.path.isfile(specfile):
+        spec_file = file('%s.spec' % options.rpm_name, 'w')
+        spec_file.write("""\
+%%{!?python_sitelib: %%define python_sitelib %%(%%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%%{!?pyver: %%define pyver %%(%%{__python} -c "import sys ; print sys.version[:3]")}
+
+%%global modname %(name)s
+
+Name:           %(rpm_name)s
+Version:        %(version)s
+Release:        %(release)s%%{?dist}
+Summary:        %(description)s
+Group:          Applications/Internet
+License:        %(license)s
+URL:            %(url)s
+Source0:        %%{modname}-%%{version}.tar.bz2
+BuildRoot:      %%{_tmppath}/%%{name}-%%{version}-%%{release}-root-%%(%%{__id_u} -n)
+BuildArch:      noarch
+BuildRequires:  python-setuptools-devel
+BuildRequires:  python-paver
+Requires:       moksha
+
+%%description
+%(long_description)s
+
+%%prep
+%%setup -q -n %%{modname}-%%{version}
+
+%%build
+rm -rf %%{buildroot}
+paver build
+
+%%install
+%%{__rm} -rf %%{buildroot}
+paver install -O1 --skip-build --root %%{buildroot}
+%%{__rm} %%{buildroot}%%{python_sitelib}/moksha/apps/__init__.py{,c,o}
+
+%%clean
+%%{__rm} -rf %%{buildroot}
+
+%%files
+%%defattr(-,root,root,-)
+%%{python_sitelib}/%%{modname}-%%{version}-py%%{pyver}-nspkg.pth
+%%{python_sitelib}/%%{modname}-%%{version}-py%%{pyver}.egg-info/
+%%{python_sitelib}/moksha/apps/*
+        """ % {'name': options.name, 'version': options.version,
+               'release': options.release, 'description': options.description,
+               'long_description': options.long_description, 'license': options.license,
+               'url': options.url, 'rpm_name': options.rpm_name})
+        spec_file.close()
+
+    sh('paver sdist --format=bztar')
+    sh('mv dist/* ~/rpmbuild/SOURCES/')
+    sh('cp %s.spec ~/rpmbuild/SPECS/' % options.rpm_name)
+    sh('rpmbuild -ba ~/rpmbuild/SPECS/%s.spec' % options.rpm_name)
+
+ at task
+ at needs(['rpm'])
+def reinstall():
+    sh('sudo rpm -ivh --replacefiles --replacepkgs ~/rpmbuild/RPMS/noarch/%s-%s-%s.noarch.rpm' % (options.rpm_name, options.version, options.release))


commit d4f60775ab101d0985fc613f56a31a1537f95313
Author: Luke Macken <lmacken at redhat.com>
Date:   Thu Aug 6 15:34:45 2009 -0400

    Rename the manifest

diff --git a/moksha/apps/menus/MANIFEST b/moksha/apps/menus/MANIFEST
new file mode 100644
index 0000000..5121d7c
--- /dev/null
+++ b/moksha/apps/menus/MANIFEST
@@ -0,0 +1 @@
+recursive-include moksha *.mak *.html *.js *.png *.gif *.css *.jpg *.jpeg
diff --git a/moksha/apps/menus/MANIFEST.in b/moksha/apps/menus/MANIFEST.in
deleted file mode 100644
index 5121d7c..0000000
--- a/moksha/apps/menus/MANIFEST.in
+++ /dev/null
@@ -1 +0,0 @@
-recursive-include moksha *.mak *.html *.js *.png *.gif *.css *.jpg *.jpeg


commit 34742de340d098c85f90146bb738545b69e7ebca
Author: Luke Macken <lmacken at redhat.com>
Date:   Thu Aug 6 15:33:28 2009 -0400

    Refactor the new moksha.menus app

diff --git a/moksha/api/menus/__init__.py b/moksha/api/menus/__init__.py
deleted file mode 100644
index 3e1f6d1..0000000
--- a/moksha/api/menus/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from widgets import *
-from default import *
diff --git a/moksha/api/menus/controllers/__init__.py b/moksha/api/menus/controllers/__init__.py
deleted file mode 100644
index 2d5c4cd..0000000
--- a/moksha/api/menus/controllers/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from menu import *
diff --git a/moksha/api/menus/controllers/menu.py b/moksha/api/menus/controllers/menu.py
deleted file mode 100644
index 6c68758..0000000
--- a/moksha/api/menus/controllers/menu.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import moksha
-
-from tg import expose
-from moksha.lib.base import Controller
-
-class MokshaMenuController(Controller):
-    name = 'Moksha Menus'
-
-    @expose()
-    def default(self, menuId, *args, **kw):
-        """ For the selected `menuId`, return the menu HTML.
-
-        The `menuId` is the name of the portion of the menu that was clicked
-        on.  For example, if the menu name was 'default_menu', and the first
-        section was called 'Help', then the menuId would be 'default_menu_help'.
-        This controller will then call the help() method on the
-        MokshaModel.
-        """
-        split = menuId.lower().split('_')
-        menu_id = '_'.join(split[:-1])
-        menu_item = split[-1]
-        menu = getattr(moksha.menus[menu_id], menu_item)(**kw)
-        return """
-            <div id="%(menuId)s" class="menu">
-                %(menu)s
-            </div>
-        """ % {'menuId': menuId, 'menu': menu}
diff --git a/moksha/api/menus/default.py b/moksha/api/menus/default.py
deleted file mode 100644
index 27f7965..0000000
--- a/moksha/api/menus/default.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""
-:mod:`moksha.api.menus.default` - The default Moksha Menu
-=========================================================
-The default Moksha menu is an example Menu that lists
-the installed Applications, Widgets, etc.
-
-.. moduleauthor:: Luke Macken <lmacken at redhat.com>
-"""
-
-import moksha
-from moksha.api.menus import MokshaMenu, MokshaContextualMenu
-
-class MokshaContextMenu(MokshaContextualMenu):
-
-    def default(self, *args, **kw):
-        return """
-            <a rel="text">
-                <img src="/images/moksha-icon.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/><br/>
-            </a>
-            <a href="/widget">Documentation</a>
-            <a href="https://fedorahosted.org/moksha/report/3">Tickets</a>
-            <a href="https://fedorahosted.org/moksha/">Wiki</a>
-            <a menu="moksha">Moksha</a>
-        """
-
-class MokshaDefaultMenu(MokshaMenu):
-    menus = ['Moksha', 'Widgets', 'Fedora']
-
-    def widgets(self, *args, **kw):
-        menu = """
-        <a rel="text">
-            <img src="/images/block.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/>
-            <br/>
-        </a>
-        """
-        for id, widget in moksha._widgets.iteritems():
-            if not getattr(widget['widget'], 'hidden', False):
-                menu += """
-                      <a href="#" onclick="$('#footer')
-                            .append($('<div/>')
-                            .attr('id', '%(id)s_loader')); 
-                            $.ajax({
-                                url: moksha.url('/widgets/%(id)s?chrome=True'),
-                                success: function(r, s) {
-                                    var $panel = $('#%(id)s_loader');
-                                    var $stripped = moksha.filter_resources(r);
-                                    $panel.html($stripped);
-                                }
-                            });
-                            return false;">%(name)s</a>
-
-                """ % {'name': widget['name'], 'id': id}
-        return menu
-
-    def moksha(self, *args, **kw):
-        return """
-        <a rel="text">
-            <img src="/images/moksha-icon.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/><br>
-            <br>Moksha is a platform for creating live collaborative web applications.<br><br>
-        </a>
-        <a rel="separator"></a>
-        <a href="/apps/docs/">Documentation</a>
-        <a href="https://fedorahosted.org/moksha/report/3">Tickets</a>
-        <a href="https://fedorahosted.org/moksha/">Wiki</a>
-        """
-
-    def fedora(self, *args, **kw):
-        links = {
-                'Wiki': 'http://fedoraproject.org/wiki',
-                'Hosted': 'http://fedorahosted.org',
-                'Bugzilla': 'http://bugzilla.redhat.com',
-                'Elections': 'https://admin.fedoraproject.org/voting',
-                'Translations': 'http://translate.fedoraproject.org',
-                'Build System': 'http://koji.fedoraproject.org',
-                'Update System': 'http://bodhi.fedoraproject.org',
-                'Package Database': 'http://admin.fedoraproject.org/pkgdb',
-                'Account System': 'http://admin.fedoraproject.org/accounts',
-                'Hardware Database': 'http://smolts.org',
-        }
-        menu = """
-            <a rel="text">
-                <img src="/images/fedora-icon.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/><br>
-            </a>
-            <a rel="separator"></a>
-        """
-        for title, url in links.items():
-            menu += '<a href="%s" target="_blank">%s</a>' % (url, title)
-        return menu
diff --git a/moksha/api/menus/static/GPL-LICENSE.txt b/moksha/api/menus/static/GPL-LICENSE.txt
deleted file mode 100755
index 9266bbc..0000000
--- a/moksha/api/menus/static/GPL-LICENSE.txt
+++ /dev/null
@@ -1,279 +0,0 @@
-        GNU GENERAL PUBLIC LICENSE
-           Version 2, June 1991
-
- Copyright (C) 1989, 1991 Open Lab srl.
- via Venezia 18b - 50121 Firenze, Italia
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-          Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-        GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-          NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
diff --git a/moksha/api/menus/static/css/menu.css b/moksha/api/menus/static/css/menu.css
deleted file mode 100644
index 2ee9963..0000000
--- a/moksha/api/menus/static/css/menu.css
+++ /dev/null
@@ -1,195 +0,0 @@
-.rootVoices{
-	background-color:#f3f3f3;
-	padding:5px;
-    padding-bottom:0;
-}
-.rootVoices td.rootvoice {
-	background-color:transparent;
-	width:120px;
-	height:32px;
-    font-family:Arial,Helvetica,sans-serif;
-	color: gray;
-	font-size:12px;
-	padding:8px;
-    padding-left:10px;
-	cursor: pointer;
-}
-.rootVoices td.selected{
-	background-color:gray;
-	color:#ffffff;
-	cursor: pointer;
-	font-size:14px;
-}
-
-.menuShadow{
-    padding:2px;
-    padding-bottom:0px;
-    left:-2;
-    top:1px;
-}
-
-.menuContainer{
-	background-color:gray;
-}
-
-.menuContainer .line{
-	background-color:white;
-	width:100%;
-	padding-left:-5;
-}
-
-.menuContainer .line.title {
-    text-align:right;
-}
-
-.menuContainer .line.title a{
-    color:dimgray;
-    font-size:14px;
-}
-
-.menuContainer td a{
-	text-decoration:none;
-	color: #000000;
-}
-
-.menuContainer td.voice{
-	border-top:1px solid #f3f3f3;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-	padding:5px;
-}
-
-.menuContainer .separator{
-	background-color:#f1f1f1;
-	height:1px;
-}
-.menuContainer td.img{
-    border-top:1px solid #f3f3f3;
-	font-family:Arial,Helvetica,sans-serif;
-	text-align:center;
-	font-size:12px;
-	color: #c3c3c3;
-	background-color:#f9f9f9;
-	width:24px;
-	padding:5px;
-}
-.menuContainer td.img img{
-	width:20px;
-}
-.menuContainer .textBox{
-	padding: 5px;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-	background-color:#ffffff;
-	color: #c3c3c3;
-}
-.menuContainer .selected td{
-	background-color:#f3f3f3;
-    background-image:url("../images/bgnd_sel_2.jpg")
-}
-.menuContainer .selected td a{
-	color:#000;
-}
-.menuContainer .disabled td, .menuContainer .disabled td a {
-	color: #cccccc;
-}
-.menuContainer .subMenuOpener{
-	background-image:url("../images/menuArrow.gif");
-	background-repeat:no-repeat;
-	background-position:right;
-}
-
-/*
-vertical menu
-*/
-
-
-/**/
-
-.rootVerticalVoices{
-	background-color:#333;
-	padding:0px;
-}
-.rootVerticalVoices td.rootvoice {
-    /*border-top:1px solid #666;*/
-	width:130px;
-	font-family:Arial,Helvetica,sans-serif;
-	color: gray;
-	font-size:13px;
-	padding:7px;
-	cursor: pointer;
-}
-.rootVerticalVoices td.selected{
-    background-image:url("../images/bgnd_sel_4.png");
-	color:#ffffff;
-	cursor: pointer;
-}
-
-
-.verticalMenu{
-	background-color:#000;
-/*
-The menu container style must be set via the options paramiter
-within the function call due to a Safari bug interpreting css on the fly...
-*/
-}
-.verticalMenu .line{
-	background-color:#333;
-	width:100%;
-	padding-left:-5px;
-}
-.verticalMenu td a{
-	text-decoration:none;
-	color: #d3d3d3;
-}
-.verticalMenu td.voice{
-	border-top:0px solid #666;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-	padding:5px;
-}
-.verticalMenu .separator{
-	background-color:#666;
-	height:1px;
-}
-.verticalMenu td.img{
-    border-top:0px solid #666;
-	font-family:Arial,Helvetica,sans-serif;
-	text-align:center;
-	font-size:12px;
-	color: #c3c3c3;
-	background-color:#333;
-	width:24px;
-	padding:5px;
-}
-.verticalMenu td.img img{
-	width:20px;
-}
-.verticalMenu .textBox{
-	padding: 10px;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-	color: #c3c3c3;
-}
-.verticalMenu .selected td{
-    background-image:url("../images/bgnd_sel_4.png");
-}
-.verticalMenu .selected td a{
-	color:#fff;
-}
-.verticalMenu .disabled td, .verticalMenu .disabled td a {
-	color: #666;
-}
-
-
-.verticalMenu .subMenuOpener{
-	background-image:url("../images/menuArrow_w.gif");
-	background-repeat:no-repeat;
-	background-position:right;
-}
-
-.verticalMenu .menuShadow{
-	background:black;
-    padding:5px;
-}
-
diff --git a/moksha/api/menus/static/css/menu1.css b/moksha/api/menus/static/css/menu1.css
deleted file mode 100644
index 22e495d..0000000
--- a/moksha/api/menus/static/css/menu1.css
+++ /dev/null
@@ -1,198 +0,0 @@
-.rootVoices{
-	background-color:#f3f3f3;
-	padding:5px;
-	padding-bottom:0;
-}
-.rootVoices td.rootVoice {
-	background-color:transparent;
-	width:120px;
-	height:32px;
-	font-family:Arial,Helvetica,sans-serif;
-	color: gray;
-	font-size:12px;
-	padding:8px;
-	padding-left:10px;
-	cursor: pointer;
-	-moz-border-radius:8px 8px 0 0;
-	-webkit-border-top-right-radius:8px;
-	-webkit-border-top-left-radius:8px;
-}
-.rootVoices.vertical td.rootVoice{
-	-moz-border-radius:8px 0px 0 8px;
-	-webkit-border-top-right-radius:0px;
-	-webkit-border-top-left-radius:8px;
-	-webkit-border-bottom-right-radius:0px;
-	-webkit-border-bottom-left-radius:8px;
-
-}
-.rootVoices td.selected{
-	background:orangered url("../images/bgnd_sel_4.png");
-	color:#ffffff;
-	cursor: pointer;
-	font-size:14px;
-}
-
-.menuShadow{
-	padding:2px;
-	padding-bottom:0px;
-	left:-2;
-	top:1px;
-}
-
-/**/
-
-.menuContainer{
-	background-color:gray;
-	padding:0;
-}
-.menuContainer .line{
-	background-color:transparent;
-	width:100%;
-}
-.menuContainer .line.title {
-	background-color:#B23305;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:14px;
-	border-bottom:1px solid darkred;
-}
-.menuContainer .line.title a{
-	font-size:14px;
-}
-.menuContainer td a{
-	text-decoration:none;
-	color: #f3f3f3;
-}
-.menuContainer td.voice{
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-	padding:7px;
-}
-.menuContainer td.voice a{
-	display:block;
-	width:100%;
-}
-
-.menuContainer .separator{
-	background-color:#999;
-	height:5px;
-}
-.menuContainer td.img{
-	font-family:Arial,Helvetica,sans-serif;
-	text-align:center;
-	font-size:12px;
-	color: #c3c3c3;
-	background-color:transparent;
-	width:24px;
-	padding:5px;
-}
-.menuContainer td.img img{
-	width:20px;
-}
-.menuContainer .textBox{
-	padding: 10px;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-/*	background:dimgray url("../images/header_bgnd.jpg");
- */
-	color: #c3c3c3;
-}
-.menuContainer .selected td{
-	background-color:#f3f3f3;
-	background-image:url("../images/bgnd_sel_2.jpg")
-}
-.menuContainer .selected td a{
-	color:#000;
-}
-.menuContainer .disabled td, .menuContainer .disabled td a {
-	color: #cccccc;
-}
-.menuContainer .subMenuOpener{
-	background-image:url("../images/menuArrow_w.gif");
-	background-repeat:no-repeat;
-	background-position:right;
-}
-.menuContainer .selected .subMenuOpener{
-	background-image:url("../images/menuArrow.gif");
-	background-repeat:no-repeat;
-	background-position:right;
-}
-
-/*
-vertical menu
-*/
-
-.rootVerticalVoices{
-	background-color:#fff;
-	padding:0px;
-}
-.rootVerticalVoices td.rootVoice {
-	width:120px;
-	font-family:Arial,Helvetica,sans-serif;
-	color: #000;
-	font-size:13px;
-	padding:7px;
-	cursor: pointer;
-}
-.rootVerticalVoices td.selected{
-	background:lightslategray url("../images/bgnd_sel_4.png");
-	color:#ffffff;
-	cursor: pointer;
-}
-
-.verticalMenu{
-	background-color:lightslategray;
-}
-.verticalMenu .line{
-	background-color:lightslategray;
-	width:100%;
-	padding-left:-5px;
-}
-.verticalMenu td a{
-	text-decoration:none;
-	color: #f3f3f3;
-}
-.verticalMenu td.voice{
-	border-bottom:1px solid slategray;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-	padding:5px;
-}
-.verticalMenu .separator{
-	background-color:dimgray;
-	height:1px;
-}
-.verticalMenu td.img{
-	border-bottom:1px solid slategray;
-	font-family:Arial,Helvetica,sans-serif;
-	text-align:center;
-	font-size:12px;
-	color: #c3c3c3;
-	width:24px;
-	padding:5px;
-}
-.verticalMenu td.img img{
-	width:20px;
-}
-.verticalMenu .textBox{
-	padding: 5px;
-	font-family:Arial,Helvetica,sans-serif;
-	font-size:12px;
-	background:transparent;
-	color: #fff;
-}
-.verticalMenu .selected td{
-	background-image:url("../images/bgnd_sel_4.png")
-}
-.verticalMenu .selected td a{
-	color:#fff;
-}
-.verticalMenu .disabled td, .verticalMenu .disabled td a {
-	color:lightsteelblue;
-}
-
-
-.verticalMenu .subMenuOpener{
-	background-image:url("../images/menuArrow_w.gif");
-	background-repeat:no-repeat;
-	background-position:right;
-}
diff --git a/moksha/api/menus/static/images/0682.gif b/moksha/api/menus/static/images/0682.gif
deleted file mode 100755
index b01c8d0..0000000
Binary files a/moksha/api/menus/static/images/0682.gif and /dev/null differ
diff --git a/moksha/api/menus/static/images/16-member-remove.png b/moksha/api/menus/static/images/16-member-remove.png
deleted file mode 100755
index efcfdda..0000000
Binary files a/moksha/api/menus/static/images/16-member-remove.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/24-book-blue-check.png b/moksha/api/menus/static/images/24-book-blue-check.png
deleted file mode 100755
index c19ca9a..0000000
Binary files a/moksha/api/menus/static/images/24-book-blue-check.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/24-image-add.png b/moksha/api/menus/static/images/24-image-add.png
deleted file mode 100755
index 9c65780..0000000
Binary files a/moksha/api/menus/static/images/24-image-add.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/24-tag-add.png b/moksha/api/menus/static/images/24-tag-add.png
deleted file mode 100755
index 1dcffb6..0000000
Binary files a/moksha/api/menus/static/images/24-tag-add.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/Applet.gif b/moksha/api/menus/static/images/Applet.gif
deleted file mode 100755
index c153ddd..0000000
Binary files a/moksha/api/menus/static/images/Applet.gif and /dev/null differ
diff --git a/moksha/api/menus/static/images/DV_Tools.jpg b/moksha/api/menus/static/images/DV_Tools.jpg
deleted file mode 100755
index 45ef02b..0000000
Binary files a/moksha/api/menus/static/images/DV_Tools.jpg and /dev/null differ
diff --git a/moksha/api/menus/static/images/bgColor.gif b/moksha/api/menus/static/images/bgColor.gif
deleted file mode 100755
index 8b3dde7..0000000
Binary files a/moksha/api/menus/static/images/bgColor.gif and /dev/null differ
diff --git a/moksha/api/menus/static/images/bgnd_sel_1.jpg b/moksha/api/menus/static/images/bgnd_sel_1.jpg
deleted file mode 100644
index c510583..0000000
Binary files a/moksha/api/menus/static/images/bgnd_sel_1.jpg and /dev/null differ
diff --git a/moksha/api/menus/static/images/bgnd_sel_2.jpg b/moksha/api/menus/static/images/bgnd_sel_2.jpg
deleted file mode 100644
index facb585..0000000
Binary files a/moksha/api/menus/static/images/bgnd_sel_2.jpg and /dev/null differ
diff --git a/moksha/api/menus/static/images/bgnd_sel_3.jpg b/moksha/api/menus/static/images/bgnd_sel_3.jpg
deleted file mode 100644
index e6853cc..0000000
Binary files a/moksha/api/menus/static/images/bgnd_sel_3.jpg and /dev/null differ
diff --git a/moksha/api/menus/static/images/bgnd_sel_4.png b/moksha/api/menus/static/images/bgnd_sel_4.png
deleted file mode 100644
index 1389caa..0000000
Binary files a/moksha/api/menus/static/images/bgnd_sel_4.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/blank.gif b/moksha/api/menus/static/images/blank.gif
deleted file mode 100755
index 099c95f..0000000
Binary files a/moksha/api/menus/static/images/blank.gif and /dev/null differ
diff --git a/moksha/api/menus/static/images/browser.png b/moksha/api/menus/static/images/browser.png
deleted file mode 100755
index 4773604..0000000
Binary files a/moksha/api/menus/static/images/browser.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/buttonfind.gif b/moksha/api/menus/static/images/buttonfind.gif
deleted file mode 100755
index b79f1c2..0000000
Binary files a/moksha/api/menus/static/images/buttonfind.gif and /dev/null differ
diff --git a/moksha/api/menus/static/images/header_bgnd.jpg b/moksha/api/menus/static/images/header_bgnd.jpg
deleted file mode 100644
index 9458441..0000000
Binary files a/moksha/api/menus/static/images/header_bgnd.jpg and /dev/null differ
diff --git a/moksha/api/menus/static/images/ico_view.gif b/moksha/api/menus/static/images/ico_view.gif
deleted file mode 100755
index 4c03e3e..0000000
Binary files a/moksha/api/menus/static/images/ico_view.gif and /dev/null differ
diff --git a/moksha/api/menus/static/images/iconDone.png b/moksha/api/menus/static/images/iconDone.png
deleted file mode 100755
index 2cdddea..0000000
Binary files a/moksha/api/menus/static/images/iconDone.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/icon_13.png b/moksha/api/menus/static/images/icon_13.png
deleted file mode 100755
index 22f300d..0000000
Binary files a/moksha/api/menus/static/images/icon_13.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/icon_14.png b/moksha/api/menus/static/images/icon_14.png
deleted file mode 100755
index 981ac6b..0000000
Binary files a/moksha/api/menus/static/images/icon_14.png and /dev/null differ
diff --git a/moksha/api/menus/static/images/menuArrow.gif b/moksha/api/menus/static/images/menuArrow.gif
deleted file mode 100755
index b1b3340..0000000
Binary files a/moksha/api/menus/static/images/menuArrow.gif and /dev/null differ
diff --git a/moksha/api/menus/static/images/menuArrow_w.gif b/moksha/api/menus/static/images/menuArrow_w.gif
deleted file mode 100644
index 09919c0..0000000
Binary files a/moksha/api/menus/static/images/menuArrow_w.gif and /dev/null differ
diff --git a/moksha/api/menus/static/mbMenu.js b/moksha/api/menus/static/mbMenu.js
deleted file mode 100644
index 5d43fc0..0000000
--- a/moksha/api/menus/static/mbMenu.js
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- *         developed by Matteo Bicocchi on JQuery
- *        © 2002-2009 Open Lab srl, Matteo Bicocchi
- *			    www.open-lab.com - info at open-lab.com
- *       	version 1.5.3
- *       	tested on: 	Explorer and FireFox for PC
- *                  		FireFox and Safari for Mac Os X
- *                  		FireFox for Linux
- *         GPL (GPL-LICENSE.txt) licenses.
- */
-//document.oncontextmenu = function() { return false };
-
-// to get the element that is fireing a contextMenu event you have $.mbMenu.lastContextMenuEl that returns an object.
-(function($) {
-	$.mbMenu = {
-		actualMenuOpener:false,
-		options: {
-			template:"yourMenuVoiceTemplate",// the url that returns the menu voices via ajax. the data passed in the request is the "menu" attribute value as "menuId"
-			additionalData:"",
-			menuSelector:".menuContainer",
-			menuWidth:150,
-			openOnRight:false,
-			iconPath:"ico/",
-			hasImages:true,
-			fadeInTime:100,
-			fadeOuTime:100,
-			menuTop:0,
-			menuLeft:0,
-			submenuTop:0,
-			submenuLeft:4,
-			opacity:1,
-			shadow:false,
-			shadowColor:"black",
-			openOnClick:true,
-			closeOnMouseOut:false,
-			closeAfter:500,
-			minZindex:"auto", // or number
-			shadowOpacity:.2,
-			onContextualMenu:function(o,e){}
-		},
-		buildMenu : function (options){
-			return this.each (function ()
-			{
-				var thisMenu =this;
-				thisMenu.id = !this.id ? "menu_"+Math.floor (Math.random () * 1000): this.id;
-				this.options = {};
-
-				$.extend (this.options, $.mbMenu.options);
-				$.extend (this.options, options);
-
-				$(".menu").hide();
-				thisMenu.clicked = false;
-				thisMenu.rootMenu=false;
-				thisMenu.clearClicked=false;
-				thisMenu.actualOpenedMenu=false;
-				thisMenu.menuvoice=false;
-				var root=$(this);
-				var openOnClick=this.options.openOnClick;
-				var closeOnMouseOut=this.options.closeOnMouseOut;
-
-				//build roots
-				$(root).each(function(){
-					thisMenu.menuvoice=$(this).find("[menu]");
-					$(thisMenu.menuvoice).each(function(){
-						$(this).addClass("rootVoice");
-						$(this).attr("nowrap","nowrap");
-					});
-					var action= openOnClick?"click":"mouseover";
-					$(thisMenu.menuvoice).bind(action,function(){
-						if (!$(this).attr("isOpen")){
-							$(this).buildMbMenu(thisMenu,$(this).attr("menu"));
-						}
-						$(this).attr("isOpen","true");
-
-						//empty
-						if($(this).attr("menu")=="empty"){
-							if(thisMenu.actualOpenedMenu){
-								$(thisMenu.actualOpenedMenu).removeClass("selected");
-								thisMenu.clicked=true;
-								$(this).removeAttr("isOpen");
-								clearTimeout(thisMenu.clearClicked);
-							}
-							$(this).removeMbMenu(thisMenu);
-						}
-
-						return false;
-					});
-
-					var mouseOver=$.browser.msie?"mouseenter":"mouseover";
-					var mouseOut=$.browser.msie?"mouseleave":"mouseout";
-					$(thisMenu.menuvoice).bind(mouseOver,function(){
-						if (closeOnMouseOut) clearTimeout($.mbMenu.deleteOnMouseOut);
-						if (!openOnClick) $(thisMenu).find(".selected").removeClass("selected");
-						if(thisMenu.actualOpenedMenu){ $(thisMenu.actualOpenedMenu).removeClass("selected");}
-						$(this).addClass("selected");
-						if(thisMenu.clicked && !$(this).attr("isOpen")){
-							clearTimeout(thisMenu.clearClicked);
-							$(this).buildMbMenu(thisMenu,$(this).attr("menu"));
-						}
-					})
-					$(thisMenu.menuvoice).bind(mouseOut,function(){
-						if(!thisMenu.clicked)
-							$(this).removeClass("selected");
-						$(document).bind("click",function(){
-							$(this).removeMbMenu(thisMenu);
-						})
-					})
-				})
-			})
-		},
-		buildContextualMenu :  function (options){
-			return this.each (function ()
-			{
-				var thisMenu = this;
-				thisMenu.options = {};
-				$.extend (thisMenu.options, $.mbMenu.options);
-				$.extend (thisMenu.options, options);
-				$(".menu").hide();
-				thisMenu.clicked = false;
-				thisMenu.rootMenu=false;
-				thisMenu.clearClicked=false;
-				thisMenu.actualOpenedMenu=false;
-				thisMenu.menuvoice=false;
-				var cMenuEls= $("[cMenu]");
-				$(cMenuEls).each(function(){
-					$(this).css("-khtml-user-select","none");
-					var cm=this;
-					cm.id = !cm.id ? "menu_"+Math.floor (Math.random () * 100): cm.id;
-					$(cm).css({cursor:"default"});
-					$(cm).bind("contextmenu","mousedown",function(event){
-						$(this).blur();
-						if (event.which==3){
-							event.preventDefault();
-							event.stopPropagation();
-							event.cancelBubble=true;
-
-							//add custom behavior to contextMenuEvent passing the el and the event
-							//you can for example store to global var the obj that is fireing the event
-							//mbActualContextualMenuObj=cm;
-							$.mbMenu.lastContextMenuEl=cm;
-							thisMenu.options.onContextualMenu(this,event);
-
-							if ($.mbMenu.options.actualMenuOpener) {
-								$(thisMenu).removeMbMenu($.mbMenu.options.actualMenuOpener);
-							}
-							$(this).buildMbMenu(thisMenu,$(this).attr("cMenu"),"cm",event);
-							$(this).attr("isOpen","true");
-						}
-					})
-				})
-			})
-		}
-	}
-	$.fn.extend({
-		buildMbMenu: function(op,m,type,e){
-			var msie6=$.browser.msie && $.browser.version=="6.0";
-			var mouseOver=$.browser.msie?"mouseenter":"mouseover";
-			var mouseOut=$.browser.msie?"mouseleave":"mouseout";
-			$().bind("click",function(){$(document).removeMbMenu(op)})
-			if (e) {
-				this.mouseX=$(this).getMouseX(e);
-				this.mouseY=$(this).getMouseY(e);
-			}
-
-			if ($.mbMenu.options.actualMenuOpener && $.mbMenu.options.actualMenuOpener!=op)
-				$(op).removeMbMenu($.mbMenu.options.actualMenuOpener);
-			$.mbMenu.options.actualMenuOpener=op;
-			if(!type || type=="cm")	{
-				if (op.rootMenu) {
-					$(op.rootMenu).remove();
-					$(op.actualOpenedMenu).removeAttr("isOpen")
-				}
-				op.clicked=true;
-				op.actualOpenedMenu=this;
-				$(op.actualOpenedMenu).attr("isOpen","true")
-				$(op.actualOpenedMenu).addClass("selected");
-			}
-			var opener=this;
-			var where=(!type|| type=="cm")?$(document.body):$(this).parent().parent();
-
-			//empty
-			if($(this).attr("menu")=="empty"){
-				return;
-			}
-
-			var menuClass= op.options.menuSelector.replace(".","")
-			where.append("<div class='menuDiv'><div class='"+menuClass+"' style='display:table'></div></div>");
-			this.menu  = where.find(".menuDiv");
-			if (op.options.minZindex!="auto"){
-				$(this.menu).css({zIndex:op.options.minZindex++});
-			}else{
-				$(this.menu).mbBringToFront();
-			}
-			this.menuContainer  = $(this.menu).find(op.options.menuSelector);
-			$(this.menuContainer).bind(mouseOver,function(){
-				$(opener).addClass("selected");
-			})
-			$(this.menuContainer).css({
-				position:"absolute",
-				opacity:op.options.opacity
-			});
-			if (!$("#"+m).html()){
-				$.ajax({
-					type: "POST",
-					url: op.options.template,
-					cache: false,
-					async: false,
-					data:"menuId="+m+(op.options.additionalData!=""?"&"+op.options.additionalData:""),
-					success: function(html){
-						$("body").after(html);
-						$("#"+m).hide();
-					}
-				});
-			}
-			$(this.menuContainer).hide();
-			this.voices= $("#"+m).find("a").clone();
-
-			if (op.options.shadow) {
-				var shadow = $("<div class='menuShadow'></div>").hide();
-				if(msie6)
-					shadow = $("<iframe class='menuShadow'></iframe>").hide();
-			}
-
-			// build each voices of the menu
-			$(this.voices).each(function(i){
-
-				var voice=this;
-				var imgPlace="";
-
-				var isText=$(voice).attr("rel")=="text";
-				var isTitle=$(voice).attr("rel")=="title";
-				var isDisabled=$(voice).is("[disabled]");
-				var isSeparator=$(voice).attr("rel")=="separator";
-
-				if (op.options.hasImages && !isText){
-
-					var imgPath=$(voice).attr("img")?$(voice).attr("img"):"blank.gif";
-					imgPath=(imgPath.length>3 && imgPath.indexOf(".")>-1)?"<img class='imgLine' src='"+op.options.iconPath+imgPath+"'>":imgPath;
-					imgPlace="<td class='img'>"+imgPath+"</td>"
-				}
-				var line="<table id='"+m+"_"+i+"' class='line"+(isTitle?" title":"")+"' cellspacing='0' cellpadding='0' border='0' style='width:100%; display:table' width='100%'><tr>"+imgPlace+"<td class='voice' nowrap></td></tr></table>";
-				if(isSeparator)
-					line="<div class='separator' style='width:100%; display:inline-block'><img src='"+op.options.iconPath+"blank.gif' width='1' height='1'></div>"
-				if(isText)
-					line="<div style='width:100%; display:table' class='line' id='"+m+"_"+i+"'><div class='voice'></div></div>";
-
-				$(opener.menuContainer).append(line);
-
-				if(!isSeparator){
-					$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").append(this);
-					if($(this).attr("menu")){
-						$(opener.menuContainer).find("#"+m+"_"+i).find(".voice a").wrap("<div class='menuArrow'></div>");
-						$(opener.menuContainer).find("#"+m+"_"+i).find(".menuArrow").addClass("subMenuOpener");
-						$(opener.menuContainer).find("#"+m+"_"+i).css({cursor:"default"})
-						this.isOpener=true;
-					}
-					if(isText){
-						$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").addClass("textBox");
-						this.isOpener=true;
-					}
-					if(isDisabled){
-						$(opener.menuContainer).find("#"+m+"_"+i)
-							.addClass("disabled")
-							.css({cursor:"default"})
-					}
-
-					if(!(isText || isTitle || isDisabled)){
-						$(opener.menuContainer)
-							.find("#"+m+"_"+i)
-							.css({cursor:"pointer"})
-							.bind("mouseover",function(event){
-							clearTimeout($.mbMenu.deleteOnMouseOut);
-							$(this).addClass("selected");
-							if(opener.menuContainer.actualSubmenu && !$(voice).attr("menu")){
-								$(opener.menu).find(".menuDiv").remove();
-								$(opener.menuContainer.actualSubmenu).removeClass("selected");
-								opener.menuContainer.actualSubmenu=false;
-								//return false;
-							}
-							if ($(voice).attr("menu")){
-
-								if(opener.menuContainer.actualSubmenu && opener.menuContainer.actualSubmenu!=this){
-									$(opener.menu).find(".menuDiv").remove();
-									$(opener.menuContainer.actualSubmenu).removeClass("selected");
-									opener.menuContainer.actualSubmenu=false;
-								}
-								if (!$(voice).attr("action")) $(opener.menuContainer).find("#"+m+"_"+i).css("cursor","default")
-								if (!opener.menuContainer.actualSubmenu || opener.menuContainer.actualSubmenu!=this){
-									$(opener.menu).find(".menuDiv").remove();
-
-									opener.menuContainer.actualSubmenu=false;
-									$(this).buildMbMenu(op,$(voice).attr("menu"),"sm",event);
-									opener.menuContainer.actualSubmenu=this;
-								}
-								$(this).attr("isOpen","true")
-								return false;
-							}
-						})
-						$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOut,function(){
-							$(this).removeClass("selected");
-						})
-					}
-					if(isDisabled || isTitle){
-						$(this).removeAttr("href");
-						$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOver,function(){
-							$(document).unbind("click");
-							if(opener.menuContainer.actualSubmenu){
-								$(opener.menu).find(".menuDiv").remove();
-								opener.menuContainer.actualSubmenu=false;
-							}
-						}).css("cursor","default")
-					}
-					$(opener.menuContainer).find("#"+m+"_"+i).bind("click",function(){
-						if (($(voice).attr("action") || $(voice).attr("href")) && !isDisabled){
-							var target=$(voice).attr("target")?$(voice).attr("target"):"_self";
-							if ($(voice).attr("href") && $(voice).attr("href").indexOf("javascript:")>-1){
-								$(voice).attr("action",$(voice).attr("href").replace("javascript:",""));
-								$(voice).removeAttr("href");
-							}
-							var link=$(voice).attr("action")?$(voice).attr("action"):"window.open('"+$(voice).attr("href")+"', '"+target+"')";
-							$(voice).removeAttr("href");
-							eval(link);
-							$(this).removeMbMenu(op);
-						}else if($(voice).attr("menu"))
-							return false;
-					})
-				}
-			})
-
-			// Close on Mouseout
-
-			var closeOnMouseOut=$(op)[0].options.closeOnMouseOut;
-			if (closeOnMouseOut){
-				$(opener.menuContainer).bind("mouseenter",function(){
-					clearTimeout($.mbMenu.deleteOnMouseOut);
-				})
-				$(opener.menuContainer).bind("mouseleave",function(){
-					var menuToRemove=$.mbMenu.options.actualMenuOpener;
-					$.mbMenu.deleteOnMouseOut= setTimeout(function(){$(this).removeMbMenu(menuToRemove)},$(op)[0].options.closeAfter);
-				})
-			}
-
-
-			//positioning opened
-			var t=0,l=0
-			$(this.menuContainer).css({
-				width:op.options.menuWidth
-			})
-			if ($.browser.msie) $(this.menuContainer).css("width",$(this.menuContainer).width()+2);
-
-
-			switch(type){
-				case "sm":
-					t=$(this).position().top+op.options.submenuTop;
-
-					l=$(this).position().left+$(this).width()-op.options.submenuLeft;
-					break;
-				case "cm":
-					t=this.mouseY-5;
-					l=this.mouseX-5;
-					break;
-				default:
-					if (op.options.openOnRight){
-						t=$(this).offset().top-($.browser.msie?2:0)+op.options.menuTop;
-						l=$(this).offset().left+$(this).outerWidth()-op.options.menuLeft-($.browser.msie?2:0);
-					}else{
-						t=$(this).offset().top+$(this).outerHeight()-(!$.browser.mozilla?2:0)+op.options.menuTop;
-						l=$(this).offset().left+op.options.menuLeft;
-					}
-					break;
-			}
-
-			$(this.menu).css({
-				position:"absolute",
-				top:t,
-				left:l
-			})
-
-			if (!type || type=="cm") op.rootMenu=this.menu;
-			$(this.menuContainer).bind(mouseOut,function(){
-				$(document).bind("click",function(){$(document).removeMbMenu(op)})
-			})
-
-			if (op.options.fadeInTime>0) $(this.menuContainer).fadeIn(op.options.fadeInTime);
-			else $(this.menuContainer).show();
-
-			if (op.options.shadow) {
-				$(this.menu).prepend(shadow)
-				shadow.css({
-					width:$(this.menuContainer).outerWidth(),
-					height:$(this.menuContainer).outerHeight()-1,
-					position:'absolute',
-					backgroundColor:op.options.shadowColor,
-					border:0,
-					opacity:op.options.shadowOpacity
-				}).show();
-			}
-
-			var wh=$(window).height();
-			var ww=$(window).width();
-			var mh=$(this.menuContainer).outerHeight();
-			var mw=shadow?shadow.outerWidth():$(this.menuContainer).outerWidth();
-
-			var actualX=$(where.find(".menuDiv:first")).offset().left;
-			var actualY=$(where.find(".menuDiv:first")).offset().top;
-			switch(type){
-				case "sm":
-					if ((actualX+mw)>= ww){
-						l-=((op.options.menuWidth*2)-(op.options.submenuLeft*2))
-					}
-					break;
-				case "cm":
-					if ((actualX+(op.options.menuWidth*1.5))>= ww){
-						l-=((op.options.menuWidth*2)-(op.options.submenuLeft))
-					}
-					break;
-				default:
-					if ((actualX+mw)>= ww){
-						l-=($(this.menuContainer).offset().left+mw)-ww;
-					}
-					break;
-			}
-			if ((actualY+mh)>= wh-10){
-				t-=((actualY+mh)-wh)+30;
-			}
-
-			$(this.menu).css({
-				top:t,
-				left:l
-			})
-		},
-		removeMbMenu: function(op){
-			if(!op)op=$.mbMenu.options.actualMenuOpener;
-			if (op.rootMenu) {
-				$(op.actualOpenedMenu)
-					.removeAttr("isOpen")
-					.removeClass("selected")
-				$(op.rootMenu).fadeOut($.mbMenu.options.fadeOuTime,function(){$(this).remove()});
-				op.rootMenu=false;
-				op.clicked=false
-				$(document).unbind("click");
-			}
-		},
-
-		//mouse  Position
-		getMouseX : function (e){
-			var mouseX;
-			if ($.browser.msie)mouseX = event.clientX + document.body.scrollLeft;
-			else mouseX = e.pageX;
-			if (mouseX < 0) mouseX = 0;
-			return mouseX;
-		},
-		getMouseY : function (e){
-			var mouseY;
-			if ($.browser.msie)	mouseY = event.clientY + document.body.scrollTop;
-			else mouseY = e.pageY;
-			if (mouseY < 0)	mouseY = 0;
-			return mouseY;
-		},
-		//get max z-inedex of the page
-		mbBringToFront: function(){
-			var zi=10;
-			$('*').each(function() {
-				if($(this).css("position")=="absolute"){
-					var cur = parseInt($(this).css('zIndex'));
-					zi = cur > zi ? parseInt($(this).css('zIndex')) : zi;
-				}
-			});
-
-			$(this).css('zIndex',zi+=10);
-		}
-
-	})
-	$.fn.buildMenu = $.mbMenu.buildMenu;
-	$.fn.buildContextualMenu = $.mbMenu.buildContextualMenu;
-})(jQuery);
\ No newline at end of file
diff --git a/moksha/api/menus/static/mbMenu.min.js b/moksha/api/menus/static/mbMenu.min.js
deleted file mode 100644
index e7fd2d4..0000000
--- a/moksha/api/menus/static/mbMenu.min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function($){$.mbMenu={actualMenuOpener:false,options:{template:"yourMenuVoiceTemplate",additionalData:"",menuSelector:".menuContainer",menuWidth:150,openOnRight:false,iconPath:"ico/",hasImages:true,fadeInTime:100,fadeOuTime:100,menuTop:0,menuLeft:0,submenuTop:0,submenuLeft:4,opacity:1,shadow:false,shadowColor:"black",openOnClick:true,closeOnMouseOut:false,closeAfter:500,minZindex:"auto",shadowOpacity:0.2,onContextualMenu:function(o,e){}},buildMenu:function(options){return this.each(function(){var thisMenu=this;thisMenu.id=!this.id?"menu_"+Math.floor(Math.random()*1000):this.id;this.options={};$.extend(this.options,$.mbMenu.options);$.extend(this.options,options);$(".menu").hide();thisMenu.clicked=false;thisMenu.rootMenu=false;thisMenu.clearClicked=false;thisMenu.actualOpenedMenu=false;thisMenu.menuvoice=false;var root=$(this);var openOnClick=this.options.openOnClick;var closeOnMouseOut=this.options.closeOnMouseOut;$(root).each(function(){thisMenu.menuvoice=$(this).find("[menu]");$(thisMenu.menuvoice).each(function(){$(this).addClass("rootVoice");$(this).attr("nowrap","nowrap")});var action=openOnClick?"click":"mouseover";$(thisMenu.menuvoice).bind(action,function(){if(!$(this).attr("isOpen")){$(this).buildMbMenu(thisMenu,$(this).attr("menu"))}$(this).attr("isOpen","true");if($(this).attr("menu")=="empty"){if(thisMenu.actualOpenedMenu){$(thisMenu.actualOpenedMenu).removeClass("selected");thisMenu.clicked=true;$(this).removeAttr("isOpen");clearTimeout(thisMenu.clearClicked)}$(this).removeMbMenu(thisMenu)}return false});var mouseOver=$.browser.msie?"mouseenter":"mouseover";var mouseOut=$.browser.msie?"mouseleave":"mouseout";$(thisMenu.menuvoice).bind(mouseOver,function(){if(closeOnMouseOut){clearTimeout($.mbMenu.deleteOnMouseOut)}if(!openOnClick){$(thisMenu).find(".selected").removeClass("selected")}if(thisMenu.actualOpenedMenu){$(thisMenu.actualOpenedMenu).removeClass("selected")}$(this).addClass("selected");if(thisMenu.clicked&&!$(this).attr("isOpen")){clearTimeout(thisMenu.clearClicked);$(this).buildMbMenu(thisMenu,$(this).attr("menu"))}});$(thisMenu.menuvoice).bind(mouseOut,function(){if(!thisMenu.clicked){$(this).removeClass("selected")}$(document).bind("click",function(){$(this).removeMbMenu(thisMenu)})})})})},buildContextualMenu:function(options){return this.each(function(){var thisMenu=this;thisMenu.options={};$.extend(thisMenu.options,$.mbMenu.options);$.extend(thisMenu.options,options);$(".menu").hide();thisMenu.clicked=false;thisMenu.rootMenu=false;thisMenu.clearClicked=false;thisMenu.actualOpenedMenu=false;thisMenu.menuvoice=false;var cMenuEls=$("[cMenu]");$(cMenuEls).each(function(){$(this).css("-khtml-user-select","none");var cm=this;cm.id=!cm.id?"menu_"+Math.floor(Math.random()*100):cm.id;$(cm).css({cursor:"default"});$(cm).bind("contextmenu","mousedown",function(event){$(this).blur();if(event.which==3){event.preventDefault();event.stopPropagation();event.cancelBubble=true;$.mbMenu.lastContextMenuEl=cm;thisMenu.options.onContextualMenu(this,event);if($.mbMenu.options.actualMenuOpener){$(thisMenu).removeMbMenu($.mbMenu.options.actualMenuOpener)}$(this).buildMbMenu(thisMenu,$(this).attr("cMenu"),"cm",event);$(this).attr("isOpen","true")}})})})}};$.fn.extend({buildMbMenu:function(op,m,type,e){var msie6=$.browser.msie&&$.browser.version=="6.0";var mouseOver=$.browser.msie?"mouseenter":"mouseover";var mouseOut=$.browser.msie?"mouseleave":"mouseout";$().bind("click",function(){$(document).removeMbMenu(op)});if(e){this.mouseX=$(this).getMouseX(e);this.mouseY=$(this).getMouseY(e)}if($.mbMenu.options.actualMenuOpener&&$.mbMenu.options.actualMenuOpener!=op){$(op).removeMbMenu($.mbMenu.options.actualMenuOpener)}$.mbMenu.options.actualMenuOpener=op;if(!type||type=="cm"){if(op.rootMenu){$(op.rootMenu).remove();$(op.actualOpenedMenu).removeAttr("isOpen")}op.clicked=true;op.actualOpenedMenu=this;$(op.actualOpenedMenu).attr("isOpen","true");$(op.actualOpenedMenu).addClass("selected")}var opener=this;var where=(!type||type=="cm")?$(document.body):$(this).parent().parent();if($(this).attr("menu")=="empty"){return }var menuClass=op.options.menuSelector.replace(".","");where.append("<div class='menuDiv'><div class='"+menuClass+"' style='display:table'></div></div>");this.menu=where.find(".menuDiv");if(op.options.minZindex!="auto"){$(this.menu).css({zIndex:op.options.minZindex++})}else{$(this.menu).mbBringToFront()}this.menuContainer=$(this.menu).find(op.options.menuSelector);$(this.menuContainer).bind(mouseOver,function(){$(opener).addClass("selected")});$(this.menuContainer).css({position:"absolute",opacity:op.options.opacity});if(!$("#"+m).html()){$.ajax({type:"POST",url:op.options.template,cache:false,async:false,data:"menuId="+m+(op.options.additionalData!=""?"&"+op.options.additionalData:""),success:function(html){$("body").after(html);$("#"+m).hide()}})}$(this.menuContainer).hide();this.voices=$("#"+m).find("a").clone();if(op.options.shadow){var shadow=$("<div class='menuShadow'></div>").hide();if(msie6){shadow=$("<iframe class='menuShadow'></iframe>").hide()}}$(this.voices).each(function(i){var voice=this;var imgPlace="";var isText=$(voice).attr("rel")=="text";var isTitle=$(voice).attr("rel")=="title";var isDisabled=$(voice).is("[disabled]");var isSeparator=$(voice).attr("rel")=="separator";if(op.options.hasImages&&!isText){var imgPath=$(voice).attr("img")?$(voice).attr("img"):"blank.gif";imgPath=(imgPath.length>3&&imgPath.indexOf(".")>-1)?"<img class='imgLine' src='"+op.options.iconPath+imgPath+"'>":imgPath;imgPlace="<td class='img'>"+imgPath+"</td>"}var line="<table id='"+m+"_"+i+"' class='line"+(isTitle?" title":"")+"' cellspacing='0' cellpadding='0' border='0' style='width:100%; display:table' width='100%'><tr>"+imgPlace+"<td class='voice' nowrap></td></tr></table>";if(isSeparator){line="<div class='separator' style='width:100%; display:inline-block'><img src='"+op.options.iconPath+"blank.gif' width='1' height='1'></div>"}if(isText){line="<div style='width:100%; display:table' class='line' id='"+m+"_"+i+"'><div class='voice'></div></div>"}$(opener.menuContainer).append(line);if(!isSeparator){$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").append(this);if($(this).attr("menu")){$(opener.menuContainer).find("#"+m+"_"+i).find(".voice a").wrap("<div class='menuArrow'></div>");$(opener.menuContainer).find("#"+m+"_"+i).find(".menuArrow").addClass("subMenuOpener");$(opener.menuContainer).find("#"+m+"_"+i).css({cursor:"default"});this.isOpener=true}if(isText){$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").addClass("textBox");this.isOpener=true}if(isDisabled){$(opener.menuContainer).find("#"+m+"_"+i).addClass("disabled").css({cursor:"default"})}if(!(isText||isTitle||isDisabled)){$(opener.menuContainer).find("#"+m+"_"+i).css({cursor:"pointer"}).bind("mouseover",function(event){clearTimeout($.mbMenu.deleteOnMouseOut);$(this).addClass("selected");if(opener.menuContainer.actualSubmenu&&!$(voice).attr("menu")){$(opener.menu).find(".menuDiv").remove();$(opener.menuContainer.actualSubmenu).removeClass("selected");opener.menuContainer.actualSubmenu=false}if($(voice).attr("menu")){if(opener.menuContainer.actualSubmenu&&opener.menuContainer.actualSubmenu!=this){$(opener.menu).find(".menuDiv").remove();$(opener.menuContainer.actualSubmenu).removeClass("selected");opener.menuContainer.actualSubmenu=false}if(!$(voice).attr("action")){$(opener.menuContainer).find("#"+m+"_"+i).css("cursor","default")}if(!opener.menuContainer.actualSubmenu||opener.menuContainer.actualSubmenu!=this){$(opener.menu).find(".menuDiv").remove();opener.menuContainer.actualSubmenu=false;$(this).buildMbMenu(op,$(voice).attr("menu"),"sm",event);opener.menuContainer.actualSubmenu=this}$(this).attr("isOpen","true");return false}});$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOut,function(){$(this).removeClass("selected")})}if(isDisabled||isTitle){$(this).removeAttr("href");$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOver,function(){$(document).unbind("click");if(opener.menuContainer.actualSubmenu){$(opener.menu).find(".menuDiv").remove();opener.menuContainer.actualSubmenu=false}}).css("cursor","default")}$(opener.menuContainer).find("#"+m+"_"+i).bind("click",function(){if(($(voice).attr("action")||$(voice).attr("href"))&&!isDisabled){var target=$(voice).attr("target")?$(voice).attr("target"):"_self";if($(voice).attr("href")&&$(voice).attr("href").indexOf("javascript:")>-1){$(voice).attr("action",$(voice).attr("href").replace("javascript:",""));$(voice).removeAttr("href")}var link=$(voice).attr("action")?$(voice).attr("action"):"window.open('"+$(voice).attr("href")+"', '"+target+"')";$(voice).removeAttr("href");eval(link);$(this).removeMbMenu(op)}else{if($(voice).attr("menu")){return false}}})}});var closeOnMouseOut=$(op)[0].options.closeOnMouseOut;if(closeOnMouseOut){$(opener.menuContainer).bind("mouseenter",function(){clearTimeout($.mbMenu.deleteOnMouseOut)});$(opener.menuContainer).bind("mouseleave",function(){var menuToRemove=$.mbMenu.options.actualMenuOpener;$.mbMenu.deleteOnMouseOut=setTimeout(function(){$(this).removeMbMenu(menuToRemove)},$(op)[0].options.closeAfter)})}var t=0,l=0;$(this.menuContainer).css({width:op.options.menuWidth});if($.browser.msie){$(this.menuContainer).css("width",$(this.menuContainer).width()+2)}switch(type){case"sm":t=$(this).position().top+op.options.submenuTop;l=$(this).position().left+$(this).width()-op.options.submenuLeft;break;case"cm":t=this.mouseY-5;l=this.mouseX-5;break;default:if(op.options.openOnRight){t=$(this).offset().top-($.browser.msie?2:0)+op.options.menuTop;l=$(this).offset().left+$(this).outerWidth()-op.options.menuLeft-($.browser.msie?2:0)}else{t=$(this).offset().top+$(this).outerHeight()-(!$.browser.mozilla?2:0)+op.options.menuTop;l=$(this).offset().left+op.options.menuLeft}break}$(this.menu).css({position:"absolute",top:t,left:l});if(!type||type=="cm"){op.rootMenu=this.menu}$(this.menuContainer).bind(mouseOut,function(){$(document).bind("click",function(){$(document).removeMbMenu(op)})});if(op.options.fadeInTime>0){$(this.menuContainer).fadeIn(op.options.fadeInTime)}else{$(this.menuContainer).show()}if(op.options.shadow){$(this.menu).prepend(shadow);shadow.css({width:$(this.menuContainer).outerWidth(),height:$(this.menuContainer).outerHeight()-1,position:"absolute",backgroundColor:op.options.shadowColor,border:0,opacity:op.options.shadowOpacity}).show()}var wh=$(window).height();var ww=$(window).width();var mh=$(this.menuContainer).outerHeight();var mw=shadow?shadow.outerWidth():$(this.menuContainer).outerWidth();var actualX=$(where.find(".menuDiv:first")).offset().left;var actualY=$(where.find(".menuDiv:first")).offset().top;switch(type){case"sm":if((actualX+mw)>=ww){l-=((op.options.menuWidth*2)-(op.options.submenuLeft*2))}break;case"cm":if((actualX+(op.options.menuWidth*1.5))>=ww){l-=((op.options.menuWidth*2)-(op.options.submenuLeft))}break;default:if((actualX+mw)>=ww){l-=($(this.menuContainer).offset().left+mw)-ww}break}if((actualY+mh)>=wh-10){t-=((actualY+mh)-wh)+30}$(this.menu).css({top:t,left:l})},removeMbMenu:function(op){if(!op){op=$.mbMenu.options.actualMenuOpener}if(op.rootMenu){$(op.actualOpenedMenu).removeAttr("isOpen").removeClass("selected");$(op.rootMenu).fadeOut($.mbMenu.options.fadeOuTime,function(){$(this).remove()});op.rootMenu=false;op.clicked=false;$(document).unbind("click")}},getMouseX:function(e){var mouseX;if($.browser.msie){mouseX=event.clientX+document.body.scrollLeft}else{mouseX=e.pageX}if(mouseX<0){mouseX=0}return mouseX},getMouseY:function(e){var mouseY;if($.browser.msie){mouseY=event.clientY+document.body.scrollTop}else{mouseY=e.pageY}if(mouseY<0){mouseY=0}return mouseY},mbBringToFront:function(){var zi=10;$("*").each(function(){if($(this).css("position")=="absolute"){var cur=parseInt($(this).css("zIndex"));zi=cur>zi?parseInt($(this).css("zIndex")):zi}});$(this).css("zIndex",zi+=10)}});$.fn.buildMenu=$.mbMenu.buildMenu;$.fn.buildContextualMenu=$.mbMenu.buildContextualMenu})(jQuery);
diff --git a/moksha/api/menus/static/styleswitch.js b/moksha/api/menus/static/styleswitch.js
deleted file mode 100644
index 156ac78..0000000
--- a/moksha/api/menus/static/styleswitch.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
-* Styleswitch stylesheet switcher built on jQuery
-* Under an Attribution, Share Alike License
-* By Kelvin Luck ( http://www.kelvinluck.com/ )
-**/
-
-$(document).ready(function() {
-	$('.styleswitch').click(function()
-	{
-		switchStylestyle(this.getAttribute("rel"));
-		return false;
-	});
-	var c = readCookie('style');
-	if (c) switchStylestyle(c);
-});
-
-function switchStylestyle(styleName)
-{
-	$(document).find("@rel*=style][title]").each(function(i)
-	{
-		this.disabled = true;
-		if (this.getAttribute('title') == styleName) this.disabled = false;
-	});
-	createCookie('style', styleName, 365);
-}
-
-// cookie functions http://www.quirksmode.org/js/cookies.html
-function createCookie(name,value,days)
-{
-	if (days)
-	{
-		var date = new Date();
-		date.setTime(date.getTime()+(days*24*60*60*1000));
-		var expires = "; expires="+date.toGMTString();
-	}
-	else var expires = "";
-	document.cookie = name+"="+value+expires+"; path=/";
-}
-function readCookie(name)
-{
-	var nameEQ = name + "=";
-	var ca = document.cookie.split(';');
-	for(var i=0;i < ca.length;i++)
-	{
-		var c = ca[i];
-		while (c.charAt(0)==' ') c = c.substring(1,c.length);
-		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
-	}
-	return null;
-}
-function eraseCookie(name)
-{
-	createCookie(name,"",-1);
-}
-// /cookie functions
\ No newline at end of file
diff --git a/moksha/api/menus/templates/mbmenu.mak b/moksha/api/menus/templates/mbmenu.mak
deleted file mode 100644
index e9f4a95..0000000
--- a/moksha/api/menus/templates/mbmenu.mak
+++ /dev/null
@@ -1,19 +0,0 @@
-<table  border="0" cellpadding="0" cellspacing="0" bgcolor="#EDEDED">
-    <tr>
-        <td valign="bottom">
-            <table  border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" class="container">
-                <tr>
-                    <td class="${id}" align="right">
-
-                        <table class="${rootMenuSelector}" cellspacing='0' cellpadding='0' border='0'><tr>
-                            % for menu_id, menu in menus:
-                                <td menu="${id}_${menu_id}">${menu}</td>
-                            % endfor
-                        </tr></table>
-                    </td>
-                </tr>
-            </table>
-        </td>
-    </tr>
-</table>
-
diff --git a/moksha/api/menus/widgets.py b/moksha/api/menus/widgets.py
deleted file mode 100644
index be4f04c..0000000
--- a/moksha/api/menus/widgets.py
+++ /dev/null
@@ -1,144 +0,0 @@
-## -*- coding: utf-8 -*-
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""
-:mod:`moksha.api.menus.widgets` - Moksha Menu Widgets
-=====================================================
-
-This is a powerful component to build easily a multilevel tree menu or a
-contextual menu (right click) in an intuitive way.
-
-This module contains ToscaWidgets for the `mbMenu jQuery Plugin
-<http://plugins.jquery.com/project/mbMenu>`_, which was developed by Matteo
-Bicocchi. © 2002-2008 Open Lab srl, Matteo Bicocchi. GPL licensed.
-
-.. moduleauthor:: Luke Macken <lmacken at redhat.com>
-"""
-
-from tw.api import JSLink, Widget, CSSLink, js_function, js_callback
-from tw.jquery import jquery_js, jQuery
-
-modname = __name__
-
-jquery_mbmenu_js = JSLink(modname=modname,
-                          filename='static/mbMenu.js',
-                          javascript=[jquery_js])
-
-jquery_mbmenu_min_js = JSLink(modname=modname,
-                              filename='static/mbMenu.min.js',
-                              javascript=[jquery_js])
-
-
-class MokshaMenuBase(Widget):
-    template = "mako:moksha.api.menus.templates.mbmenu"
-    javascript = [jquery_mbmenu_min_js]
-    css = [CSSLink(modname=modname, filename='static/css/menu1.css',
-                   media='screen')]
-    params = ['callback', 'rootMenuSelector', 'menuSelector', 'id', 'menus',
-              'additionalData', 'iconPath', 'menuWidth', 'openOnRight',
-              'hasImages', 'fadeTime', 'adjustLeft', 'adjustTop', 'opacity',
-              'shadow', 'fadeInTime', 'fadeOutTime', 'overflow', 'effect',
-              'minZindex']
-
-    rootMenuSelector = 'rootVoices'
-    menuSelector = 'menuContainer'
-    callback = '/apps/menu'
-    iconPath = '/toscawidgets/resources/moksha.api.menus.widgets/static/images/'
-    additionalData = ""
-    menus = []
-    menuWidth = 200
-    openOnRight =  False
-    hasImages = True
-    fadeTime = 200
-    fadeInTime = 100
-    fadeOutTime = 100
-    adjustLeft = 2
-    adjustTop = 10
-    opacity = 0.95
-    shadow = True
-    overflow = 2
-    effect = 'fade'
-    minZindex = 'auto'
-
-
-class MokshaMenu(MokshaMenuBase):
-
-    def update_params(self, d):
-        super(MokshaMenu, self).update_params(d)
-
-        if not d.id:
-            raise Exception("MokshaMenu must have an id!")
-        if not d.callback:
-            raise Exception("Must provide a callback URL!")
-
-        menus = []
-        for menu in d.menus:
-            menus.append((menu.lower().replace(' ', ''), menu))
-        d.menus = menus
-
-        self.add_call(jQuery('.%s' % d.id).buildMenu({
-                'template': d.callback,
-                'additionalData': d.additionalData,
-                'menuWidth': d.menuWidth,
-                'openOnRight': d.openOnRight,
-                'rootMenuSelector': ".%s" % d.rootMenuSelector,
-                'menuSelector': ".%s" % d.menuSelector,
-                'iconPath': d.iconPath,
-                'hasImages': d.hasImages,
-                'fadeTime': d.fadeTime,
-                'fadeInTime': d.fadeInTime,
-                'fadeOutTime': d.fadeOutTime,
-                'adjustLeft': d.adjustLeft,
-                'adjustTop': d.adjustTop,
-                'opacity': d.opacity,
-                'shadow': d.shadow,
-                'minZindex': d.minZindex,
-                }))
-
-
-class MokshaContextualMenu(MokshaMenuBase):
-
-    def update_params(self, d):
-        super(MokshaContextualMenu, self).update_params(d)
-
-        if not d.id:
-            raise Exception("MokshaMenu must have an id!")
-        if not d.callback:
-            raise Exception("Must provide a callback URL!")
-
-        menus = []
-        for menu in d.menus:
-            menus.append((menu.lower().replace(' ', ''), menu))
-        d.menus = menus
-
-        self.add_call(jQuery(js_callback('document')).buildContextualMenu({
-                'template': d.callback,
-                'menuWidth': d.menuWidth,
-                'rootMenuSelector': ".%s" % d.rootMenuSelector,
-                'menuSelector': ".%s" % d.menuSelector,
-                'iconPath': d.iconPath,
-                'hasImages': d.hasImages,
-                'fadeTime': d.fadeTime,
-                'fadeInTime': d.fadeInTime,
-                'fadeOutTime': d.fadeOutTime,
-                'adjustLeft': d.adjustLeft,
-                'adjustTop': d.adjustTop,
-                'opacity': d.opacity,
-                'shadow': d.shadow,
-                'effect': d.effect,
-                'minZindex': d.minZindex
-                }))
diff --git a/moksha/apps/menus/MANIFEST.in b/moksha/apps/menus/MANIFEST.in
new file mode 100644
index 0000000..5121d7c
--- /dev/null
+++ b/moksha/apps/menus/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include moksha *.mak *.html *.js *.png *.gif *.css *.jpg *.jpeg
diff --git a/moksha/apps/menus/moksha-menus.spec b/moksha/apps/menus/moksha-menus.spec
new file mode 100644
index 0000000..aa0dfbc
--- /dev/null
+++ b/moksha/apps/menus/moksha-menus.spec
@@ -0,0 +1,55 @@
+%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%{!?pyver: %define pyver %(%{__python} -c "import sys ; print sys.version[:3]")}
+
+%global modname moksha.menus
+
+Name:           moksha-menus
+Version:        0.1
+Release:        1%{?dist}
+Summary:        A dynamic menu API for Moksha
+Group:          Applications/Internet
+License:        AGPLv3
+URL:            https://fedorahosted.org/moksha
+Source0:        moksha.menus-%{version}.tar.gz
+
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildArch:      noarch
+
+BuildRequires: python-setuptools-devel
+BuildRequires: python-paver
+
+Requires: moksha
+
+%description
+TODO
+
+%prep
+%setup -q -n moksha.menus-%{version}
+
+%build
+paver bdist_egg
+
+%install
+%{__rm} -rf %{buildroot}
+%{__mkdir} -p %{buildroot}%{python_sitelib}
+PYTHONPATH=%{buildroot}%{python_sitelib} easy_install \
+    --prefix %{buildroot}%{_usr} --no-deps --always-unzip \
+    dist/*.egg
+
+# TODO: see if this is absolutely necessar!
+%{__rm} %{buildroot}%{python_sitelib}/easy-install.pth
+
+%{__rm} %{buildroot}%{python_sitelib}/site.py{,c}
+
+%clean
+%{__rm} -rf %{buildroot}
+
+
+%files 
+%defattr(-,root,root,-)
+#%doc README AUTHORS LICENSE COPYING
+%{python_sitelib}/%{modname}-%{version}-py%{pyver}.egg/
+
+%changelog
+* Thu Aug 06 2009 Luke Macken <lmacken at redhat.com> - 0.1-1
+- Initial package
diff --git a/moksha/apps/menus/moksha/__init__.py b/moksha/apps/menus/moksha/__init__.py
index e69de29..de40ea7 100644
--- a/moksha/apps/menus/moksha/__init__.py
+++ b/moksha/apps/menus/moksha/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/moksha/apps/menus/moksha/apps/menus/__init__.py b/moksha/apps/menus/moksha/apps/menus/__init__.py
new file mode 100644
index 0000000..3e1f6d1
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/__init__.py
@@ -0,0 +1,18 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from widgets import *
+from default import *
diff --git a/moksha/apps/menus/moksha/apps/menus/controllers/__init__.py b/moksha/apps/menus/moksha/apps/menus/controllers/__init__.py
new file mode 100644
index 0000000..2d5c4cd
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/controllers/__init__.py
@@ -0,0 +1,17 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from menu import *
diff --git a/moksha/apps/menus/moksha/apps/menus/controllers/menu.py b/moksha/apps/menus/moksha/apps/menus/controllers/menu.py
new file mode 100644
index 0000000..6c68758
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/controllers/menu.py
@@ -0,0 +1,43 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import moksha
+
+from tg import expose
+from moksha.lib.base import Controller
+
+class MokshaMenuController(Controller):
+    name = 'Moksha Menus'
+
+    @expose()
+    def default(self, menuId, *args, **kw):
+        """ For the selected `menuId`, return the menu HTML.
+
+        The `menuId` is the name of the portion of the menu that was clicked
+        on.  For example, if the menu name was 'default_menu', and the first
+        section was called 'Help', then the menuId would be 'default_menu_help'.
+        This controller will then call the help() method on the
+        MokshaModel.
+        """
+        split = menuId.lower().split('_')
+        menu_id = '_'.join(split[:-1])
+        menu_item = split[-1]
+        menu = getattr(moksha.menus[menu_id], menu_item)(**kw)
+        return """
+            <div id="%(menuId)s" class="menu">
+                %(menu)s
+            </div>
+        """ % {'menuId': menuId, 'menu': menu}
diff --git a/moksha/apps/menus/moksha/apps/menus/default.py b/moksha/apps/menus/moksha/apps/menus/default.py
new file mode 100644
index 0000000..5c19a62
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/default.py
@@ -0,0 +1,104 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+:mod:`moksha.apps.menus.default` - The default Moksha Menu
+=========================================================
+The default Moksha menu is an example Menu that lists
+the installed Applications, Widgets, etc.
+
+.. moduleauthor:: Luke Macken <lmacken at redhat.com>
+"""
+
+import moksha
+from moksha.apps.menus import MokshaMenu, MokshaContextualMenu
+
+class MokshaContextMenu(MokshaContextualMenu):
+
+    def default(self, *args, **kw):
+        return """
+            <a rel="text">
+                <img src="/images/moksha-icon.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/><br/>
+            </a>
+            <a href="/widget">Documentation</a>
+            <a href="https://fedorahosted.org/moksha/report/3">Tickets</a>
+            <a href="https://fedorahosted.org/moksha/">Wiki</a>
+            <a menu="moksha">Moksha</a>
+        """
+
+class MokshaDefaultMenu(MokshaMenu):
+    menus = ['Moksha', 'Widgets', 'Fedora']
+
+    def widgets(self, *args, **kw):
+        menu = """
+        <a rel="text">
+            <img src="/images/block.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/>
+            <br/>
+        </a>
+        """
+        for id, widget in moksha._widgets.iteritems():
+            if not getattr(widget['widget'], 'hidden', False):
+                menu += """
+                      <a href="#" onclick="$('#footer')
+                            .append($('<div/>')
+                            .attr('id', '%(id)s_loader')); 
+                            $.ajax({
+                                url: moksha.url('/widgets/%(id)s?chrome=True'),
+                                success: function(r, s) {
+                                    var $panel = $('#%(id)s_loader');
+                                    var $stripped = moksha.filter_resources(r);
+                                    $panel.html($stripped);
+                                }
+                            });
+                            return false;">%(name)s</a>
+
+                """ % {'name': widget['name'], 'id': id}
+        return menu
+
+    def moksha(self, *args, **kw):
+        return """
+        <a rel="text">
+            <img src="/images/moksha-icon.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/><br>
+            <br>Moksha is a platform for creating live collaborative web applications.<br><br>
+        </a>
+        <a rel="separator"></a>
+        <a href="/apps/docs/">Documentation</a>
+        <a href="https://fedorahosted.org/moksha/report/3">Tickets</a>
+        <a href="https://fedorahosted.org/moksha/">Wiki</a>
+        """
+
+    def fedora(self, *args, **kw):
+        links = {
+                'Wiki': 'http://fedoraproject.org/wiki',
+                'Hosted': 'http://fedorahosted.org',
+                'Bugzilla': 'http://bugzilla.redhat.com',
+                'Elections': 'https://admin.fedoraproject.org/voting',
+                'Translations': 'http://translate.fedoraproject.org',
+                'Build System': 'http://koji.fedoraproject.org',
+                'Update System': 'http://bodhi.fedoraproject.org',
+                'Package Database': 'http://admin.fedoraproject.org/pkgdb',
+                'Account System': 'http://admin.fedoraproject.org/accounts',
+                'Hardware Database': 'http://smolts.org',
+        }
+        menu = """
+            <a rel="text">
+                <img src="/images/fedora-icon.png" style="position:absolute;margin-top:-20px; margin-left:-25px;margin-bottom:10px"/><br>
+            </a>
+            <a rel="separator"></a>
+        """
+        for title, url in links.items():
+            menu += '<a href="%s" target="_blank">%s</a>' % (url, title)
+        return menu
diff --git a/moksha/apps/menus/moksha/apps/menus/static/GPL-LICENSE.txt b/moksha/apps/menus/moksha/apps/menus/static/GPL-LICENSE.txt
new file mode 100755
index 0000000..9266bbc
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/static/GPL-LICENSE.txt
@@ -0,0 +1,279 @@
+        GNU GENERAL PUBLIC LICENSE
+           Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Open Lab srl.
+ via Venezia 18b - 50121 Firenze, Italia
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+        GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+          NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/moksha/apps/menus/moksha/apps/menus/static/css/menu.css b/moksha/apps/menus/moksha/apps/menus/static/css/menu.css
new file mode 100644
index 0000000..2ee9963
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/static/css/menu.css
@@ -0,0 +1,195 @@
+.rootVoices{
+	background-color:#f3f3f3;
+	padding:5px;
+    padding-bottom:0;
+}
+.rootVoices td.rootvoice {
+	background-color:transparent;
+	width:120px;
+	height:32px;
+    font-family:Arial,Helvetica,sans-serif;
+	color: gray;
+	font-size:12px;
+	padding:8px;
+    padding-left:10px;
+	cursor: pointer;
+}
+.rootVoices td.selected{
+	background-color:gray;
+	color:#ffffff;
+	cursor: pointer;
+	font-size:14px;
+}
+
+.menuShadow{
+    padding:2px;
+    padding-bottom:0px;
+    left:-2;
+    top:1px;
+}
+
+.menuContainer{
+	background-color:gray;
+}
+
+.menuContainer .line{
+	background-color:white;
+	width:100%;
+	padding-left:-5;
+}
+
+.menuContainer .line.title {
+    text-align:right;
+}
+
+.menuContainer .line.title a{
+    color:dimgray;
+    font-size:14px;
+}
+
+.menuContainer td a{
+	text-decoration:none;
+	color: #000000;
+}
+
+.menuContainer td.voice{
+	border-top:1px solid #f3f3f3;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+	padding:5px;
+}
+
+.menuContainer .separator{
+	background-color:#f1f1f1;
+	height:1px;
+}
+.menuContainer td.img{
+    border-top:1px solid #f3f3f3;
+	font-family:Arial,Helvetica,sans-serif;
+	text-align:center;
+	font-size:12px;
+	color: #c3c3c3;
+	background-color:#f9f9f9;
+	width:24px;
+	padding:5px;
+}
+.menuContainer td.img img{
+	width:20px;
+}
+.menuContainer .textBox{
+	padding: 5px;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+	background-color:#ffffff;
+	color: #c3c3c3;
+}
+.menuContainer .selected td{
+	background-color:#f3f3f3;
+    background-image:url("../images/bgnd_sel_2.jpg")
+}
+.menuContainer .selected td a{
+	color:#000;
+}
+.menuContainer .disabled td, .menuContainer .disabled td a {
+	color: #cccccc;
+}
+.menuContainer .subMenuOpener{
+	background-image:url("../images/menuArrow.gif");
+	background-repeat:no-repeat;
+	background-position:right;
+}
+
+/*
+vertical menu
+*/
+
+
+/**/
+
+.rootVerticalVoices{
+	background-color:#333;
+	padding:0px;
+}
+.rootVerticalVoices td.rootvoice {
+    /*border-top:1px solid #666;*/
+	width:130px;
+	font-family:Arial,Helvetica,sans-serif;
+	color: gray;
+	font-size:13px;
+	padding:7px;
+	cursor: pointer;
+}
+.rootVerticalVoices td.selected{
+    background-image:url("../images/bgnd_sel_4.png");
+	color:#ffffff;
+	cursor: pointer;
+}
+
+
+.verticalMenu{
+	background-color:#000;
+/*
+The menu container style must be set via the options paramiter
+within the function call due to a Safari bug interpreting css on the fly...
+*/
+}
+.verticalMenu .line{
+	background-color:#333;
+	width:100%;
+	padding-left:-5px;
+}
+.verticalMenu td a{
+	text-decoration:none;
+	color: #d3d3d3;
+}
+.verticalMenu td.voice{
+	border-top:0px solid #666;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+	padding:5px;
+}
+.verticalMenu .separator{
+	background-color:#666;
+	height:1px;
+}
+.verticalMenu td.img{
+    border-top:0px solid #666;
+	font-family:Arial,Helvetica,sans-serif;
+	text-align:center;
+	font-size:12px;
+	color: #c3c3c3;
+	background-color:#333;
+	width:24px;
+	padding:5px;
+}
+.verticalMenu td.img img{
+	width:20px;
+}
+.verticalMenu .textBox{
+	padding: 10px;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+	color: #c3c3c3;
+}
+.verticalMenu .selected td{
+    background-image:url("../images/bgnd_sel_4.png");
+}
+.verticalMenu .selected td a{
+	color:#fff;
+}
+.verticalMenu .disabled td, .verticalMenu .disabled td a {
+	color: #666;
+}
+
+
+.verticalMenu .subMenuOpener{
+	background-image:url("../images/menuArrow_w.gif");
+	background-repeat:no-repeat;
+	background-position:right;
+}
+
+.verticalMenu .menuShadow{
+	background:black;
+    padding:5px;
+}
+
diff --git a/moksha/apps/menus/moksha/apps/menus/static/css/menu1.css b/moksha/apps/menus/moksha/apps/menus/static/css/menu1.css
new file mode 100644
index 0000000..22e495d
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/static/css/menu1.css
@@ -0,0 +1,198 @@
+.rootVoices{
+	background-color:#f3f3f3;
+	padding:5px;
+	padding-bottom:0;
+}
+.rootVoices td.rootVoice {
+	background-color:transparent;
+	width:120px;
+	height:32px;
+	font-family:Arial,Helvetica,sans-serif;
+	color: gray;
+	font-size:12px;
+	padding:8px;
+	padding-left:10px;
+	cursor: pointer;
+	-moz-border-radius:8px 8px 0 0;
+	-webkit-border-top-right-radius:8px;
+	-webkit-border-top-left-radius:8px;
+}
+.rootVoices.vertical td.rootVoice{
+	-moz-border-radius:8px 0px 0 8px;
+	-webkit-border-top-right-radius:0px;
+	-webkit-border-top-left-radius:8px;
+	-webkit-border-bottom-right-radius:0px;
+	-webkit-border-bottom-left-radius:8px;
+
+}
+.rootVoices td.selected{
+	background:orangered url("../images/bgnd_sel_4.png");
+	color:#ffffff;
+	cursor: pointer;
+	font-size:14px;
+}
+
+.menuShadow{
+	padding:2px;
+	padding-bottom:0px;
+	left:-2;
+	top:1px;
+}
+
+/**/
+
+.menuContainer{
+	background-color:gray;
+	padding:0;
+}
+.menuContainer .line{
+	background-color:transparent;
+	width:100%;
+}
+.menuContainer .line.title {
+	background-color:#B23305;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:14px;
+	border-bottom:1px solid darkred;
+}
+.menuContainer .line.title a{
+	font-size:14px;
+}
+.menuContainer td a{
+	text-decoration:none;
+	color: #f3f3f3;
+}
+.menuContainer td.voice{
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+	padding:7px;
+}
+.menuContainer td.voice a{
+	display:block;
+	width:100%;
+}
+
+.menuContainer .separator{
+	background-color:#999;
+	height:5px;
+}
+.menuContainer td.img{
+	font-family:Arial,Helvetica,sans-serif;
+	text-align:center;
+	font-size:12px;
+	color: #c3c3c3;
+	background-color:transparent;
+	width:24px;
+	padding:5px;
+}
+.menuContainer td.img img{
+	width:20px;
+}
+.menuContainer .textBox{
+	padding: 10px;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+/*	background:dimgray url("../images/header_bgnd.jpg");
+ */
+	color: #c3c3c3;
+}
+.menuContainer .selected td{
+	background-color:#f3f3f3;
+	background-image:url("../images/bgnd_sel_2.jpg")
+}
+.menuContainer .selected td a{
+	color:#000;
+}
+.menuContainer .disabled td, .menuContainer .disabled td a {
+	color: #cccccc;
+}
+.menuContainer .subMenuOpener{
+	background-image:url("../images/menuArrow_w.gif");
+	background-repeat:no-repeat;
+	background-position:right;
+}
+.menuContainer .selected .subMenuOpener{
+	background-image:url("../images/menuArrow.gif");
+	background-repeat:no-repeat;
+	background-position:right;
+}
+
+/*
+vertical menu
+*/
+
+.rootVerticalVoices{
+	background-color:#fff;
+	padding:0px;
+}
+.rootVerticalVoices td.rootVoice {
+	width:120px;
+	font-family:Arial,Helvetica,sans-serif;
+	color: #000;
+	font-size:13px;
+	padding:7px;
+	cursor: pointer;
+}
+.rootVerticalVoices td.selected{
+	background:lightslategray url("../images/bgnd_sel_4.png");
+	color:#ffffff;
+	cursor: pointer;
+}
+
+.verticalMenu{
+	background-color:lightslategray;
+}
+.verticalMenu .line{
+	background-color:lightslategray;
+	width:100%;
+	padding-left:-5px;
+}
+.verticalMenu td a{
+	text-decoration:none;
+	color: #f3f3f3;
+}
+.verticalMenu td.voice{
+	border-bottom:1px solid slategray;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+	padding:5px;
+}
+.verticalMenu .separator{
+	background-color:dimgray;
+	height:1px;
+}
+.verticalMenu td.img{
+	border-bottom:1px solid slategray;
+	font-family:Arial,Helvetica,sans-serif;
+	text-align:center;
+	font-size:12px;
+	color: #c3c3c3;
+	width:24px;
+	padding:5px;
+}
+.verticalMenu td.img img{
+	width:20px;
+}
+.verticalMenu .textBox{
+	padding: 5px;
+	font-family:Arial,Helvetica,sans-serif;
+	font-size:12px;
+	background:transparent;
+	color: #fff;
+}
+.verticalMenu .selected td{
+	background-image:url("../images/bgnd_sel_4.png")
+}
+.verticalMenu .selected td a{
+	color:#fff;
+}
+.verticalMenu .disabled td, .verticalMenu .disabled td a {
+	color:lightsteelblue;
+}
+
+
+.verticalMenu .subMenuOpener{
+	background-image:url("../images/menuArrow_w.gif");
+	background-repeat:no-repeat;
+	background-position:right;
+}
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/0682.gif b/moksha/apps/menus/moksha/apps/menus/static/images/0682.gif
new file mode 100755
index 0000000..b01c8d0
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/0682.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/16-member-remove.png b/moksha/apps/menus/moksha/apps/menus/static/images/16-member-remove.png
new file mode 100755
index 0000000..efcfdda
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/16-member-remove.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/24-book-blue-check.png b/moksha/apps/menus/moksha/apps/menus/static/images/24-book-blue-check.png
new file mode 100755
index 0000000..c19ca9a
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/24-book-blue-check.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/24-image-add.png b/moksha/apps/menus/moksha/apps/menus/static/images/24-image-add.png
new file mode 100755
index 0000000..9c65780
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/24-image-add.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/24-tag-add.png b/moksha/apps/menus/moksha/apps/menus/static/images/24-tag-add.png
new file mode 100755
index 0000000..1dcffb6
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/24-tag-add.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/Applet.gif b/moksha/apps/menus/moksha/apps/menus/static/images/Applet.gif
new file mode 100755
index 0000000..c153ddd
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/Applet.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/DV_Tools.jpg b/moksha/apps/menus/moksha/apps/menus/static/images/DV_Tools.jpg
new file mode 100755
index 0000000..45ef02b
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/DV_Tools.jpg differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/bgColor.gif b/moksha/apps/menus/moksha/apps/menus/static/images/bgColor.gif
new file mode 100755
index 0000000..8b3dde7
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/bgColor.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_1.jpg b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_1.jpg
new file mode 100644
index 0000000..c510583
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_1.jpg differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_2.jpg b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_2.jpg
new file mode 100644
index 0000000..facb585
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_2.jpg differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_3.jpg b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_3.jpg
new file mode 100644
index 0000000..e6853cc
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_3.jpg differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_4.png b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_4.png
new file mode 100644
index 0000000..1389caa
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/bgnd_sel_4.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/blank.gif b/moksha/apps/menus/moksha/apps/menus/static/images/blank.gif
new file mode 100755
index 0000000..099c95f
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/blank.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/browser.png b/moksha/apps/menus/moksha/apps/menus/static/images/browser.png
new file mode 100755
index 0000000..4773604
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/browser.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/buttonfind.gif b/moksha/apps/menus/moksha/apps/menus/static/images/buttonfind.gif
new file mode 100755
index 0000000..b79f1c2
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/buttonfind.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/header_bgnd.jpg b/moksha/apps/menus/moksha/apps/menus/static/images/header_bgnd.jpg
new file mode 100644
index 0000000..9458441
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/header_bgnd.jpg differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/ico_view.gif b/moksha/apps/menus/moksha/apps/menus/static/images/ico_view.gif
new file mode 100755
index 0000000..4c03e3e
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/ico_view.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/iconDone.png b/moksha/apps/menus/moksha/apps/menus/static/images/iconDone.png
new file mode 100755
index 0000000..2cdddea
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/iconDone.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/icon_13.png b/moksha/apps/menus/moksha/apps/menus/static/images/icon_13.png
new file mode 100755
index 0000000..22f300d
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/icon_13.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/icon_14.png b/moksha/apps/menus/moksha/apps/menus/static/images/icon_14.png
new file mode 100755
index 0000000..981ac6b
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/icon_14.png differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/menuArrow.gif b/moksha/apps/menus/moksha/apps/menus/static/images/menuArrow.gif
new file mode 100755
index 0000000..b1b3340
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/menuArrow.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/images/menuArrow_w.gif b/moksha/apps/menus/moksha/apps/menus/static/images/menuArrow_w.gif
new file mode 100644
index 0000000..09919c0
Binary files /dev/null and b/moksha/apps/menus/moksha/apps/menus/static/images/menuArrow_w.gif differ
diff --git a/moksha/apps/menus/moksha/apps/menus/static/mbMenu.js b/moksha/apps/menus/moksha/apps/menus/static/mbMenu.js
new file mode 100644
index 0000000..5d43fc0
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/static/mbMenu.js
@@ -0,0 +1,476 @@
+/*
+ *         developed by Matteo Bicocchi on JQuery
+ *        © 2002-2009 Open Lab srl, Matteo Bicocchi
+ *			    www.open-lab.com - info at open-lab.com
+ *       	version 1.5.3
+ *       	tested on: 	Explorer and FireFox for PC
+ *                  		FireFox and Safari for Mac Os X
+ *                  		FireFox for Linux
+ *         GPL (GPL-LICENSE.txt) licenses.
+ */
+//document.oncontextmenu = function() { return false };
+
+// to get the element that is fireing a contextMenu event you have $.mbMenu.lastContextMenuEl that returns an object.
+(function($) {
+	$.mbMenu = {
+		actualMenuOpener:false,
+		options: {
+			template:"yourMenuVoiceTemplate",// the url that returns the menu voices via ajax. the data passed in the request is the "menu" attribute value as "menuId"
+			additionalData:"",
+			menuSelector:".menuContainer",
+			menuWidth:150,
+			openOnRight:false,
+			iconPath:"ico/",
+			hasImages:true,
+			fadeInTime:100,
+			fadeOuTime:100,
+			menuTop:0,
+			menuLeft:0,
+			submenuTop:0,
+			submenuLeft:4,
+			opacity:1,
+			shadow:false,
+			shadowColor:"black",
+			openOnClick:true,
+			closeOnMouseOut:false,
+			closeAfter:500,
+			minZindex:"auto", // or number
+			shadowOpacity:.2,
+			onContextualMenu:function(o,e){}
+		},
+		buildMenu : function (options){
+			return this.each (function ()
+			{
+				var thisMenu =this;
+				thisMenu.id = !this.id ? "menu_"+Math.floor (Math.random () * 1000): this.id;
+				this.options = {};
+
+				$.extend (this.options, $.mbMenu.options);
+				$.extend (this.options, options);
+
+				$(".menu").hide();
+				thisMenu.clicked = false;
+				thisMenu.rootMenu=false;
+				thisMenu.clearClicked=false;
+				thisMenu.actualOpenedMenu=false;
+				thisMenu.menuvoice=false;
+				var root=$(this);
+				var openOnClick=this.options.openOnClick;
+				var closeOnMouseOut=this.options.closeOnMouseOut;
+
+				//build roots
+				$(root).each(function(){
+					thisMenu.menuvoice=$(this).find("[menu]");
+					$(thisMenu.menuvoice).each(function(){
+						$(this).addClass("rootVoice");
+						$(this).attr("nowrap","nowrap");
+					});
+					var action= openOnClick?"click":"mouseover";
+					$(thisMenu.menuvoice).bind(action,function(){
+						if (!$(this).attr("isOpen")){
+							$(this).buildMbMenu(thisMenu,$(this).attr("menu"));
+						}
+						$(this).attr("isOpen","true");
+
+						//empty
+						if($(this).attr("menu")=="empty"){
+							if(thisMenu.actualOpenedMenu){
+								$(thisMenu.actualOpenedMenu).removeClass("selected");
+								thisMenu.clicked=true;
+								$(this).removeAttr("isOpen");
+								clearTimeout(thisMenu.clearClicked);
+							}
+							$(this).removeMbMenu(thisMenu);
+						}
+
+						return false;
+					});
+
+					var mouseOver=$.browser.msie?"mouseenter":"mouseover";
+					var mouseOut=$.browser.msie?"mouseleave":"mouseout";
+					$(thisMenu.menuvoice).bind(mouseOver,function(){
+						if (closeOnMouseOut) clearTimeout($.mbMenu.deleteOnMouseOut);
+						if (!openOnClick) $(thisMenu).find(".selected").removeClass("selected");
+						if(thisMenu.actualOpenedMenu){ $(thisMenu.actualOpenedMenu).removeClass("selected");}
+						$(this).addClass("selected");
+						if(thisMenu.clicked && !$(this).attr("isOpen")){
+							clearTimeout(thisMenu.clearClicked);
+							$(this).buildMbMenu(thisMenu,$(this).attr("menu"));
+						}
+					})
+					$(thisMenu.menuvoice).bind(mouseOut,function(){
+						if(!thisMenu.clicked)
+							$(this).removeClass("selected");
+						$(document).bind("click",function(){
+							$(this).removeMbMenu(thisMenu);
+						})
+					})
+				})
+			})
+		},
+		buildContextualMenu :  function (options){
+			return this.each (function ()
+			{
+				var thisMenu = this;
+				thisMenu.options = {};
+				$.extend (thisMenu.options, $.mbMenu.options);
+				$.extend (thisMenu.options, options);
+				$(".menu").hide();
+				thisMenu.clicked = false;
+				thisMenu.rootMenu=false;
+				thisMenu.clearClicked=false;
+				thisMenu.actualOpenedMenu=false;
+				thisMenu.menuvoice=false;
+				var cMenuEls= $("[cMenu]");
+				$(cMenuEls).each(function(){
+					$(this).css("-khtml-user-select","none");
+					var cm=this;
+					cm.id = !cm.id ? "menu_"+Math.floor (Math.random () * 100): cm.id;
+					$(cm).css({cursor:"default"});
+					$(cm).bind("contextmenu","mousedown",function(event){
+						$(this).blur();
+						if (event.which==3){
+							event.preventDefault();
+							event.stopPropagation();
+							event.cancelBubble=true;
+
+							//add custom behavior to contextMenuEvent passing the el and the event
+							//you can for example store to global var the obj that is fireing the event
+							//mbActualContextualMenuObj=cm;
+							$.mbMenu.lastContextMenuEl=cm;
+							thisMenu.options.onContextualMenu(this,event);
+
+							if ($.mbMenu.options.actualMenuOpener) {
+								$(thisMenu).removeMbMenu($.mbMenu.options.actualMenuOpener);
+							}
+							$(this).buildMbMenu(thisMenu,$(this).attr("cMenu"),"cm",event);
+							$(this).attr("isOpen","true");
+						}
+					})
+				})
+			})
+		}
+	}
+	$.fn.extend({
+		buildMbMenu: function(op,m,type,e){
+			var msie6=$.browser.msie && $.browser.version=="6.0";
+			var mouseOver=$.browser.msie?"mouseenter":"mouseover";
+			var mouseOut=$.browser.msie?"mouseleave":"mouseout";
+			$().bind("click",function(){$(document).removeMbMenu(op)})
+			if (e) {
+				this.mouseX=$(this).getMouseX(e);
+				this.mouseY=$(this).getMouseY(e);
+			}
+
+			if ($.mbMenu.options.actualMenuOpener && $.mbMenu.options.actualMenuOpener!=op)
+				$(op).removeMbMenu($.mbMenu.options.actualMenuOpener);
+			$.mbMenu.options.actualMenuOpener=op;
+			if(!type || type=="cm")	{
+				if (op.rootMenu) {
+					$(op.rootMenu).remove();
+					$(op.actualOpenedMenu).removeAttr("isOpen")
+				}
+				op.clicked=true;
+				op.actualOpenedMenu=this;
+				$(op.actualOpenedMenu).attr("isOpen","true")
+				$(op.actualOpenedMenu).addClass("selected");
+			}
+			var opener=this;
+			var where=(!type|| type=="cm")?$(document.body):$(this).parent().parent();
+
+			//empty
+			if($(this).attr("menu")=="empty"){
+				return;
+			}
+
+			var menuClass= op.options.menuSelector.replace(".","")
+			where.append("<div class='menuDiv'><div class='"+menuClass+"' style='display:table'></div></div>");
+			this.menu  = where.find(".menuDiv");
+			if (op.options.minZindex!="auto"){
+				$(this.menu).css({zIndex:op.options.minZindex++});
+			}else{
+				$(this.menu).mbBringToFront();
+			}
+			this.menuContainer  = $(this.menu).find(op.options.menuSelector);
+			$(this.menuContainer).bind(mouseOver,function(){
+				$(opener).addClass("selected");
+			})
+			$(this.menuContainer).css({
+				position:"absolute",
+				opacity:op.options.opacity
+			});
+			if (!$("#"+m).html()){
+				$.ajax({
+					type: "POST",
+					url: op.options.template,
+					cache: false,
+					async: false,
+					data:"menuId="+m+(op.options.additionalData!=""?"&"+op.options.additionalData:""),
+					success: function(html){
+						$("body").after(html);
+						$("#"+m).hide();
+					}
+				});
+			}
+			$(this.menuContainer).hide();
+			this.voices= $("#"+m).find("a").clone();
+
+			if (op.options.shadow) {
+				var shadow = $("<div class='menuShadow'></div>").hide();
+				if(msie6)
+					shadow = $("<iframe class='menuShadow'></iframe>").hide();
+			}
+
+			// build each voices of the menu
+			$(this.voices).each(function(i){
+
+				var voice=this;
+				var imgPlace="";
+
+				var isText=$(voice).attr("rel")=="text";
+				var isTitle=$(voice).attr("rel")=="title";
+				var isDisabled=$(voice).is("[disabled]");
+				var isSeparator=$(voice).attr("rel")=="separator";
+
+				if (op.options.hasImages && !isText){
+
+					var imgPath=$(voice).attr("img")?$(voice).attr("img"):"blank.gif";
+					imgPath=(imgPath.length>3 && imgPath.indexOf(".")>-1)?"<img class='imgLine' src='"+op.options.iconPath+imgPath+"'>":imgPath;
+					imgPlace="<td class='img'>"+imgPath+"</td>"
+				}
+				var line="<table id='"+m+"_"+i+"' class='line"+(isTitle?" title":"")+"' cellspacing='0' cellpadding='0' border='0' style='width:100%; display:table' width='100%'><tr>"+imgPlace+"<td class='voice' nowrap></td></tr></table>";
+				if(isSeparator)
+					line="<div class='separator' style='width:100%; display:inline-block'><img src='"+op.options.iconPath+"blank.gif' width='1' height='1'></div>"
+				if(isText)
+					line="<div style='width:100%; display:table' class='line' id='"+m+"_"+i+"'><div class='voice'></div></div>";
+
+				$(opener.menuContainer).append(line);
+
+				if(!isSeparator){
+					$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").append(this);
+					if($(this).attr("menu")){
+						$(opener.menuContainer).find("#"+m+"_"+i).find(".voice a").wrap("<div class='menuArrow'></div>");
+						$(opener.menuContainer).find("#"+m+"_"+i).find(".menuArrow").addClass("subMenuOpener");
+						$(opener.menuContainer).find("#"+m+"_"+i).css({cursor:"default"})
+						this.isOpener=true;
+					}
+					if(isText){
+						$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").addClass("textBox");
+						this.isOpener=true;
+					}
+					if(isDisabled){
+						$(opener.menuContainer).find("#"+m+"_"+i)
+							.addClass("disabled")
+							.css({cursor:"default"})
+					}
+
+					if(!(isText || isTitle || isDisabled)){
+						$(opener.menuContainer)
+							.find("#"+m+"_"+i)
+							.css({cursor:"pointer"})
+							.bind("mouseover",function(event){
+							clearTimeout($.mbMenu.deleteOnMouseOut);
+							$(this).addClass("selected");
+							if(opener.menuContainer.actualSubmenu && !$(voice).attr("menu")){
+								$(opener.menu).find(".menuDiv").remove();
+								$(opener.menuContainer.actualSubmenu).removeClass("selected");
+								opener.menuContainer.actualSubmenu=false;
+								//return false;
+							}
+							if ($(voice).attr("menu")){
+
+								if(opener.menuContainer.actualSubmenu && opener.menuContainer.actualSubmenu!=this){
+									$(opener.menu).find(".menuDiv").remove();
+									$(opener.menuContainer.actualSubmenu).removeClass("selected");
+									opener.menuContainer.actualSubmenu=false;
+								}
+								if (!$(voice).attr("action")) $(opener.menuContainer).find("#"+m+"_"+i).css("cursor","default")
+								if (!opener.menuContainer.actualSubmenu || opener.menuContainer.actualSubmenu!=this){
+									$(opener.menu).find(".menuDiv").remove();
+
+									opener.menuContainer.actualSubmenu=false;
+									$(this).buildMbMenu(op,$(voice).attr("menu"),"sm",event);
+									opener.menuContainer.actualSubmenu=this;
+								}
+								$(this).attr("isOpen","true")
+								return false;
+							}
+						})
+						$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOut,function(){
+							$(this).removeClass("selected");
+						})
+					}
+					if(isDisabled || isTitle){
+						$(this).removeAttr("href");
+						$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOver,function(){
+							$(document).unbind("click");
+							if(opener.menuContainer.actualSubmenu){
+								$(opener.menu).find(".menuDiv").remove();
+								opener.menuContainer.actualSubmenu=false;
+							}
+						}).css("cursor","default")
+					}
+					$(opener.menuContainer).find("#"+m+"_"+i).bind("click",function(){
+						if (($(voice).attr("action") || $(voice).attr("href")) && !isDisabled){
+							var target=$(voice).attr("target")?$(voice).attr("target"):"_self";
+							if ($(voice).attr("href") && $(voice).attr("href").indexOf("javascript:")>-1){
+								$(voice).attr("action",$(voice).attr("href").replace("javascript:",""));
+								$(voice).removeAttr("href");
+							}
+							var link=$(voice).attr("action")?$(voice).attr("action"):"window.open('"+$(voice).attr("href")+"', '"+target+"')";
+							$(voice).removeAttr("href");
+							eval(link);
+							$(this).removeMbMenu(op);
+						}else if($(voice).attr("menu"))
+							return false;
+					})
+				}
+			})
+
+			// Close on Mouseout
+
+			var closeOnMouseOut=$(op)[0].options.closeOnMouseOut;
+			if (closeOnMouseOut){
+				$(opener.menuContainer).bind("mouseenter",function(){
+					clearTimeout($.mbMenu.deleteOnMouseOut);
+				})
+				$(opener.menuContainer).bind("mouseleave",function(){
+					var menuToRemove=$.mbMenu.options.actualMenuOpener;
+					$.mbMenu.deleteOnMouseOut= setTimeout(function(){$(this).removeMbMenu(menuToRemove)},$(op)[0].options.closeAfter);
+				})
+			}
+
+
+			//positioning opened
+			var t=0,l=0
+			$(this.menuContainer).css({
+				width:op.options.menuWidth
+			})
+			if ($.browser.msie) $(this.menuContainer).css("width",$(this.menuContainer).width()+2);
+
+
+			switch(type){
+				case "sm":
+					t=$(this).position().top+op.options.submenuTop;
+
+					l=$(this).position().left+$(this).width()-op.options.submenuLeft;
+					break;
+				case "cm":
+					t=this.mouseY-5;
+					l=this.mouseX-5;
+					break;
+				default:
+					if (op.options.openOnRight){
+						t=$(this).offset().top-($.browser.msie?2:0)+op.options.menuTop;
+						l=$(this).offset().left+$(this).outerWidth()-op.options.menuLeft-($.browser.msie?2:0);
+					}else{
+						t=$(this).offset().top+$(this).outerHeight()-(!$.browser.mozilla?2:0)+op.options.menuTop;
+						l=$(this).offset().left+op.options.menuLeft;
+					}
+					break;
+			}
+
+			$(this.menu).css({
+				position:"absolute",
+				top:t,
+				left:l
+			})
+
+			if (!type || type=="cm") op.rootMenu=this.menu;
+			$(this.menuContainer).bind(mouseOut,function(){
+				$(document).bind("click",function(){$(document).removeMbMenu(op)})
+			})
+
+			if (op.options.fadeInTime>0) $(this.menuContainer).fadeIn(op.options.fadeInTime);
+			else $(this.menuContainer).show();
+
+			if (op.options.shadow) {
+				$(this.menu).prepend(shadow)
+				shadow.css({
+					width:$(this.menuContainer).outerWidth(),
+					height:$(this.menuContainer).outerHeight()-1,
+					position:'absolute',
+					backgroundColor:op.options.shadowColor,
+					border:0,
+					opacity:op.options.shadowOpacity
+				}).show();
+			}
+
+			var wh=$(window).height();
+			var ww=$(window).width();
+			var mh=$(this.menuContainer).outerHeight();
+			var mw=shadow?shadow.outerWidth():$(this.menuContainer).outerWidth();
+
+			var actualX=$(where.find(".menuDiv:first")).offset().left;
+			var actualY=$(where.find(".menuDiv:first")).offset().top;
+			switch(type){
+				case "sm":
+					if ((actualX+mw)>= ww){
+						l-=((op.options.menuWidth*2)-(op.options.submenuLeft*2))
+					}
+					break;
+				case "cm":
+					if ((actualX+(op.options.menuWidth*1.5))>= ww){
+						l-=((op.options.menuWidth*2)-(op.options.submenuLeft))
+					}
+					break;
+				default:
+					if ((actualX+mw)>= ww){
+						l-=($(this.menuContainer).offset().left+mw)-ww;
+					}
+					break;
+			}
+			if ((actualY+mh)>= wh-10){
+				t-=((actualY+mh)-wh)+30;
+			}
+
+			$(this.menu).css({
+				top:t,
+				left:l
+			})
+		},
+		removeMbMenu: function(op){
+			if(!op)op=$.mbMenu.options.actualMenuOpener;
+			if (op.rootMenu) {
+				$(op.actualOpenedMenu)
+					.removeAttr("isOpen")
+					.removeClass("selected")
+				$(op.rootMenu).fadeOut($.mbMenu.options.fadeOuTime,function(){$(this).remove()});
+				op.rootMenu=false;
+				op.clicked=false
+				$(document).unbind("click");
+			}
+		},
+
+		//mouse  Position
+		getMouseX : function (e){
+			var mouseX;
+			if ($.browser.msie)mouseX = event.clientX + document.body.scrollLeft;
+			else mouseX = e.pageX;
+			if (mouseX < 0) mouseX = 0;
+			return mouseX;
+		},
+		getMouseY : function (e){
+			var mouseY;
+			if ($.browser.msie)	mouseY = event.clientY + document.body.scrollTop;
+			else mouseY = e.pageY;
+			if (mouseY < 0)	mouseY = 0;
+			return mouseY;
+		},
+		//get max z-inedex of the page
+		mbBringToFront: function(){
+			var zi=10;
+			$('*').each(function() {
+				if($(this).css("position")=="absolute"){
+					var cur = parseInt($(this).css('zIndex'));
+					zi = cur > zi ? parseInt($(this).css('zIndex')) : zi;
+				}
+			});
+
+			$(this).css('zIndex',zi+=10);
+		}
+
+	})
+	$.fn.buildMenu = $.mbMenu.buildMenu;
+	$.fn.buildContextualMenu = $.mbMenu.buildContextualMenu;
+})(jQuery);
\ No newline at end of file
diff --git a/moksha/apps/menus/moksha/apps/menus/static/mbMenu.min.js b/moksha/apps/menus/moksha/apps/menus/static/mbMenu.min.js
new file mode 100644
index 0000000..e7fd2d4
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/static/mbMenu.min.js
@@ -0,0 +1 @@
+(function($){$.mbMenu={actualMenuOpener:false,options:{template:"yourMenuVoiceTemplate",additionalData:"",menuSelector:".menuContainer",menuWidth:150,openOnRight:false,iconPath:"ico/",hasImages:true,fadeInTime:100,fadeOuTime:100,menuTop:0,menuLeft:0,submenuTop:0,submenuLeft:4,opacity:1,shadow:false,shadowColor:"black",openOnClick:true,closeOnMouseOut:false,closeAfter:500,minZindex:"auto",shadowOpacity:0.2,onContextualMenu:function(o,e){}},buildMenu:function(options){return this.each(function(){var thisMenu=this;thisMenu.id=!this.id?"menu_"+Math.floor(Math.random()*1000):this.id;this.options={};$.extend(this.options,$.mbMenu.options);$.extend(this.options,options);$(".menu").hide();thisMenu.clicked=false;thisMenu.rootMenu=false;thisMenu.clearClicked=false;thisMenu.actualOpenedMenu=false;thisMenu.menuvoice=false;var root=$(this);var openOnClick=this.options.openOnClick;var closeOnMouseOut=this.options.closeOnMouseOut;$(root).each(function(){thisMenu.menuvoice=$(this).find("[menu]");$(thisMenu.menuvoice).each(function(){$(this).addClass("rootVoice");$(this).attr("nowrap","nowrap")});var action=openOnClick?"click":"mouseover";$(thisMenu.menuvoice).bind(action,function(){if(!$(this).attr("isOpen")){$(this).buildMbMenu(thisMenu,$(this).attr("menu"))}$(this).attr("isOpen","true");if($(this).attr("menu")=="empty"){if(thisMenu.actualOpenedMenu){$(thisMenu.actualOpenedMenu).removeClass("selected");thisMenu.clicked=true;$(this).removeAttr("isOpen");clearTimeout(thisMenu.clearClicked)}$(this).removeMbMenu(thisMenu)}return false});var mouseOver=$.browser.msie?"mouseenter":"mouseover";var mouseOut=$.browser.msie?"mouseleave":"mouseout";$(thisMenu.menuvoice).bind(mouseOver,function(){if(closeOnMouseOut){clearTimeout($.mbMenu.deleteOnMouseOut)}if(!openOnClick){$(thisMenu).find(".selected").removeClass("selected")}if(thisMenu.actualOpenedMenu){$(thisMenu.actualOpenedMenu).removeClass("selected")}$(this).addClass("selected");if(thisMenu.clicked&&!$(this).attr("isOpen")){clearTimeout(thisMenu.clearClicked);$(this).buildMbMenu(thisMenu,$(this).attr("menu"))}});$(thisMenu.menuvoice).bind(mouseOut,function(){if(!thisMenu.clicked){$(this).removeClass("selected")}$(document).bind("click",function(){$(this).removeMbMenu(thisMenu)})})})})},buildContextualMenu:function(options){return this.each(function(){var thisMenu=this;thisMenu.options={};$.extend(thisMenu.options,$.mbMenu.options);$.extend(thisMenu.options,options);$(".menu").hide();thisMenu.clicked=false;thisMenu.rootMenu=false;thisMenu.clearClicked=false;thisMenu.actualOpenedMenu=false;thisMenu.menuvoice=false;var cMenuEls=$("[cMenu]");$(cMenuEls).each(function(){$(this).css("-khtml-user-select","none");var cm=this;cm.id=!cm.id?"menu_"+Math.floor(Math.random()*100):cm.id;$(cm).css({cursor:"default"});$(cm).bind("contextmenu","mousedown",function(event){$(this).blur();if(event.which==3){event.preventDefault();event.stopPropagation();event.cancelBubble=true;$.mbMenu.lastContextMenuEl=cm;thisMenu.options.onContextualMenu(this,event);if($.mbMenu.options.actualMenuOpener){$(thisMenu).removeMbMenu($.mbMenu.options.actualMenuOpener)}$(this).buildMbMenu(thisMenu,$(this).attr("cMenu"),"cm",event);$(this).attr("isOpen","true")}})})})}};$.fn.extend({buildMbMenu:function(op,m,type,e){var msie6=$.browser.msie&&$.browser.version=="6.0";var mouseOver=$.browser.msie?"mouseenter":"mouseover";var mouseOut=$.browser.msie?"mouseleave":"mouseout";$().bind("click",function(){$(document).removeMbMenu(op)});if(e){this.mouseX=$(this).getMouseX(e);this.mouseY=$(this).getMouseY(e)}if($.mbMenu.options.actualMenuOpener&&$.mbMenu.options.actualMenuOpener!=op){$(op).removeMbMenu($.mbMenu.options.actualMenuOpener)}$.mbMenu.options.actualMenuOpener=op;if(!type||type=="cm"){if(op.rootMenu){$(op.rootMenu).remove();$(op.actualOpenedMenu).removeAttr("isOpen")}op.clicked=true;op.actualOpenedMenu=this;$(op.actualOpenedMenu).attr("isOpen","true");$(op.actualOpenedMenu).addClass("selected")}var opener=this;var where=(!type||type=="cm")?$(document.body):$(this).parent().parent();if($(this).attr("menu")=="empty"){return }var menuClass=op.options.menuSelector.replace(".","");where.append("<div class='menuDiv'><div class='"+menuClass+"' style='display:table'></div></div>");this.menu=where.find(".menuDiv");if(op.options.minZindex!="auto"){$(this.menu).css({zIndex:op.options.minZindex++})}else{$(this.menu).mbBringToFront()}this.menuContainer=$(this.menu).find(op.options.menuSelector);$(this.menuContainer).bind(mouseOver,function(){$(opener).addClass("selected")});$(this.menuContainer).css({position:"absolute",opacity:op.options.opacity});if(!$("#"+m).html()){$.ajax({type:"POST",url:op.options.template,cache:false,async:false,data:"menuId="+m+(op.options.additionalData!=""?"&"+op.options.additionalData:""),success:function(html){$("body").after(html);$("#"+m).hide()}})}$(this.menuContainer).hide();this.voices=$("#"+m).find("a").clone();if(op.options.shadow){var shadow=$("<div class='menuShadow'></div>").hide();if(msie6){shadow=$("<iframe class='menuShadow'></iframe>").hide()}}$(this.voices).each(function(i){var voice=this;var imgPlace="";var isText=$(voice).attr("rel")=="text";var isTitle=$(voice).attr("rel")=="title";var isDisabled=$(voice).is("[disabled]");var isSeparator=$(voice).attr("rel")=="separator";if(op.options.hasImages&&!isText){var imgPath=$(voice).attr("img")?$(voice).attr("img"):"blank.gif";imgPath=(imgPath.length>3&&imgPath.indexOf(".")>-1)?"<img class='imgLine' src='"+op.options.iconPath+imgPath+"'>":imgPath;imgPlace="<td class='img'>"+imgPath+"</td>"}var line="<table id='"+m+"_"+i+"' class='line"+(isTitle?" title":"")+"' cellspacing='0' cellpadding='0' border='0' style='width:100%; display:table' width='100%'><tr>"+imgPlace+"<td class='voice' nowrap></td></tr></table>";if(isSeparator){line="<div class='separator' style='width:100%; display:inline-block'><img src='"+op.options.iconPath+"blank.gif' width='1' height='1'></div>"}if(isText){line="<div style='width:100%; display:table' class='line' id='"+m+"_"+i+"'><div class='voice'></div></div>"}$(opener.menuContainer).append(line);if(!isSeparator){$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").append(this);if($(this).attr("menu")){$(opener.menuContainer).find("#"+m+"_"+i).find(".voice a").wrap("<div class='menuArrow'></div>");$(opener.menuContainer).find("#"+m+"_"+i).find(".menuArrow").addClass("subMenuOpener");$(opener.menuContainer).find("#"+m+"_"+i).css({cursor:"default"});this.isOpener=true}if(isText){$(opener.menuContainer).find("#"+m+"_"+i).find(".voice").addClass("textBox");this.isOpener=true}if(isDisabled){$(opener.menuContainer).find("#"+m+"_"+i).addClass("disabled").css({cursor:"default"})}if(!(isText||isTitle||isDisabled)){$(opener.menuContainer).find("#"+m+"_"+i).css({cursor:"pointer"}).bind("mouseover",function(event){clearTimeout($.mbMenu.deleteOnMouseOut);$(this).addClass("selected");if(opener.menuContainer.actualSubmenu&&!$(voice).attr("menu")){$(opener.menu).find(".menuDiv").remove();$(opener.menuContainer.actualSubmenu).removeClass("selected");opener.menuContainer.actualSubmenu=false}if($(voice).attr("menu")){if(opener.menuContainer.actualSubmenu&&opener.menuContainer.actualSubmenu!=this){$(opener.menu).find(".menuDiv").remove();$(opener.menuContainer.actualSubmenu).removeClass("selected");opener.menuContainer.actualSubmenu=false}if(!$(voice).attr("action")){$(opener.menuContainer).find("#"+m+"_"+i).css("cursor","default")}if(!opener.menuContainer.actualSubmenu||opener.menuContainer.actualSubmenu!=this){$(opener.menu).find(".menuDiv").remove();opener.menuContainer.actualSubmenu=false;$(this).buildMbMenu(op,$(voice).attr("menu"),"sm",event);opener.menuContainer.actualSubmenu=this}$(this).attr("isOpen","true");return false}});$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOut,function(){$(this).removeClass("selected")})}if(isDisabled||isTitle){$(this).removeAttr("href");$(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOver,function(){$(document).unbind("click");if(opener.menuContainer.actualSubmenu){$(opener.menu).find(".menuDiv").remove();opener.menuContainer.actualSubmenu=false}}).css("cursor","default")}$(opener.menuContainer).find("#"+m+"_"+i).bind("click",function(){if(($(voice).attr("action")||$(voice).attr("href"))&&!isDisabled){var target=$(voice).attr("target")?$(voice).attr("target"):"_self";if($(voice).attr("href")&&$(voice).attr("href").indexOf("javascript:")>-1){$(voice).attr("action",$(voice).attr("href").replace("javascript:",""));$(voice).removeAttr("href")}var link=$(voice).attr("action")?$(voice).attr("action"):"window.open('"+$(voice).attr("href")+"', '"+target+"')";$(voice).removeAttr("href");eval(link);$(this).removeMbMenu(op)}else{if($(voice).attr("menu")){return false}}})}});var closeOnMouseOut=$(op)[0].options.closeOnMouseOut;if(closeOnMouseOut){$(opener.menuContainer).bind("mouseenter",function(){clearTimeout($.mbMenu.deleteOnMouseOut)});$(opener.menuContainer).bind("mouseleave",function(){var menuToRemove=$.mbMenu.options.actualMenuOpener;$.mbMenu.deleteOnMouseOut=setTimeout(function(){$(this).removeMbMenu(menuToRemove)},$(op)[0].options.closeAfter)})}var t=0,l=0;$(this.menuContainer).css({width:op.options.menuWidth});if($.browser.msie){$(this.menuContainer).css("width",$(this.menuContainer).width()+2)}switch(type){case"sm":t=$(this).position().top+op.options.submenuTop;l=$(this).position().left+$(this).width()-op.options.submenuLeft;break;case"cm":t=this.mouseY-5;l=this.mouseX-5;break;default:if(op.options.openOnRight){t=$(this).offset().top-($.browser.msie?2:0)+op.options.menuTop;l=$(this).offset().left+$(this).outerWidth()-op.options.menuLeft-($.browser.msie?2:0)}else{t=$(this).offset().top+$(this).outerHeight()-(!$.browser.mozilla?2:0)+op.options.menuTop;l=$(this).offset().left+op.options.menuLeft}break}$(this.menu).css({position:"absolute",top:t,left:l});if(!type||type=="cm"){op.rootMenu=this.menu}$(this.menuContainer).bind(mouseOut,function(){$(document).bind("click",function(){$(document).removeMbMenu(op)})});if(op.options.fadeInTime>0){$(this.menuContainer).fadeIn(op.options.fadeInTime)}else{$(this.menuContainer).show()}if(op.options.shadow){$(this.menu).prepend(shadow);shadow.css({width:$(this.menuContainer).outerWidth(),height:$(this.menuContainer).outerHeight()-1,position:"absolute",backgroundColor:op.options.shadowColor,border:0,opacity:op.options.shadowOpacity}).show()}var wh=$(window).height();var ww=$(window).width();var mh=$(this.menuContainer).outerHeight();var mw=shadow?shadow.outerWidth():$(this.menuContainer).outerWidth();var actualX=$(where.find(".menuDiv:first")).offset().left;var actualY=$(where.find(".menuDiv:first")).offset().top;switch(type){case"sm":if((actualX+mw)>=ww){l-=((op.options.menuWidth*2)-(op.options.submenuLeft*2))}break;case"cm":if((actualX+(op.options.menuWidth*1.5))>=ww){l-=((op.options.menuWidth*2)-(op.options.submenuLeft))}break;default:if((actualX+mw)>=ww){l-=($(this.menuContainer).offset().left+mw)-ww}break}if((actualY+mh)>=wh-10){t-=((actualY+mh)-wh)+30}$(this.menu).css({top:t,left:l})},removeMbMenu:function(op){if(!op){op=$.mbMenu.options.actualMenuOpener}if(op.rootMenu){$(op.actualOpenedMenu).removeAttr("isOpen").removeClass("selected");$(op.rootMenu).fadeOut($.mbMenu.options.fadeOuTime,function(){$(this).remove()});op.rootMenu=false;op.clicked=false;$(document).unbind("click")}},getMouseX:function(e){var mouseX;if($.browser.msie){mouseX=event.clientX+document.body.scrollLeft}else{mouseX=e.pageX}if(mouseX<0){mouseX=0}return mouseX},getMouseY:function(e){var mouseY;if($.browser.msie){mouseY=event.clientY+document.body.scrollTop}else{mouseY=e.pageY}if(mouseY<0){mouseY=0}return mouseY},mbBringToFront:function(){var zi=10;$("*").each(function(){if($(this).css("position")=="absolute"){var cur=parseInt($(this).css("zIndex"));zi=cur>zi?parseInt($(this).css("zIndex")):zi}});$(this).css("zIndex",zi+=10)}});$.fn.buildMenu=$.mbMenu.buildMenu;$.fn.buildContextualMenu=$.mbMenu.buildContextualMenu})(jQuery);
diff --git a/moksha/apps/menus/moksha/apps/menus/static/styleswitch.js b/moksha/apps/menus/moksha/apps/menus/static/styleswitch.js
new file mode 100644
index 0000000..156ac78
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/static/styleswitch.js
@@ -0,0 +1,55 @@
+/**
+* Styleswitch stylesheet switcher built on jQuery
+* Under an Attribution, Share Alike License
+* By Kelvin Luck ( http://www.kelvinluck.com/ )
+**/
+
+$(document).ready(function() {
+	$('.styleswitch').click(function()
+	{
+		switchStylestyle(this.getAttribute("rel"));
+		return false;
+	});
+	var c = readCookie('style');
+	if (c) switchStylestyle(c);
+});
+
+function switchStylestyle(styleName)
+{
+	$(document).find("@rel*=style][title]").each(function(i)
+	{
+		this.disabled = true;
+		if (this.getAttribute('title') == styleName) this.disabled = false;
+	});
+	createCookie('style', styleName, 365);
+}
+
+// cookie functions http://www.quirksmode.org/js/cookies.html
+function createCookie(name,value,days)
+{
+	if (days)
+	{
+		var date = new Date();
+		date.setTime(date.getTime()+(days*24*60*60*1000));
+		var expires = "; expires="+date.toGMTString();
+	}
+	else var expires = "";
+	document.cookie = name+"="+value+expires+"; path=/";
+}
+function readCookie(name)
+{
+	var nameEQ = name + "=";
+	var ca = document.cookie.split(';');
+	for(var i=0;i < ca.length;i++)
+	{
+		var c = ca[i];
+		while (c.charAt(0)==' ') c = c.substring(1,c.length);
+		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
+	}
+	return null;
+}
+function eraseCookie(name)
+{
+	createCookie(name,"",-1);
+}
+// /cookie functions
\ No newline at end of file
diff --git a/moksha/apps/menus/moksha/apps/menus/templates/__init__.py b/moksha/apps/menus/moksha/apps/menus/templates/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/menus/moksha/apps/menus/templates/mbmenu.mak b/moksha/apps/menus/moksha/apps/menus/templates/mbmenu.mak
new file mode 100644
index 0000000..e9f4a95
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/templates/mbmenu.mak
@@ -0,0 +1,19 @@
+<table  border="0" cellpadding="0" cellspacing="0" bgcolor="#EDEDED">
+    <tr>
+        <td valign="bottom">
+            <table  border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" class="container">
+                <tr>
+                    <td class="${id}" align="right">
+
+                        <table class="${rootMenuSelector}" cellspacing='0' cellpadding='0' border='0'><tr>
+                            % for menu_id, menu in menus:
+                                <td menu="${id}_${menu_id}">${menu}</td>
+                            % endfor
+                        </tr></table>
+                    </td>
+                </tr>
+            </table>
+        </td>
+    </tr>
+</table>
+
diff --git a/moksha/apps/menus/moksha/apps/menus/widgets.py b/moksha/apps/menus/moksha/apps/menus/widgets.py
new file mode 100644
index 0000000..e37e8c5
--- /dev/null
+++ b/moksha/apps/menus/moksha/apps/menus/widgets.py
@@ -0,0 +1,144 @@
+## -*- coding: utf-8 -*-
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+:mod:`moksha.apps.menus.widgets` - Moksha Menu Widgets
+=====================================================
+
+This is a powerful component to build easily a multilevel tree menu or a
+contextual menu (right click) in an intuitive way.
+
+This module contains ToscaWidgets for the `mbMenu jQuery Plugin
+<http://plugins.jquery.com/project/mbMenu>`_, which was developed by Matteo
+Bicocchi. © 2002-2008 Open Lab srl, Matteo Bicocchi. GPL licensed.
+
+.. moduleauthor:: Luke Macken <lmacken at redhat.com>
+"""
+
+from tw.api import JSLink, Widget, CSSLink, js_function, js_callback
+from tw.jquery import jquery_js, jQuery
+
+modname = __name__
+
+jquery_mbmenu_js = JSLink(modname=modname,
+                          filename='static/mbMenu.js',
+                          javascript=[jquery_js])
+
+jquery_mbmenu_min_js = JSLink(modname=modname,
+                              filename='static/mbMenu.min.js',
+                              javascript=[jquery_js])
+
+
+class MokshaMenuBase(Widget):
+    template = "mako:moksha.apps.menus.templates.mbmenu"
+    javascript = [jquery_mbmenu_min_js]
+    css = [CSSLink(modname=modname, filename='static/css/menu1.css',
+                   media='screen')]
+    params = ['callback', 'rootMenuSelector', 'menuSelector', 'id', 'menus',
+              'additionalData', 'iconPath', 'menuWidth', 'openOnRight',
+              'hasImages', 'fadeTime', 'adjustLeft', 'adjustTop', 'opacity',
+              'shadow', 'fadeInTime', 'fadeOutTime', 'overflow', 'effect',
+              'minZindex']
+
+    rootMenuSelector = 'rootVoices'
+    menuSelector = 'menuContainer'
+    callback = '/apps/menu'
+    iconPath = '/toscawidgets/resources/moksha.apps.menus.widgets/static/images/'
+    additionalData = ""
+    menus = []
+    menuWidth = 200
+    openOnRight =  False
+    hasImages = True
+    fadeTime = 200
+    fadeInTime = 100
+    fadeOutTime = 100
+    adjustLeft = 2
+    adjustTop = 10
+    opacity = 0.95
+    shadow = True
+    overflow = 2
+    effect = 'fade'
+    minZindex = 'auto'
+
+
+class MokshaMenu(MokshaMenuBase):
+
+    def update_params(self, d):
+        super(MokshaMenu, self).update_params(d)
+
+        if not d.id:
+            raise Exception("MokshaMenu must have an id!")
+        if not d.callback:
+            raise Exception("Must provide a callback URL!")
+
+        menus = []
+        for menu in d.menus:
+            menus.append((menu.lower().replace(' ', ''), menu))
+        d.menus = menus
+
+        self.add_call(jQuery('.%s' % d.id).buildMenu({
+                'template': d.callback,
+                'additionalData': d.additionalData,
+                'menuWidth': d.menuWidth,
+                'openOnRight': d.openOnRight,
+                'rootMenuSelector': ".%s" % d.rootMenuSelector,
+                'menuSelector': ".%s" % d.menuSelector,
+                'iconPath': d.iconPath,
+                'hasImages': d.hasImages,
+                'fadeTime': d.fadeTime,
+                'fadeInTime': d.fadeInTime,
+                'fadeOutTime': d.fadeOutTime,
+                'adjustLeft': d.adjustLeft,
+                'adjustTop': d.adjustTop,
+                'opacity': d.opacity,
+                'shadow': d.shadow,
+                'minZindex': d.minZindex,
+                }))
+
+
+class MokshaContextualMenu(MokshaMenuBase):
+
+    def update_params(self, d):
+        super(MokshaContextualMenu, self).update_params(d)
+
+        if not d.id:
+            raise Exception("MokshaMenu must have an id!")
+        if not d.callback:
+            raise Exception("Must provide a callback URL!")
+
+        menus = []
+        for menu in d.menus:
+            menus.append((menu.lower().replace(' ', ''), menu))
+        d.menus = menus
+
+        self.add_call(jQuery(js_callback('document')).buildContextualMenu({
+                'template': d.callback,
+                'menuWidth': d.menuWidth,
+                'rootMenuSelector': ".%s" % d.rootMenuSelector,
+                'menuSelector': ".%s" % d.menuSelector,
+                'iconPath': d.iconPath,
+                'hasImages': d.hasImages,
+                'fadeTime': d.fadeTime,
+                'fadeInTime': d.fadeInTime,
+                'fadeOutTime': d.fadeOutTime,
+                'adjustLeft': d.adjustLeft,
+                'adjustTop': d.adjustTop,
+                'opacity': d.opacity,
+                'shadow': d.shadow,
+                'effect': d.effect,
+                'minZindex': d.minZindex
+                }))
diff --git a/moksha/apps/menus/pavement.py b/moksha/apps/menus/pavement.py
index 6438034..098ebca 100644
--- a/moksha/apps/menus/pavement.py
+++ b/moksha/apps/menus/pavement.py
@@ -1,14 +1,15 @@
 from paver.easy import *
-from paver.setuputils import setup
+from paver.setuputils import setup, find_package_data, find_packages
 
 setup(
     name="moksha.menus",
-    version="1.0",
+    version="0.1",
     url="http://moksha.fedorahosted.org",
     description="Moksha Menus App",
     author="Luke Macken",
     author_email="lmacken at redhat.com",
-    packages=['moksha'],
+    packages=find_packages(),
+    package_data=find_package_data(),
     namespace_packages=['moksha'],
     install_requires=["Moksha"],
     entry_points="""
@@ -21,3 +22,16 @@ setup(
 
     """,
 )
+
+ at task
+def rpm():
+    sh('rm -fr dist')
+    sh('paver sdist')
+    sh('mv dist/* ~/rpmbuild/SOURCES/')
+    sh('cp *.spec ~/rpmbuild/SPECS/')
+    sh('rpmbuild -ba ~/rpmbuild/SPECS/moksha-menus.spec')
+
+ at task
+ at needs(['rpm'])
+def reinstall():
+    sh('sudo rpm -ivh --replacefiles --replacepkgs ~/rpmbuild/RPMS/noarch/moksha-menus-0.1-1.noarch.rpm')


commit 621e07e339b39b4fce00f76c86fbf0e635b33710
Author: Luke Macken <lmacken at redhat.com>
Date:   Thu Aug 6 11:39:03 2009 -0400

    Add an initial menus app

diff --git a/moksha/apps/menus/moksha/__init__.py b/moksha/apps/menus/moksha/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/menus/moksha/apps/__init__.py b/moksha/apps/menus/moksha/apps/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/menus/pavement.py b/moksha/apps/menus/pavement.py
new file mode 100644
index 0000000..6438034
--- /dev/null
+++ b/moksha/apps/menus/pavement.py
@@ -0,0 +1,23 @@
+from paver.easy import *
+from paver.setuputils import setup
+
+setup(
+    name="moksha.menus",
+    version="1.0",
+    url="http://moksha.fedorahosted.org",
+    description="Moksha Menus App",
+    author="Luke Macken",
+    author_email="lmacken at redhat.com",
+    packages=['moksha'],
+    namespace_packages=['moksha'],
+    install_requires=["Moksha"],
+    entry_points="""
+
+    [moksha.menu]
+    default_menu = moksha.apps.menus:MokshaDefaultMenu
+
+    [moksha.application]
+    menu = moksha.apps.menus.controllers:MokshaMenuController
+
+    """,
+)


commit 04d9f1ae7518b80f57dc0c671ed585863e550bf7
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Jul 24 20:20:58 2009 -0400

    Give Michael credit for the amazing logo

diff --git a/AUTHORS b/AUTHORS
index a4f5e6f..d34f006 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,5 @@
 Luke Macken <lmacken at redhat.com>
 John (J5) Palmieri <johnp at redhat.com>
 Mairin Duffy <duffy at redhat.com>
+
+Logo design by Michael Langlie <mlanglie at redhat.com>


commit 8c448739c52b5d9725646ed7bafa2dbc9817e42a
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Jul 24 20:17:41 2009 -0400

    Initialize app controllers properly in the MokshaMiddleware

diff --git a/moksha/middleware/middleware.py b/moksha/middleware/middleware.py
index bbc69c6..9ef2e11 100644
--- a/moksha/middleware/middleware.py
+++ b/moksha/middleware/middleware.py
@@ -118,7 +118,7 @@ class MokshaMiddleware(object):
             app_path = app_entry.dist.location
             app_name = getattr(app_class, 'name', app_entry.name),
             if isclass(app_class):
-                app = app_class()
+                app_class = app_class()
             moksha._apps[app_entry.name].update({
                     'name': app_name,
                     'controller': app_class,


commit 8445dba2ee8f4f2af170cc0cb8350d74ba1d0c11
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Jul 24 13:17:26 2009 -0400

    Deprecate the demo stream, as we are moving it to it's own app

diff --git a/moksha/apps/demo/streams/demostream.py b/moksha/apps/demo/streams/demostream.py
index 0ed742e..4208e80 100644
--- a/moksha/apps/demo/streams/demostream.py
+++ b/moksha/apps/demo/streams/demostream.py
@@ -14,6 +14,12 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+:deprecated: This module was used for some very early Moksha demos, and generates a lot of useless data.  This has since been deprecated by a more useful, self-aware, Moksha demo.
+
+.. moduleauthor:: Luke Macken <lmacken at redhat.com>
+"""
+
 import math
 from random import random
 from datetime import timedelta


commit 53abd41a1706c7b8e3e214a4ed407ac36785e460
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Jul 24 13:14:42 2009 -0400

    Pull our Sphinx/WidgetBrowser out into it's own moksha.docs app

diff --git a/moksha/api/menus/default.py b/moksha/api/menus/default.py
index 6b1664b..27f7965 100644
--- a/moksha/api/menus/default.py
+++ b/moksha/api/menus/default.py
@@ -75,7 +75,7 @@ class MokshaDefaultMenu(MokshaMenu):
             <br>Moksha is a platform for creating live collaborative web applications.<br><br>
         </a>
         <a rel="separator"></a>
-        <a href="/docs/">Documentation</a>
+        <a href="/apps/docs/">Documentation</a>
         <a href="https://fedorahosted.org/moksha/report/3">Tickets</a>
         <a href="https://fedorahosted.org/moksha/">Wiki</a>
         """
diff --git a/moksha/apps/docs/__init__.py b/moksha/apps/docs/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/moksha/apps/docs/docs.py b/moksha/apps/docs/docs.py
new file mode 100644
index 0000000..175db7f
--- /dev/null
+++ b/moksha/apps/docs/docs.py
@@ -0,0 +1,52 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+:mod:`moksha.apps.docs.docs` - Moksha Documentation & Widget Demo App
+=====================================================================
+
+This Moksha app integrates your Sphinx documentation with the ToscaWidgets
+WidgetBrowser.  This gives you the ability to write your documentation
+in reStructuredText, and easily expose it in your application via the 
+`/apps/docs` URL.  Since it integrates the ToscaWidgets WidgetBrowser,
+this also gives you the ability to create Widget demos and embed them
+in your documentation.
+
+.. seealso::
+
+    See the ToscaWidgets WidgetBrowser documentation for more information
+    http://toscawidgets.org/documentation/WidgetBrowser/widget_demo_howto.html
+
+.. moduleauthor:: Luke Macken <lmacken at redhat.com>
+
+"""
+
+import os
+
+from tg import config
+from tg.controllers import WSGIAppController
+from pkg_resources import resource_filename
+from widgetbrowser import WidgetBrowser
+
+os.environ['TW_BROWSER_PREFIX'] = '/apps/docs'
+
+docs = WSGIAppController(
+            WidgetBrowser(
+                template_dirs=[
+                    resource_filename('moksha','templates/widget_browser')],
+                docs_dir=config.get('docs_dir', 'docs'),
+                full_stack=False,
+                interactive=False))
diff --git a/moksha/apps/docs/pavement.py b/moksha/apps/docs/pavement.py
new file mode 100644
index 0000000..d34229d
--- /dev/null
+++ b/moksha/apps/docs/pavement.py
@@ -0,0 +1,19 @@
+from paver.easy import *
+from paver.setuputils import setup
+
+setup(
+    name="moksha.docs",
+    version="1.0",
+    url="http://moksha.fedorahosted.org",
+    description="Moksha Docs App",
+    author="Luke Macken",
+    author_email="lmacken at redhat.com",
+    packages=[],
+    install_requires=["Moksha"],
+    entry_points="""
+
+    [moksha.application]
+    docs = moksha.apps.docs.docs:docs
+
+    """,
+)
diff --git a/moksha/controllers/apps.py b/moksha/controllers/apps.py
index 9b06d9a..2fc1b22 100644
--- a/moksha/controllers/apps.py
+++ b/moksha/controllers/apps.py
@@ -22,11 +22,10 @@ from tw.api import Widget
 from tw.jquery import jQuery
 from tg import expose, tmpl_context
 
-from moksha.lib.base import Controller
-from moksha.exc import ApplicationNotFound
-
 from moksha.api.widgets.containers import DashboardContainer
 from moksha.api.widgets import ContextAwareWidget
+from moksha.exc import ApplicationNotFound
+from moksha.lib.base import Controller
 from moksha.lib.helpers import Category, MokshaApp, MokshaWidget
 
 class AppWidgetContainer(DashboardContainer, ContextAwareWidget):
diff --git a/moksha/controllers/root.py b/moksha/controllers/root.py
index 83040b8..324d6f6 100644
--- a/moksha/controllers/root.py
+++ b/moksha/controllers/root.py
@@ -18,31 +18,17 @@
 
 import moksha
 import pylons
-import os
 
-from tg import config, url
-from tg import expose, flash, require, tmpl_context, redirect, validate
-from tg.controllers import WSGIAppController
-from tg.decorators import after_render
-
-from repoze.what import predicates
-from pkg_resources import resource_filename
-#from widgetbrowser import WidgetBrowser
-from pylons.i18n import ugettext as _, lazy_ugettext as l_
+from tg import url
+from tg import expose, flash, tmpl_context, redirect
 
 from moksha import _
-from moksha.model import DBSession
 from moksha.lib.base import BaseController
-from moksha.lib.helpers import cache_rendered_data
-from moksha.exc import ApplicationNotFound
 from moksha.controllers.error import ErrorController
 from moksha.controllers.apps import AppController
 from moksha.controllers.widgets import WidgetController
 from moksha.controllers.secure import SecureController
 
-# So we can mount the WidgetBrowser as /docs
-os.environ['TW_BROWSER_PREFIX'] = '/docs'
-
 class RootController(BaseController):
 
     apps = AppController()
@@ -50,18 +36,6 @@ class RootController(BaseController):
     error = ErrorController()
     moksha_admin = SecureController()
 
-    # ToscaWidgets WidgetBrowser integration
-    """
-    docs = WSGIAppController(
-                WidgetBrowser(
-                    template_dirs=[
-                        resource_filename('moksha','templates/widget_browser')],
-                    docs_dir=config.get('docs_dir', 'docs'),
-                    full_stack=False,
-                    interactive=False))
-    """
-
-    #@after_render(cache_rendered_data)
     @expose('mako:moksha.templates.index')
     def index(self):
         if 'default_menu' in moksha.menus:
@@ -71,17 +45,6 @@ class RootController(BaseController):
         #tmpl_context.contextual_menu_widget = moksha.menus['contextual_menu']
         return dict(title='[ Moksha ]')
 
-    @expose()
-    def lookup(self, *remainder):
-        """
-        Moksha's default lookup method, called by the
-        :class:`MokshaMiddleware`.  This currently dispatches to our
-        WidgetBrowser when Moksha is being used as WSGI middleware in another
-        application.
-        """
-        if pylons.request.path.startswith('/docs/'):
-            return self.docs, remainder
-
     @expose('mako:moksha.templates.login')
     def login(self, came_from=None):
         """Start the user login."""
diff --git a/moksha/wsgiapp.py b/moksha/wsgiapp.py
index 6ad66af..7f58d25 100644
--- a/moksha/wsgiapp.py
+++ b/moksha/wsgiapp.py
@@ -47,7 +47,6 @@ class MokshaAppDispatcher(PylonsApp):
         path = strip_script(environ)
         if path.startswith('/apps/') or \
            path.startswith('/widget') or \
-           path.startswith('/docs/') or \
            path.startswith('/moksha_admin/'):
             return self.root()
         else:


commit a2bbd7d42a5a8b75d4e4a0d964c83bf5363d3de3
Author: Luke Macken <lmacken at redhat.com>
Date:   Fri Jul 24 13:02:46 2009 -0400

    Rename the moksha.apps dict to moksha._apps
    
    - This lets us have a real moksha.apps package
    - This is consistent with moksha._widgets
    - This adds a moksha.get_app getter method

diff --git a/moksha/__init__.py b/moksha/__init__.py
index 8921cf9..1387592 100644
--- a/moksha/__init__.py
+++ b/moksha/__init__.py
@@ -24,14 +24,14 @@ feed_cache = None
 feed_storage = None
 
 # All loaded moksha applications
-apps = None
-
-# All WSGI applications
-wsgiapps = None
+_apps = None
 
 # All loaded ToscaWidgets
 _widgets = None
 
+# All WSGI applications
+wsgiapps = None
+
 # All loaded moksha menus
 menus = None
 
@@ -42,6 +42,10 @@ def get_widget(name):
     """ Get a widget instance by name """
     return _widgets[name]['widget']
 
+def get_app(name):
+    """ Get an app controller by name """
+    return _apps[name]['controller']
+
 def shutdown():
     """ Called when Moksha shuts down """
     try:
diff --git a/moksha/apps/demo/streams/__init__.py b/moksha/apps/demo/streams/__init__.py
new file mode 100644
index 0000000..8bc12eb
--- /dev/null
+++ b/moksha/apps/demo/streams/__init__.py
@@ -0,0 +1,17 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from demostream import MokshaDemoDataStream
diff --git a/moksha/apps/demo/streams/demostream.py b/moksha/apps/demo/streams/demostream.py
new file mode 100644
index 0000000..0ed742e
--- /dev/null
+++ b/moksha/apps/demo/streams/demostream.py
@@ -0,0 +1,100 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import math
+from random import random
+from datetime import timedelta
+
+from moksha.api.widgets.feed import Feed
+from moksha.api.streams import PollingDataStream
+
+class MokshaDemoDataStream(PollingDataStream):
+    """
+    This class provides the default Moksha demo with some fake data to render
+    """
+
+    frequency = timedelta(seconds=0.5)
+
+    # Flot demo specific variables
+    offset = 0.0
+    skip = 0
+    bars = [[0, 3], [4, 8], [8, 5], [9, 13]]
+    n = 0
+
+    # Feed demo specific variables
+    i = 0
+
+    def __init__(self, *args, **kw):
+        self.feed = Feed(url='http://doggdot.us/rss')
+        self.feed_entries = self.feed.entries()
+        super(MokshaDemoDataStream, self).__init__(*args, **kw)
+
+    def poll(self):
+        self.n += 1
+
+        if self.n % 3 == 0:
+            self.i += 1
+            entry = self.feed_entries[self.n % len(self.feed_entries)]
+            self.send_message('feed_demo', [
+                {'title': entry['title'], 'link': entry['link'], 'i': self.i},
+            ])
+
+        ## Generate flot data
+        d1 = []
+        i = 0
+        for x in range(26):
+            d1.append((i, math.sin(i + self.offset)))
+            i += 0.5
+
+        for bar in self.bars:
+            bar[1] = bar[1] + (int(random() * 3) - 1)
+            if bar[1] <= -5: bar[1] = -4
+            if bar[1] >= 15: bar[1] = 15
+        d2 = self.bars
+
+        d3 = []
+        i = 0
+        for x in range(26):
+            d3.append((i, math.cos(i + self.offset)))
+            i += 0.5
+        self.offset += 0.1
+
+        d4 = []
+        i = 0
+        for x in range(26):
+            d4.append((i, math.sqrt(i * 10)))
+            i += 0.5
+
+        d5 = []
+        i = 0
+        for x in range(26):
+            d5.append((i, math.sqrt(i * self.offset)))
+            i += 0.5
+
+        flot_data = [{'data': [
+            {'data': d1, 'lines': {'show': 'true', 'fill': 'true'}},
+            {'data': d2, 'bars': {'show': 'true'}},
+            {'data': d3, 'points': {'show': 'true'}},
+            {'data': d4, 'lines': {'show': 'true'}},
+            {'data': d5, 'lines': {'show': 'true'}, 'points' : {'show': 'true'}}
+        ], 'options': {'yaxis' : { 'max' : '15' }}
+        }]
+
+        self.send_message('flot_demo', flot_data)
+
+    def stop(self):
+        self.feed.close()
+        super(MokshaDemoDataStream, self).stop()
diff --git a/moksha/apps/feeds/streams/__init__.py b/moksha/apps/feeds/streams/__init__.py
new file mode 100644
index 0000000..750debf
--- /dev/null
+++ b/moksha/apps/feeds/streams/__init__.py
@@ -0,0 +1,17 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from feedstream import FeedStream
diff --git a/moksha/apps/feeds/streams/feedstream.py b/moksha/apps/feeds/streams/feedstream.py
new file mode 100644
index 0000000..55c6be7
--- /dev/null
+++ b/moksha/apps/feeds/streams/feedstream.py
@@ -0,0 +1,289 @@
+# This file is part of Moksha.
+# Copyright (C) 2008-2009  Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors: Luke Macken <lmacken at redhat.com>
+
+import logging
+import feedparser
+import time
+import os
+
+try:
+    from cStringIO import cStringIO as StringIO
+except ImportError:
+    from StringIO import StringIO
+
+from twisted.web import client
+from twisted.web.client import HTTPPageGetter, HTTPClientFactory
+from twisted.internet import reactor, protocol, defer
+
+from datetime import timedelta
+from feedcache import Cache
+from shove import Shove
+from tg import config
+
+from moksha.hub import MokshaHub
+from moksha.api.streams import PollingDataStream
+
+log = logging.getLogger('moksha.hub')
+
+feed_storage = Shove(config['feed_cache'], compress=True)
+feed_cache = Cache(feed_storage)
+
+class ConditionalHTTPPageGetter(HTTPPageGetter):
+
+    def handleStatus_200(self):
+        """ Attempt to save the last-modified header """
+        if self.headers.has_key('last-modified'):
+            self.factory.lastModified(self.headers['last-modified'])
+
+    def handleStatus_304(self):
+        """ Close the connection """
+        self.factory.notModified()
+        self.transport.loseConnection()
+
+
+class ConditionalHTTPClientFactory(HTTPClientFactory):
+
+    protocol = ConditionalHTTPPageGetter
+
+    def __init__(self, url, method='GET', postdata=None, headers=None,
+                 agent=None, timeout=0, cookies=None, followRedirect=1):
+
+        self.url = url
+
+        if url in feed_storage:
+            lastModified = time.ctime(feed_storage[url][0])
+            if headers is not None:
+                headers['last-modified'] = lastModified
+            else:
+                headers = {'last-modified': lastModified}
+
+        HTTPClientFactory.__init__(self, url, method=method, postdata=postdata,
+                headers=headers, agent=agent, timeout=timeout, cookies=cookies,
+                followRedirect=followRedirect)
+
+        self.waiting = True
+        self.deferred = defer.Deferred()
+
+    def lastModified(self, modtime):
+        t = time.mktime(time.strptime(modtime[0], '%a, %d %b %Y %H:%M:%S %Z'))
+        parsed_feed = {}
+
+        if self.url in feed_storage:
+            current_feed = feed_storage[self.url][1]
+            if current_feed and not current_feed.get('bozo_exception'):
+                parsed_feed = current_feed
+
+        try:
+            feed_storage[self.url] = (t, parsed_feed)
+        except Exception, e:
+            log.error("Unable to store parsed_feed: %r" % parsed_feed)
+            log.exception(e)
+
+    def notModified(self):
+        if self.waiting:
+            self.waiting = False
+
+
+def conditional_get_page(url, contextFactory=None, *args, **kwargs):
+    scheme, host, port, path = client._parse(url)
+    factory = ConditionalHTTPClientFactory(url, *args, **kwargs)
+    if scheme == 'https':
+        from twisted.internet import ssl
+        if contextFactory is None:
+            contextFactory = ssl.ClientContextFactory()
+        reactor.connectSSL(host, port, factory, contextFactory)
+    else:
+        reactor.connectTCP(host, port, factory)
+    return factory.deferred
+
+
+class FeederProtocol(object):
+
+    max_age = int(config.get('feed.max_age', 300))
+    timeout = int(config.get('feed.timeout', 30))
+
+    def __init__(self):
+        self.parsed = 1
+        self.hub = MokshaHub()
+
+    def is_cached(self, site):
+        already_got = feed_storage.get(site)
+        if already_got:
+            elapsed_time = time.time() - already_got[0]
+            if elapsed_time < self.max_age:
+                return True
+            else:
+                return False
+        else:
+            return False
+
+    def on_error(self, traceback, extra_args):
+        log.error(extra_args)
+        log.exception(traceback)
+
+    def get_feed_from_cache(self, data, key=None):
+        """ Return feed data from the cache based on a given ``key`` """
+        log.debug('Getting cached feed for %s' % key)
+        return defer.succeed(feed_storage.get(key, key)[1])
+
+    def parse_feed(self, feed, url):
+        if not feed:
+            log.warning('parse_feed got %r for %s' % (feed, url))
+            return {}
+        if not isinstance(feed, basestring):
+            feed = str(feed)
+        feed = feedparser.parse(StringIO(feed))
+        assert feed
+        if feed.get('bozo_exception'):
+            bozo_exc = str(feed['bozo_exception'])
+            log.warning("Feed %s getting bozo_exception %r" % (feed, bozo_exc))
+            feed['bozo_exception'] = bozo_exc
+        return feed
+
+    def store_feed(self, feed, addr):
+        feed_storage[addr] = (time.time(), feed)
+        return feed
+
+    def get_feed(self, addr):
+        try:
+            return feed_storage[addr][1]
+        except KeyError:
+            return None
+
+    def process_feed(self, parsed_feed, addr, olddata):
+        """ Process the parsed feed.
+
+        If `olddata` is provided, this method will look for new feed entries,
+        and send notifications to the `feed.$FEED_URL` MokshaHub Topic.
+
+        :param parsed_feed: A parsed :mod:`feedcache` feed
+        :param addr: The URL of the feed
+        :param olddata: The cached feed data
+        """
+        if not parsed_feed:
+            log.error("Cannot process %r feed for %s" % (parsed_feed, addr))
+            return
+
+        chan = parsed_feed.get('channel', None)
+        if chan:
+            log.debug(chan.get('title', ''))
+
+        # Previous data provided; look for new entries.
+        if olddata:
+            oldtitles = [entry.get('title') for entry in olddata['entries']]
+            new_entries = parsed_feed.get('entries', [{}])
+            if not len(new_entries):
+                log.warning('Feed contains empty entries: %s' % addr)
+                return
+
+            # If there are no new entries, move on...
+            newtitle = new_entries[0].get('title', None)
+            if newtitle == oldtitles[0]:
+                return
+
+            # Send notifications for each new entry
+            for entry in new_entries[::-1]:
+                entry_title = entry.get('title', '[No Title]')
+                channel_link = entry.get('channel', {'link': addr})['link']
+                if entry['title'] not in oldtitles:
+                    log.info('New feed entry found: %s' % entry['title'])
+                    self.hub.send_message(['feed.%s' % channel_link, 'feeds'],
+                            {'title': entry_title, 'link': entry.get('link')})
+
+    def get_page(self, data, args):
+        return conditional_get_page(args, timeout=self.timeout)
+
+    def start(self, data=None):
+        d = defer.succeed(True)
+        for feed in data:
+            olddata = None
+            if self.is_cached(feed):
+                d.addCallback(self.get_feed_from_cache, feed)
+                d.addErrback(self.on_error, (feed, 'fetching from cache'))
+            else:
+                d.addCallback(self.get_page, feed)
+                d.addErrback(self.on_error, (feed, 'fetching'))
+                d.addCallback(self.parse_feed, feed)
+                d.addErrback(self.on_error, (feed, 'parsing'))
+                olddata = self.get_feed(feed)
+                d.addCallback(self.store_feed, feed)
+                d.addErrback(self.on_error, (feed, 'storing'))
+            d.addCallback(self.process_feed, feed, olddata)
+            d.addErrback(self.on_error, (feed, 'processing'))
+            del(olddata)
+        return d
+
+
+class FeederFactory(protocol.ClientFactory):
+
+    protocol = FeederProtocol()
+
+    def __init__(self):
+        """Initialize the Feeder Factory.
+
+        :param deferred_groups: The number of simultaneous connections
+        """
+        self.protocol.factory = self
+        self.deferred_groups = int(config.get('feed.deferred_groups', 50))
+
+    def start(self, addresses):
+        """Divide into groups all the feeds to download.
+
+        :param addresses: A list of feed urls
+        """
+        log.info("Starting the FeederFactory...")
+        if len(addresses) > self.deferred_groups:
+            url_groups = [[] for x in xrange(self.deferred_groups)]
+            for i, addr in enumerate(addresses):
+                url_groups[i % self.deferred_groups].append(addr)
+        else:
+            url_groups = [[addr] for addr in addresses]
+        log.info("Creating %d url groups" % len(url_groups))
+        for group in url_groups:
+            self.protocol.start(group)
+
+
+class FeedStream(PollingDataStream):
+    """
+    If you expose your feed widget on the moksha.widget entry point,
+    then Moksha will automatically handle polling it.  Upon new entries,
+    AMQP messages will be sent to the `feeds.$URL` queue.
+    """
+    frequency = timedelta(minutes=15)
+    #now = False
+
+    def poll(self):
+        """ Poll all feeds in our feed cache """
+        log.debug('FeedStream.poll()')
+
+        feeds = set()
+        for feed in feed_storage.keys():
+            feeds.add(str(feed))
+
+        # Read in all feeds from the `feeds.txt` file for testing...
+        if os.path.isfile('feeds.txt'):
+            feed_list = file('feeds.txt')
+            for feed in feed_list.readlines():
+                feeds.add(str(feed.strip()))
+
+        f = FeederFactory()
+        f.start(addresses=feeds)
+
+    def stop(self):
+        feed_storage.close()
+        super(FeedStream, self).stop()
diff --git a/moksha/controllers/apps.py b/moksha/controllers/apps.py
index 9abd00b..9b06d9a 100644
--- a/moksha/controllers/apps.py
+++ b/moksha/controllers/apps.py
@@ -38,15 +38,15 @@ class AppController(Controller):
 
     @expose()
     def lookup(self, app, *remainder):
-        if app not in moksha.apps:
+        if app not in moksha._apps:
             raise ApplicationNotFound(app)
-        return moksha.apps[app]['controller'], remainder
+        return moksha.get_app(app), remainder
 
     @expose('mako:moksha.templates.widget')
     def container(self, application, height=675, width=910, left=55,
                   top=50, **kw):
         """ Return an application rendered in a Moksha Widget Container """
-        app = moksha.apps.get(application)
+        app = moksha.get_app(application)
         if not app:
             raise ApplicationNotFound(application)
 
diff --git a/moksha/lib/helpers.py b/moksha/lib/helpers.py
index 771d5ca..9345d65 100644
--- a/moksha/lib/helpers.py
+++ b/moksha/lib/helpers.py
@@ -383,7 +383,7 @@ class MokshaApp(App):
 
     def process(self, d=None):
         # We return a placeholder if the app is not registered
-        if not moksha.apps.has_key(self.app):
+        if not moksha._apps.has_key(self.app):
             return MokshaWidget(self.label, 'placeholder',
                                 self.content_id,
                                 {'appname':self.app},
diff --git a/moksha/middleware/middleware.py b/moksha/middleware/middleware.py
index 03a1d1c..bbc69c6 100644
--- a/moksha/middleware/middleware.py
+++ b/moksha/middleware/middleware.py
@@ -53,7 +53,7 @@ class MokshaMiddleware(object):
         self.application = application
         self.mokshaapp = MokshaAppDispatcher(application)
 
-        moksha.apps = {}        # {'app name': tg.TGController/tg.WSGIAppController}
+        moksha._apps = {}        # {'app name': tg.TGController/tg.WSGIAppController}
         moksha._widgets = {}    # {'widget name': tw.api.Widget}
         moksha.menus = {}       # {'menu name': moksha.api.menus.MokshaMenu}
         self.engines = {}       # {'app name': sqlalchemy.engine.base.Engine}
@@ -92,11 +92,11 @@ class MokshaMiddleware(object):
         beforehand.
         """
         for app_entry in pkg_resources.iter_entry_points('moksha.application'):
-            if app_entry.name in moksha.apps:
+            if app_entry.name in moksha._apps:
                 raise MokshaException('Duplicate application name: %s' %
                                       app_entry.name)
             app_path = app_entry.dist.location
-            moksha.apps[app_entry.name] = {
+            moksha._apps[app_entry.name] = {
                     'name': app_entry.name,
                     'path': app_path,
                     }
@@ -116,9 +116,12 @@ class MokshaMiddleware(object):
             log.info('Loading %s application' % app_entry.name)
             app_class = app_entry.load()
             app_path = app_entry.dist.location
-            moksha.apps[app_entry.name].update({
-                    'name': getattr(app_class, 'name', app_entry.name),
-                    'controller': app_class(),
+            app_name = getattr(app_class, 'name', app_entry.name),
+            if isclass(app_class):
+                app = app_class()
+            moksha._apps[app_entry.name].update({
+                    'name': app_name,
+                    'controller': app_class,
                     'path': app_path,
                     'model': None,
                     })
@@ -126,9 +129,9 @@ class MokshaMiddleware(object):
                 model = __import__('%s.model' % app_entry.name,
                                    globals(), locals(),
                                    [app_entry.name])
-                moksha.apps[app_entry.name]['model'] = model
-            except ImportError:
-                pass
+                moksha._apps[app_entry.name]['model'] = model
+            except ImportError, e:
+                log.error(e)
 
     def load_wsgi_applications(self):
         log.info('Loading moksha WSGI applications')
@@ -136,7 +139,7 @@ class MokshaMiddleware(object):
             log.info('Loading %s WSGI application' % app_entry.name)
             app_class = app_entry.load()
             app_path = app_entry.dist.location
-            moksha.apps[app_entry.name] = {
+            moksha._apps[app_entry.name] = {
                     'name': getattr(app_class, 'name', app_entry.name),
                     'controller': WSGIAppController(app_class()),
                     'path': app_path,
@@ -288,14 +291,14 @@ class MokshaMiddleware(object):
         main_app_config_path = os.path.dirname(get_main_app_config_path())
         loaded_configs = []
 
-        apps += moksha.apps.values()
+        apps += moksha._apps.values()
         for app in apps:
             for configfile in ('production.ini', 'development.ini'):
                 confpath = os.path.join(app['path'], configfile)
                 if os.path.exists(confpath):
                     conf = appconfig('config:' + confpath)
                     if app.get('name'):
-                        moksha.apps[app['name']]['config'] = conf
+                        moksha._apps[app['name']]['config'] = conf
                     if app['path'] == main_app_config_path or \
                             confpath in loaded_configs:
                         continue
@@ -326,7 +329,7 @@ class MokshaMiddleware(object):
         if they don't already exist.
 
         """
-        for name, app in moksha.apps.items():
+        for name, app in moksha._apps.items():
             sa_url = app.get('config', {}).get('sqlalchemy.url', None)
             if sa_url:
                 if app['config']['__file__'] == get_moksha_config_path():
diff --git a/moksha/streams/demo/__init__.py b/moksha/streams/demo/__init__.py
deleted file mode 100644
index 8bc12eb..0000000
--- a/moksha/streams/demo/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from demostream import MokshaDemoDataStream
diff --git a/moksha/streams/demo/demostream.py b/moksha/streams/demo/demostream.py
deleted file mode 100644
index 0ed742e..0000000
--- a/moksha/streams/demo/demostream.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import math
-from random import random
-from datetime import timedelta
-
-from moksha.api.widgets.feed import Feed
-from moksha.api.streams import PollingDataStream
-
-class MokshaDemoDataStream(PollingDataStream):
-    """
-    This class provides the default Moksha demo with some fake data to render
-    """
-
-    frequency = timedelta(seconds=0.5)
-
-    # Flot demo specific variables
-    offset = 0.0
-    skip = 0
-    bars = [[0, 3], [4, 8], [8, 5], [9, 13]]
-    n = 0
-
-    # Feed demo specific variables
-    i = 0
-
-    def __init__(self, *args, **kw):
-        self.feed = Feed(url='http://doggdot.us/rss')
-        self.feed_entries = self.feed.entries()
-        super(MokshaDemoDataStream, self).__init__(*args, **kw)
-
-    def poll(self):
-        self.n += 1
-
-        if self.n % 3 == 0:
-            self.i += 1
-            entry = self.feed_entries[self.n % len(self.feed_entries)]
-            self.send_message('feed_demo', [
-                {'title': entry['title'], 'link': entry['link'], 'i': self.i},
-            ])
-
-        ## Generate flot data
-        d1 = []
-        i = 0
-        for x in range(26):
-            d1.append((i, math.sin(i + self.offset)))
-            i += 0.5
-
-        for bar in self.bars:
-            bar[1] = bar[1] + (int(random() * 3) - 1)
-            if bar[1] <= -5: bar[1] = -4
-            if bar[1] >= 15: bar[1] = 15
-        d2 = self.bars
-
-        d3 = []
-        i = 0
-        for x in range(26):
-            d3.append((i, math.cos(i + self.offset)))
-            i += 0.5
-        self.offset += 0.1
-
-        d4 = []
-        i = 0
-        for x in range(26):
-            d4.append((i, math.sqrt(i * 10)))
-            i += 0.5
-
-        d5 = []
-        i = 0
-        for x in range(26):
-            d5.append((i, math.sqrt(i * self.offset)))
-            i += 0.5
-
-        flot_data = [{'data': [
-            {'data': d1, 'lines': {'show': 'true', 'fill': 'true'}},
-            {'data': d2, 'bars': {'show': 'true'}},
-            {'data': d3, 'points': {'show': 'true'}},
-            {'data': d4, 'lines': {'show': 'true'}},
-            {'data': d5, 'lines': {'show': 'true'}, 'points' : {'show': 'true'}}
-        ], 'options': {'yaxis' : { 'max' : '15' }}
-        }]
-
-        self.send_message('flot_demo', flot_data)
-
-    def stop(self):
-        self.feed.close()
-        super(MokshaDemoDataStream, self).stop()
diff --git a/moksha/streams/feed/__init__.py b/moksha/streams/feed/__init__.py
deleted file mode 100644
index 750debf..0000000
--- a/moksha/streams/feed/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from feedstream import FeedStream
diff --git a/moksha/streams/feed/feedstream.py b/moksha/streams/feed/feedstream.py
deleted file mode 100644
index 55c6be7..0000000
--- a/moksha/streams/feed/feedstream.py
+++ /dev/null
@@ -1,289 +0,0 @@
-# This file is part of Moksha.
-# Copyright (C) 2008-2009  Red Hat, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Authors: Luke Macken <lmacken at redhat.com>
-
-import logging
-import feedparser
-import time
-import os
-
-try:
-    from cStringIO import cStringIO as StringIO
-except ImportError:
-    from StringIO import StringIO
-
-from twisted.web import client
-from twisted.web.client import HTTPPageGetter, HTTPClientFactory
-from twisted.internet import reactor, protocol, defer
-
-from datetime import timedelta
-from feedcache import Cache
-from shove import Shove
-from tg import config
-
-from moksha.hub import MokshaHub
-from moksha.api.streams import PollingDataStream
-
-log = logging.getLogger('moksha.hub')
-
-feed_storage = Shove(config['feed_cache'], compress=True)
-feed_cache = Cache(feed_storage)
-
-class ConditionalHTTPPageGetter(HTTPPageGetter):
-
-    def handleStatus_200(self):
-        """ Attempt to save the last-modified header """
-        if self.headers.has_key('last-modified'):
-            self.factory.lastModified(self.headers['last-modified'])
-
-    def handleStatus_304(self):
-        """ Close the connection """
-        self.factory.notModified()
-        self.transport.loseConnection()
-
-
-class ConditionalHTTPClientFactory(HTTPClientFactory):
-
-    protocol = ConditionalHTTPPageGetter
-
-    def __init__(self, url, method='GET', postdata=None, headers=None,
-                 agent=None, timeout=0, cookies=None, followRedirect=1):
-
-        self.url = url
-
-        if url in feed_storage:
-            lastModified = time.ctime(feed_storage[url][0])
-            if headers is not None:
-                headers['last-modified'] = lastModified
-            else:
-                headers = {'last-modified': lastModified}
-
-        HTTPClientFactory.__init__(self, url, method=method, postdata=postdata,
-                headers=headers, agent=agent, timeout=timeout, cookies=cookies,
-                followRedirect=followRedirect)
-
-        self.waiting = True
-        self.deferred = defer.Deferred()
-
-    def lastModified(self, modtime):
-        t = time.mktime(time.strptime(modtime[0], '%a, %d %b %Y %H:%M:%S %Z'))
-        parsed_feed = {}
-
-        if self.url in feed_storage:
-            current_feed = feed_storage[self.url][1]
-            if current_feed and not current_feed.get('bozo_exception'):
-                parsed_feed = current_feed
-
-        try:
-            feed_storage[self.url] = (t, parsed_feed)
-        except Exception, e:
-            log.error("Unable to store parsed_feed: %r" % parsed_feed)
-            log.exception(e)
-
-    def notModified(self):
-        if self.waiting:
-            self.waiting = False
-
-
-def conditional_get_page(url, contextFactory=None, *args, **kwargs):
-    scheme, host, port, path = client._parse(url)
-    factory = ConditionalHTTPClientFactory(url, *args, **kwargs)
-    if scheme == 'https':
-        from twisted.internet import ssl
-        if contextFactory is None:
-            contextFactory = ssl.ClientContextFactory()
-        reactor.connectSSL(host, port, factory, contextFactory)
-    else:
-        reactor.connectTCP(host, port, factory)
-    return factory.deferred
-
-
-class FeederProtocol(object):
-
-    max_age = int(config.get('feed.max_age', 300))
-    timeout = int(config.get('feed.timeout', 30))
-
-    def __init__(self):
-        self.parsed = 1
-        self.hub = MokshaHub()
-
-    def is_cached(self, site):
-        already_got = feed_storage.get(site)
-        if already_got:
-            elapsed_time = time.time() - already_got[0]
-            if elapsed_time < self.max_age:
-                return True
-            else:
-                return False
-        else:
-            return False
-
-    def on_error(self, traceback, extra_args):
-        log.error(extra_args)
-        log.exception(traceback)
-
-    def get_feed_from_cache(self, data, key=None):
-        """ Return feed data from the cache based on a given ``key`` """
-        log.debug('Getting cached feed for %s' % key)
-        return defer.succeed(feed_storage.get(key, key)[1])
-
-    def parse_feed(self, feed, url):
-        if not feed:
-            log.warning('parse_feed got %r for %s' % (feed, url))
-            return {}
-        if not isinstance(feed, basestring):
-            feed = str(feed)
-        feed = feedparser.parse(StringIO(feed))
-        assert feed
-        if feed.get('bozo_exception'):
-            bozo_exc = str(feed['bozo_exception'])
-            log.warning("Feed %s getting bozo_exception %r" % (feed, bozo_exc))
-            feed['bozo_exception'] = bozo_exc
-        return feed
-
-    def store_feed(self, feed, addr):
-        feed_storage[addr] = (time.time(), feed)
-        return feed
-
-    def get_feed(self, addr):
-        try:
-            return feed_storage[addr][1]
-        except KeyError:
-            return None
-
-    def process_feed(self, parsed_feed, addr, olddata):
-        """ Process the parsed feed.
-
-        If `olddata` is provided, this method will look for new feed entries,
-        and send notifications to the `feed.$FEED_URL` MokshaHub Topic.
-
-        :param parsed_feed: A parsed :mod:`feedcache` feed
-        :param addr: The URL of the feed
-        :param olddata: The cached feed data
-        """
-        if not parsed_feed:
-            log.error("Cannot process %r feed for %s" % (parsed_feed, addr))
-            return
-
-        chan = parsed_feed.get('channel', None)
-        if chan:
-            log.debug(chan.get('title', ''))
-
-        # Previous data provided; look for new entries.
-        if olddata:
-            oldtitles = [entry.get('title') for entry in olddata['entries']]
-            new_entries = parsed_feed.get('entries', [{}])
-            if not len(new_entries):
-                log.warning('Feed contains empty entries: %s' % addr)
-                return
-
-            # If there are no new entries, move on...
-            newtitle = new_entries[0].get('title', None)
-            if newtitle == oldtitles[0]:
-                return
-
-            # Send notifications for each new entry
-            for entry in new_entries[::-1]:
-                entry_title = entry.get('title', '[No Title]')
-                channel_link = entry.get('channel', {'link': addr})['link']
-                if entry['title'] not in oldtitles:
-                    log.info('New feed entry found: %s' % entry['title'])
-                    self.hub.send_message(['feed.%s' % channel_link, 'feeds'],
-                            {'title': entry_title, 'link': entry.get('link')})
-
-    def get_page(self, data, args):
-        return conditional_get_page(args, timeout=self.timeout)
-
-    def start(self, data=None):
-        d = defer.succeed(True)
-        for feed in data:
-            olddata = None
-            if self.is_cached(feed):
-                d.addCallback(self.get_feed_from_cache, feed)
-                d.addErrback(self.on_error, (feed, 'fetching from cache'))
-            else:
-                d.addCallback(self.get_page, feed)
-                d.addErrback(self.on_error, (feed, 'fetching'))
-                d.addCallback(self.parse_feed, feed)
-                d.addErrback(self.on_error, (feed, 'parsing'))
-                olddata = self.get_feed(feed)
-                d.addCallback(self.store_feed, feed)
-                d.addErrback(self.on_error, (feed, 'storing'))
-            d.addCallback(self.process_feed, feed, olddata)
-            d.addErrback(self.on_error, (feed, 'processing'))
-            del(olddata)
-        return d
-
-
-class FeederFactory(protocol.ClientFactory):
-
-    protocol = FeederProtocol()
-
-    def __init__(self):
-        """Initialize the Feeder Factory.
-
-        :param deferred_groups: The number of simultaneous connections
-        """
-        self.protocol.factory = self
-        self.deferred_groups = int(config.get('feed.deferred_groups', 50))
-
-    def start(self, addresses):
-        """Divide into groups all the feeds to download.
-
-        :param addresses: A list of feed urls
-        """
-        log.info("Starting the FeederFactory...")
-        if len(addresses) > self.deferred_groups:
-            url_groups = [[] for x in xrange(self.deferred_groups)]
-            for i, addr in enumerate(addresses):
-                url_groups[i % self.deferred_groups].append(addr)
-        else:
-            url_groups = [[addr] for addr in addresses]
-        log.info("Creating %d url groups" % len(url_groups))
-        for group in url_groups:
-            self.protocol.start(group)
-
-
-class FeedStream(PollingDataStream):
-    """
-    If you expose your feed widget on the moksha.widget entry point,
-    then Moksha will automatically handle polling it.  Upon new entries,
-    AMQP messages will be sent to the `feeds.$URL` queue.
-    """
-    frequency = timedelta(minutes=15)
-    #now = False
-
-    def poll(self):
-        """ Poll all feeds in our feed cache """
-        log.debug('FeedStream.poll()')
-
-        feeds = set()
-        for feed in feed_storage.keys():
-            feeds.add(str(feed))
-
-        # Read in all feeds from the `feeds.txt` file for testing...
-        if os.path.isfile('feeds.txt'):
-            feed_list = file('feeds.txt')
-            for feed in feed_list.readlines():
-                feeds.add(str(feed.strip()))
-
-        f = FeederFactory()
-        f.start(addresses=feeds)
-
-    def stop(self):
-        feed_storage.close()
-        super(FeedStream, self).stop()




More information about the Moksha-commits mailing list