From d99ed1f2e55c55fe8b2849d5e408f7c24f5fc956 Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Fri, 10 Jun 2011 16:44:20 +0200 Subject: [PATCH] the Python server --- python/bootstrap.py | 260 +++ python/buildout.cfg | 106 + python/data/.placeholder | 0 python/data/cache/.placeholder | 0 python/data/logs/.placeholder | 0 python/data/logs/mongodb/.placeholder | 0 python/data/mongodb/.placeholder | 0 python/dev.cfg | 7 + python/etc/.placeholder | 0 python/prod.cfg | 10 + python/src/sailing.connector/README.txt | 6 + python/src/sailing.connector/docs/HISTORY.txt | 7 + .../src/sailing.connector/sailing/__init__.py | 6 + .../sailing/connector/__init__.py | 84 + .../sailing/connector/provider.py | 275 +++ python/src/sailing.connector/setup.py | 34 + python/src/sailing.db/README.txt | 6 + python/src/sailing.db/docs/HISTORY.txt | 7 + python/src/sailing.db/sailing/__init__.py | 6 + python/src/sailing.db/sailing/db/__init__.py | 45 + python/src/sailing.db/sailing/db/config.py | 11 + python/src/sailing.db/sailing/db/database.py | 71 + .../sailing.db/sailing/db/model/__init__.py | 58 + .../src/sailing.db/sailing/db/model/base.py | 277 +++ .../sailing.db/sailing/db/model/entities.py | 83 + .../src/sailing.db/sailing/db/model/util.py | 32 + .../src/sailing.db/sailing/db/monitoring.py | 35 + python/src/sailing.db/setup.py | 32 + python/src/sailing.web/MANIFEST.in | 3 + python/src/sailing.web/README.txt | 6 + python/src/sailing.web/docs/HISTORY.txt | 7 + python/src/sailing.web/sailing/__init__.py | 6 + .../src/sailing.web/sailing/web/__init__.py | 29 + .../sailing/web/adapter/__init__.py | 0 .../sailing/web/adapter/configure.zcml | 10 + .../sailing/web/browser/__init__.py | 0 .../sailing/web/browser/configure.zcml | 43 + .../sailing.web/sailing/web/browser/core.py | 185 ++ .../sailing/web/browser/functions.py | 481 +++++ .../web/browser/moderator-static/app.js | 6 + .../browser/moderator-static/arrow-bottom.png | Bin 0 -> 317 bytes .../browser/moderator-static/arrow-left.png | Bin 0 -> 421 bytes .../browser/moderator-static/arrow-right.png | Bin 0 -> 420 bytes .../browser/moderator-static/arrow-top.png | Bin 0 -> 286 bytes .../moderator-static/border-activity.png | Bin 0 -> 148 bytes .../web/browser/moderator-static/freeze.png | Bin 0 -> 179 bytes .../web/browser/moderator-static/index.html | 1714 +++++++++++++++++ .../moderator-static/iphone-splash-screen.png | Bin 0 -> 60985 bytes .../web/browser/moderator-static/iphone.html | 120 ++ .../web/browser/moderator-static/jquery.js | 18 + .../web/browser/moderator-static/mobile.css | 112 ++ .../web/browser/moderator-static/overall.html | 1145 +++++++++++ .../browser/moderator-static/refresh-icon.png | Bin 0 -> 735 bytes .../web/browser/moderator-static/sap-logo.png | Bin 0 -> 8421 bytes .../moderator-static/sap-sailing-app-icon.png | Bin 0 -> 12354 bytes .../web/browser/moderator-static/screen.css | 452 +++++ .../moderator-static/sort-arrow-bottom.png | Bin 0 -> 326 bytes .../moderator-static/sort-arrow-top.png | Bin 0 -> 321 bytes .../web/browser/moderator-static/style.css | 0 .../sailing/web/browser/static/core.js | 49 + .../css/jquery-ui-1.8.11.custom.css.txt | 502 +++++ .../static/css/jquery.timeslider.css.txt | 117 ++ .../web/browser/static/css/styles.css.txt | 174 ++ .../static/images/ajax-loader-small.gif | Bin 0 -> 723 bytes .../static/images/ajax-loader-whitebg.gif | Bin 0 -> 3208 bytes .../web/browser/static/images/ajax-loader.gif | Bin 0 -> 2892 bytes .../web/browser/static/images/boat.png | Bin 0 -> 6082 bytes .../web/browser/static/images/boat16.png | Bin 0 -> 1179 bytes .../web/browser/static/images/boat32.png | Bin 0 -> 4267 bytes .../static/images/button_minus_green.png | Bin 0 -> 11515 bytes .../static/images/button_sort_down.gif | Bin 0 -> 88 bytes .../static/images/button_sort_none.gif | Bin 0 -> 86 bytes .../browser/static/images/button_sort_up.gif | Bin 0 -> 89 bytes .../web/browser/static/images/favicon.ico | Bin 0 -> 5430 bytes .../web/browser/static/images/plus-icon.png | Bin 0 -> 3031 bytes .../web/browser/static/images/pt_controls.png | Bin 0 -> 1049 bytes .../web/browser/static/images/sort_asc.png | Bin 0 -> 263 bytes .../static/images/sort_asc_disabled.png | Bin 0 -> 252 bytes .../web/browser/static/images/sort_both.png | Bin 0 -> 282 bytes .../web/browser/static/images/sort_desc.png | Bin 0 -> 260 bytes .../static/images/sort_desc_disabled.png | Bin 0 -> 251 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../static/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../static/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../static/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../static/images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../static/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../web/browser/static/js/jquery-1.4.4.min.js | 167 ++ .../static/js/jquery-ui-timepicker-addon.js | 985 ++++++++++ .../js/jquery-ui/i18n/jquery-ui-i18n.js | 1379 +++++++++++++ .../jquery-ui/i18n/jquery.ui.datepicker-af.js | 23 + .../i18n/jquery.ui.datepicker-ar-DZ.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-ar.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-az.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-bg.js | 24 + .../jquery-ui/i18n/jquery.ui.datepicker-bs.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-ca.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-cs.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-da.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-de.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-el.js | 23 + .../i18n/jquery.ui.datepicker-en-AU.js | 23 + .../i18n/jquery.ui.datepicker-en-GB.js | 23 + .../i18n/jquery.ui.datepicker-en-NZ.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-eo.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-es.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-et.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-eu.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-fa.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-fi.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-fo.js | 23 + .../i18n/jquery.ui.datepicker-fr-CH.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-fr.js | 25 + .../jquery-ui/i18n/jquery.ui.datepicker-gl.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-he.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-hr.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-hu.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-hy.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-id.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-is.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-it.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-ja.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-ko.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-kz.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-lt.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-lv.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-ml.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-ms.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-nl.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-no.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-pl.js | 23 + .../i18n/jquery.ui.datepicker-pt-BR.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-pt.js | 22 + .../jquery-ui/i18n/jquery.ui.datepicker-rm.js | 21 + .../jquery-ui/i18n/jquery.ui.datepicker-ro.js | 26 + .../jquery-ui/i18n/jquery.ui.datepicker-ru.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-sk.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-sl.js | 24 + .../jquery-ui/i18n/jquery.ui.datepicker-sq.js | 23 + .../i18n/jquery.ui.datepicker-sr-SR.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-sr.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-sv.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-ta.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-th.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-tj.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-tr.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-uk.js | 23 + .../jquery-ui/i18n/jquery.ui.datepicker-vi.js | 23 + .../i18n/jquery.ui.datepicker-zh-CN.js | 23 + .../i18n/jquery.ui.datepicker-zh-HK.js | 23 + .../i18n/jquery.ui.datepicker-zh-TW.js | 23 + .../js/jquery-ui/jquery.effects.core.min.js | 30 + .../js/jquery-ui/jquery.ui.accordion.min.js | 30 + .../jquery-ui/jquery.ui.autocomplete.min.js | 32 + .../static/js/jquery-ui/jquery.ui.core.min.js | 17 + .../js/jquery-ui/jquery.ui.datepicker.min.js | 82 + .../js/jquery-ui/jquery.ui.dialog.min.js | 40 + .../js/jquery-ui/jquery.ui.mouse.min.js | 17 + .../js/jquery-ui/jquery.ui.position.min.js | 16 + .../js/jquery-ui/jquery.ui.resizable.min.js | 47 + .../js/jquery-ui/jquery.ui.selectable.min.js | 22 + .../js/jquery-ui/jquery.ui.slider.min.js | 33 + .../js/jquery-ui/jquery.ui.sortable.min.js | 60 + .../static/js/jquery-ui/jquery.ui.tabs.min.js | 35 + .../js/jquery-ui/jquery.ui.widget.min.js | 15 + .../web/browser/static/js/jquery.form.js | 815 ++++++++ .../static/js/jquery.googlemaps1.01.js | 417 ++++ .../browser/static/js/jquery.timeslider.js | 486 +++++ .../web/browser/static/js/mapmarker.js | 413 ++++ .../sailing/web/browser/static/maps.js | 237 +++ .../web/browser/templates/database-stats.pt | 28 + .../templates/general-competitor-info.pt | 51 + .../browser/templates/general-race-info.pt | 55 + .../web/browser/templates/java-connector.pt | 89 + .../web/browser/templates/leaderboard-info.pt | 48 + .../web/browser/templates/leaderboard-live.pt | 1693 ++++++++++++++++ .../web/browser/templates/leaderboard.pt | 37 + .../web/browser/templates/live-info-view.pt | 52 + .../web/browser/templates/live-info.pt | 45 + .../web/browser/templates/maintemplate.pt | 44 + .../browser/templates/map-overview-details.pt | 141 ++ .../web/browser/templates/map-overview.pt | 45 + .../sailing/web/browser/templates/start.pt | 126 ++ .../web/browser/templates/udp-configurator.pt | 86 + .../web/browser/templates/waypoint-info.pt | 16 + .../browser/templates/wind-settings-info.pt | 76 + .../web/browser/templates/wind-settings.pt | 45 + python/src/sailing.web/sailing/web/config.py | 44 + .../sailing.web/sailing/web/configure.zcml | 8 + .../src/sailing.web/sailing/web/interfaces.py | 1 + .../sailing.web/sailing/web/locale/base.pot | 0 .../sailing.web/sailing/web/tests/__init__.py | 0 .../sailing/web/tests/data/events.txt | 1 + .../sailing/web/tests/data/events2.txt | 5 + .../sailing/web/tests/data/events2updated.txt | 5 + .../sailing/web/tests/data/fixes.txt | 1 + .../sailing/web/tests/data/race.txt | 1 + .../sailing/web/tests/data/race_t1.txt | 1 + .../sailing/web/tests/data/waypoints.txt | 1 + .../sailing/web/tests/test_base.py | 268 +++ .../sailing.web/sailing/web/tests/utils.py | 50 + python/src/sailing.web/sailing/web/util.py | 83 + python/src/sailing.web/setup.py | 37 + python/templates/app_debug.sh | 8 + python/templates/app_production_start.sh | 9 + python/templates/app_production_stop.sh | 9 + python/templates/db.ini | 20 + python/templates/mongodb-master.cfg | 8 + python/templates/webserver-dev.ini | 44 + python/templates/webserver-prod.ini | 39 + 217 files changed, 16739 insertions(+) create mode 100644 python/bootstrap.py create mode 100644 python/buildout.cfg create mode 100644 python/data/.placeholder create mode 100644 python/data/cache/.placeholder create mode 100644 python/data/logs/.placeholder create mode 100644 python/data/logs/mongodb/.placeholder create mode 100644 python/data/mongodb/.placeholder create mode 100644 python/dev.cfg create mode 100644 python/etc/.placeholder create mode 100644 python/prod.cfg create mode 100644 python/src/sailing.connector/README.txt create mode 100644 python/src/sailing.connector/docs/HISTORY.txt create mode 100644 python/src/sailing.connector/sailing/__init__.py create mode 100644 python/src/sailing.connector/sailing/connector/__init__.py create mode 100644 python/src/sailing.connector/sailing/connector/provider.py create mode 100644 python/src/sailing.connector/setup.py create mode 100644 python/src/sailing.db/README.txt create mode 100644 python/src/sailing.db/docs/HISTORY.txt create mode 100644 python/src/sailing.db/sailing/__init__.py create mode 100644 python/src/sailing.db/sailing/db/__init__.py create mode 100644 python/src/sailing.db/sailing/db/config.py create mode 100644 python/src/sailing.db/sailing/db/database.py create mode 100644 python/src/sailing.db/sailing/db/model/__init__.py create mode 100644 python/src/sailing.db/sailing/db/model/base.py create mode 100644 python/src/sailing.db/sailing/db/model/entities.py create mode 100644 python/src/sailing.db/sailing/db/model/util.py create mode 100644 python/src/sailing.db/sailing/db/monitoring.py create mode 100644 python/src/sailing.db/setup.py create mode 100644 python/src/sailing.web/MANIFEST.in create mode 100644 python/src/sailing.web/README.txt create mode 100644 python/src/sailing.web/docs/HISTORY.txt create mode 100644 python/src/sailing.web/sailing/__init__.py create mode 100644 python/src/sailing.web/sailing/web/__init__.py create mode 100644 python/src/sailing.web/sailing/web/adapter/__init__.py create mode 100644 python/src/sailing.web/sailing/web/adapter/configure.zcml create mode 100644 python/src/sailing.web/sailing/web/browser/__init__.py create mode 100644 python/src/sailing.web/sailing/web/browser/configure.zcml create mode 100644 python/src/sailing.web/sailing/web/browser/core.py create mode 100644 python/src/sailing.web/sailing/web/browser/functions.py create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/app.js create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/arrow-bottom.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/arrow-left.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/arrow-right.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/arrow-top.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/border-activity.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/freeze.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/index.html create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/iphone-splash-screen.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/iphone.html create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/jquery.js create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/mobile.css create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/overall.html create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/refresh-icon.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/sap-logo.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/sap-sailing-app-icon.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/screen.css create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-bottom.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-top.png create mode 100644 python/src/sailing.web/sailing/web/browser/moderator-static/style.css create mode 100644 python/src/sailing.web/sailing/web/browser/static/core.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/css/jquery-ui-1.8.11.custom.css.txt create mode 100644 python/src/sailing.web/sailing/web/browser/static/css/jquery.timeslider.css.txt create mode 100644 python/src/sailing.web/sailing/web/browser/static/css/styles.css.txt create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-small.gif create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-whitebg.gif create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ajax-loader.gif create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/boat.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/boat16.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/boat32.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/button_minus_green.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/button_sort_down.gif create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/button_sort_none.gif create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/button_sort_up.gif create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/favicon.ico create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/plus-icon.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/pt_controls.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/sort_asc.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/sort_asc_disabled.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/sort_both.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/sort_desc.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/sort_desc_disabled.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-icons_222222_256x240.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-icons_2e83ff_256x240.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-icons_454545_256x240.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-icons_888888_256x240.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/images/ui-icons_cd0a0a_256x240.png create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-1.4.4.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui-timepicker-addon.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery-ui-i18n.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-af.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ar-DZ.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ar.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-az.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-bg.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-bs.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ca.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-cs.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-da.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-de.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-el.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-en-AU.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-en-GB.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-en-NZ.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-eo.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-es.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-et.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-eu.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-fa.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-fi.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-fo.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-fr-CH.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-fr.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-gl.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-he.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-hr.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-hu.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-hy.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-id.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-is.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-it.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ja.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ko.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-kz.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-lt.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-lv.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ml.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ms.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-nl.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-no.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-pl.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-pt-BR.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-pt.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-rm.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ro.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ru.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-sk.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-sl.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-sq.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-sr-SR.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-sr.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-sv.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-ta.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-th.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-tj.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-tr.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-uk.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-vi.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-zh-CN.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-zh-HK.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/i18n/jquery.ui.datepicker-zh-TW.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.effects.core.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.accordion.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.autocomplete.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.core.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.datepicker.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.dialog.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.mouse.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.position.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.resizable.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.selectable.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.slider.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.sortable.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.tabs.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery-ui/jquery.ui.widget.min.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery.form.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery.googlemaps1.01.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/jquery.timeslider.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/js/mapmarker.js create mode 100644 python/src/sailing.web/sailing/web/browser/static/maps.js create mode 100644 python/src/sailing.web/sailing/web/browser/templates/database-stats.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/general-competitor-info.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/general-race-info.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/java-connector.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/leaderboard-info.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/leaderboard-live.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/leaderboard.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/live-info-view.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/live-info.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/maintemplate.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/map-overview-details.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/map-overview.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/start.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/udp-configurator.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/waypoint-info.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/wind-settings-info.pt create mode 100644 python/src/sailing.web/sailing/web/browser/templates/wind-settings.pt create mode 100644 python/src/sailing.web/sailing/web/config.py create mode 100644 python/src/sailing.web/sailing/web/configure.zcml create mode 100644 python/src/sailing.web/sailing/web/interfaces.py create mode 100644 python/src/sailing.web/sailing/web/locale/base.pot create mode 100644 python/src/sailing.web/sailing/web/tests/__init__.py create mode 100644 python/src/sailing.web/sailing/web/tests/data/events.txt create mode 100644 python/src/sailing.web/sailing/web/tests/data/events2.txt create mode 100644 python/src/sailing.web/sailing/web/tests/data/events2updated.txt create mode 100644 python/src/sailing.web/sailing/web/tests/data/fixes.txt create mode 100644 python/src/sailing.web/sailing/web/tests/data/race.txt create mode 100644 python/src/sailing.web/sailing/web/tests/data/race_t1.txt create mode 100644 python/src/sailing.web/sailing/web/tests/data/waypoints.txt create mode 100644 python/src/sailing.web/sailing/web/tests/test_base.py create mode 100644 python/src/sailing.web/sailing/web/tests/utils.py create mode 100644 python/src/sailing.web/sailing/web/util.py create mode 100644 python/src/sailing.web/setup.py create mode 100755 python/templates/app_debug.sh create mode 100755 python/templates/app_production_start.sh create mode 100755 python/templates/app_production_stop.sh create mode 100644 python/templates/db.ini create mode 100644 python/templates/mongodb-master.cfg create mode 100644 python/templates/webserver-dev.ini create mode 100644 python/templates/webserver-prod.ini diff --git a/python/bootstrap.py b/python/bootstrap.py new file mode 100644 index 00000000000..5f2cb0835c9 --- /dev/null +++ b/python/bootstrap.py @@ -0,0 +1,260 @@ +############################################################################## +# +# Copyright (c) 2006 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +"""Bootstrap a buildout-based project + +Simply run this script in a directory containing a buildout.cfg. +The script accepts buildout command-line options, so you can +use the -c option to specify an alternate configuration file. +""" + +import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess +from optparse import OptionParser + +if sys.platform == 'win32': + def quote(c): + if ' ' in c: + return '"%s"' % c # work around spawn lamosity on windows + else: + return c +else: + quote = str + +# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. +stdout, stderr = subprocess.Popen( + [sys.executable, '-Sc', + 'try:\n' + ' import ConfigParser\n' + 'except ImportError:\n' + ' print 1\n' + 'else:\n' + ' print 0\n'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() +has_broken_dash_S = bool(int(stdout.strip())) + +# In order to be more robust in the face of system Pythons, we want to +# run without site-packages loaded. This is somewhat tricky, in +# particular because Python 2.6's distutils imports site, so starting +# with the -S flag is not sufficient. However, we'll start with that: +if not has_broken_dash_S and 'site' in sys.modules: + # We will restart with python -S. + args = sys.argv[:] + args[0:0] = [sys.executable, '-S'] + args = map(quote, args) + os.execv(sys.executable, args) +# Now we are running with -S. We'll get the clean sys.path, import site +# because distutils will do it later, and then reset the path and clean +# out any namespace packages from site-packages that might have been +# loaded by .pth files. +clean_path = sys.path[:] +import site +sys.path[:] = clean_path +for k, v in sys.modules.items(): + if k in ('setuptools', 'pkg_resources') or ( + hasattr(v, '__path__') and + len(v.__path__)==1 and + not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))): + # This is a namespace package. Remove it. + sys.modules.pop(k) + +is_jython = sys.platform.startswith('java') + +setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' +distribute_source = 'http://python-distribute.org/distribute_setup.py' + +# parsing arguments +def normalize_to_url(option, opt_str, value, parser): + if value: + if '://' not in value: # It doesn't smell like a URL. + value = 'file://%s' % ( + urllib.pathname2url( + os.path.abspath(os.path.expanduser(value))),) + if opt_str == '--download-base' and not value.endswith('/'): + # Download base needs a trailing slash to make the world happy. + value += '/' + else: + value = None + name = opt_str[2:].replace('-', '_') + setattr(parser.values, name, value) + +usage = '''\ +[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] + +Bootstraps a buildout-based project. + +Simply run this script in a directory containing a buildout.cfg, using the +Python that you want bin/buildout to use. + +Note that by using --setup-source and --download-base to point to +local resources, you can keep this script from going over the network. +''' + +parser = OptionParser(usage=usage) +parser.add_option("-v", "--version", dest="version", + help="use a specific zc.buildout version") +parser.add_option("-d", "--distribute", + action="store_true", dest="use_distribute", default=False, + help="Use Distribute rather than Setuptools.") +parser.add_option("--setup-source", action="callback", dest="setup_source", + callback=normalize_to_url, nargs=1, type="string", + help=("Specify a URL or file location for the setup file. " + "If you use Setuptools, this will default to " + + setuptools_source + "; if you use Distribute, this " + "will default to " + distribute_source +".")) +parser.add_option("--download-base", action="callback", dest="download_base", + callback=normalize_to_url, nargs=1, type="string", + help=("Specify a URL or directory for downloading " + "zc.buildout and either Setuptools or Distribute. " + "Defaults to PyPI.")) +parser.add_option("--eggs", + help=("Specify a directory for storing eggs. Defaults to " + "a temporary directory that is deleted when the " + "bootstrap script completes.")) +parser.add_option("-t", "--accept-buildout-test-releases", + dest='accept_buildout_test_releases', + action="store_true", default=False, + help=("Normally, if you do not specify a --version, the " + "bootstrap script and buildout gets the newest " + "*final* versions of zc.buildout and its recipes and " + "extensions for you. If you use this flag, " + "bootstrap and buildout will get the newest releases " + "even if they are alphas or betas.")) +parser.add_option("-c", None, action="store", dest="config_file", + help=("Specify the path to the buildout configuration " + "file to be used.")) + +options, args = parser.parse_args() + +# if -c was provided, we push it back into args for buildout's main function +if options.config_file is not None: + args += ['-c', options.config_file] + +if options.eggs: + eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) +else: + eggs_dir = tempfile.mkdtemp() + +if options.setup_source is None: + if options.use_distribute: + options.setup_source = distribute_source + else: + options.setup_source = setuptools_source + +if options.accept_buildout_test_releases: + args.append('buildout:accept-buildout-test-releases=true') +args.append('bootstrap') + +try: + import pkg_resources + import setuptools # A flag. Sometimes pkg_resources is installed alone. + if not hasattr(pkg_resources, '_distribute'): + raise ImportError +except ImportError: + ez_code = urllib2.urlopen( + options.setup_source).read().replace('\r\n', '\n') + ez = {} + exec ez_code in ez + setup_args = dict(to_dir=eggs_dir, download_delay=0) + if options.download_base: + setup_args['download_base'] = options.download_base + if options.use_distribute: + setup_args['no_fake'] = True + ez['use_setuptools'](**setup_args) + if 'pkg_resources' in sys.modules: + reload(sys.modules['pkg_resources']) + import pkg_resources + # This does not (always?) update the default working set. We will + # do it. + for path in sys.path: + if path not in pkg_resources.working_set.entries: + pkg_resources.working_set.add_entry(path) + +cmd = [quote(sys.executable), + '-c', + quote('from setuptools.command.easy_install import main; main()'), + '-mqNxd', + quote(eggs_dir)] + +if not has_broken_dash_S: + cmd.insert(1, '-S') + +find_links = options.download_base +if not find_links: + find_links = os.environ.get('bootstrap-testing-find-links') +if find_links: + cmd.extend(['-f', quote(find_links)]) + +if options.use_distribute: + setup_requirement = 'distribute' +else: + setup_requirement = 'setuptools' +ws = pkg_resources.working_set +setup_requirement_path = ws.find( + pkg_resources.Requirement.parse(setup_requirement)).location +env = dict( + os.environ, + PYTHONPATH=setup_requirement_path) + +requirement = 'zc.buildout' +version = options.version +if version is None and not options.accept_buildout_test_releases: + # Figure out the most recent final version of zc.buildout. + import setuptools.package_index + _final_parts = '*final-', '*final' + def _final_version(parsed_version): + for part in parsed_version: + if (part[:1] == '*') and (part not in _final_parts): + return False + return True + index = setuptools.package_index.PackageIndex( + search_path=[setup_requirement_path]) + if find_links: + index.add_find_links((find_links,)) + req = pkg_resources.Requirement.parse(requirement) + if index.obtain(req) is not None: + best = [] + bestv = None + for dist in index[req.project_name]: + distv = dist.parsed_version + if _final_version(distv): + if bestv is None or distv > bestv: + best = [dist] + bestv = distv + elif distv == bestv: + best.append(dist) + if best: + best.sort() + version = best[-1].version +if version: + requirement = '=='.join((requirement, version)) +cmd.append(requirement) + +if is_jython: + import subprocess + exitcode = subprocess.Popen(cmd, env=env).wait() +else: # Windows prefers this, apparently; otherwise we would prefer subprocess + exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) +if exitcode != 0: + sys.stdout.flush() + sys.stderr.flush() + print ("An error occurred when trying to install zc.buildout. " + "Look above this message for any errors that " + "were output by easy_install.") + sys.exit(exitcode) + +ws.add_entry(eggs_dir) +ws.require(requirement) +import zc.buildout.buildout +zc.buildout.buildout.main(args) +if not options.eggs: # clean up temporary egg directory + shutil.rmtree(eggs_dir) diff --git a/python/buildout.cfg b/python/buildout.cfg new file mode 100644 index 00000000000..0e0fdf7fedc --- /dev/null +++ b/python/buildout.cfg @@ -0,0 +1,106 @@ +[buildout] +newest = false + +parts = + dirs + py + paster + supervisor + mongodb + mongodb-client-config + mongodb-master-config + +develop = + src/sailing.db + src/sailing.connector + src/sailing.web + +eggs = + PasteScript + sailing.db + sailing.connector + sailing.web + +[conf] +db_home = ${buildout:directory}/data/ +log_home= ${buildout:directory}/data/logs +mongodb_master = localhost +mongodb_host = localhost +mongodb_port = 10200 +supervisord_host_port = 0.0.0.0:10001 + +[supervisor] +recipe = collective.recipe.supervisor +logfile = ${conf:log_home}/supervisord.log +port = 12456 +user = admin +password = admin +loglevel = info +programs = + 10 mongod ${buildout:bin-directory}/mongod [--config ${buildout:directory}/etc/mongodb-master.cfg] ${buildout:directory} + +[dirs] +recipe = z3c.recipe.mkdir +paths = + +[py] +recipe = zc.recipe.egg +eggs = ${buildout:eggs} +interpreter = py +scripts = + trac_listener + +[paster] +recipe = zc.recipe.egg +eggs = ${buildout:eggs} +interpreter = py +scripts = + paster + +[test] +recipe = zc.recipe.testrunner +defaults = ['-v'] +eggs = + ${buildout:eggs} +script = test + +[mongodb] +recipe = rod.recipe.mongodb +linux2-32bit-url = http://downloads.mongodb.org/linux/mongodb-linux-i686-1.8.1.tgz +linux2-64bit-url = http://downloads.mongodb.org/linux/mongodb-linux-x86_64-1.8.1.tgz + +[mongodb-client-config] +recipe = collective.recipe.template +input = templates/db.ini +output = ${buildout:directory}/etc/db.ini + +[mongodb-master-config] +recipe = collective.recipe.template +input = templates/mongodb-master.cfg +output = ${buildout:directory}/etc/mongodb-master.cfg + +[webserver-dev-config] +recipe = collective.recipe.template +input = templates/webserver-dev.ini +output = ${buildout:directory}/etc/webserver-development.ini + +[webserver-dev-runner] +recipe = collective.recipe.template +input = templates/app_debug.sh +output = ${buildout:directory}/bin/debug.sh + +[webserver-prod-config] +recipe = collective.recipe.template +input = templates/webserver-prod.ini +output = ${buildout:directory}/etc/webserver-production.ini + +[webserver-prod-runner-start] +recipe = collective.recipe.template +input = templates/app_production_start.sh +output = ${buildout:directory}/bin/start.sh + +[webserver-prod-runner-stop] +recipe = collective.recipe.template +input = templates/app_production_stop.sh +output = ${buildout:directory}/bin/stop.sh + diff --git a/python/data/.placeholder b/python/data/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/cache/.placeholder b/python/data/cache/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/logs/.placeholder b/python/data/logs/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/logs/mongodb/.placeholder b/python/data/logs/mongodb/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/mongodb/.placeholder b/python/data/mongodb/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/dev.cfg b/python/dev.cfg new file mode 100644 index 00000000000..46b5f3df1fe --- /dev/null +++ b/python/dev.cfg @@ -0,0 +1,7 @@ +[buildout] +extends = buildout.cfg + +parts += + test + webserver-dev-config + webserver-dev-runner diff --git a/python/etc/.placeholder b/python/etc/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/prod.cfg b/python/prod.cfg new file mode 100644 index 00000000000..5f076352645 --- /dev/null +++ b/python/prod.cfg @@ -0,0 +1,10 @@ +[buildout] +extends = buildout.cfg + +eggs += + pastegevent + +parts += + webserver-prod-config + webserver-prod-runner-start + webserver-prod-runner-stop diff --git a/python/src/sailing.connector/README.txt b/python/src/sailing.connector/README.txt new file mode 100644 index 00000000000..329413e04ca --- /dev/null +++ b/python/src/sailing.connector/README.txt @@ -0,0 +1,6 @@ +Introduction +============ + + + +This product may contain traces of nuts. diff --git a/python/src/sailing.connector/docs/HISTORY.txt b/python/src/sailing.connector/docs/HISTORY.txt new file mode 100644 index 00000000000..306a4fd0e50 --- /dev/null +++ b/python/src/sailing.connector/docs/HISTORY.txt @@ -0,0 +1,7 @@ +Changelog +========= + +1.0dev (unreleased) +------------------- + +- Initial release diff --git a/python/src/sailing.connector/sailing/__init__.py b/python/src/sailing.connector/sailing/__init__.py new file mode 100644 index 00000000000..f48ad105287 --- /dev/null +++ b/python/src/sailing.connector/sailing/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/python/src/sailing.connector/sailing/connector/__init__.py b/python/src/sailing.connector/sailing/connector/__init__.py new file mode 100644 index 00000000000..1cb4a8565f4 --- /dev/null +++ b/python/src/sailing.connector/sailing/connector/__init__.py @@ -0,0 +1,84 @@ + +import cjson +import urllib, urllib2 + +from sailing.web.util import get_abspath + +import logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger(__name__) + +class URIConfigurator(object): + + def __init__(self, host, port): + self.host = host + self.port = port + + def copy(self): + inst = URIConfigurator(self.host, self.port) + inst.__dict__ = self.__dict__.copy() + return inst + + def key(self): + return '%s:%s' % (self.host, self.port) + + def clear(self): + try: + del self.__dict__['parameters'] + del self.__dict__['_parameters'] + except: + pass + + def setContext(self, context): + self.clear() + self.context = context + + def setCommand(self, command): + self.command = command + + def setRace(self, race): + self.race = race + + def setParameters(self, parameters={}): + if hasattr(self, 'command'): + parameters['action'] = self.command + + if hasattr(self, 'race') and self.race: + parameters['eventname'] = self.race.event + parameters['racename'] = self.race.name + + self.parameters = urllib.urlencode(parameters) + self._parameters = parameters + + def hasParameter(self, name): + return self._parameters.has_key(name) + + def URI(self): + if not hasattr(self, 'parameters'): + # ensure that parameters are set correctly + self.setParameters() + + uri = 'http://%s:%s/%s?%s' % (self.host, self.port, self.context, self.parameters) + return uri + + def trigger(self, request=None): + log.info('Triggering URI %s' % self.URI()) + return urllib2.urlopen(self.URI()) + +def jsonByUrl(configurator): + """ Connects to specified REST service and returns parsed data """ + + # small hack to make tests easier + if configurator.port is None: + handle = open(get_abspath('sailing.web:tests/data/%s' % configurator.host), 'r') + data = handle.read() + handle.close() + + else: + data = configurator.trigger().read() + + if data.find('Exception')>0: + raise Exception, 'Java triggered exception: %s' % data[:350] + + return cjson.decode(data.strip()) + diff --git a/python/src/sailing.connector/sailing/connector/provider.py b/python/src/sailing.connector/sailing/connector/provider.py new file mode 100644 index 00000000000..8c92ca6bc60 --- /dev/null +++ b/python/src/sailing.connector/sailing/connector/provider.py @@ -0,0 +1,275 @@ + +import sys, threading, datetime, time + +import cjson +import urllib, urllib2 + +from sailing.db import database +from sailing.db import model +from sailing.connector import jsonByUrl + +from sailing.web import config +from sailing.connector import URIConfigurator + +import logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger('sailing.connector.run#main') + +class LiveDataReceiver(threading.Thread): + + def __init__(self, host, port, eventname, racename): + self.host = host + self.port = port + self.eventname = eventname + self.racename = racename + + self.last_update = None + self.updatecount = 0 + + self.running = False + self.paused = True + + threading.Thread.__init__(self) + + def run(self): + log.info('START listener for %s:%s (%s, %s)' % (self.host, self.port, self.eventname, self.racename)) + self.running = True + + lock = threading.Lock() + while self.running is True: + + # make it possible to pause listener + if self.paused is True: + time.sleep(1) + continue + + conf = URIConfigurator(self.host, self.port) + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIVE_EVENTS) + conf.setRace(model.RaceImpl.queryOneBy(event=self.eventname, name=self.racename)) + + # blocking call by updatecount setting + conf.setParameters(dict(eventname=self.eventname, racename=self.racename, sinceupdate=self.updatecount)) + + try: + # need to lock because other threads could overwrite information + with lock: + updatecount = liveRaceInformation(conf) + + self.last_update = datetime.datetime.now() + self.updatecount = updatecount + + except Exception, ex: + # print error but do not kill thread as this could be recoverable + log.error('Error in thread for %s %s' % (self.eventname, self.racename), exc_info=True) + + # avoid filling console with errors + time.sleep(2) + + # avoid hammering java server - can occur if call does not block correctly + time.sleep(1) + + log.info('STOP listener for %s:%s (%s, %s)' % (self.host, self.port, self.eventname, self.racename)) + +def computeRank(newvalue, oldvalue): + return newvalue + +def eventConfiguration(configurator): + """ Reads current event configuration from server """ + + # this can block if there are no tracked races available + events = jsonByUrl(configurator) + + for event in events: + dbevent = model.EventImpl.queryOneBy(name=event['name']) + if not dbevent: + dbevent = model.EventImpl() + + # create competitors for the whole event + cpnames = []; cobjects = [] + for cp in event['competitors']: + cpnames.append(cp['name']) + + cfound = model.CompetitorImpl.queryOneBy(name=cp['name'], event=event['name']) + if not cfound: + competitor = model.CompetitorImpl() + competitor.update(dict(name=cp['name'], nationality=cp['nationality'], event=event['name'])) + cobjects.append(competitor) + else: + cobjects.append(cfound) + + # prepare race and mark names + rcnames = []; rcmarks = [] + raceindex = 0; + for rc in event['races']: + rcnames.append( (rc['name'], rc['start']) ) + raceindex += 1 + + dbrace = model.RaceImpl.queryOneBy(event=event['name'], name=rc['name']) + if not dbrace: + dbrace = model.RaceImpl() + dbrace.update(dict(event=event['name'], name=rc['name'])) + + # make sure to include start to enable sorting + if rc.has_key('start'): + dbrace.update(dict(start=rc['start'])) + + marknames = [] + for leg in rc['legs']: + # including all legs where something ends into model + # in this case we get the last mark that equals the + # points for the whole race + marknames.append(leg['end']) + + rcmarks.append(marknames) + + rcnames.sort(lambda x,y: cmp(x[1], y[1])) + + # fill competitors with empty data + for cp in cobjects: + races = [0.0 for r in range(raceindex)] + + marks = cp.marks; values = cp.values + for r in range(raceindex): + if len(races) < r+1: + races.append(0.0) + + if len(marks) < r+1: + marks.append([]) + + if len(values) < r+1: + values.append([]) + + for m in range(len(rcmarks[r])): + if len(marks[r]) < m+1: + marks[r].append(0.0) + + if len(values[r]) < m+1: + values[r].append([]) + + cp.update(dict(races=races, marks=marks)) + + # finally create or update event + dbevent.update(dict(name=event['name'], boatclass=event['boatclass'], competitors=cpnames, races=[rname[0] for rname in rcnames], marks=rcmarks)) + + # return all received events + return events + +def liveRaceInformation(configurator): + """ Reads live race information from provider. Should be called + in a thread because execution can block until new data are available. """ + + data = jsonByUrl(configurator) + + racename = configurator.race.name + eventname = configurator.race.event + + # it is important to know which position the race has + # so we look it up in the Event itself + event = model.EventImpl.queryOneBy(name=eventname) + raceindex = event.races.index(racename) + + # this should help us finding out which legs are still running + # we assume that only one race at time is running so we stick + # to the legs + + lcount = 0; current_legs = {} + for leg in data['legs']: + for competitor in leg['competitors']: + comp = model.CompetitorImpl.queryOneBy(name=competitor['name'], event=eventname) + if not comp: + raise Exception, 'Could not find competitor %s for event %s' % (competitor['name'], eventname) + + c_races = comp.races + c_marks = comp.marks + c_values = comp.values + c_total_rank = comp.total + + # if competitor hasn't yet started we just ignore this leg + if competitor.get('started', False) is False: + continue + + # we take to into account because this is the one we have saved before + mark_name = leg['to'] + + # last mark in race? + is_last_mark = event.marks[raceindex][-1] == mark_name + + # competitor finished this leg? + finished = competitor['finished'] + + # we are now in race[raceindex].legs[legcount] and need to map this + # to competitor structures + + if finished: + # competitor has finished this leg so we need to save rank + # to the next mark (e.g. mark_name is 'Mark 1' and finished + # then competitor.marks[raceindex][lcount] = rank). This works + # because leg[position] equals marks[position] in list + if competitor.has_key('rank'): + c_marks[raceindex][lcount] = computeRank(competitor['rank'], c_marks[raceindex][lcount]) + + # if finished and last mark then update race information + if is_last_mark: + c_races[raceindex] = computeRank(competitor['rank'], c_races[raceindex]) + + # for the last race just update total rank + if raceindex+1 == len(c_races): + c_total_rank = computeRank(competitor['rank'], c_total_rank) + + else: + c_marks[raceindex][lcount] = 0.0 + if is_last_mark: + c_races[raceindex] = 0.0 + + if raceindex+1 == len(c_races): + c_total_rank = 0.0 + + else: + # leg not finished so put this leg into unfinished legs + current_legs[lcount] = 1 + + # now update values for the current position + for key in config.SORTED_LEG_VALUE_NAMES: + + # dynamically extend this one + attr = config.LEG_VALUE_DATA[key] + if len(c_values[raceindex][lcount]) < attr[0]+1: + c_values[raceindex][lcount].append(0.0) + + k = competitor.get(key, None) + if k in [None, 'null', 'Null', '']: + k = 0.0 + + c_values[raceindex][lcount][attr[0]] = k + + # compute total rank for competitor + rank = competitor.get('rank', 0) + if data.has_key('ranks'): + for c in data['ranks']: + if c['competitor'] == competitor['name']: + rank = c['rank'] + break + + comp.update(dict(current_rank=rank,races=c_races, marks=c_marks, values=c_values, total=c_total_rank)) + + # next leg + lcount += 1 + + # update race with current information + dbrace = model.RaceImpl.queryOneBy(event=eventname, name=racename) + mdup = dict(startoftracking=data['startoftracking'], + start=data['start'], finish=data['finish'], + timeofnewestevent=data['timeofnewestevent'], + updatecount=data['updatecount']) + + if data.get('wind'): + mdup['wind_source'] = data['wind']['source'] + mdup['wind_bearing'] = data['wind']['truebearingdeg'] + mdup['wind_speed'] = data['wind']['knowspeed'] + + mdup['current_legs'] = current_legs.keys() + dbrace.update(mdup) + + return data['updatecount'] + diff --git a/python/src/sailing.connector/setup.py b/python/src/sailing.connector/setup.py new file mode 100644 index 00000000000..f85396561db --- /dev/null +++ b/python/src/sailing.connector/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup, find_packages +import os + +version = '1.0' + +setup(name='sailing.connector', + version=version, + description="Connector to TracTrac Application wrapped by Java", + long_description=open("README.txt").read() + "\n" + + open(os.path.join("docs", "HISTORY.txt")).read(), + # Get more strings from + # http://pypi.python.org/pypi?:action=list_classifiers + classifiers=[ + "Programming Language :: Python", + ], + keywords='', + author='', + author_email='', + url='http://svn.plone.org/svn/collective/', + license='GPL', + packages=find_packages(exclude=['ez_setup']), + namespace_packages=['sailing'], + include_package_data=True, + zip_safe=False, + install_requires=[ + 'setuptools', + 'pymongo', + 'mongokit', + 'python-cjson' + ], + entry_points=""" + # -*- Entry points: -*- + """, + ) diff --git a/python/src/sailing.db/README.txt b/python/src/sailing.db/README.txt new file mode 100644 index 00000000000..329413e04ca --- /dev/null +++ b/python/src/sailing.db/README.txt @@ -0,0 +1,6 @@ +Introduction +============ + + + +This product may contain traces of nuts. diff --git a/python/src/sailing.db/docs/HISTORY.txt b/python/src/sailing.db/docs/HISTORY.txt new file mode 100644 index 00000000000..306a4fd0e50 --- /dev/null +++ b/python/src/sailing.db/docs/HISTORY.txt @@ -0,0 +1,7 @@ +Changelog +========= + +1.0dev (unreleased) +------------------- + +- Initial release diff --git a/python/src/sailing.db/sailing/__init__.py b/python/src/sailing.db/sailing/__init__.py new file mode 100644 index 00000000000..f48ad105287 --- /dev/null +++ b/python/src/sailing.db/sailing/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/python/src/sailing.db/sailing/db/__init__.py b/python/src/sailing.db/sailing/db/__init__.py new file mode 100644 index 00000000000..36bdf0afeeb --- /dev/null +++ b/python/src/sailing.db/sailing/db/__init__.py @@ -0,0 +1,45 @@ + +import os, logging +from ConfigParser import ConfigParser + +LOG = logging.getLogger('sailing.db') + +ALL_KEYS = ('host', 'port', 'dbname', 'username', 'password', 'collections', 'master_host') +MANDATORY_KEYS = ('host', 'port', 'dbname', 'collections') + +def readDatabaseConfiguration(db_ini='db.ini'): + """ Read the database configuration """ + + if not os.path.exists(db_ini): + raise ConfigurationError('No database configuration found (%s)' % db_ini) + + CP = ConfigParser() + CP.read(db_ini) + result = dict() + for section in CP.sections(): + d = dict() + for k in ALL_KEYS: + v = None + if CP.has_option(section, k): + if k == 'port': + v = CP.getint(section, k) + elif k == 'collections': + v = [x.strip() for x in CP.get(section, k).split(',') if x.strip()] + else: + v = CP.get(section, k) + + if k in MANDATORY_KEYS and not v: + raise ConfigurationError('Database configuration error: [%s]>%s in "%s" is mandatory' % (section, k, db_ini)) + d[k] = v + result[section] = d + return result + + +# Read the database configuration either from $YSH_DATABASE_CONFIGURATION +# or /etc/db.ini + +filename = os.environ.get('YSH_DATABASE_CONFIGURATION', + os.path.join(os.getcwd(), 'etc', 'db.ini')) +LOG.info('Reading database configuration from %s' % filename) +DB_CONFIG = readDatabaseConfiguration(filename) + diff --git a/python/src/sailing.db/sailing/db/config.py b/python/src/sailing.db/sailing/db/config.py new file mode 100644 index 00000000000..662cb4436f5 --- /dev/null +++ b/python/src/sailing.db/sailing/db/config.py @@ -0,0 +1,11 @@ +# format for dates +# http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior +# DATE_TIME_FORMAT = '%Y/%m/%d %H:%M' +DATE_TIME_FORMAT = '%Y/%m/%d' +DATE_FORMAT_STRING = '%b %d %Y' + +# db backend sort identifier +import pymongo +ASCENDING = pymongo.ASCENDING +DESCENDING = pymongo.DESCENDING + diff --git a/python/src/sailing.db/sailing/db/database.py b/python/src/sailing.db/sailing/db/database.py new file mode 100644 index 00000000000..920627f01fd --- /dev/null +++ b/python/src/sailing.db/sailing/db/database.py @@ -0,0 +1,71 @@ +import logging + +import mongokit +import mongokit.master_slave_connection + +from sailing.db import DB_CONFIG + +logging.basicConfig(level=logging.INFO) +LOG = logging.getLogger('sailing.db') + +__all__ = ('getCollection',) + +def setupDatabases(): + """ Setup MongoDB database connections and collections """ + + global collections, databases, connections, collection2database + + for d in DB_CONFIG.values(): + + dbname = d['dbname'] + slave_configuration = dict(host=d['host'], port=d['port']) + + if d['master_host']: + # master and slaves share the same configuration - except + # the hostname of the master host + master_configuration = slave_configuration.copy() + master_configuration['host'] = d['master_host'] + LOG.info('Setting up database as master-slave (database: %s, master: %s, slave: %s)' % + (dbname, master_configuration, slave_configuration)) + conn = mongokit.master_slave_connection.MasterSlaveConnection(master_configuration, [slave_configuration]) + else: + LOG.info('Setting up database (database:%s , master: %s)' % (dbname, slave_configuration)) + conn = mongokit.Connection(**slave_configuration) + + db = mongokit.Database(conn, dbname) + databases[dbname] = db + connections[dbname] = conn + + for collection in d['collections']: + collections[collection] = mongokit.Collection(db, collection) + collection2connection[collection] = conn + + LOG.info('Attached collections: %s' % ', '.join(collections)) + +def getCollection(collection): + """ Return a MongoDB collection by its name """ + coll = collections.get(collection) + if not coll: + raise ValueError('No collection %s configured' % collection) + return coll + +def getConnection(database): + """ Return connection for a given database """ + conn = connections.get(database) + if not conn: + raise ValueError('No connection for database %s found' % database) + return conn + +def getConnectionByCollectionName(collection): + """ Return connection object for a given collection name """ + db = collection2connection.get(collection) + if not db: + raise ValueError('No database for collection %s found' % collection) + return db + +collection2connection = dict() +connections = dict() +databases = dict() +collections = dict() +setupDatabases() + diff --git a/python/src/sailing.db/sailing/db/model/__init__.py b/python/src/sailing.db/sailing/db/model/__init__.py new file mode 100644 index 00000000000..0c6d2f1a5d2 --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/__init__.py @@ -0,0 +1,58 @@ + +import datetime + +from base import ModelBase +from util import registerClass, queryContent, createContent + +from entities import * + +class EventImpl(ModelBase): + linked_model = Event + +class RaceImpl(ModelBase): + linked_model = Race + + default_values = { + 'running': False, + } + +class CompetitorImpl(ModelBase): + linked_model = Competitor + + default_values = { + 'races': [], + 'marks': [[]] + } + + @classmethod + def sortedBy(cls, eventname, raceindex=None, markindex=None, valueindex=None): + """ Returns competitors sorted by given index. If index + is None no sorting is performed on this index. If all index + params are None sorting is performed by total. """ + + def sorter(x, y): + xval = x.total + yval = y.total + + if valueindex is not None: + try: + xval = x.values[raceindex][markindex][valueindex] + yval = y.values[raceindex][markindex][valueindex] + except IndexError: + xval = 0.0 + yval = 0.0 + + elif markindex is not None: + xval = x.marks[raceindex][markindex] + yval = y.marks[raceindex][markindex] + + elif raceindex is not None: + xval = x.races[raceindex] + yval = y.races[raceindex] + + return cmp(xval, yval) + + competitors = cls.queryBy(event=eventname) + competitors.sort(sorter) + return competitors + diff --git a/python/src/sailing.db/sailing/db/model/base.py b/python/src/sailing.db/sailing/db/model/base.py new file mode 100644 index 00000000000..fec1ffb86bc --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/base.py @@ -0,0 +1,277 @@ + +import datetime + +import mongokit +from pymongo.objectid import ObjectId + +from sailing.db.model.util import queryContent, createContent +from sailing.db import config + +MARKER = object + +class BaseDocument(mongokit.Document): + skip_validation = True + safe_mode = True + + def _updateInternal(self, **kw): + kw['safe'] = self.safe_mode + if not hasattr(self, 'created') or \ + not kw.get('created', None): + self['created'] = datetime.datetime.now() + + if not hasattr(self, 'typename') or \ + not kw.get('typename', None): + self['typename'] = self.__class__.__name__ + + return kw + + def save(self, *args, **kw): + kw = self._updateInternal(**kw) + super(BaseDocument, self).save(*args, **kw) + + def insert(self, *args, **kw): + kw = self._updateInternal(**kw) + super(BaseDocument, self).insert(*args, **kw) + + def update(self, *args, **kw): + kw = self._updateInternal(**kw) + super(BaseDocument, self).update(*args, **kw) + +class ModelBase(object): + + @classmethod + def collectionName(cls): + return cls.linked_model._collection + + @classmethod + def query(cls, uid, wrap=True): + uid = str(uid).strip() + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.get_from_id(ObjectId(uid)) + + if wrap is True: + if backend_instance: + if isinstance(backend_instance, list): + backend_instance = backend_instance[0] + return cls(backend_instance) + else: + return backend_instance + + return None + + @classmethod + def queryRaw(cls, input, limit=0, sortby='created', sortorder=config.DESCENDING): + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(input).limit(limit).sort(sortby, sortorder) + + if backend_instance: + if backend_instance.count(): + return [cls(ba) for ba in backend_instance] + + return [] + + @classmethod + def queryBy(cls, limit=0, sortby='created', sortorder=config.DESCENDING, **fields): + assert isinstance(limit, int) + + klass = queryContent(cls.linked_model.__name__) + + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + # better would be to use fetch here because this includes structure but + # because we have one type per collection this doesn't matter + backend_instance = klass.find(fields).limit(limit).sort(sortby, direction=sortorder) + + if backend_instance: + if backend_instance.count(): + return [cls(ba) for ba in backend_instance] + + return [] + + @classmethod + def queryByCount(cls, limit=0, sortby='created', sortorder=config.DESCENDING, **fields): + assert isinstance(limit, int) + + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(fields).limit(limit).sort(sortby, direction=sortorder) + return backend_instance.count() + + @classmethod + def queryCount(cls, limit=0, sortby='created', sortorder=config.DESCENDING, **fields): + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(fields).limit(limit).sort(sortby, direction=sortorder) + return backend_instance.count() + + @classmethod + def queryRawCount(cls, input, limit=0, sortby='created', sortorder=config.DESCENDING): + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(input).limit(limit).sort(sortby, direction=sortorder) + return backend_instance.count() + + @classmethod + def queryOneBy(cls, **fields): + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find_one(fields) + + if backend_instance: + return cls(backend_instance) + return None + + @classmethod + def removeAllBy(cls, **fields): + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + fields['atomic'] = True + klass = queryContent(cls.linked_model.__name__) + klass.collection.remove(**fields) + + # assuming that we clean all objects + klass.collection.drop_indexes() + + def __getstate__(self): + # we need to return a state where there is no connection + # to mongodb directly established - we just save the internal + # UID so to be able to rebuild the state later on + + dc = self.__dict__.copy() + inst = dc['_instance'] + + if getattr(inst, '__dict__', None): + # we preserve the instance to avoid reloading it + # on unpickle - just preserving raw values + idc = {}; footprint = inst.structure + + for k in footprint.keys(): + # model changes can yield non-complete instances + if inst.has_key(k): + idc[str(k)] = inst[k] + + idc['_id'] = dc['_instance']['_id'] + + del dc['_instance'] + dc['_instance'] = idc + + return dc + + def __setstate__(self, state): + self.__dict__ = state + + def __init__(self, instance = None, *args, **kw): + self._instance = instance + + def __getattr__(self, key): + # instance attributes are held by backend + value = self.get(key, default=object) + + # make sure to fall back to this class + if value is object: + return getattr(self.__class__, key) + + return value + + def get(self, key, default=None): + if key in self.__class__.linked_model.structure or key in ['_id', ]: + inst = self.__dict__['_instance'] + if inst.has_key(key): + return inst.get(key) + return default + + @property + def uid(self): + uid = getattr(self, '_id', None) + if uid: + return unicode(str(uid)) + return None + + def _backend(self): + return self.__class__.linked_model + + def _instance_(self): + # use this method only for direct operations (crud) + inst = self.__dict__['_instance'] + if inst: + # unpickling returns dict and not real mongokit instance + if not hasattr(inst, '__dict__'): + self.__dict__['_instance'] = self.query(inst['_id'], wrap=False) + return self.__dict__['_instance'] + return inst + + def getURL(self): + raise Exception, 'NotImplementedHere' + + def getTitle(self): + raise Exception, 'NotImplementedHere' + + def creationTime(self, pretty=False): + if pretty is True: + return pretty_date(self.created) + return self.created + + def reload(self): + self._instance = self.query(self.uid, wrap=False) + + def delete(self): + uid = self.uid + if not uid: + return False + + self._instance_().delete() + return True + + def update(self, dictionary=None, dosave=True): + klassname = self._backend().__name__ + + # make sure to make a difference between new and update + # new objects should always have empty uid field + if self.uid is None: + self._instance = createContent(klassname) + iis = self._instance_() + + if hasattr(self, '_before_update'): + self._before_update(dictionary, creation=True) + + # check that defaults are NOT set on backend + if hasattr(iis.__class__, 'default_values'): + if len(iis.__class__.default_values.keys())>0: + raise Exception, 'Implementation error: instance can not have defaults! Set defaults in model! Model: %s' % self._instance.__class__ + + # make sure to activate defaults + if hasattr(self.__class__, 'default_values'): + for dk,dv in self.__class__.default_values.items(): + if dictionary is None \ + or not dk in dictionary: + if callable(dv): + dv = dv() + + iis[dk] = dv + else: + if self._instance_() is None: + self._instance = self.query(self.uid, wrap=False) + + iis = self._instance_() + if hasattr(self, '_before_update'): + self._before_update(dictionary, creation=False) + + if dictionary: + for k,v in dictionary.items(): + iis[k] = v # need explicit set here + + # save also works for update process + if dosave is True: + iis.save() + diff --git a/python/src/sailing.db/sailing/db/model/entities.py b/python/src/sailing.db/sailing/db/model/entities.py new file mode 100644 index 00000000000..94a35355da9 --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/entities.py @@ -0,0 +1,83 @@ + +import datetime + +from base import BaseDocument +from util import registerClass, queryContent, createContent + +class Event(BaseDocument): + _collection = 'events' + skip_validation = True + + structure = { + 'name': unicode, + 'boatclass': unicode, + 'competitors': [unicode, ], + 'races': [unicode, ], + 'marks': [[unicode, ]], + 'typename': unicode, + 'created': datetime.datetime + } + + indexes = [ + { + 'fields' : ['name'], + 'unique': True + }, + ] + +registerClass(Event) + +class Race(BaseDocument): + _collection = 'races' + skip_validation = True + + structure = { + 'name': unicode, + 'event': unicode, + 'current_legs': [int, ], # holds a list of positions of current legs + 'startoftracking': float, + 'start': float, + 'finish' : float, + 'timeofnewestevent': float, + 'updatecount': float, + 'wind_source': unicode, + 'wind_bearing': float, + 'wind_speed': float, + 'typename': unicode, + 'created': datetime.datetime + } + + indexes = [ + { + 'fields' : ['name', 'event'], + 'unique': True + }, + ] + +registerClass(Race) + +class Competitor(BaseDocument): + _collection = 'competitors' + skip_validation = True + + structure = { + 'name': unicode, + 'event': unicode, + 'nationality': unicode, + + 'total': float, + 'current_rank': int, # current rank for given time + 'races' : [float, ], + 'marks' : [[float, ], ], + 'values' : [[[float, ]]] + } + + indexes = [ + { + 'fields' : ['name', 'event'], + 'unique': True + }, + ] + +registerClass(Competitor) + diff --git a/python/src/sailing.db/sailing/db/model/util.py b/python/src/sailing.db/sailing/db/model/util.py new file mode 100644 index 00000000000..800127eaa37 --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/util.py @@ -0,0 +1,32 @@ +from sailing.db.database import getConnection, getCollection, getConnectionByCollectionName + +classes = dict() + +def registerClass(cls): + """ Register class with MongoKit """ + + collection = cls._collection + conn = getConnectionByCollectionName(collection) + conn.register([cls]) + classes[cls.__name__] = cls + +def createContent(cls_name, **kw): + + try: + collection = getCollection(classes[cls_name]._collection) + except KeyError: + raise ValueError('Class "%s" is not registered' % cls_name) + + inst = getattr(collection, cls_name)() + for k,v in kw.items(): + inst[k] = v + return inst + +def queryContent(cls_name): + try: + collection = getCollection(classes[cls_name]._collection) + except KeyError: + raise ValueError('Class "%s" is not registered' % cls_name) + + return getattr(collection, cls_name) + diff --git a/python/src/sailing.db/sailing/db/monitoring.py b/python/src/sailing.db/sailing/db/monitoring.py new file mode 100644 index 00000000000..58af35096bb --- /dev/null +++ b/python/src/sailing.db/sailing/db/monitoring.py @@ -0,0 +1,35 @@ +from database import databases, collections + +def dbStats(): + result = dict() + for dbname in databases: + db = databases[dbname] + stats = db.command('dbstats') + result[dbname] = stats + return result + +def serverStatus(): + db = databases[databases.keys()[0]] + stats = db.command('serverStatus') + return stats + + +def collectionStats(): + result = dict() + for dbname in databases: + db = databases[dbname] + for coll in db.collection_names(): + result[coll] = db.command({'collstats' : coll}) + result[coll]['dbname'] = dbname + return result + +def dropDB(): + """ Drops all database data """ + + from database import databases + for k, db in databases.items(): + for name in db.collection_names(): + if name not in ('system.indexes',): + db[name].drop_indexes() + db.drop_collection(name) + diff --git a/python/src/sailing.db/setup.py b/python/src/sailing.db/setup.py new file mode 100644 index 00000000000..68dc6f4ddc9 --- /dev/null +++ b/python/src/sailing.db/setup.py @@ -0,0 +1,32 @@ +from setuptools import setup, find_packages +import os + +version = '1.0' + +setup(name='sailing.db', + version=version, + description="Connection to database for sailing", + long_description=open("README.txt").read() + "\n" + + open(os.path.join("docs", "HISTORY.txt")).read(), + # Get more strings from + # http://pypi.python.org/pypi?:action=list_classifiers + classifiers=[ + "Programming Language :: Python", + ], + keywords='', + author='', + author_email='', + url='http://svn.plone.org/svn/collective/', + license='GPL', + packages=find_packages(exclude=['ez_setup']), + namespace_packages=['sailing'], + include_package_data=True, + zip_safe=False, + install_requires=[ + 'setuptools', + # -*- Extra requirements: -*- + ], + entry_points=dict(console_scripts=( + 'trac_listener=sailing.connector.run:main', + )), + ) diff --git a/python/src/sailing.web/MANIFEST.in b/python/src/sailing.web/MANIFEST.in new file mode 100644 index 00000000000..68a2d33eeb7 --- /dev/null +++ b/python/src/sailing.web/MANIFEST.in @@ -0,0 +1,3 @@ +include *.ini *.cfg +exclude .installed.cfg +recursive-include src *.html diff --git a/python/src/sailing.web/README.txt b/python/src/sailing.web/README.txt new file mode 100644 index 00000000000..329413e04ca --- /dev/null +++ b/python/src/sailing.web/README.txt @@ -0,0 +1,6 @@ +Introduction +============ + + + +This product may contain traces of nuts. diff --git a/python/src/sailing.web/docs/HISTORY.txt b/python/src/sailing.web/docs/HISTORY.txt new file mode 100644 index 00000000000..306a4fd0e50 --- /dev/null +++ b/python/src/sailing.web/docs/HISTORY.txt @@ -0,0 +1,7 @@ +Changelog +========= + +1.0dev (unreleased) +------------------- + +- Initial release diff --git a/python/src/sailing.web/sailing/__init__.py b/python/src/sailing.web/sailing/__init__.py new file mode 100644 index 00000000000..f48ad105287 --- /dev/null +++ b/python/src/sailing.web/sailing/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/python/src/sailing.web/sailing/web/__init__.py b/python/src/sailing.web/sailing/web/__init__.py new file mode 100644 index 00000000000..9e0d65a9bd3 --- /dev/null +++ b/python/src/sailing.web/sailing/web/__init__.py @@ -0,0 +1,29 @@ + +from pyramid.config import Configurator + +from pyramid_beaker import BeakerSessionFactoryConfig,\ + session_factory_from_settings, set_cache_regions_from_settings + +def init_app(request): + return {} + +def app(global_config, **settings): + """ This function returns a pyramid.router.Router object. + It is usually called by the PasteDeploy framework during ``paster serve``. + """ + + # paster app config callback + import sailing.web + + # beaker stuff for session and caching + session_factory = session_factory_from_settings(settings) + set_cache_regions_from_settings(settings) + + from sailing.web.util import reloader_watch_files + reloader_watch_files(global_config, **settings) + + config = Configurator(settings=settings, root_factory=init_app, session_factory=session_factory) + config.include('pyramid_zcml') + config.load_zcml('configure.zcml') + + return config.make_wsgi_app() diff --git a/python/src/sailing.web/sailing/web/adapter/__init__.py b/python/src/sailing.web/sailing/web/adapter/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/src/sailing.web/sailing/web/adapter/configure.zcml b/python/src/sailing.web/sailing/web/adapter/configure.zcml new file mode 100644 index 00000000000..5408ee3cc75 --- /dev/null +++ b/python/src/sailing.web/sailing/web/adapter/configure.zcml @@ -0,0 +1,10 @@ + + + + + + diff --git a/python/src/sailing.web/sailing/web/browser/__init__.py b/python/src/sailing.web/sailing/web/browser/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/src/sailing.web/sailing/web/browser/configure.zcml b/python/src/sailing.web/sailing/web/browser/configure.zcml new file mode 100644 index 00000000000..0e4df24dfc1 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/configure.zcml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + diff --git a/python/src/sailing.web/sailing/web/browser/core.py b/python/src/sailing.web/sailing/web/browser/core.py new file mode 100644 index 00000000000..205282462c5 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/core.py @@ -0,0 +1,185 @@ + +import time, datetime + +import urllib + +from webob.exc import HTTPFound +from pyramid.renderers import get_renderer, render_to_response + +from sailing.connector import provider, URIConfigurator, jsonByUrl +from sailing.db import model +from sailing.db import monitoring + +from sailing.web import config + +import logging +log = logging.getLogger(__name__) +logging.basicConfig() + +current_leaderboard_event = None + +class BaseView(object): + + def __init__(self, context, request): + self.context = context + self.request = request + + # don't forget to call save() if you changed s/th on the session + self.session = request['beaker.session'] + + def __call__(self): + return {'main': self.mainTemplate()} + + def yieldMessage(self, message): + parameters = urllib.urlencode(dict(message=message)) + return HTTPFound(location='/?%s' % parameters) + + def mainTemplate(self): + return get_renderer('templates/maintemplate.pt').implementation() + + def eventUrlHistory(self): + return self.session.get('event.url_history', ['No URLs to TracTrac events gathered until now']) + + def raceUrlHistory(self): + return self.session.get('race.url_history', ['No URLs to TracTrac races gathered until now']) + + def dbDatabaseStats(self): + return monitoring.dbStats() + + def dbCollectionStats(self): + return monitoring.collectionStats() + + def dbServerStatus(self): + return monitoring.serverStatus() + + def millisToDatetime(self, millis, short=False): + if millis is None or millis >= 9023372036854775807: + return None + + try: + tm = time.gmtime(millis/1000) + + if tm.tm_year >= 2000: + dt = datetime.datetime(year=tm.tm_year, month=tm.tm_mon, day=tm.tm_mday, hour=tm.tm_hour, minute=tm.tm_min, second=tm.tm_sec) + return dt + except: + log.error('Error', exc_info=True) + + return None + + def datetimeToMillis(self, dt): + if dt: + dtnew = datetime.datetime(year=dt.year, month=dt.month, day=dt.day, hour=dt.hour+2, minute=dt.minute, second=dt.second) + return time.mktime(dtnew.timetuple())*1000 + return 0 + + def parseDatetime(self, dt, format='%m/%d/%Y %H:%M:%S'): + return datetime.datetime.strptime(dt.strip(), format) + + def listenerStarted(self): + return self.session.get('listener-started', False) + + def listenerConf(self): + if self.listenerStarted(): + return self.session['listener-conf'].copy() + return None + + def currentRace(self): + if not self.session.has_key('current-race'): + raise Exception, 'No current race could be determined' + + return model.RaceImpl.queryOneBy(event=self.session['current-event'], name=self.session['current-race']) + + def currentEvent(self): + return model.EventImpl.queryOneBy(name=self.session['current-event']) + + def currentLeaderboardEvent(self): + cev = model.EventImpl.queryOneBy(name=current_leaderboard_event) + + # XXX remove this + if not cev: + return model.EventImpl.queryBy()[0] + + return cev + + def raceBy(self, event, name): + return model.RaceImpl.queryOneBy(event=event, name=name) + + def currentWind(self): + conf = self.listenerConf() + race = self.currentRace() + + conf.setContext(config.ADMIN) + conf.setCommand(config.SHOW_WIND) + conf.setParameters(dict(eventname=race.event, racename=race.name)) + + return jsonByUrl(conf) + + def allEvents(self): + return model.EventImpl.queryBy() + + def allRacesFor(self, event=None): + if event is None: + allevents = self.allEvents() + + races = [] + for event in allevents: + races += event.races + + return races + + return model.EventImpl.queryOneBy(name=event).races + + def allCompetitorsFor(self, event): + return model.CompetitorImpl.queryBy(event=event) + + def competitorsSortedBy(self, eventname, sortparam): + param = sortparam + if param == 'name': + competitors = model.CompetitorImpl.sortedBy(eventname=eventname) + competitors.sort(lambda x,y: cmp(x.name, y.name)) + + elif param == 'total': + competitors = model.CompetitorImpl.sortedBy(eventname=eventname) + + elif param.find(',')>0: + params = param.strip().split(',') + + if len(params) == 2: + competitors = model.CompetitorImpl.sortedBy(eventname=eventname, raceindex=int(params[0])-1, markindex=int(params[1])-1) + elif len(params) == 3: + competitors = model.CompetitorImpl.sortedBy(eventname=eventname, raceindex=int(params[0])-1, markindex=int(params[1])-1, valueindex=int(params[2])-1) + + else: + param = int(param.strip()) + competitors = model.CompetitorImpl.sortedBy(eventname=eventname, raceindex=param-1) + + return competitors + +def callFunction(context, request): + """ Calls a function dynamically """ + + import functions + return getattr(functions, request.matchdict.get('function'))(context, request) + +def renderTemplate(context, request): + """ Renders a template dynamically """ + + view = BaseView(context, request) + return render_to_response('templates/%s.pt' % request.matchdict.get('template'), + {'context' : context, 'view':view, + 'main' : view.mainTemplate()}, + request=request) + +def renderCSS(context, request): + """ Renders a CSS template dynamically """ + + response = render_to_response('static/css/%s.txt' % request.matchdict.get('template'), + {'context' : context}, + request=request) + + # could be more generic + response.content_type = 'text/css' + return response + + diff --git a/python/src/sailing.web/sailing/web/browser/functions.py b/python/src/sailing.web/sailing/web/browser/functions.py new file mode 100644 index 00000000000..89c00564766 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/functions.py @@ -0,0 +1,481 @@ + +import urllib, urllib2 +import time +import threading + +from webob.exc import HTTPFound +from webob import Response + +from pyramid.exceptions import NotFound +from pyramid.renderers import render_to_response + +from sailing.db import model +from sailing.db.monitoring import dropDB as realDropDB + +from sailing.connector import provider, URIConfigurator, jsonByUrl + +from sailing.web import config +from sailing.web.util import jsonize + +import core + +import logging +log = logging.getLogger(__name__) +logging.basicConfig() + +# map holding association of host:port -> threads +threaded_listener = {} + +def dropDB(context, request): + from sailing.db.monitoring import dropDB + dropDB() + return HTTPFound(location='/') + +def startListenerThreads(conf, eventlist): + # now we should have an event configuration + # read this configuration and for each event and race + # start a listener thread + + lock = threading.Lock() + with lock: + for event in eventlist: + event_impl = model.EventImpl.queryOneBy(name=event['name']) + for racename in event_impl.races: + key = hash('%s-%s-%s-%s' % (conf.host, conf.port, event['name'], racename)) + + # remove dead threads + lstn = threaded_listener.get(key, None) + if lstn and lstn.running is False and lstn.is_alive() is False: + del threaded_listener[key] + + # now there should be only running threads left + if not threaded_listener.has_key(key): + t = provider.LiveDataReceiver(conf.host, conf.port, event['name'], racename) + threaded_listener[key] = t + t.start() + +# addEvent +def configureListener(context, request): + host = request.POST.get('host', 'localhost') + port = request.POST.get('port', '8888') + + lock = threading.Lock() + + view = core.BaseView(context, request) + + conf = URIConfigurator(host, port) + view.session['listener-conf'] = conf + + if request.POST.get('listener-start', None): + conf.setContext(config.ADMIN) + + if request.POST.get('eventJSONURL'): + conf.setCommand(config.ADD_EVENT) + conf.setParameters(dict(eventJSONURL=request.POST.get('eventJSONURL'), + liveURI=request.POST.get('liveURI'), + storedURI=request.POST.get('storedURI'))) + + elif request.POST.get('paramURL'): + conf.setCommand(config.ADD_RACE) + conf.setParameters(dict(paramURL=request.POST.get('paramURL'), + liveURI=request.POST.get('liveURI'), + storedURI=request.POST.get('storedURI'))) + + if not view.session.get('race.url_history'): + view.session['race.url_history'] = [] + + if request.POST.get('paramURL') not in view.session['race.url_history']: + view.session['race.url_history'].append(request.POST.get('paramURL')) + view.session.save() + + else: + return view.yieldMessage('Please specify an event or race URL!') + + try: + result = conf.trigger() + except Exception, ex: + return view.yieldMessage('Error: %s' % str(ex)) + + # can take a while until event data is ready + if request.POST.get('drop_db'): + realDropDB() + + time.sleep(5) + + # load event listing here + with lock: + eventlist = [] + try: + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIST_EVENTS) + eventlist = provider.eventConfiguration(conf) + + # do not accept empty event list + if len(eventlist) == 0: + raise Exception, 'No events configured.' + + except Exception, ex: + return view.yieldMessage('Could not gather any data! Seems that Java listener is not ready yet. Please reconnect. Error: %s' % str(ex)) + + startListenerThreads(conf, eventlist) + + # mark all stuff done and listener running + view.session['listener-started'] = True + view.session.save() + + elif request.POST.get('disconnect-server', None): + # disconnect does not stop listeners but just disconnects the + # session of the user from server + view.session['listener-started'] = False + del view.session['listener-conf'] + view.session.save() + + elif request.POST.get('listener-stop', None): + + eventname = request.POST.get('event', None) + racename = request.POST.get('race', None) + + conf.setContext(config.ADMIN) + + if racename: + conf.setCommand(config.STOP_RACE) + conf.setParameters(dict(eventname=eventname, racename=racename)) + else: + conf.setCommand(config.STOP_EVENT) + conf.setParameters(dict(eventname=eventname)) + + # remove listener started before any error can occur + view.session['listener-started'] = False + del view.session['listener-conf'] + view.session.save() + + key = hash('%s-%s-%s-%s' % (conf.host, conf.port, eventname, racename)) + if threaded_listener.has_key(key): + threaded_listener[key].running = False + + try: + conf.trigger() + except Exception, ex: + return view.yieldMessage('Error: %s' % str(ex)) + + elif request.POST.get('listener-event-refresh', None): + with lock: + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIST_EVENTS) + eventlist = provider.eventConfiguration(conf) + + if model.EventImpl.queryCount() == 0: + return view.yieldMessage('Seems that there are no events that can be shown! Listener not started?') + + # start listener thread if this is not yet active + startListenerThreads(conf, eventlist) + + view.session['listener-started'] = True + view.session['listener-conf'] = conf + view.session.save() + + return view.yieldMessage('Event handler refreshed!') + + elif request.POST.get('leaderboard-default-event', None): + core.current_leaderboard_event = request.POST.get('event') + + return HTTPFound(location='/') + +@jsonize +def configuredListeners(context, request): + + out = [] + for key, listener in threaded_listener.items(): + out.append( {'host': listener.host, 'port': listener.port, + 'eventname': listener.eventname, 'last_update': listener.last_update and listener.last_update.strftime('%d.%m %H:%M:%S') or '-', + 'paused' : listener.paused, 'running': listener.running, 'id' : key, + 'racename': listener.racename} ) + + return out + +@jsonize +def pauseListener(context, request): + tid = int(request.params.get('tid', 0)) + + if request.params.get('all'): + for v in threaded_listener.values(): + v.paused = True + else: + if threaded_listener.has_key(tid): + threaded_listener.get(tid).paused = True + return True + +@jsonize +def unPauseListener(context, request): + tid = int(request.params.get('tid', 0)) + + if request.params.get('all'): + for v in threaded_listener.values(): + v.paused = False + else: + if threaded_listener.has_key(tid): + threaded_listener.get(tid).paused = False + return True + +@jsonize +def stopListener(context, request): + tid = int(request.params.get('tid', 0)) + if threaded_listener.has_key(tid): + threaded_listener.get(tid).running = False + return True + +def saveEventRace(context, request): + eventname = request.params.get('eventname', request.params.get('event')) + racename = request.params.get('racename', request.params.get('race')) + + lock = threading.Lock() + + view = core.BaseView(context, request) + if not racename: + racename = view.currentRace().name + + view.session['current-event'] = eventname + view.session['current-race'] = racename + view.session.save() + + if request.params.get('template'): + return render_to_response('templates/%s.pt' % request.params.get('template'), + {'view': view, 'additional': request.params.get('additional')}, request=request) + +@jsonize +def mapCompetitors(context, request): + # returns competitors with their current rank at the given timepoint + + view = core.BaseView(context, request) + + _at = request.params.get('at') + at_millis = view.datetimeToMillis(view.parseDatetime(_at)) + + conf = view.listenerConf() + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIVE_EVENTS) + + race = view.currentRace() + conf.setRace(race) + conf.setParameters(dict(eventname=race.event, racename=race.name, timeasmillis='%.f' % at_millis)) + + data = jsonByUrl(conf) + + if data.get('ranks'): + data = data['ranks'] + data.sort(lambda x,y: cmp(x['rank'], y['rank'])) + + return data + +@jsonize +def windSettings(context, request): + view = core.BaseView(context, request) + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setRace(view.currentRace()) + + if request.POST.get('setsource'): + conf.setCommand(config.SET_WIND_SOURCE) + conf.setParameters(dict(sourcename=request.POST.get('windsource'))) + conf.trigger() + + elif request.POST.get('setcustom'): + conf.setCommand(config.SET_WIND) + + dc = {} + for k in ['truebearingdegrees', 'knotspeed', 'lngdeg', 'latdeg', 'timeasmillis']: + if request.POST.get(k): + dc[k] = request.POST.get(k) + + conf.setParameters(dc) + conf.trigger() + + return True + +@jsonize +def readWind(context, request): + view = core.BaseView(context, request) + + wind = view.currentWind() + source = wind[wind['currentwindsource']] + + if source and len(source) > 0: + return source[0] + return {} + +@jsonize +def readWaypoints(context, request): + return readWaypointsImpl(context, request) + +def readWaypointsImpl(context, request): + view = core.BaseView(context, request) + + conf = view.listenerConf() + conf.setContext(config.MODERATOR) + conf.setCommand(config.SHOW_WAYPOINTS) + conf.setRace(view.currentRace()) + + data = jsonByUrl(conf) + + # we want to show unique buoys so lets iter thru data + result = {} + for wp in data: + for by in wp['buoys']: + result[by['name']] = by + + return result.values() + +@jsonize +def loadTracks(context, request): + view = core.BaseView(context, request) + + _at = request.POST.get('at') + at_millis = view.datetimeToMillis(view.parseDatetime(_at)) + + # lets take 2 secs before and after given time + from_millis = at_millis - 1000 + to_millis = at_millis + 1000 + + conf = view.listenerConf() + conf.setContext(config.MODERATOR) + conf.setCommand(config.SHOW_BOAT_POSITIONS) + conf.setRace(view.currentRace()) + conf.setParameters(dict(sinceasmillis='%.f' % from_millis, toasmillis='%.f' % to_millis)) + + data = jsonByUrl(conf) + + # filter out the position that is the most current one + results = [] + for c in data['competitors']: + if len(c['track'])>0: + fix = c['track'][-1] or {} + else: fix = {} + results.append(dict(name=c['name'], **fix)) + + return results + +@jsonize +def determineWindDirection(context, request): + """ Returns the wind for all known marks """ + + buoys = readWaypointsImpl(context, request) + + view = core.BaseView(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.ADD_WIND) + conf.setRace(view.currentRace()) + + _at = request.params.get('at') + if _at: + at_millis = view.datetimeToMillis(view.parseDatetime(_at)) + conf.setParameters(dict(timeasmillis='%.f' % at_millis)) + + else: + # take start of race + conf.setParameters(dict(timeasmillis='%.f' % view.currentRace().start)) + + params = [] + for buoy in buoys: + if buoy.has_key('lat'): + params.append('latdeg=%s' % buoy['lat']) + params.append('lngdeg=%s' % buoy['lng']) + + conf.parameters += '&%s' % '&'.join(params) + + try: + data = jsonByUrl(conf) + except Exception, ex: + log.error('Error', exc_info=True) + return str(ex) + + # simply return the list + return data + +@jsonize +def listWindTrackers(context, request): + view = core.BaseView(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.LIST_WIND_TRACKERS) + + data = jsonByUrl(conf) + return data + +@jsonize +def stopReceiver(context, request): + view = core.BaseView(context, request) + + saveEventRace(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.STOP_EXP_WIND) + conf.setRace(view.currentRace()) + conf.trigger() + + return 1 + +@jsonize +def startWindTracker(context, request): + view = core.BaseView(context, request) + + saveEventRace(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.START_EXP_WIND) + conf.setRace(view.currentRace()) + + correct = request.POST.get('declination', False) and 'true' or 'false' + conf.setParameters(dict(port=request.POST.get('port'), correctexpeditionwindbearingbydeclination=correct)) + conf.trigger() + + return 1 + +@jsonize +def adminLiveData(context, request): + # searches for all running races and displays information for all competitors + + view = core.BaseView(context, request) + + race = view.currentRace() + event = model.EventImpl.queryOneBy(name=race.event) + racepos = event.races.index(race.name) + + competitors = model.CompetitorImpl.queryBy(event=event.name) + currentlegs = race.current_legs + + if currentlegs: + if currentlegs[0] != 0: + # always show the last leg + currentlegs.insert(0, currentlegs[0]-1) + + results = '' + for pos in range(len(currentlegs)): + legpos = currentlegs[pos] + + results += '\nLEG: %s RACE-START: %s NEWEST: %s WIND: (%s %s %s)\n' % (legpos+1, view.millisToDatetime(race.start), view.millisToDatetime(race.timeofnewestevent), race.wind_source, race.wind_bearing, race.wind_speed) + results += 'NAME'.ljust(16) + 'TOTAL'.ljust(7) + 'CRANK'.ljust(7) + 'RRANK'.ljust(7) + results += 'MRANK'.ljust(7) + 'LRANK'.ljust(9) + 'SPD'.ljust(9) + 'DST'.ljust(9) + 'VMG'.ljust(9) + 'AVMG'.ljust(9) + 'SGAP'.ljust(9) + 'ETA'.ljust(9) + 'DSTGO'.ljust(9) + results += '\n' + + # sort competitors by rank in current leg + competitors.sort(lambda x,y:cmp(x.values[racepos][legpos] and x.values[racepos][legpos][0] or 6000, y.values[racepos][legpos] and y.values[racepos][legpos][0] or 6000)) + + for c in competitors: + results += '%s %s %s' % (c.name.ljust(15), str(c.total).ljust(6), str(c.current_rank).ljust(6)) + results += '%s %s' % (str(c.races[racepos]).ljust(7), str(c.marks[racepos][legpos]).ljust(7)) + + for v in c.values[racepos][legpos]: + results += str('%.1f' % v).ljust(9) + + results += '\n' + + if not results: + return 'This race seems to be finished!' + + return results + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/app.js b/python/src/sailing.web/sailing/web/browser/moderator-static/app.js new file mode 100644 index 00000000000..5ec810a351a --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/app.js @@ -0,0 +1,6 @@ +$(document).ready(function() { + var wHeight = $(window).height(); + + $("#rootwrapper").css("height", wHeight); + $("#appinterface").css("height", wHeight-131); +}); diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-bottom.png b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..e453bf96a7435436a5ae460b1367548f4c69f123 GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^5;{g#vh6T$0t3!vEQMFyW{?Xj;2YPQqR~P<^K0%ca1o6D2tIp zn)#!)5YK(aBQ{GS7!Eykk@_drakgM)^LeHT-DSdwj+S!9AEFozi3Ny1Vp3rL5R}Bo z5&qEN53j&%;Yzi!e%n(F*-CbGDz5HFEQG+=M&JY N44$rjF6*2UngFhVZi)Z^ literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-left.png b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-left.png new file mode 100644 index 0000000000000000000000000000000000000000..e65e1d434a25873b4aee07f0a733f94b6e776b25 GIT binary patch literal 421 zcmV;W0b2fvP)+9USHX#4~|dZZM@eAs}7~ z#M{Yn7%d$a4#YQrIEoTOs2#1+Ks*hI{RUf6k_Nq0ShL+i2s=nBOxDklY(Ar_7h8)N-^MP1vuvPrkKzx#(4kN{Jvw(QnU~MwJ z2I6QS_6OppgS9=k35d0!Avq`;n;(HV9f%!(`2JvR2_J-pVjmFy9gNNN??7A(#8yCj zd9d~&P64qA5Z43oFKRiC7JUd}s3BS!my2jVA8m-Vsc&4=!(@ti-*af*p>#uic5kZ=Xdb@0q6GK>koD> zeA+mEJny~F`|R>@9OqP5At$`Da8n)b7)9UV@(EAtCqA%`N5yR|;{oR=slIbZc*U0L zfmp&FE-|lqT6gh|9o1H{fNR`hQMJ!)+q-z6+JpmK;2z7WH$)XLXkbS1`WoFRO*~;$ z^=@6mGfpv=*7X%Q2>OOSM2b_%if!|W>d171c9I{?dJNS^4IQ;%b5yCyUxN9lT+a?b zsMJb+(6VZU<31#f%5`mGjwXGO%gTM@4C^j}xvX4d)#@sZOkb#D!*#GpD;L^H>?w`u zLmXl=&0ynHu47%k@1t`k4L7h*SBn4m1KUo?&k_H!vQJ=HIN$46fB^si??NroE4nWL O0000M{U;vm zz?G_SrJ8O3Ne4y5SfB>P&Hu>*e}LE-h`Er>WI@Z=nm{ZM#OHzdABp7@GZ3o*@ogY} k1QTQ&t~)x!}mlz`((x@chmEFHRDN+XWgugJLpRUtL`s gXNyYwjn_WF@W+zrwLo;iVW0^Np00i_>zopr0GUWLA^-pY literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/freeze.png b/python/src/sailing.web/sailing/web/browser/moderator-static/freeze.png new file mode 100644 index 0000000000000000000000000000000000000000..3931b442c0ab1b2a3494bc53c4d1a47c496f387c GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^x8U}fi7AzZCsS>Jib6eI978H@y}7=TmqCGp!O_s~KuFFZjW<3|S)wF_H2+2G z=ry_-ZvMFY%$&vU76lIuG%j9ND!)3*WzMp9|2|CG3lv~x=aaFBQu(uaC%=qE!IUkm a5)3TUd2i2VUcv~pfWgz%&t;ucLK6T5x; + + + SAP Sailing Analytics + + + +
+ +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 1 + + GER10 + + EVANS +
+ 2 + + GBR12 + + ALONSO +
+ 3 + + AUS15 + + ALONSO +
+ 4 + + AUS1 + + BROTHERTHOl +
+ 5 + + IND66 + + ASQUITH +
+ 6 + + SUI 89 + + CZAJKOWSKI +
+ 7 + + NZL878 + + NIELSEN +
+ 8 + + USA23 + + NIELSEN +
+ 9 + + GBR25 + + PIASECKI +
+ 10 + + AUS34 + + FONSECA +
+ 11 + + GER34 + + GRAEL +
+ 12 + + GER2 + + NORREGAARD +
+ 13 + + GBR45 + + LANG +
+ 14 + + AUS26 + + KOSTOV +
+ 15 + + SWE87 + + CUPAC +
+ 16 + + NOR3 + + STORCK +
+ 17 + + GBR9 + + MOORE +
+ 18 + + SUI28 + + DELLE +
+ 19 + + DEN234 + + RESCH +
+ 20 + + GER666 + + DRAPER +
+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+ + +
+ + +
+
    +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • + 6 +
  • +
  • + 7 +
  • +
  • + 8 +
  • +
  • + 9 +
  • +
  • + 10 +
  • +
  • + 11 +
  • +
  • + 12 +
  • +
  • + 13 +
  • +
  • + 14 +
  • +
  • + 15 +
  • +
  • + 16 +
  • +
  • + 17 +
  • +
  • + 18 +
  • +
  • + 19 +
  • +
  • + 20 +
  • +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ gap + + a. speed + + distance + + g&l mt + + g&l pl +
