[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 = "↑"
- 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('←');
- }
- else {
- self.presenceShown = true;
- $("#presence").show();
- $("#presenceToggle").html('→');
- }
- 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 = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- };
- 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">
- →
- </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 = "↑"
- 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 = "↑"
- 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('←');
- }
- else {
- self.presenceShown = true;
- $("#presence").show();
- $("#presenceToggle").html('→');
- }
- 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 = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- };
- 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">
- →
- </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">
- →
- </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 = "↑"
+ 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('←');
+ }
+ else {
+ self.presenceShown = true;
+ $("#presence").show();
+ $("#presenceToggle").html('→');
+ }
+ 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 = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ };
+ 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">
+ →
+ </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 = "↑"
+ 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 = "↑"
+ 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('←');
+ }
+ else {
+ self.presenceShown = true;
+ $("#presence").show();
+ $("#presenceToggle").html('→');
+ }
+ 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 = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ };
+ 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">
+ →
+ </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">
+ →
+ </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">>>> </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> </i></span>
- * <span class="ui-toolbar-btn-center">
- * <button><span>{{text}}</span></button>
- * </span>
- * <span class="ui-toolbar-btn-right"><i> </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>
- *
- * </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> </i></span>
- * <span class="ui-toolbar-btn-center">
- * <button><span>{{text}}</span></button>
- * </span>
- * <span class="ui-toolbar-btn-right"><i> </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…',
- 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>© 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">>>> </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> </i></span>
+ * <span class="ui-toolbar-btn-center">
+ * <button><span>{{text}}</span></button>
+ * </span>
+ * <span class="ui-toolbar-btn-right"><i> </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>
+ *
+ * </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> </i></span>
+ * <span class="ui-toolbar-btn-center">
+ * <button><span>{{text}}</span></button>
+ * </span>
+ * <span class="ui-toolbar-btn-right"><i> </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…',
+ 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>© 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">>>> </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> </i></span>
- * <span class="ui-toolbar-btn-center">
- * <button><span>{{text}}</span></button>
- * </span>
- * <span class="ui-toolbar-btn-right"><i> </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>
- *
- * </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> </i></span>
- * <span class="ui-toolbar-btn-center">
- * <button><span>{{text}}</span></button>
- * </span>
- * <span class="ui-toolbar-btn-right"><i> </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…',
- 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>© 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">>>> </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> </i></span>
+ * <span class="ui-toolbar-btn-center">
+ * <button><span>{{text}}</span></button>
+ * </span>
+ * <span class="ui-toolbar-btn-right"><i> </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>
+ *
+ * </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> </i></span>
+ * <span class="ui-toolbar-btn-center">
+ * <button><span>{{text}}</span></button>
+ * </span>
+ * <span class="ui-toolbar-btn-right"><i> </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…',
+ 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>© 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