+ + + + + + + + + +
+ 1 + + 30 + + 20 + + 50 + + 10 +
+ 2 + + 31 + + 21 + + 51 + + 11 +
+ 3 + + 32 + + 22 + + 52 + + 12 +
+ 4 + + 33 + + 23 + + 53 + + 13 +
+ 5 + + 34 + + 24 + + 54 + + 14 +
+ 6 + + 35 + + 25 + + 55 + + 15 +
+ 7 + + 36 + + 26 + + 56 + + 16 +
+ 8 + + 37 + + 27 + + 57 + + 17 +
+ 9 + + 38 + + 28 + + 58 + + 18 +
+ 10 + + 39 + + 29 + + 59 + + 19 +
+ 11 + + 40 + + 30 + + 60 + + 20 +
+ 12 + + 41 + + 31 + + 61 + + 21 +
+ 13 + + 42 + + 32 + + 62 + + 22 +
+ 14 + + 43 + + 33 + + 63 + + 23 +
+ 15 + + 44 + + 34 + + 64 + + 24 +
+ 16 + + 45 + + 35 + + 65 + + 25 +
+ 17 + + 46 + + 36 + + 66 + + 26 +
+ 18 + + 47 + + 37 + + 67 + + 27 +
+ 19 + + 48 + + 38 + + 68 + + 28 +
+ 20 + + 49 + + 39 + + 69 + + 29 +
+
+ + + + + + + + +
+ + + + + +
+ + +
+
+ + + + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/iphone-splash-screen.png b/python/src/sailing.web/sailing/web/browser/moderator-static/iphone-splash-screen.png new file mode 100644 index 0000000000000000000000000000000000000000..56b6ea4e6d81a349501785bcdab568b0dcde48d9 GIT binary patch literal 60985 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 + + + SAP Sailing Analytics + + + + + + + + +
    +
  • +

    Event: Bla Event

    +
  • +
  • +

    Current Race 1

    +
  • +
  • +

    Current Leg M2

    +
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rank + + Name +
1EVANS
2ALONSO
3ALONSO
4BROTHERTHOl
5ASQUITH
6CZAJKOWSKI
7NIELSEN
8NIELSEN
9PIASECKI
10FONSECA
11GRAEL
12NORREGAARD
13LANG
14KOSTOV
15CUPAC
16STORCK
17MOORE
18DELLE
19RESCH
20DRAPER
+ + + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/jquery.js b/python/src/sailing.web/sailing/web/browser/moderator-static/jquery.js new file mode 100644 index 00000000000..b2ac1747f3c --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/jquery.js @@ -0,0 +1,18 @@ +/*! + * jQuery JavaScript Library v1.6.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu May 12 15:04:36 2011 -0400 + */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!cj[a]){var b=f("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),c.body.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write("");b=cl.createElement(a),cl.body.appendChild(b),d=f.css(b,"display"),c.body.removeChild(ck)}cj[a]=d}return cj[a]}function cu(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function ct(){cq=b}function cs(){setTimeout(ct,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g=0===c})}function W(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function O(a,b){return(a&&a!=="*"?a+".":"")+b.replace(A,"`").replace(B,"&")}function N(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function L(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function F(){return!0}function E(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function H(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(H,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=d.userAgent,x,y,z,A=Object.prototype.toString,B=Object.prototype.hasOwnProperty,C=Array.prototype.push,D=Array.prototype.slice,E=String.prototype.trim,F=Array.prototype.indexOf,G={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.1",length:0,size:function(){return this.length},toArray:function(){return D.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?C.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(D.apply(this,arguments),"slice",D.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:C,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!y){y=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",z,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",z),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&H()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):G[A.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!B.call(a,"constructor")&&!B.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||B.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};f=c.createElement("select"),g=f.appendChild(c.createElement("option")),h=a.getElementsByTagName("input")[0],j={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},h.checked=!0,j.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,j.optDisabled=!g.disabled;try{delete a.test}catch(s){j.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function b(){j.noCloneEvent=!1,a.detachEvent("onclick",b)}),a.cloneNode(!0).fireEvent("onclick")),h=c.createElement("input"),h.value="t",h.setAttribute("type","radio"),j.radioValue=h.value==="t",h.setAttribute("checked","checked"),a.appendChild(h),k=c.createDocumentFragment(),k.appendChild(a.firstChild),j.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",l=c.createElement("body"),m={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(q in m)l.style[q]=m[q];l.appendChild(a),b.insertBefore(l,b.firstChild),j.appendChecked=h.checked,j.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,j.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",j.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",n=a.getElementsByTagName("td"),r=n[0].offsetHeight===0,n[0].style.display="",n[1].style.display="none",j.reliableHiddenOffsets=r&&n[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(i=c.createElement("div"),i.style.width="0",i.style.marginRight="0",a.appendChild(i),j.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(i,null)||{marginRight:0}).marginRight,10)||0)===0),l.innerHTML="",b.removeChild(l);if(a.attachEvent)for(q in{submit:1,change:1,focusin:1})p="on"+q,r=p in a,r||(a.setAttribute(p,"return;"),r=typeof a[p]=="function"),j[q+"Bubbles"]=r;return j}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;return(e.value||"").replace(p,"")}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);c=j&&f.attrFix[c]||c,i=f.attrHooks[c],i||(!t.test(c)||typeof d!="boolean"&&d!==b&&d.toLowerCase()!==c.toLowerCase()?v&&(f.nodeName(a,"form")||u.test(c))&&(i=v):i=w);if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j)return i.get(a,c);h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);c=i&&f.propFix[c]||c,h=f.propHooks[c];return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return a[f.propFix[c]||c]?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=b),a.setAttribute(c,c.toLowerCase()));return c}},f.attrHooks.value={get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return a.value},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=Object.prototype.hasOwnProperty,y=/\.(.*)$/,z=/^(?:textarea|input|select)$/i,A=/\./g,B=/ /g,C=/[^\w\s.|`]/g,D=function(a){return a.replace(C,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=E;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=E);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),D).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem +)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},K=function(c){var d=c.target,e,g;if(!!z.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=J(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:K,beforedeactivate:K,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&K.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&K.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",J(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in I)f.event.add(this,c+".specialChange",I[c]);return z.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return z.test(this.nodeName)}},I=f.event.special.change.filters,I.focus=I.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=U.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(W(c[0])||W(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=T.call(arguments);P.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!V[a]?f.unique(e):e,(this.length>1||R.test(d))&&Q.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y=/ jQuery\d+="(?:\d+|null)"/g,Z=/^\s+/,$=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,_=/<([\w:]+)/,ba=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Y,""):null;if(typeof a=="string"&&!bc.test(a)&&(f.support.leadingWhitespace||!Z.test(a))&&!bg[(_.exec(a)||["",""])[1].toLowerCase()]){a=a.replace($,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bj(a,d),e=bk(a),g=bk(d);for(h=0;e[h];++h)bj(e[h],g[h])}if(b){bi(a,d);if(c){e=bk(a),g=bk(d);for(h=0;e[h];++h)bi(e[h],g[h])}}return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bb.test(k))k=b.createTextNode(k);else{k=k.replace($,"<$1>");var l=(_.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=ba.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Z.test(k)&&o.insertBefore(b.createTextNode(Z.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bp.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bo.test(g)?g.replace(bo,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,c){var d,e,g;c=c.replace(br,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bs.test(d)&&bt.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bE=/%20/g,bF=/\[\]$/,bG=/\r?\n/g,bH=/#.*$/,bI=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bJ=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bK=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bL=/^(?:GET|HEAD)$/,bM=/^\/\//,bN=/\?/,bO=/)<[^<]*)*<\/script>/gi,bP=/^(?:select|textarea)/i,bQ=/\s+/,bR=/([?&])_=[^&]*/,bS=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bT=f.fn.load,bU={},bV={},bW,bX;try{bW=e.href}catch(bY){bW=c.createElement("a"),bW.href="",bW=bW.href}bX=bS.exec(bW.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bT)return bT.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bO,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bP.test(this.nodeName)||bJ.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bG,"\r\n")}}):{name:b.name,value:c.replace(bG,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bW,isLocal:bK.test(bX[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bZ(bU),ajaxTransport:bZ(bV),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?ca(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=cb(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bI.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bH,"").replace(bM,bX[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bQ),d.crossDomain==null&&(r=bS.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bX[1]&&r[2]==bX[2]&&(r[3]||(r[1]==="http:"?80:443))==(bX[3]||(bX[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bU,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bL.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bN.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bR,"$1_="+x);d.url=y+(y===d.url?(bN.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bV,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bE,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq,cr=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){return this[0]?parseFloat(f.css(this[0],d,"padding")):null},f.fn["outer"+c]=function(a){return this[0]?parseFloat(f.css(this[0],d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/mobile.css b/python/src/sailing.web/sailing/web/browser/moderator-static/mobile.css new file mode 100644 index 00000000000..5e1b5a4af1b --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/mobile.css @@ -0,0 +1,112 @@ +.overall-blue { + background: #008fcc !important; } + +.c-race-1-orange { + background: #de8a2e !important; } + +.c-race-2-yellow { + background: #fec631 !important; } + +.c-race-3-lila { + background: #9c277b !important; } + +.c-race-4-green { + background: #95aa31 !important; } + +.c-race-5-red { + background: #d83c3c !important; } + +.c-table-odd { + background: #484848 !important; } + +.c-systeminfo { + background: #e1e1e1 !important; } + +.c-main-dark-bg { + background: #151515 !important; } + +.c-font-white { + background: #ececec !important; } + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; } + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; } + +body { + line-height: 1; } + +ol, ul { + list-style: none; } + +blockquote, q { + quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; + content: none; } + +table { + border-collapse: collapse; + border-spacing: 0; } + +.clear { + clear: both; + font-size: 1px; + height: 0px; + line-height: 0px; + margin: -1px 0 0; + width: 100%; } + +.cover { + left: -1000px; + overflow: hidden; + position: absolute; + top: -1000px; } + +body { + background: #151515; + color: #ececec; + font-family: "Trebuchet MS"; } + body a { + text-decoration: none; + color: #ececec; } + body a:hover { + text-decoration: none; + color: #ececec; } + +.overview li { + padding: 10px; } + .overview li.current-race { + background: #484848; } + +.race-table thead th { + background: #008fcc; + padding: 10px; + text-align: left; + vertical-align: top; } +.race-table tbody tr td { + padding: 10px; } +.race-table tbody tr.odd td { + background: #484848; } diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/overall.html b/python/src/sailing.web/sailing/web/browser/moderator-static/overall.html new file mode 100644 index 00000000000..5574551392d --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/overall.html @@ -0,0 +1,1145 @@ + + + + SAP Sailing Analytics + + + +
+ +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 1 + + GER10 + + EVANS +
+ 2 + + GBR12 + + ALONSO +
+ 3 + + AUS15 + + ALONSO +
+ 4 + + AUS1 + + BROTHERTHOl +
+ 5 + + IND66 + + ASQUITH +
+ 6 + + SUI 89 + + CZAJKOWSKI +
+ 7 + + NZL878 + + NIELSEN +
+ 8 + + USA23 + + NIELSEN +
+ 9 + + GBR25 + + PIASECKI +
+ 10 + + AUS34 + + FONSECA +
+ 11 + + GER34 + + GRAEL +
+ 12 + + GER2 + + NORREGAARD +
+ 13 + + GBR45 + + LANG +
+ 14 + + AUS26 + + KOSTOV +
+ 15 + + SWE87 + + CUPAC +
+ 16 + + NOR3 + + STORCK +
+ 17 + + GBR9 + + MOORE +
+ 18 + + SUI28 + + DELLE +
+ 19 + + DEN234 + + RESCH +
+ 20 + + GER666 + + DRAPER +
+
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rank + + Flag + + Skipper + + Crew + + Total Points + + Net Points +
+ + + + + + + + + + + +
+ 1 + + 30 + + 20 + + 50 + + 10 + + 10 +
+ 2 + + 31 + + 21 + + 51 + + 11 + + 11 +
+ 3 + + 32 + + 22 + + 52 + + 12 + + 12 +
+ 4 + + 33 + + 23 + + 53 + + 13 + + 13 +
+ 5 + + 34 + + 24 + + 54 + + 14 + + 14 +
+ 6 + + 35 + + 25 + + 55 + + 15 + + 15 +
+ 7 + + 36 + + 26 + + 56 + + 16 + + 16 +
+ 8 + + 37 + + 27 + + 57 + + 17 + + 17 +
+ 9 + + 38 + + 28 + + 58 + + 18 + + 18 +
+ 10 + + 39 + + 29 + + 59 + + 19 + + 19 +
+ 11 + + 40 + + 30 + + 60 + + 20 + + 20 +
+ 12 + + 41 + + 31 + + 61 + + 21 + + 21 +
+ 13 + + 42 + + 32 + + 62 + + 22 + + 22 +
+ 14 + + 43 + + 33 + + 63 + + 23 + + 23 +
+ 15 + + 44 + + 34 + + 64 + + 24 + + 24 +
+ 16 + + 45 + + 35 + + 65 + + 25 + + 25 +
+ 17 + + 46 + + 36 + + 66 + + 26 + + 26 +
+ 18 + + 47 + + 37 + + 67 + + 27 + + 27 +
+ 19 + + 48 + + 38 + + 68 + + 28 + + 28 +
+ 20 + + 49 + + 39 + + 69 + + 29 + + 29 +
+
+ + +
+
+ + + + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/refresh-icon.png b/python/src/sailing.web/sailing/web/browser/moderator-static/refresh-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c3b502104879b09e10b5b5cf002e6f86a1a8e9ce GIT binary patch literal 735 zcmV<50wDc~P);+eEbsB3h)2HZ9u~6-5LIL4`y_w5>1*Yv_Y4(=oHL zv8LaFBRnqmKEpc;lY8LD%)EEsegAtt?zv1u`u-wO! z;>E3+S8@9WXOtoJgz3r1^1EN3joTtv;j;y0v_j1n_Q6y51V3P>3L1@Bi~IsP%k|9~reO`U zZF>^0Rl|BX1-qf$@LFD*Mb;-LKf^otWn7nvY}dkaSt`~|*1=I&X^fG=yG}&D`*?B; zUchT;Hd4drSnkEl?+v0S$d1UD(vJv;dIoR&-WGZQglRV`exl**n z4}9Ep-OU^X%Z)4Q%OW>VqeoE z*Rz;F3HMb;w-FEh)Z<;wg5=~jnGT*w=E$Ffe<`Ea1AcO9Rk4ycNrMm2|m~$NeDI&Bn<8h5Zs+GxI2Se2rj_~ zC&1?%?u@61+}KN2sV6? zMD~20lp0VX)lUu&F7~%Z)z)f(is&32SUJpQhm60e+dDWfe;<0ecrz~}_$oQXDwgLF z^UDuo&YTTmd=is<%Xe87ZTCRPPEHu+18_@p$ zv;Ajo+LnL6^WT6LO!{y5A9xQ~_e2c@+-xHX<`g)cwI_ZvX#EOsNBz}h`9~MN2^RxN zq)=rH+tLsCYAJ`Z>3g0>`tz|nosu|p4<{QrL@}F=lOfy_B<-oy54n zri>5z52sAoS@K)6afg0k@1*~K$YuM!^~Mh&s@y~-MvP?ef26v$9Y=Jm>9(I$)rN?_ zF?se#y_E4G;4pd4-uyc5FwtrkGvc4LvEZ)~$5?Z<@EfHB`=z@;0C9pJ!2cxYIa5pN zsKdq$#}Af$*xUNZ&U;R`fw!RRhT(fo!rK@H3)aZwJ8`Ly;W5=j!t2zRDj@~Kp}N;~ zfW5jVG-_T8Y_Y6a+JDmgIf%%_4OG<;q7+=jA&IIg?^O117%X%Hii}iTYOAK`V-j#F zHY%ou_wIJ)1NLa5HI6ibM{7QrriZ_*NuFi+uAdmJ$V;RRY@H5F`AZ$MIwSs2rD(jt zNmhjK70X+pq8o@epVB>mH&6#m2AL&q@{mMF-d)$ZY7R)f#h%@uMeLW>D^l+Y=&(P^ z%0>%G$|S@pvDoT0OaS*GAwa&02$Gp33heZuFrC6}i{NJNZ<7>vmf$>>c(ssD{sCFz zl%z6jl*B#-04eojpaa6ot&P$36=|wo3VKb2 zW$gy;s@|#&#(D{vbdAoj|4}oVBag*mc207vVuh^&}XBvdsYi1isr*I#up= zOqkt+Ul+e90nrQ`ylj{Z%{!l+9|4uN7;vR`ėj8 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 Y0H<_{wVOI$-2eap07*qoM6N<$f**u|y8r+H literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-top.png b/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-top.png new file mode 100644 index 0000000000000000000000000000000000000000..f6ca94142478200ada25edf27b687f6b05524d4a GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^LO^W7!3HGTtutzXlw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6JlqQ{;tjv*DdlJ;C*dfb8cz>oj`{|7d^@k*IyTv71i`Sjt# zf-XlNo)D%Z5=;1w6l<7vNOnADE;JIT4oC{%6Nq-YsSy5gLh=M9f$a((mp1O0F4LTr zROl!raC>r+fQC;@;fcmQCp>!`74%CU7Ov!)HN8;EM6#om!^O!?VD>{}4VDh(PLJpf zDF@rmDooH`HgUp?tqnV*W;+TuL`*p{Cy?>Tt`lsHLAg4Tkv+VxT+`A-MMVRmZt@-Z zlkzNFQ{mqsrrvj9T*m+PCpelftk`l!4(RL!Aon{NzG&+``ygv0BZ~w>N_&M@cU?#v P(7Oztu6{1-oD!M'; + +/** + * format("i can speak {language} since i was {age}",{language:'javascript',age:10}); + */ +var format = function (str, col) { + col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1); + + return str.replace(/\{([^}]+)\}/gm, function () { + return col[arguments[1]]; + }); +}; + +/** + * Renders the given template and invokes the callback with response + */ +function template(templatename, parameters, callback) { + $.get(_base_url() + '@@/' + templatename, parameters, function(data) { + callback(data); + }); +} + +/** + * Calls the given function. Must return JSON + */ +function GET(name, parameters, callback) { + $.get(_base_url() + '++/' + name, parameters, function(data) { + if (callback) + callback(data); + }) +} + +function displayLoader(element_desc) { + $(element_desc).html(loader_whitebg); +} + +$(document).ready(function() { + $.ajaxSetup({cache:false}); +}); diff --git a/python/src/sailing.web/sailing/web/browser/static/css/jquery-ui-1.8.11.custom.css.txt b/python/src/sailing.web/sailing/web/browser/static/css/jquery-ui-1.8.11.custom.css.txt new file mode 100644 index 00000000000..5e5a4144698 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/css/jquery-ui-1.8.11.custom.css.txt @@ -0,0 +1,502 @@ +/* + * jQuery UI CSS Framework 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* + * jQuery UI CSS Framework 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(${request.application_url}/images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(${request.application_url}/images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(${request.application_url}/images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(${request.application_url}/images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(${request.application_url}/images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(${request.application_url}/images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(${request.application_url}/images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(${request.application_url}/images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(${request.application_url}/images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(${request.application_url}/images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(${request.application_url}/images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(${request.application_url}/images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(${request.application_url}/images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(${request.application_url}/images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(${request.application_url}/images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(${request.application_url}/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(${request.application_url}/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* + * jQuery UI Resizable 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* + * jQuery UI Selectable 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/* + * jQuery UI Accordion 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; } +/* + * jQuery UI Autocomplete 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.11 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* + * jQuery UI Dialog 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* + * jQuery UI Tabs 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* + * jQuery UI Datepicker 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-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: 200px; /*must have*/ + height: 200px; /*must have*/ +} diff --git a/python/src/sailing.web/sailing/web/browser/static/css/jquery.timeslider.css.txt b/python/src/sailing.web/sailing/web/browser/static/css/jquery.timeslider.css.txt new file mode 100644 index 00000000000..d90bf038034 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/css/jquery.timeslider.css.txt @@ -0,0 +1,117 @@ +.timeslider-container, div.timeslider-arrow, +a.timeslider-slider, div.timeslider-slider-line, +div.timeslider-labels, div.timeslider-label +{ + margin: 0; + padding: 0; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +.timeslider-container +{ + position: relative; + width: 146px; + min-height: 40px; +} + +div.timeslider-container +{ + display: -moz-inline-box; + display: inline-block; +} + +div.timeslider-arrow +{ + width: 18px; + height: 18px; + cursor: pointer; + position: absolute; +} + +div.timeslider-down-arrow +{ + left: 0; + background: url("/static/images/pt_controls.png") -18px 0px; +} + +div.timeslider-up-arrow +{ + left: 126px; + background: url("/static/images/pt_controls.png") 0px 0px; +} + +div.timeslider-down-arrow.timeslider-disabled, div.timeslider-disabled div.timeslider-down-arrow +{ + background: url("/static/images/pt_controls.png") -18px -20px; + cursor: inherit; +} + +div.timeslider-up-arrow.timeslider-disabled, div.timeslider-disabled div.timeslider-up-arrow +{ + background: url("/static/images/pt_controls.png") 0px -20px; + cursor: inherit; +} + +div.timeslider-slider-line +{ + position: absolute; + left: 18px; + width: 108px; + height: 18px; + background: url("/static/images/pt_controls.png") -52px 0px; +} + +div.timeslider-disabled div.timeslider-slider-line +{ + background: url("/static/images/pt_controls.png") -52px -20px; +} + +div.timeslider-slider-line-clickable +{ + cursor: pointer; +} + +a.timeslider-slider +{ + display: none; + position: absolute; + left: 0; + width: 16px; + height: 20px; + background: url("/static/images/pt_controls.png") -36px 0px; + cursor: pointer; + text-decoration: none; +} + +a.timeslider-slider:hover +{ + text-decoration: none; +} + +div.timeslider-disabled a.timeslider-slider +{ + background: url("/static/images/pt_controls.png") -36px -20px; + cursor: default; +} + +div.timeslider-labels +{ + position: absolute; + top: 20px; + left: 18px; +} + +div.timeslider-label +{ + position: absolute; + font-size: 85%; +} + +div.timeslider-disabled div.timeslider-labels +{ + visibility: hidden; +} + + diff --git a/python/src/sailing.web/sailing/web/browser/static/css/styles.css.txt b/python/src/sailing.web/sailing/web/browser/static/css/styles.css.txt new file mode 100644 index 00000000000..8167596f7b4 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/css/styles.css.txt @@ -0,0 +1,174 @@ + +body { + font-family: Verdana, Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.4; + padding: 0px; + margin: 0px; + color: #5A554E; + } + +h1, h2, h3 { + margin: 0; + padding: 0; + font-weight: normal; +} + +h1 { + font-size: 2em; +} + +h2 { + font-size: 2.4em; + margin: 3px; +} + +h3 { + font-size: 1.6em; +} + +p, ul, ol { + margin-top: 0; + line-height: 200%; +} + +ul, ol { + margin: 0px; + padding: 0px; + list-style: none; +} + +img { + border: 0; +} + +a { + text-decoration: underline; + color: #516C00; +} + +a:hover { + text-decoration: none; +} + +h2 a { + text-decoration: none; +} + +table { + border-width: 1px; + border-spacing: 0px; + border-color: #ececec; + border-style: solid; +} + +table td { + border-width: 1px; + padding: 2px; + border-style: solid; + border-color: #ececec; +} + +.clear { + clear: both; + font-size: 1px; + line-height: 1px; + } + +div.help { + margin: 2px 1px 6px 1px; + padding: 10px; + border: 1px solid #ececec; +} + +div.field { + padding: 3px 0px 4px 2px; + margin: 5px 3px 2px 2px; +} + +div.field span { + font-weight: bold; +} + + +div.field input { + border: 1px solid #8F8F8F; + width: 234px; + padding: 5px; +} + +div.field input.large { + width: 687px; +} + +form input[type=submit] { + padding: 5px 35px; + margin: 5px 2px 2px 2px; + border: 1px solid #c8c8c8; + background-color: white; + color: black; +} + +select { + border: 1px solid #c8c8c8; + padding: 3px 2px 3px 9px; + background-color: white; +} + +.loader { + text-align: center; + vertical-align: middle; + padding: 5px; + margin: 7px 0px 7px 0px; +} + +div.message { + color: #a0522d; + background-color: #ffffe0; + margin: 10px; + padding: 5px; +} + +#tabs { + margin: 3px !important; +} + +div.info { + margin: 10px 2px 2px 2px; + padding: 7px; + border: 1px solid #ececec; +} + +.maplabel { + color: red; + background-color: white; + font-family: "Lucida Grande", "Arial", sans-serif; + font-size: 9px; + font-weight: bold; + text-align: center; + width: 50px; + border: 2px solid black; + white-space: nowrap; +} + + +.ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; } +.ui-timepicker-div dl{ text-align: left; } +.ui-timepicker-div dl dt{ height: 25px; } +.ui-timepicker-div dl dd{ margin: -25px 10px 10px 65px; } +.ui-timepicker-div td { font-size: 90%; } + +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* + diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-small.gif b/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-small.gif new file mode 100644 index 0000000000000000000000000000000000000000..09d621ede9dbe610877292e554c858d60573359e GIT binary patch literal 723 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 literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/boat.png b/python/src/sailing.web/sailing/web/browser/static/images/boat.png new file mode 100644 index 0000000000000000000000000000000000000000..cc57b86a0f1ad5c728b6bb8801b3be0e91d4f2f4 GIT binary patch literal 6082 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 literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/boat16.png b/python/src/sailing.web/sailing/web/browser/static/images/boat16.png new file mode 100644 index 0000000000000000000000000000000000000000..be876ac4958674618abf3e1dff022f1c36fa913a GIT binary patch literal 1179 zcma)*ODIH97{|}mnDH9MBZQL3LLnCa82TmqjL$pr%8xTcN{j>pt||U{p UyL@#2VyX~dxhra&8)a=HpTqxV4*&oF literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/boat32.png b/python/src/sailing.web/sailing/web/browser/static/images/boat32.png new file mode 100644 index 0000000000000000000000000000000000000000..43181c8a4b83251add2b8e718d5190e79fa88006 GIT binary patch literal 4267 zcmd6qOGuPa6vyxM7*iXv$097qMFr);Rf{Z)Y)q%fLZq}s4{IBg3YCkXb`cTOCM$A? z$X2f06!cgXMif0L$ii9}8AL=ySdjhx`rY9=eDlcpX6g*Tx#ymH?>Xl_zB}KX+}2nh zDJd^8#zbNb(I(0YF)Pe>M_1Q3icm*WeXZ$xw0ML{xNUQN)Qss9ztwvVOYy;m)(&Gz z=ZlcJaA_gNqR!Zsx}w2wxHME1@18SYOj%_ty1u!kI8;$K^qC%k$;H4tO~KK2#*9s2 zTp&Z1d%^!n0y-c%9lyOKC<-gj2xo&Ad}OjjjevLDB8V5=+MDX;A( zWsM9$OBD_k&|P}J1Z?}^AQPC4GtJC8w}EY`Sat=hP337d1R<|+k}9|YN&FH}+mZ3s z9KQM(>(0tgm-|!+sQ)^3n2NMB$S+{BO}^2s z^ZMkYD8s2HXZ#Y_i2axv^DL|6KRJO#*ls|sCtkiY$r5!)PT&bP1<%L6E1oNQ{WLQi z%Ng`x567IfTI%(DPN`cnooM2Z({(6VTe_vbM;0sckjX=QX7z;W5^`^^Ty@>1dVkb) zoRH*0m}m%Cu?Jg^-Y?g8x&)M|21;x>QOoYzj?Ma0$B?$%vBQ=9dzn2D=c#t(26`e77mKuf+1w4AbEgJGzIy`Ux4Wi|kpLBA#1 oo)*wn>3SZ59=HwK@)+y_#WYvej&9n~|MrvgSY2bZuXfLgKlKkB(EtDd literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/button_minus_green.png b/python/src/sailing.web/sailing/web/browser/static/images/button_minus_green.png new file mode 100644 index 0000000000000000000000000000000000000000..94dc29e5662b85a94d8249e104fc121a4a1f603f GIT binary patch literal 11515 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

GV#pa>3E9Id zAg6S=NM~neX4t{&vV+^ng4JW;OB`4jC5=8m6ml8Q76-Sa~lRpT^ zqrmd zjSNb*sbn@GGqGcp+&ypv=oSPamI-Kz)kYJt0&pZQEBlo4NsF`64_%JaB5`R~DP&5vb76Ey2igV#UQru3fU)Ts#~M)&Ttv7kvN# literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/button_sort_none.gif b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_none.gif new file mode 100644 index 0000000000000000000000000000000000000000..285f041ad84c11bb023bd133d33c6280918e3a19 GIT binary patch literal 86 zcmZ?wbhEHbWM|-En8?7u`(O0<@#Fvh|7T!eQ2fcl38WZwKmR_j literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/button_sort_up.gif b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_up.gif new file mode 100644 index 0000000000000000000000000000000000000000..d820987b6a7be19b94ac9fe33b97f592bdfa8221 GIT binary patch literal 89 zcmZ?wbhEHbWM|-En8?7OsI0;JU-bC#Y<$GPD5lSLz$5U0LysJ18;^hhgEauqMimV{m3{juDv|Y`p1k zI$@i_cqwfeLtb@I=zwtxlhQ$fV!OgJ3#9`DG5LAUy*-DvtVsB}p5({#Jiq7nJon+; z!==4~5F@-Gs8j;6Dxppx2pT~U6vWav=S4vnC4M5|h(vgcfbx+R03nL#9z@T;^LYlE zkLu8rehAbyr_126#07FJPi-)tt`mt~vETEf&v*kex;YvUi7e z;$|6IbCb||JXyT`anhb=X!|q?tB;(RtSg84>rC7$J-MUzUI^PSWw=9nQM8{-5()M+ zLq}c`82Zm2fx~ny;^m%7pB59*v>*s>npe)?rg3s;qIBY#otc7w(AU|m6_qCQtbW1jFC%6Fx61Z z^D~C+>#Z#~Ay#GaoOfaXv!+T=o~?(sigEX}M(jVMjyS`U(GDiZrhf_Uo?48QreUBk zfk1v+Y}{$6#TiXemm3<_v#XySU!-`wfg= z`2hBtc~~6O!&;e!p$lsG9^T^`=2$CIVf!hEg;=!crFhwH;hd}EJE?y7f(FCiB#0vy zckYAJbe8MGouvoeuwGVU&KRm$b=hDo(_rf7?dylv{_}Jh6IauSPAzGveym(Aj#p|z z_Q7@~4v+i4$JXj{cnhr9doe-s_8(J1@}8a&*s5Q_Y-8?@8cM8tCNbBP3)-93+p4!Q zSsgFhug38irfZa7aJ3$X1XC{O96@=ibJVDKPL3(J-GgzgC(8xbIcnp?*&8ZphWUCG zWGDlc#C1Wwln;u7a?T)sM-Sdt1+ELx$BC{+m14oD28SVjhwlmEs4v9<%VMTsxdm1e zrVr;AjqxJ6UD40~(LIQsf#>%OJo6dONI^IZK~NGLAUGJXF~kZK1q6o)lmssk93(hE z5JMm>)+dss?!;5z2JEzR(|ZCLlZBi%|^E`Nx&PZGpCC*tWX4Ox9f zDR?y0h^_S%UjNiH!F}e?{M79tu_yoKkRGcGvUbI3!DM|ly!H-k{Vn&RK3%iFp2LRE z4d2`#%x7c8!Sfp4V{^rge>eQ_&ktdFsteBc&)Fq0V~{_`tUaETIG>{v_b+O2zeFRB zmCL`2v*lg*9SvAt9E8_eimB^b$u9KeVW$2~$)`NU%&ipIe^3RW6dkong{v_Z`-QtH VHu`^>JZ;F)=GgtIv#nz_{{icjHB$fp literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/plus-icon.png b/python/src/sailing.web/sailing/web/browser/static/images/plus-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3e8d9466d97acdf38501d3770d606c3913ca7796 GIT binary patch literal 3031 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 Z{{pQPADixuv339e002ovPDHLkV1i3d!}|aL literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/pt_controls.png b/python/src/sailing.web/sailing/web/browser/static/images/pt_controls.png new file mode 100644 index 0000000000000000000000000000000000000000..c86484f31d49004fcec49407227e87b64c1973c8 GIT binary patch literal 1049 zcmV+!1m^pRP) zPly{;9KiAKOD3)fX6#Y;s&=(eRID0=NhJ&54Vi&Uit-Gk8G2p+Z`1U-5a z`~%*+Dip+Gdl8ftK`I_vv#{$%+$o9sC;6EN58h!2Gn?6AC$GN`44a*S%pAV_cnNt% zL?|0$437BMN$%Mjz`z|t86kKoqTFOS92&-`R4Rzb9IyrSfNfwv@KlA88#h2#S66Y4 z0`qS2R#6)6ltg?8XaWxa74A!- zpWo#2H@6E3*v4w#d-01~T)1+bz3Oy2C>4>!^c2_W{|8_%~~#Mxr~>}rSGoqupR*_y-Qx4&ZY;~wybh^*s$xN=1R%wUJG zD5=(XfAKvN;iLuZBktOB;sZ_z*2P*hV+r&ywBMtMxD<@Ny3j5|E;4xqZ*Z}&M-g?{M*ofW# z-qc^yYf+Y9C;M>b1IB+ia}npGRApSWcDmYNzrM6!QliZq@t5zMHY=~4nt19OW7sP@ z0diam;C?|qOLF3VyLc8Wf2`@t2=-_=9P0PDDiQA3V2cWv3A9=*4vwD!<-T9|&k|8` zBI2fOa@kN;O2d_EwaR!HN=RwA4PXv93LFCJB>m@qhl@}KN+&L`1Ka})&?jjdh~3{I z2S{nSGr*RcqCEf?ZVZrWR_ne_L+!Byc#D+22?e=u-Ia9jl zERN&A_nax+a~3`g_ut-**n4>!;n_MHoBdJ1eE@m!sUtkxsF}RM+E@#sG+ZAq-~wI)5PRlpdoF9I?CIChTghh#|^6WF`O@xycu#dQJ&xsE>C0G}0 z(MI9ggP(5PkXkKbcYBM_C_k7YLgC{zHr|<;I_cCvhKX}kQ=!Zj7EY&3TsLJMvMv?u z_2*8_rz{nU+jDmA%o&4YBX<9LQ-4jbMOlKK?8BK482{nSMVyaPm2uJ9>1u<0`P?y+ z5^d&)Upjltyzt}^KXr@WbB3J&Ij#k8zaXC_IdNY-e;g}+tm(^$34VN|-{Y!8xP=D0 zU-xM?n;aZJ1rQu4u-PS#4O81-vKd5>dM6EPU#J`)Gb$ T2pr8S00000NkvXXu0mjfccKB4 literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_asc.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_asc.png new file mode 100644 index 0000000000000000000000000000000000000000..a56d0e21902ce620cd57f87fa58a6d3e804135cf GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+5i>l2Ka=y{`vF&J9*~+_wWBdfBFCW_y37A{>@tOZ^^2EJ(K_a|Nno&o$%d2jr=7+e!)O45@5J; zXU0OHl&hzUV@SoVE9Xw~GAQscA1s)^?0*rXqM}DeLv7?|BU8z@QCOGupVzP9Hek5&L+Gnl%BD>~0~tJB{an^LB{Ts5b0m7= literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_asc_disabled.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_asc_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..b7e621ef1c68da839ce077cec6e201a55c1ba168 GIT binary patch literal 252 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+5i=)2l#}z{`>du$&)AV-@pIyd9;k)4B*-rq$b|z2+ZRf0KnW*L z7srr_TUXBQ7GeV6G?@}f$7k6Jhw{qGm$-QDzD`qrDaZ3s$b2XF;fBBPU nqjNDy&Nw~puHFA+-v&m8`?>-yUFVHK{$ucT^>bP0l+XkKhw^g= literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_both.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_both.png new file mode 100644 index 0000000000000000000000000000000000000000..839ac4bb5b0b414834c950de9deafff6dd94ed2d GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+5i=)2l#}z{`>du$&)AV-@pIyd9;k)4B*-rq$b|z2+ZRf0K#2rT z7srr_TRjsz`4|*ASOSl%eg6Ob+(JtRwX|O@S}a^IESQCgTe~DWM4fR9b+X literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_desc.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_desc.png new file mode 100644 index 0000000000000000000000000000000000000000..90b295159df995329b3a84340d32761f3d1dbade GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+5i>l2Ka=y{`vF&J9*~+_wWBdfBFCW_y37A{>@tOZ^^2EJ(K_a|Nno&o$%d2jr=7+e!)O45@5J; zXU0OHl#{26V@SoVqz8vtc$~v}dc~O{CLEF2anNavMpdMP)0v(X&o(k0opIq!LdvtJ wj~up7@0`wiSoe($&y07EkGxK6U|?nlJSz0{?wJWUfu=Edy85}Sb4q9e0C9MGu>b%7 literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_desc_disabled.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_desc_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..2409653dc94cd21a281a31c0e3819323b84704b7 GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+5i=)2l#}z{`>du$&)AV-@pIyd9;k)4B*-rq$b|z2+ZRf0KnX`r z7srr_TS*TNvhX;E^>j)zMNBv%VR68zN24n8K+>5N&kUJbBQCy4c=qgBiu3mAQ)hD? n)_oJhGvi(If!Apb49pB3GXz|UGFKJ=4P)?h^>bP0l+XkK*57ji literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_0_aaaaaa_40x100.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_75_ffffff_40x100.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_55_fbf9ee_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_65_ffffff_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_dadada_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_2e83ff_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..09d1cdc856c292c4ab6dd818c7543ac0828bd616 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_454545_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..59bd45b907c4fd965697774ce8c5fc6b2fd9c105 GIT binary patch literal 4369 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 oBo%DI*Kv;w;*%(i9W@f3_WCF#rGn literal 0 HcmV?d00001 diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_cd0a0a_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..2ab019b73ec11a485fa09378f3a0e155194f6a5d GIT binary patch literal 4369 zcmd^?`8O2)_s3@pGmLE*`#M>&Z`mr_kcwz5Nh&gy7G+@45H9p05OJ)J0CH2owMSaGIN$+5!N; z<11j56?ANg=9hMl-IBGX-T8hf$N$b*H?$f4Xt&I`oABt1nR=k%#z{{*a!Axm|t}hCz zJg0Ln7;M4Zjx{$mwhMW+kWN;|j>qTx_-zNX!GzqEZRa}QF8_0yk6+=w}$QD^&hM4%OkT=uh$q9;5u~NL-I+NQyaVc|3l+iWI5~|(hA-G z08i8AMr@{uY_cWTxo^y|Qyb33mlZLvc7H2Zm~>mB7&=-1X^@|D z&0*~i?GBE&NM(Pv&Vt^zWu_bD3e|R?wTL{cSFwD^Ij9v%g=aLY@1U2Bxn#Te*{>%D zOOW-O-bfnJ7T8jd<*>8`Z2DsFQi~S$%^npJwXam5>>p zMd}QEjM)@~##n$LXpz1Hkl|2UGXi-JFFePXBWL+-5f%!S>L#KL3>Vl0w#d^21Jn<~_7q zWx^Xg1(>PsPGO&cu{S;(pRQ;=Vw2J<9NdQVWx<+g-`ia=Q@puS)75M+?u>DTa95e9 zt#1T?#a)uWC>Mia!K6>g|InPW{&Kp9$tC_3*;R_Xsz6^Eu|xW1$6j#0?XLs7^l+%O zlxddE)h^|=K(2UqS*0ECuDe0ic|H_^t*VOoTCKx0Qmn_^LyJ|b8l$Jvl3{2=3x8&7 z$1ik&YG>w#@x@y~$r`fhlUDo;yXecc6$`30m`3K8s{k8G&3RVp8n#|l6h(Xw`Axw9 z%6Y^J6k0P@4YAuSd%q7=eg)&u8EMoEmq$CWj1GY|rGQWw3ida!FHk&wCqrQh_0Bcw z!ZBS3CbxgZ+}~wzgGIQ#QId%T_TE~_qdUqxjqS#8#jPxdwO@(@-5_nSP&uT?aGYYD z6km36K9=gjUjImwO=5Hl#u85VF?r0HbW)#h^SR|s_L47Tl$&Z&Rz*ksl!t*(2O2;D z+8`6$qpLn}LchhCmv*X}moGMX5?F@juGeHQAddAn}0~r zS_0|d3*0v%Y)8+8K{ zGyoYPb|W9Grm9M4E?vb^@16ePbI4omZv+(NoZ##fLUmKlB(G_jEbtDCM*27t$v`JovAZa+%*Q5dDXF*Ftt*n!O>#ohCM4lZ)h5rdKV-3A za}2AO6@!`W>ROk5FN*>2Zza^Z%}8KT%*jBGH|rml2X1LR{wZhWx8V4>|5i}; zMnLIHn3!^)`87GYh}&Y`KMwyLbA#^pch}Z!`@P_qH&N^LS9SxpEy8mc!wFusq&Z@` zeO}<6PC@VNaII|=n(^cNUiLseig*$;NjG7;IwvfYCBN>kzv@v-V2eBQZ@oIs^)NLqMR935k|1}U;5<{s(Ebdj4r`?QtrrAPfQooq zmPs_(YTy|??+nitNIFDoR7~qLPPFFCf^_~8OUt{#!|9o*3Q{!@9ZAI$7O~piD!;WX8#v&RxNH27i59$`1{o zEYU_zE{bKEI%f3BbE0Fc;f2!4LjUlC`wgh4@R{1?O78r5t$hWKiLV{#QWWq{QZiPx zm3?x$;&DDRVt0SByRiFczw$-e)GSvpCRbzk^=E zz=(+LjEc{Ps_2(OYg=G(93!oS=IeJ|WA8STv+LgI*Oj1c-QC06N~mvJ&KKx{arGp5 zswvJ6{%BvBYo>#2$%O$~TITuh?Rr^jCpAUXh)}m74`O|aOU>w2KI`k<#efwa5=-l4Xx!o>Z9Evg`RLN5W7SQp3$@D3_hY4EV!0( ztMm6>zBcgY{RvHZ{9Ey&&)jr2B4s0qDPBUh1ITaAp&>rj3ng*B=VGXz* zs@eR<;J(XkpD6Q1U3}#FR)wlafiFMU(-=&e9(eQ`isrS-9aNwJ)7frS8RiXM4*SbC zL|4*c?h^jfYvSOpn%Z$W?C|TuZ;uy2pFWHXuGW`ZkGV&kPJsKqJJQ!NswAE!!cb2k zumi=AE$YIkm})cVlg>nn&PBjBRI*@mfhhRMsa5U8k#A!ztfiw)d7I_UyAif8$5sJ9a7WUv5!o%fL z(J7-8EQzv1YIc)BNeWkLK~m%y4vqe&q@|_ZR5;eC3-9rkf*T{_19jtuWKhdW4Bn|~ zZ-YyFLN!k)0AKg{dO)|v3K?=oy+dzb4%T1F4}JsByncB1Z(`2p@O0!E!JQelouN^* z%Q^YfQUh66D$Zx-RDZvLctsr9`_+1p#tz&4SMd@i_-8()tyg3OyhU~?Gt#-a{NKFN z0VGf+AH%@o6;-_*?$$T4QX-f_>Ny-5CV8Ccq+@>gNSeovbFr0@b}RiTcJbLx>ws&r zsvY!rR{4al#MpVKut~?&kTmF>_v3UaC!gvuxgg%5-{l{20}~&F6CUarF9N=u)BG71 zoQDlAwT+T=mfo&$Xy%4-kmW;4wuh6{{ABClybHV6L>t&k4?9_Ny8A_^?)ff#dEjhL z2RbC~cFVbz^fJ`$I0%prYc0g-9(7X3eUp}^#Mzv)Z1EsGW;qr3cY$+e2HU5d_O9L% zpbljP*1!A0PqpzNo3W&y(hD87qgweq5YQWYEkxrOuSain2-q@Z*P`x*ht-9)Fr5Ho zSTKduvc9h6`S^#$i)LgjDi3_PQ+RbaGP!!di^Y;4kB0lGo$y{if)rJIaXTbpRgO#B z1El6|18;s}$0FRjgK-7~ZwmI`_1{a`32+Y>&O_iTpm%vz6hNkjGR(#*! zpfJ2>OAQbTFba9S3j9BlRHXaG{)Zt(J<3ppA?}j+7F#{bV{M7zU)5e@~R&J_xf$+GKK~ z3{R;Y9fZGe^ifEqKL;!VMXv26=R~^TG(#*2!JKCWoo&c^$utAs#Gfq-?t!c&9TH5- zj&i5L4NWbdNs*djvsY}bC&ddUbh=iyc0;3-@Y#d^s8|Ql{ax(yenFcG#i|K%lRxy| zFys4w!@EPXp2AsbMUGc*eP|7uliAq-O6~(+MR>V(EZTd&9G+MY&gF2lZ=I8j*o`OC z`AxrmOGMeD=H_9Cq47clT|h34>-EI=%;E!my;o&wU(aKV&PymBzrV9q2uA62XS@JrjKYANZAU>;8mag#BU?Nv`+ZVhlAPV`HF_gKY_O zhbV2L`8qvR&f=@M5vH~geD+L&*L2s<)|5)clA0yt9TM{X)iWtx@wJO_!{vR#|AD6t z*OAg2&P_i8jjW5y0DdtOGcqvrCHD*1Uq_q1ZQmngPnf!2fHizH%sSX>#$2Rh!>1ur z+s(*-)abDuePc6~XNG8m@|KMXHVM#G4?~+V z1z!An!D0GD-7WqXE8ddUXLkI%u01$fTEhhyd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La, +"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this, +e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a, +"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+ +a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/, +C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j, +s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this, +j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length}, +toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j=== +-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false; +if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload", +b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&& +!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&& +l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H
a";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"), +k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false, +scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent= +false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom= +1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="

";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="
t
";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display= +"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h= +c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando); +else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one"; +if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true}, +attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&& +b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0}; +c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem, +arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid= +d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+ +c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== +8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k=== +"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+ +d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired= +B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type=== +"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]=== +0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); +(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3]; +break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr, +q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h= +l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n, +m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== +true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== +g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]- +0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== +i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]]; +if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m, +g);else if(typeof g.length==="number")for(var p=g.length;n";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g); +n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&& +function(){var g=k,i=t.createElement("div");i.innerHTML="

";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F|| +p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g= +t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition? +function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h= +h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context): +c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a, +2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a, +b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&& +e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1, +""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null; +else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append", +prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length- +1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script")))); +d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i, +jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true, +zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b), +h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b); +if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f= +d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left; +e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/)<[^<]*)*<\/script>/gi, +ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b=== +"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("
").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& +!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, +getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", +script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| +!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache= +false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset; +A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type", +b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& +c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| +c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]= +encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess", +[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"), +e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}}); +if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show", +3),a,b,d);else{d=0;for(var e=this.length;d=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, +d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* +Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)} +var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; +this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| +this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= +c.timers,b=0;b-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a, +e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&& +c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); +c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+ +b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/python/src/sailing.web/sailing/web/browser/static/js/jquery-ui-timepicker-addon.js b/python/src/sailing.web/sailing/web/browser/static/js/jquery-ui-timepicker-addon.js new file mode 100644 index 00000000000..14b7b683048 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/js/jquery-ui-timepicker-addon.js @@ -0,0 +1,985 @@ +/* +* jQuery timepicker addon +* By: Trent Richardson [http://trentrichardson.com] +* Version 0.9.5 +* Last Modified: 05/25/2011 +* +* Copyright 2011 Trent Richardson +* Dual licensed under the MIT and GPL licenses. +* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt +* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt +* +* HERES THE CSS: +* .ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; } +* .ui-timepicker-div dl{ text-align: left; } +* .ui-timepicker-div dl dt{ height: 25px; } +* .ui-timepicker-div dl dd{ margin: -25px 10px 10px 65px; } +* .ui-timepicker-div td { font-size: 90%; } +*/ + +(function($) { + +$.extend($.ui, { timepicker: { version: "0.9.5" } }); + +/* Time picker manager. + Use the singleton instance of this class, $.timepicker, to interact with the time picker. + Settings for (groups of) time pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Timepicker() { + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + currentText: 'Now', + closeText: 'Done', + ampm: false, + timeFormat: 'hh:mm:ss tt', + timeOnlyTitle: 'Choose Time', + timeText: 'Time', + hourText: 'Hour', + minuteText: 'Minute', + secondText: 'Second', + timezoneText: 'Time Zone' + }; + this._defaults = { // Global defaults for all the datetime picker instances + showButtonPanel: true, + timeOnly: false, + showHour: true, + showMinute: true, + showSecond: true, + showTimezone: false, + showTime: true, + stepHour: 0.05, + stepMinute: 0.05, + stepSecond: 0.05, + hour: 0, + minute: 0, + second: 0, + timezone: '+0000', + hourMin: 0, + minuteMin: 0, + secondMin: 0, + hourMax: 23, + minuteMax: 59, + secondMax: 59, + minDateTime: null, + maxDateTime: null, + hourGrid: 0, + minuteGrid: 0, + secondGrid: 0, + alwaysSetTime: true, + separator: ' ', + altFieldTimeOnly: true, + showTimepicker: true, + timezoneList: ["-1100", "-1000", "-0900", "-0800", "-0700", "-0600", + "-0500", "-0400", "-0300", "-0200", "-0100", "+0000", + "+0100", "+0200", "+0300", "+0400", "+0500", "+0600", + "+0700", "+0800", "+0900", "+1000", "+1100", "+1200"] + }; + $.extend(this._defaults, this.regional['']); +} + +$.extend(Timepicker.prototype, { + $input: null, + $altInput: null, + $timeObj: null, + inst: null, + hour_slider: null, + minute_slider: null, + second_slider: null, + timezone_select: null, + hour: 0, + minute: 0, + second: 0, + timezone: '+0000', + hourMinOriginal: null, + minuteMinOriginal: null, + secondMinOriginal: null, + hourMaxOriginal: null, + minuteMaxOriginal: null, + secondMaxOriginal: null, + ampm: '', + formattedDate: '', + formattedTime: '', + formattedDateTime: '', + timezoneList: ["-1100", "-1000", "-0900", "-0800", "-0700", "-0600", + "-0500", "-0400", "-0300", "-0200", "-0100", "+0000", + "+0100", "+0200", "+0300", "+0400", "+0500", "+0600", + "+0700", "+0800", "+0900", "+1000", "+1100", "+1200"], + + /* Override the default settings for all instances of the time picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + //######################################################################## + // Create a new Timepicker instance + //######################################################################## + _newInst: function($input, o) { + var tp_inst = new Timepicker(), + inlineSettings = {}; + + for (var attrName in this._defaults) { + var attrValue = $input.attr('time:' + attrName); + if (attrValue) { + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, { + beforeShow: function(input, dp_inst) { + if ($.isFunction(o.beforeShow)) + o.beforeShow(input, dp_inst, tp_inst); + }, + onChangeMonthYear: function(year, month, dp_inst) { + // Update the time as well : this prevents the time from disappearing from the $input field. + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onChangeMonthYear)) + o.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst); + }, + onClose: function(dateText, dp_inst) { + if (tp_inst.timeDefined === true && $input.val() != '') + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onClose)) + o.onClose.call($input[0], dateText, dp_inst, tp_inst); + }, + timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker'); + }); + + tp_inst.hour = tp_inst._defaults.hour; + tp_inst.minute = tp_inst._defaults.minute; + tp_inst.second = tp_inst._defaults.second; + tp_inst.ampm = ''; + tp_inst.$input = $input; + + if (o.altField) + tp_inst.$altInput = $(o.altField) + .css({ cursor: 'pointer' }) + .focus(function(){ $input.trigger("focus"); }); + + // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime.. + if(tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) + tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime()); + if(tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) + tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime()); + if(tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) + tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime()); + if(tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) + tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime()); + + return tp_inst; + }, + + //######################################################################## + // add our sliders to the calendar + //######################################################################## + _addTimePicker: function(dp_inst) { + var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? + this.$input.val() + ' ' + this.$altInput.val() : + this.$input.val(); + + this.timeDefined = this._parseTime(currDT); + this._limitMinMaxDateTime(dp_inst, false); + this._injectTimePicker(); + }, + + //######################################################################## + // parse the time string from input value or _setTime + //######################################################################## + _parseTime: function(timeString, withDate) { + var regstr = this._defaults.timeFormat.toString() + .replace(/h{1,2}/ig, '(\\d?\\d)') + .replace(/m{1,2}/ig, '(\\d?\\d)') + .replace(/s{1,2}/ig, '(\\d?\\d)') + .replace(/t{1,2}/ig, '(am|pm|a|p)?') + .replace(/z{1}/ig, '((\\+|-)\\d\\d\\d\\d)?') + .replace(/\s/g, '\\s?') + '$', + order = this._getFormatPositions(), + treg; + + if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]); + + if (withDate || !this._defaults.timeOnly) { + // the time should come after x number of characters and a space. + // x = at least the length of text specified by the date format + var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat'); + // escape special regex characters in the seperator + var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); + regstr = '.{' + dp_dateFormat.length + ',}' + this._defaults.separator.replace(specials, "\\$&") + regstr; + } + + treg = timeString.match(new RegExp(regstr, 'i')); + + if (treg) { + if (order.t !== -1) + this.ampm = ((treg[order.t] === undefined || treg[order.t].length === 0) ? + '' : + (treg[order.t].charAt(0).toUpperCase() == 'A') ? 'AM' : 'PM').toUpperCase(); + + if (order.h !== -1) { + if (this.ampm == 'AM' && treg[order.h] == '12') + this.hour = 0; // 12am = 0 hour + else if (this.ampm == 'PM' && treg[order.h] != '12') + this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12 + else this.hour = Number(treg[order.h]); + } + + if (order.m !== -1) this.minute = Number(treg[order.m]); + if (order.s !== -1) this.second = Number(treg[order.s]); + if (order.z !== -1) this.timezone = treg[order.z]; + + return true; + + } + return false; + }, + + //######################################################################## + // figure out position of time elements.. cause js cant do named captures + //######################################################################## + _getFormatPositions: function() { + var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|t{1,2}|z)/g), + orders = { h: -1, m: -1, s: -1, t: -1, z: -1 }; + + if (finds) + for (var i = 0; i < finds.length; i++) + if (orders[finds[i].toString().charAt(0)] == -1) + orders[finds[i].toString().charAt(0)] = i + 1; + + return orders; + }, + + //######################################################################## + // generate and inject html for timepicker into ui datepicker + //######################################################################## + _injectTimePicker: function() { + var $dp = this.inst.dpDiv, + o = this._defaults, + tp_inst = this, + // Added by Peter Medeiros: + // - Figure out what the hour/minute/second max should be based on the step values. + // - Example: if stepMinute is 15, then minMax is 45. + hourMax = (o.hourMax - (o.hourMax % o.stepHour)).toFixed(0), + minMax = (o.minuteMax - (o.minuteMax % o.stepMinute)).toFixed(0), + secMax = (o.secondMax - (o.secondMax % o.stepSecond)).toFixed(0), + dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, ''); + + // Prevent displaying twice + //if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) { + if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0 && o.showTimepicker) { + var noDisplay = ' style="display:none;"', + html = '
' + + '
' + o.timeText + '
' + + '
' + + '
' + o.hourText + '
', + hourGridSize = 0, + minuteGridSize = 0, + secondGridSize = 0, + size; + + if (o.showHour && o.hourGrid > 0) { + html += '
' + + '
' + + '
'; + + for (var h = o.hourMin; h < hourMax; h += o.hourGrid) { + hourGridSize++; + var tmph = (o.ampm && h > 12) ? h-12 : h; + if (tmph < 10) tmph = '0' + tmph; + if (o.ampm) { + if (h == 0) tmph = 12 +'a'; + else if (h < 12) tmph += 'a'; + else tmph += 'p'; + } + html += ''; + } + + html += '
' + tmph + '
' + + ''; + } else html += '
'; + + html += '
' + o.minuteText + '
'; + + if (o.showMinute && o.minuteGrid > 0) { + html += '
' + + '
' + + '
'; + + for (var m = o.minuteMin; m < minMax; m += o.minuteGrid) { + minuteGridSize++; + html += ''; + } + + html += '
' + ((m < 10) ? '0' : '') + m + '
' + + '
'; + } else html += '
'; + + html += '
' + o.secondText + '
'; + + if (o.showSecond && o.secondGrid > 0) { + html += '
' + + '
' + + '
'; + + for (var s = o.secondMin; s < secMax; s += o.secondGrid) { + secondGridSize++; + html += ''; + } + + html += '
' + ((s < 10) ? '0' : '') + s + '
' + + '
'; + } else html += '
'; + + html += '
' + o.timezoneText + '
'; + html += '
'; + + html += ''; + $tp = $(html); + + // if we only want time picker... + if (o.timeOnly === true) { + $tp.prepend( + '
' + + '
' + o.timeOnlyTitle + '
' + + '
'); + $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide(); + } + + this.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_id).slider({ + orientation: "horizontal", + value: this.hour, + min: o.hourMin, + max: hourMax, + step: o.stepHour, + slide: function(event, ui) { + tp_inst.hour_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + // Updated by Peter Medeiros: + // - Pass in Event and UI instance into slide function + this.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_id).slider({ + orientation: "horizontal", + value: this.minute, + min: o.minuteMin, + max: minMax, + step: o.stepMinute, + slide: function(event, ui) { + // update the global minute slider instance value with the current slider value + tp_inst.minute_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + this.second_slider = $tp.find('#ui_tpicker_second_'+ dp_id).slider({ + orientation: "horizontal", + value: this.second, + min: o.secondMin, + max: secMax, + step: o.stepSecond, + slide: function(event, ui) { + tp_inst.second_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + + this.timezone_select = $tp.find('#ui_tpicker_timezone_'+ dp_id).append('').find("select"); + $.fn.append.apply(this.timezone_select, + $.map(o.timezoneList, function(val, idx) { + return $("