From 8690d56ff0bbd1031e8cc6788dd2159aac6b7adb Mon Sep 17 00:00:00 2001 From: Trevor Elliott Date: Fri, 7 Jun 2013 11:59:57 -0700 Subject: Reorganize the build system * Move all javascript source to src/js * Update the test runner, etc. * Do less javascript compilation --- .gitignore | 1 + Makefile | 19 +- contexts/Makefile | 364 - contexts/README.md | 40 - contexts/build.mk | 280 - contexts/chrome/.gitignore | 1 - contexts/data/fiveui/background.js | 210 - contexts/data/fiveui/chan.js | 53 - contexts/data/fiveui/chrome/ajax.js | 39 - contexts/data/fiveui/chrome/background.html | 31 - contexts/data/fiveui/chrome/background.js | 165 - .../data/fiveui/chrome/chrome-injected-compute.js | 27 - contexts/data/fiveui/chrome/chrome-injected-ui.js | 27 - contexts/data/fiveui/chrome/chrome-options.js | 45 - contexts/data/fiveui/chrome/chrome-port.js | 70 - contexts/data/fiveui/entry.css | 59 - contexts/data/fiveui/entry.js | 277 - contexts/data/fiveui/ffcheck.js | 3 - contexts/data/fiveui/firefox/ajax.js | 37 - contexts/data/fiveui/firefox/bootstrap.js | 22 - .../fiveui/firefox/firefox-injected-compute.js | 55 - .../data/fiveui/firefox/firefox-injected-ui.js | 30 - contexts/data/fiveui/firefox/firefox-options.js | 33 - contexts/data/fiveui/firefox/icon-content.html | 82 - contexts/data/fiveui/firefox/icon-script.js | 42 - contexts/data/fiveui/firefox/main.js | 200 - contexts/data/fiveui/firefox/options-icon.html | 31 - contexts/data/fiveui/firefox/options-script.js | 27 - contexts/data/fiveui/firefox/storage.js | 72 - contexts/data/fiveui/firefox/tabIds.js | 36 - contexts/data/fiveui/firefox/test/test-main.js | 55 - contexts/data/fiveui/images/Gear_3.svg | 95 - contexts/data/fiveui/images/attribution.txt | 3 - contexts/data/fiveui/images/down-arrow.png | Bin 4791 -> 0 bytes contexts/data/fiveui/images/down-arrow.svg | 136 - contexts/data/fiveui/images/errorCircle.png | Bin 22950 -> 0 bytes contexts/data/fiveui/images/fiveui-icon-128.png | Bin 4703 -> 0 bytes contexts/data/fiveui/images/fiveui-icon-16.png | Bin 655 -> 0 bytes contexts/data/fiveui/images/fiveui-icon-48.png | Bin 1826 -> 0 bytes .../data/fiveui/images/fiveui-icon-disabled.png | Bin 858 -> 0 bytes .../data/fiveui/images/fiveui-icon-enabled.png | Bin 900 -> 0 bytes .../data/fiveui/images/fiveui-icon-working.png | Bin 1107 -> 0 bytes contexts/data/fiveui/images/right-arrow.png | Bin 4991 -> 0 bytes contexts/data/fiveui/images/right-arrow.svg | 145 - contexts/data/fiveui/images/warningTriangle.png | Bin 21341 -> 0 bytes .../fiveui/injected/fiveui-injected-compute.js | 320 - .../data/fiveui/injected/fiveui-injected-ui.js | 228 - contexts/data/fiveui/injected/injected.css | 151 - contexts/data/fiveui/injected/jquery-plugins.js | 174 - contexts/data/fiveui/injected/prelude.js | 432 - contexts/data/fiveui/messenger.js | 141 - contexts/data/fiveui/options.css | 144 - contexts/data/fiveui/options.html | 88 - contexts/data/fiveui/options.js | 217 - contexts/data/fiveui/rules.js | 289 - .../fiveui/selenium/selenium-injected-compute.js | 104 - contexts/data/fiveui/set.js | 58 - contexts/data/fiveui/settings.js | 389 - contexts/data/fiveui/state.js | 202 - contexts/data/fiveui/update-manager.js | 51 - contexts/data/fiveui/url-pat.js | 140 - contexts/data/fiveui/utils.js | 145 - contexts/data/lib/backbone.js | 1571 -- contexts/data/lib/jasmine/MIT.LICENSE | 20 - contexts/data/lib/jasmine/boot.js | 104 - contexts/data/lib/jasmine/jasmine-html.js | 329 - contexts/data/lib/jasmine/jasmine.css | 54 - contexts/data/lib/jasmine/jasmine.js | 2052 --- contexts/data/lib/jasmine/jasmine_favicon.png | Bin 905 -> 0 bytes .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 260 -> 0 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 251 -> 0 bytes .../images/ui-bg_flat_10_000000_40x100.png | Bin 178 -> 0 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 104 -> 0 bytes .../images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 153 -> 0 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 105 -> 0 bytes .../images/ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 4427 -> 0 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 90 -> 0 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 129 -> 0 bytes .../images/ui-icons_222222_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_228ef1_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_ef8c08_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_ffffff_256x240.png | Bin 4369 -> 0 bytes .../css/ui-lightness/jquery-ui-1.9.2.custom.css | 462 - .../ui-lightness/jquery-ui-1.9.2.custom.min.css | 5 - .../data/lib/jquery/css/ui-lightness/jquery-ui.css | 1 - contexts/data/lib/jquery/jquery-1.8.3.js | 9472 ------------ contexts/data/lib/jquery/jquery-ui-1.9.2.custom.js | 14879 ------------------- .../data/lib/jquery/jquery-ui-1.9.2.custom.min.js | 6 - contexts/data/lib/jquery/jquery-ui.js | 1 - contexts/data/lib/jquery/jquery.js | 1 - contexts/data/lib/jshash/md5.js | 379 - .../phantomjs_jasmine/jasmine-1.0.2/MIT.LICENSE | 20 - .../jasmine-1.0.2/jasmine-html.js | 188 - .../phantomjs_jasmine/jasmine-1.0.2/jasmine.css | 166 - .../lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.js | 2421 --- .../jasmine.phantomjs-reporter.js | 204 - .../data/lib/phantomjs_jasmine/jasmine_favicon.png | Bin 905 -> 0 bytes .../phantomjs_jasminexml_runner.js | 59 - contexts/data/lib/phantomjs_jasmine/utils/core.js | 41 - contexts/data/lib/underscore.js | 1227 -- contexts/data/tests/PhantomJSJasmineRunner.html | 49 - contexts/data/tests/README.md | 30 - contexts/data/tests/SpecRunner.html | 41 - contexts/data/tests/mock-storage.js | 20 - contexts/data/tests/specs/messenger.js | 96 - contexts/data/tests/specs/prelude.js | 157 - contexts/data/tests/specs/rules.js | 64 - contexts/data/tests/specs/set.js | 24 - contexts/data/tests/specs/settings.js | 87 - contexts/data/tests/specs/state.js | 29 - contexts/data/tests/specs/utils.js | 20 - contexts/manifest.json | 30 - contexts/package.json | 16 - doc/build.mk | 4 +- exampleData/ruleSets/colorRules/backgroundCheck.js | 4 +- exampleData/ruleSets/colorRules/foregroundCheck.js | 2 +- src/js/chrome/background.html | 38 + src/js/chrome/build.mk | 48 + src/js/chrome/injected/platform-compute.js | 27 + src/js/chrome/injected/platform-ui.js | 27 + src/js/chrome/js/platform-ajax.js | 39 + src/js/chrome/js/platform-background.js | 165 + src/js/chrome/js/platform-options.js | 48 + src/js/chrome/js/platform-port.js | 70 + src/js/chrome/manifest.json | 30 + src/js/firefox/build.mk | 102 + src/js/firefox/icons/fiveui-icon.html | 82 + src/js/firefox/icons/fiveui-icon.js | 42 + src/js/firefox/icons/options-icon.html | 31 + src/js/firefox/icons/options-icon.js | 27 + src/js/firefox/injected/platform-compute.js | 55 + src/js/firefox/injected/platform-ui.js | 30 + src/js/firefox/js/platform-ajax.js | 8 + src/js/firefox/js/platform-options.js | 33 + src/js/firefox/lib/ajax.js | 36 + src/js/firefox/lib/main.js | 216 + src/js/firefox/lib/storage-wrapper.js | 68 + src/js/firefox/lib/tabIds.js | 38 + src/js/firefox/package.json | 16 + src/js/firefox/test/test-main.js | 55 + src/js/fiveui/build.mk | 129 + src/js/fiveui/css/entry.css | 59 + src/js/fiveui/css/options.css | 144 + src/js/fiveui/images/Gear_3.svg | 95 + src/js/fiveui/images/attribution.txt | 3 + src/js/fiveui/images/down-arrow.png | Bin 0 -> 4791 bytes src/js/fiveui/images/down-arrow.svg | 136 + src/js/fiveui/images/errorCircle.png | Bin 0 -> 22950 bytes src/js/fiveui/images/fiveui-icon-128.png | Bin 0 -> 4703 bytes src/js/fiveui/images/fiveui-icon-16.png | Bin 0 -> 655 bytes src/js/fiveui/images/fiveui-icon-48.png | Bin 0 -> 1826 bytes src/js/fiveui/images/fiveui-icon-disabled.png | Bin 0 -> 858 bytes src/js/fiveui/images/fiveui-icon-enabled.png | Bin 0 -> 900 bytes src/js/fiveui/images/fiveui-icon-working.png | Bin 0 -> 1107 bytes src/js/fiveui/images/right-arrow.png | Bin 0 -> 4991 bytes src/js/fiveui/images/right-arrow.svg | 145 + src/js/fiveui/images/warningTriangle.png | Bin 0 -> 21341 bytes src/js/fiveui/injected/compute.js | 322 + src/js/fiveui/injected/injected.css | 151 + src/js/fiveui/injected/jquery-plugins.js | 174 + src/js/fiveui/injected/prelude.js | 428 + src/js/fiveui/injected/ui.js | 228 + src/js/fiveui/js/background.js | 210 + src/js/fiveui/js/chan.js | 53 + src/js/fiveui/js/entry.js | 277 + src/js/fiveui/js/ffcheck.js | 3 + src/js/fiveui/js/messenger.js | 141 + src/js/fiveui/js/options.js | 217 + src/js/fiveui/js/rules.js | 292 + src/js/fiveui/js/set.js | 58 + src/js/fiveui/js/settings.js | 389 + src/js/fiveui/js/state.js | 202 + src/js/fiveui/js/update-manager.js | 51 + src/js/fiveui/js/url-pat.js | 140 + src/js/fiveui/js/utils.js | 145 + src/js/fiveui/options.html | 97 + src/js/lib/backbone.js | 1571 ++ .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 260 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 251 bytes .../images/ui-bg_flat_10_000000_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 0 -> 104 bytes .../images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 0 -> 153 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 0 -> 4427 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 0 -> 90 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 0 -> 129 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_228ef1_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ef8c08_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes .../css/ui-lightness/jquery-ui-1.9.2.custom.css | 462 + .../ui-lightness/jquery-ui-1.9.2.custom.min.css | 5 + src/js/lib/jquery/css/ui-lightness/jquery-ui.css | 1 + src/js/lib/jquery/jquery-1.8.3.js | 9472 ++++++++++++ src/js/lib/jquery/jquery-ui-1.9.2.custom.js | 14879 +++++++++++++++++++ src/js/lib/jquery/jquery-ui-1.9.2.custom.min.js | 6 + src/js/lib/jquery/jquery-ui.js | 1 + src/js/lib/jquery/jquery.js | 1 + src/js/lib/md5.js | 379 + .../phantomjs_jasmine/jasmine-1.0.2/MIT.LICENSE | 20 + .../jasmine-1.0.2/jasmine-html.js | 188 + .../phantomjs_jasmine/jasmine-1.0.2/jasmine.css | 166 + .../lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.js | 2421 +++ .../jasmine.phantomjs-reporter.js | 204 + src/js/lib/phantomjs_jasmine/jasmine_favicon.png | Bin 0 -> 905 bytes .../phantomjs_jasminexml_runner.js | 59 + src/js/lib/phantomjs_jasmine/utils/core.js | 41 + src/js/lib/underscore.js | 1227 ++ src/js/selenium/selenium-injected-compute.js | 104 + src/js/tests/.gitignore | 1 + src/js/tests/PhantomJSJasmineRunner.html | 49 + src/js/tests/README.md | 30 + src/js/tests/SpecRunner.html | 41 + src/js/tests/build.mk | 18 + src/js/tests/jasmine/MIT.LICENSE | 20 + src/js/tests/jasmine/boot.js | 104 + src/js/tests/jasmine/jasmine-html.js | 329 + src/js/tests/jasmine/jasmine.css | 54 + src/js/tests/jasmine/jasmine.js | 2052 +++ src/js/tests/jasmine/jasmine_favicon.png | Bin 0 -> 905 bytes src/js/tests/mock-storage.js | 20 + src/js/tests/specs/messenger.js | 96 + src/js/tests/specs/prelude.js | 157 + src/js/tests/specs/rules.js | 64 + src/js/tests/specs/set.js | 24 + src/js/tests/specs/settings.js | 87 + src/js/tests/specs/state.js | 29 + src/js/tests/specs/utils.js | 20 + 230 files changed, 40033 insertions(+), 40409 deletions(-) delete mode 100644 contexts/Makefile delete mode 100644 contexts/README.md delete mode 100644 contexts/build.mk delete mode 100644 contexts/chrome/.gitignore delete mode 100644 contexts/data/fiveui/background.js delete mode 100644 contexts/data/fiveui/chan.js delete mode 100644 contexts/data/fiveui/chrome/ajax.js delete mode 100644 contexts/data/fiveui/chrome/background.html delete mode 100644 contexts/data/fiveui/chrome/background.js delete mode 100644 contexts/data/fiveui/chrome/chrome-injected-compute.js delete mode 100644 contexts/data/fiveui/chrome/chrome-injected-ui.js delete mode 100644 contexts/data/fiveui/chrome/chrome-options.js delete mode 100644 contexts/data/fiveui/chrome/chrome-port.js delete mode 100644 contexts/data/fiveui/entry.css delete mode 100644 contexts/data/fiveui/entry.js delete mode 100644 contexts/data/fiveui/ffcheck.js delete mode 100644 contexts/data/fiveui/firefox/ajax.js delete mode 100644 contexts/data/fiveui/firefox/bootstrap.js delete mode 100644 contexts/data/fiveui/firefox/firefox-injected-compute.js delete mode 100644 contexts/data/fiveui/firefox/firefox-injected-ui.js delete mode 100644 contexts/data/fiveui/firefox/firefox-options.js delete mode 100644 contexts/data/fiveui/firefox/icon-content.html delete mode 100644 contexts/data/fiveui/firefox/icon-script.js delete mode 100644 contexts/data/fiveui/firefox/main.js delete mode 100644 contexts/data/fiveui/firefox/options-icon.html delete mode 100644 contexts/data/fiveui/firefox/options-script.js delete mode 100644 contexts/data/fiveui/firefox/storage.js delete mode 100644 contexts/data/fiveui/firefox/tabIds.js delete mode 100644 contexts/data/fiveui/firefox/test/test-main.js delete mode 100644 contexts/data/fiveui/images/Gear_3.svg delete mode 100644 contexts/data/fiveui/images/attribution.txt delete mode 100644 contexts/data/fiveui/images/down-arrow.png delete mode 100644 contexts/data/fiveui/images/down-arrow.svg delete mode 100644 contexts/data/fiveui/images/errorCircle.png delete mode 100644 contexts/data/fiveui/images/fiveui-icon-128.png delete mode 100644 contexts/data/fiveui/images/fiveui-icon-16.png delete mode 100644 contexts/data/fiveui/images/fiveui-icon-48.png delete mode 100644 contexts/data/fiveui/images/fiveui-icon-disabled.png delete mode 100644 contexts/data/fiveui/images/fiveui-icon-enabled.png delete mode 100644 contexts/data/fiveui/images/fiveui-icon-working.png delete mode 100644 contexts/data/fiveui/images/right-arrow.png delete mode 100644 contexts/data/fiveui/images/right-arrow.svg delete mode 100644 contexts/data/fiveui/images/warningTriangle.png delete mode 100644 contexts/data/fiveui/injected/fiveui-injected-compute.js delete mode 100644 contexts/data/fiveui/injected/fiveui-injected-ui.js delete mode 100644 contexts/data/fiveui/injected/injected.css delete mode 100644 contexts/data/fiveui/injected/jquery-plugins.js delete mode 100644 contexts/data/fiveui/injected/prelude.js delete mode 100644 contexts/data/fiveui/messenger.js delete mode 100644 contexts/data/fiveui/options.css delete mode 100644 contexts/data/fiveui/options.html delete mode 100644 contexts/data/fiveui/options.js delete mode 100644 contexts/data/fiveui/rules.js delete mode 100644 contexts/data/fiveui/selenium/selenium-injected-compute.js delete mode 100644 contexts/data/fiveui/set.js delete mode 100644 contexts/data/fiveui/settings.js delete mode 100644 contexts/data/fiveui/state.js delete mode 100644 contexts/data/fiveui/update-manager.js delete mode 100644 contexts/data/fiveui/url-pat.js delete mode 100644 contexts/data/fiveui/utils.js delete mode 100644 contexts/data/lib/backbone.js delete mode 100644 contexts/data/lib/jasmine/MIT.LICENSE delete mode 100644 contexts/data/lib/jasmine/boot.js delete mode 100644 contexts/data/lib/jasmine/jasmine-html.js delete mode 100644 contexts/data/lib/jasmine/jasmine.css delete mode 100644 contexts/data/lib/jasmine/jasmine.js delete mode 100644 contexts/data/lib/jasmine/jasmine_favicon.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-icons_222222_256x240.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-icons_228ef1_256x240.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-icons_ef8c08_256x240.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-icons_ffd27a_256x240.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/images/ui-icons_ffffff_256x240.png delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/jquery-ui-1.9.2.custom.css delete mode 100755 contexts/data/lib/jquery/css/ui-lightness/jquery-ui-1.9.2.custom.min.css delete mode 120000 contexts/data/lib/jquery/css/ui-lightness/jquery-ui.css delete mode 100755 contexts/data/lib/jquery/jquery-1.8.3.js delete mode 100755 contexts/data/lib/jquery/jquery-ui-1.9.2.custom.js delete mode 100755 contexts/data/lib/jquery/jquery-ui-1.9.2.custom.min.js delete mode 120000 contexts/data/lib/jquery/jquery-ui.js delete mode 120000 contexts/data/lib/jquery/jquery.js delete mode 100755 contexts/data/lib/jshash/md5.js delete mode 100644 contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/MIT.LICENSE delete mode 100644 contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine-html.js delete mode 100644 contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.css delete mode 100644 contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.js delete mode 100644 contexts/data/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js delete mode 100644 contexts/data/lib/phantomjs_jasmine/jasmine_favicon.png delete mode 100644 contexts/data/lib/phantomjs_jasmine/phantomjs_jasminexml_runner.js delete mode 100644 contexts/data/lib/phantomjs_jasmine/utils/core.js delete mode 100644 contexts/data/lib/underscore.js delete mode 100644 contexts/data/tests/PhantomJSJasmineRunner.html delete mode 100644 contexts/data/tests/README.md delete mode 100644 contexts/data/tests/SpecRunner.html delete mode 100644 contexts/data/tests/mock-storage.js delete mode 100644 contexts/data/tests/specs/messenger.js delete mode 100644 contexts/data/tests/specs/prelude.js delete mode 100644 contexts/data/tests/specs/rules.js delete mode 100644 contexts/data/tests/specs/set.js delete mode 100644 contexts/data/tests/specs/settings.js delete mode 100644 contexts/data/tests/specs/state.js delete mode 100644 contexts/data/tests/specs/utils.js delete mode 100644 contexts/manifest.json delete mode 100644 contexts/package.json create mode 100644 src/js/chrome/background.html create mode 100644 src/js/chrome/build.mk create mode 100644 src/js/chrome/injected/platform-compute.js create mode 100644 src/js/chrome/injected/platform-ui.js create mode 100644 src/js/chrome/js/platform-ajax.js create mode 100644 src/js/chrome/js/platform-background.js create mode 100644 src/js/chrome/js/platform-options.js create mode 100644 src/js/chrome/js/platform-port.js create mode 100644 src/js/chrome/manifest.json create mode 100644 src/js/firefox/build.mk create mode 100644 src/js/firefox/icons/fiveui-icon.html create mode 100644 src/js/firefox/icons/fiveui-icon.js create mode 100644 src/js/firefox/icons/options-icon.html create mode 100644 src/js/firefox/icons/options-icon.js create mode 100644 src/js/firefox/injected/platform-compute.js create mode 100644 src/js/firefox/injected/platform-ui.js create mode 100644 src/js/firefox/js/platform-ajax.js create mode 100644 src/js/firefox/js/platform-options.js create mode 100644 src/js/firefox/lib/ajax.js create mode 100644 src/js/firefox/lib/main.js create mode 100644 src/js/firefox/lib/storage-wrapper.js create mode 100644 src/js/firefox/lib/tabIds.js create mode 100644 src/js/firefox/package.json create mode 100644 src/js/firefox/test/test-main.js create mode 100644 src/js/fiveui/build.mk create mode 100644 src/js/fiveui/css/entry.css create mode 100644 src/js/fiveui/css/options.css create mode 100644 src/js/fiveui/images/Gear_3.svg create mode 100644 src/js/fiveui/images/attribution.txt create mode 100644 src/js/fiveui/images/down-arrow.png create mode 100644 src/js/fiveui/images/down-arrow.svg create mode 100644 src/js/fiveui/images/errorCircle.png create mode 100644 src/js/fiveui/images/fiveui-icon-128.png create mode 100644 src/js/fiveui/images/fiveui-icon-16.png create mode 100644 src/js/fiveui/images/fiveui-icon-48.png create mode 100644 src/js/fiveui/images/fiveui-icon-disabled.png create mode 100644 src/js/fiveui/images/fiveui-icon-enabled.png create mode 100644 src/js/fiveui/images/fiveui-icon-working.png create mode 100644 src/js/fiveui/images/right-arrow.png create mode 100644 src/js/fiveui/images/right-arrow.svg create mode 100644 src/js/fiveui/images/warningTriangle.png create mode 100644 src/js/fiveui/injected/compute.js create mode 100644 src/js/fiveui/injected/injected.css create mode 100644 src/js/fiveui/injected/jquery-plugins.js create mode 100644 src/js/fiveui/injected/prelude.js create mode 100644 src/js/fiveui/injected/ui.js create mode 100644 src/js/fiveui/js/background.js create mode 100644 src/js/fiveui/js/chan.js create mode 100644 src/js/fiveui/js/entry.js create mode 100644 src/js/fiveui/js/ffcheck.js create mode 100644 src/js/fiveui/js/messenger.js create mode 100644 src/js/fiveui/js/options.js create mode 100644 src/js/fiveui/js/rules.js create mode 100644 src/js/fiveui/js/set.js create mode 100644 src/js/fiveui/js/settings.js create mode 100644 src/js/fiveui/js/state.js create mode 100644 src/js/fiveui/js/update-manager.js create mode 100644 src/js/fiveui/js/url-pat.js create mode 100644 src/js/fiveui/js/utils.js create mode 100644 src/js/fiveui/options.html create mode 100644 src/js/lib/backbone.js create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-icons_222222_256x240.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-icons_228ef1_256x240.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-icons_ef8c08_256x240.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-icons_ffd27a_256x240.png create mode 100755 src/js/lib/jquery/css/ui-lightness/images/ui-icons_ffffff_256x240.png create mode 100755 src/js/lib/jquery/css/ui-lightness/jquery-ui-1.9.2.custom.css create mode 100755 src/js/lib/jquery/css/ui-lightness/jquery-ui-1.9.2.custom.min.css create mode 120000 src/js/lib/jquery/css/ui-lightness/jquery-ui.css create mode 100755 src/js/lib/jquery/jquery-1.8.3.js create mode 100755 src/js/lib/jquery/jquery-ui-1.9.2.custom.js create mode 100755 src/js/lib/jquery/jquery-ui-1.9.2.custom.min.js create mode 120000 src/js/lib/jquery/jquery-ui.js create mode 120000 src/js/lib/jquery/jquery.js create mode 100644 src/js/lib/md5.js create mode 100644 src/js/lib/phantomjs_jasmine/jasmine-1.0.2/MIT.LICENSE create mode 100644 src/js/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine-html.js create mode 100644 src/js/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.css create mode 100644 src/js/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.js create mode 100644 src/js/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js create mode 100644 src/js/lib/phantomjs_jasmine/jasmine_favicon.png create mode 100644 src/js/lib/phantomjs_jasmine/phantomjs_jasminexml_runner.js create mode 100644 src/js/lib/phantomjs_jasmine/utils/core.js create mode 100644 src/js/lib/underscore.js create mode 100644 src/js/selenium/selenium-injected-compute.js create mode 100644 src/js/tests/.gitignore create mode 100644 src/js/tests/PhantomJSJasmineRunner.html create mode 100644 src/js/tests/README.md create mode 100644 src/js/tests/SpecRunner.html create mode 100644 src/js/tests/build.mk create mode 100644 src/js/tests/jasmine/MIT.LICENSE create mode 100644 src/js/tests/jasmine/boot.js create mode 100644 src/js/tests/jasmine/jasmine-html.js create mode 100644 src/js/tests/jasmine/jasmine.css create mode 100644 src/js/tests/jasmine/jasmine.js create mode 100644 src/js/tests/jasmine/jasmine_favicon.png create mode 100644 src/js/tests/mock-storage.js create mode 100644 src/js/tests/specs/messenger.js create mode 100644 src/js/tests/specs/prelude.js create mode 100644 src/js/tests/specs/rules.js create mode 100644 src/js/tests/specs/set.js create mode 100644 src/js/tests/specs/settings.js create mode 100644 src/js/tests/specs/state.js create mode 100644 src/js/tests/specs/utils.js diff --git a/.gitignore b/.gitignore index d657933..f8a7b52 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ fiveui.xpi contexts/data/tests/reports Config.mk +fiveui.pem diff --git a/Makefile b/Makefile index d98b544..f00f25c 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,11 @@ clean:: # Subdirs ###################################################################### -$(eval $(call subdir,contexts)) +$(eval $(call subdir,src/js/fiveui)) +$(eval $(call subdir,src/js/chrome)) +$(eval $(call subdir,src/js/firefox)) +$(eval $(call subdir,src/js/tests)) + $(eval $(call subdir,profiles)) $(eval $(call subdir,doc)) @@ -92,16 +96,3 @@ test: fiveui.crx fiveui.xpi $(topdir)/profiles/chrome $(topdir)/profiles/firefox cd $(HEADLESS_DIR) && $(MVN_TEST_CMD) endif - - -# JS Unit Tests ############################################################### - -ifneq "$(PHANTOM_EXE)" "" - -test: test-js -test-js: - cd $(topdir)/contexts/data && $(PHANTOM_EXE) \ - lib/phantomjs_jasmine/phantomjs_jasminexml_runner.js \ - tests/PhantomJSJasmineRunner.html tests/reports/ - -endif diff --git a/contexts/Makefile b/contexts/Makefile deleted file mode 100644 index 530a3dc..0000000 --- a/contexts/Makefile +++ /dev/null @@ -1,364 +0,0 @@ -# Module : Makefile -# Copyright : (c) 2011-2012, Galois, Inc. -# -# Maintainer : -# Stability : Provisional -# Portability: Portable -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# Entry Point ################################################################## - -.PHONY: all -all: compile package install ; - - -# Environment ################################################################## - -BUILD_ROOT := $(CURDIR) -REPO_ROOT := $(CURDIR)/.. -INSTALL_DIR := $(REPO_ROOT)/binaries - -ADDON_SDK := $(REPO_ROOT)/tools/addon-sdk -BUILD_DIR := $(REPO_ROOT)/build - -CHROME_DIR := $(BUILD_ROOT)/chrome -DATA_DIR := $(BUILD_ROOT)/data - -BIN_DIR := $(DATA_DIR)/target -FIVEUI_DATA_DIR := $(DATA_DIR)/fiveui -LIB_DIR := $(DATA_DIR)/lib - -MV := mv - -# FiveUI project Javascript sources -js_sources := $(wildcard $(FIVEUI_DATA_DIR)/*.js) - -# Namespaces, derived from the project sources. -js_namespaces := $(shell ./namespaces.awk $(js_sources)) - -# FiveUI project Javascript, known to contain application code, not library -# code. -js_app_sources := \ - $(FIVEUI_DATA_DIR)/options.js \ - $(FIVEUI_DATA_DIR)/firefox/firefox-options.js \ - $(FIVEUI_DATA_DIR)/chrome/chrome-options.js - -# Namespaces that are known to be just applications -js_app_namespaces := $(shell ./namespaces.awk $(js_app_sources)) - -# Namespaces that contain only library code -js_lib_namespaces := $(foreach ns,$(js_app_namespaces),\ - $(filter-out $(ns),$(js_namespaces))) - -# The path to the closure library -CLOSURE_LIB := $(DATA_DIR)/lib/closure-library - - -# Macros ####################################################################### - -# Generate a set of targets that will allow directory creation to be depended on -# by other targets. -# -# $1 - the directory name -define dir-exists -$1/.token: - mkdir $1 && touch $$@ -endef - -dir-dep = $1/.token - -# The ../../../../../ correpsonds to the relative path from -# goog/base.js to the context directory. -# -# $1 - The path (relative to BUILD_ROOT) to generate a root_with_prefix pair for -goog-relative = $(BUILD_ROOT)/$1 ../../../../../$1 - -# Remove the target of the current rule when the provided command exits on -# failure. -# -# $1 - The command to run -rm-on-failure = ( $1 || ($(RM) $@; exit 1) ) - -define profile -.PHONY: profile-$1 -profile-$1: $(REPO_ROOT)/profiles/$1/.token - -$(REPO_ROOT)/profiles/$1/.token: $(REPO_ROOT)/profiles/$1.tar - $(MAKE) -C $(REPO_ROOT)/profiles $1 - -.PHONY: clean-profile-$1 -clean-profile-$1: - $(MAKE) -C $(REPO_ROOT)/profiles clean-$1 - -clean: clean-profile-$1 -endef - -# General Targets ############################################################## - -.PHONY: compile -compile: - -.PHONY: package -package: - -.PHONY: install -install: - -.PHONY: clean -clean: - -# Print out the value of a variable, useful for debugging. -print-%: - @echo "$* = $($*)" - -# BIN_DIR management -$(eval $(call dir-exists,$(BIN_DIR))) - -clean: clean-BIN_DIR - -.PHONY: clean-BIN_DIR -clean-BIN_DIR: - @echo "Cleaning $(BIN_DIR)" - $(RM) -r $(BIN_DIR) - - -# CSS Utilities ################################################################ - -css_bundle := $(BUILD_DIR)/css-bundle.py - -# The jquery-ui css, in a form that has its image dependencies compiled in as -# base-64 encoded data. -$(BIN_DIR)/bundled.css: $(call dir-dep,$(BIN_DIR)) - cd $(LIB_DIR)/jquery/css/ui-lightness/ && \ - $(css_bundle) jquery-ui.css $@ - -# The injected css, with its images compiled in. -$(BIN_DIR)/injected.css: $(call dir-dep,$(BIN_DIR)) \ - $(FIVEUI_DATA_DIR)/injected/injected.css - cd $(FIVEUI_DATA_DIR)/injected && \ - $(css_bundle) injected.css $@ - - -# Javascript Utilities ######################################################### - -cl_linter := $(BUILD_DIR)/closure-linter -#cl_compiler := $(BUILD_DIR)/closure-compiler -#cl_typecheck := $(BUILD_DIR)/closure-typechecker - -# Files to ignore when running the linter -lint_excludes := lib/jquery.js - -# Run the linter over the project javascript sources. -.PHONY: lint -lint: - find data/fiveui -name "*.js" | xargs $(cl_linter) --strict --exclude_files=$(lint_excludes) - -closurebuilder := $(CLOSURE_LIB)/closure/bin/build/closurebuilder.py \ - --root=$(CLOSURE_LIB) --root=$(FIVEUI_DATA_DIR) \ - --compiler_jar=$(REPO_ROOT)/tools/closure_compiler/compiler.jar \ - --compiler_flags="--jscomp_error=checkTypes" - -# Typecheck all the project javascript source. -.PHONY: typecheck -typecheck: $(js_sources) - $(closurebuilder) --output_file=$(BIN_DIR)/trash.out --output_mode=compiled \ - $(foreach ns,$(js_namespaces),--namespace=$(ns)) && \ - $(RM) $(BIN_DIR)/trash.out - - -depswriter := /usr/bin/env $(CLOSURE_LIB)/closure/bin/build/depswriter.py - -# The dependency graph for the project javascript. -$(BIN_DIR)/deps.js: $(call dir-dep,$(BIN_DIR)) $(js_sources) - $(depswriter) --root_with_prefix="$(call goog-relative,data/fiveui)" \ - --output_file=$@ - -.PHONY: deps -deps: $(BIN_DIR)/deps.js; - -compile: deps - -closure-js := $(CLOSURE_LIB)/closure/bin/build/closurebuilder.py \ - --root=$(CLOSURE_LIB) \ - --root=$(FIVEUI_DATA_DIR) \ - --compiler_jar=$(REPO_ROOT)/tools/closure_compiler/compiler.jar \ - --compiler_flags="--accept_const_keyword" \ - --compiler_flags="--formatting=PRETTY_PRINT" \ - --output_mode="compiled" - -compile-js := $(BUILD_ROOT)/compile-js.sh --output_mode=script - -# Chrome Compilation ########################################################### - -CHROME_OPTS := --pack-extension=$(BIN_DIR)/src \ - --pack-extension-key=$(BIN_DIR)/fiveui.pem - -compile: compile-chrome - -CHROME_TARGETS := $(BIN_DIR)/chrome-background.js $(BIN_DIR)/bundled.css \ - $(BIN_DIR)/chrome-options.js $(BIN_DIR)/injected.css - -.PHONY: compile-chrome -compile-chrome: $(CHROME_TARGETS) - -# Build the compiled chrome backend script. -$(BIN_DIR)/chrome-background.js: $(call dir-dep,$(BIN_DIR)) $(js_sources) - $(call rm-on-failure,$(compile-js) --namespace=fiveui.chrome.background > $@) - -# Build the compiled options script. -$(BIN_DIR)/chrome-options.js: $(call dir-dep,$(BIN_DIR)) $(js_sources) - $(call rm-on-failure,$(compile-js) \ - --namespace=fiveui.chrome.options.init > $@) - -# Clean chrome extension build artifacts. -.PHONY: clean-chrome -clean-chrome: - @echo Cleaning Chrome extension... - $(RM) fiveui.crx - -clean: clean-chrome - - -# Firefox Compilation ########################################################## - -# Sources the correct environment before invoking the cfx command. -# -# $1 - The desired arguments to the cfx command. -cfx = ( cd $(ADDON_SDK) > /dev/null && \ - . bin/activate > /dev/null && \ - cd - > /dev/null && \ - cfx $1) - -.PHONY: firefox -firefox: package-firefox - -$(eval $(call profile,firefox)) - -compile: compile-firefox - -FIREFOX_TARGETS := profile-firefox $(BIN_DIR)/firefox-main.js \ - $(BIN_DIR)/bundled.css $(BIN_DIR)/firefox-options.js \ - $(BIN_DIR)/injected.css - -.PHONY: compile-firefox -compile-firefox: $(FIREFOX_TARGETS) - -$(BIN_DIR)/fiveui.js: $(call dir-dep,$(BIN_DIR)) $(js_sources) - $(call rm-on-failure,$(compile-js) \ - $(foreach ns,$(js_lib_namespaces), --namespace=$(ns)) > $@) - echo 'exports.fiveui = fiveui;' >> $@ - -$(BIN_DIR)/firefox-main.js: $(call dir-dep,$(BIN_DIR)) $(js_sources) - $(call rm-on-failure,$(compile-js) --namespace=fiveui.firefox.main > $@) - - -# TODO: remove 2 lines below, duplicate of above? -# compile with the closure compiler instead of the script output mode -# $(call rm-on-failure,$(closure-js) --namespace=fiveui.firefox.main > $@) - -# Build the compiled options script. -$(BIN_DIR)/firefox-options.js: $(call dir-dep,$(BIN_DIR)) $(js_sources) - $(call rm-on-failure,$(compile-js) \ - --namespace=fiveui.firefox.options.init > $@) - -# Use the cfx command to debug a firefox extension. -.PHONY: run-firefox -run-firefox: $(FIREFOX_TARGETS) - @echo Running Firefox extension... - $(call cfx,run -p $(REPO_ROOT)/profiles/firefox) - -# Use the cfx command to debug a firefox extension. -.PHONY: test-firefox -test-firefox: $(FIREFOX_TARGETS) $(BIN_DIR)/fiveui.js - @echo Testing Firefox extension... - $(call cfx,test -v -p $(REPO_ROOT)/profiles/firefox) - -# Clean firefox extension build artifacts. -.PHONY: clean-firefox -clean-firefox: - @echo Cleaning Firefox extension... - rm -rf profile - -clean: clean-firefox - - -# Package Staging ############################################################## - -STAGE_DIR := $(BUILD_ROOT)/stage - -$(eval $(call dir-exists,$(STAGE_DIR))) - -define copy-dir -mkdir -p $(STAGE_DIR)/$(dir $1) -cp -r $(BUILD_ROOT)/$1 $(STAGE_DIR)/$(dir $1) -endef - -PACKAGE_SPECS := $(addprefix $(BUILD_ROOT)/,manifest.json package.json) - -.PHONY: stage -stage: $(call dir-dep,$(STAGE_DIR)) compile $(PACKAGE_SPECS) - $(call copy-dir,data/target) - $(call copy-dir,data/fiveui) - $(call copy-dir,data/lib) - cp $(PACKAGE_SPECS) $(STAGE_DIR) - -.PHONY: clean-stage -clean-stage: - $(RM) -r $(STAGE_DIR) -clean: clean-stage - - -# CRX Generation ############################################################### - -MAKE_CRX := $(BUILD_DIR)/makecrx - -$(BUILD_ROOT)/fiveui.crx: stage - $(MAKE_CRX) $(STAGE_DIR) $(CHROME_DIR)/fiveui.pem fiveui - -.PHONY: clean-crx -clean-crx: - $(RM) $(BUILD_ROOT)/fiveui.crx -clean: clean-crx - -.PHONY: package-chrome -package-chrome: $(BUILD_ROOT)/fiveui.crx -package: package-chrome - - -# XPI Generation ############################################################### - -$(BUILD_ROOT)/fiveui.xpi: stage - $(call cfx,xpi \ - -p $(REPO_ROOT)/profiles/firefox \ - --pkgdir=$(STAGE_DIR)) - -.PHONY: run-firefox-staged -run-firefox-staged: stage - $(call cfx,run -p $(REPO_ROOT)/profiles/firefox \ - --pkgdir=$(STAGE_DIR)) - -.PHONY: clean-xpi -clean-xpi: - $(RM) $(BUILD_ROOT)/fiveui.xpi -clean: clean-xpi - -.PHONY: package-firefox -package-firefox: $(BUILD_ROOT)/fiveui.xpi ; -package: package-firefox - -# Installation ################################################################# - -install: - $(MV) $(BUILD_ROOT)/fiveui.{crx,xpi} $(INSTALL_DIR) diff --git a/contexts/README.md b/contexts/README.md deleted file mode 100644 index 0f1a6c2..0000000 --- a/contexts/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# FiveUI - -FiveUI is an extensible tool for evaluating HTML user interfaces -against sets of codified UI Guidelines. - -## Installation and getting started - -FiveUI is a basic browser extension with support for Firefox and -Google Chrome. If you're familiar with browser extensions, you can -quickly install FiveUI from the binaries: - - - Chrome: [fiveui.crx](http://galoisinc.github.com/FiveUI/binaries/fiveui.crx) - - FireFox: [fiveui.xpi](http://galoisinc.github.com/FiveUI/binaries/fiveui.xpi) - -The [Installation Guide](doc/manual_src/install.md) describes the -installation process for Firefox and Google Chrome. - -After you've installed FiveUI, take a look at the [Getting Started -Guide](doc/manual_src/gettingStarted.md) to learn about Rule Sets and -setting URL Patterns to match web sites to codified guidelines. - -## Building FiveUI - -Most (if not all) the FiveUI dependencies are included in the -repository, so building FiveUI should be as simple as running: - - $ make - -In the top-level FiveUI repository root. On success, this will put -the generated extensions in the repository root. - -### Chrome signing key - -Note that you will need to first place a Chrome key in: - - chrome\fiveui.pem - -before the chrome extension will build successfully. - - diff --git a/contexts/build.mk b/contexts/build.mk deleted file mode 100644 index 0e55997..0000000 --- a/contexts/build.mk +++ /dev/null @@ -1,280 +0,0 @@ - -# Source Info ################################################################## - -# source and resources -data-dir := $(path)/data - -# fiveui source directory -fiveui-dir := $(data-dir)/fiveui - -lib-dir := $(data-dir)/lib - -# packaged extension directory -bin-dir := $(data-dir)/target - - -# Extension Staging ############################################################ -# -# The purpose of this step is to setup all the compiled scripts necessary for -# both plugins in a common tree. From this state, we can pick and choose what -# goes into each extension. - -stage-dir := $(build-dir)/stage -target-dir := $(stage-dir)/data/target - -define stage-files-from -$(stage-dir)/$1/$2: | $(stage-dir)/$1 - $$(call cmd,mkdir) - -$(stage-dir)/$1/$2/%: $(path)/$1/$2/% | $(stage-dir)/$1/$2 - $$(call cmd,cp) -endef - -$(eval $(call stage-files-from,data/fiveui,images)) -$(eval $(call stage-files-from,data/fiveui,chrome)) -$(eval $(call stage-files-from,data/fiveui,injected)) -$(eval $(call stage-files-from,data/lib,codemirror)) -$(eval $(call stage-files-from,data/lib,jquery)) -$(eval $(call stage-files-from,data/lib,jshash)) - - - -$(eval $(call stage-files-from,data/fiveui/firefox,test)) -$(eval $(call stage-files-from,data/fiveui,firefox)) - -$(eval $(call stage-files-from,data,fiveui)) -$(eval $(call stage-files-from,data,lib)) - - -$(target-dir): | $(stage-dir)/data - $(call cmd,mkdir) - -$(stage-dir)/data: | $(stage-dir) - $(call cmd,mkdir) - -$(stage-dir): | $(build-dir) - $(call cmd,mkdir) - - -stage-path = $(patsubst $(path)/%,$(stage-dir)/%,$1) -stage-all = $(call stage-path,$(wildcard $(path)/$1/*)) - - -# Javascript "Compilation" ##################################################### -# -# In order to turn a number of different javascript modules into a single one, -# we just concatenate them all together. This should be fine, as all of the -# modules we define just provide functions, or register callbacks. - -quiet_cmd_compilejs = JSC $(call drop-prefix,$@) - cmd_compilejs = cat $^ > $@ - -# generic background script dependencies -background-deps := \ - $(addprefix $(fiveui-dir)/, \ - set.js \ - background.js \ - url-pat.js \ - settings.js \ - messenger.js \ - state.js \ - rules.js) - -# generic options page dependencies -options-deps := $(addprefix $(fiveui-dir)/,\ - settings.js \ - chan.js \ - messenger.js \ - options.js \ - update-manager.js \ - utils.js \ - entry.js \ - rules.js \ - url-pat.js ) - - -# CSS Staging ################################################################## - -css-bundle := $(topdir)/tools/bin/css-bundle.py - -quiet_cmd_cssbundle = CSSC $(call drop-prefix,$@) - cmd_cssbundle = ( cd $(dir $(TARGET)) && \ - $(css-bundle) $(notdir $(TARGET)) $@ $(redir) ) - -$(stage-dir)/data/target/bundled.css: TARGET := $(lib-dir)/jquery/css/ui-lightness/jquery-ui.css -$(stage-dir)/data/target/bundled.css: \ - $(wildcard $(lib-dir)/jquery/css/ui-lightness/*.css) \ - $(wildcard $(lib-dir)/jquery/css/ui-lightness/images/*.png) \ - | $(stage-dir)/data - $(call cmd,cssbundle) - -$(stage-dir)/data/target/injected.css: TARGET := $(fiveui-dir)/injected/injected.css -$(stage-dir)/data/target/injected.css: \ - $(fiveui-dir)/injected/injected.css \ - $(fiveui-dir)/images/errorCircle.png \ - $(fiveui-dir)/images/warningTriangle.png \ - $(fiveui-dir)/images/right-arrow.png \ - $(fiveui-dir)/images/down-arrow.png \ - | $(stage-dir)/data/target - $(call cmd,cssbundle) - - - -# Both Extensions ############################################################## - -jquery := $(addprefix $(path)/data/lib/jquery/,\ - jquery-1.8.3.js \ - jquery-ui-1.9.2.custom.js) - -$(stage-dir)/data/underscore.js: $(lib-dir)/underscore.js - $(call cmd,cp) - -$(stage-dir)/data/backbone.js: $(lib-dir)/backbone.js - $(call cmd,cp) - -all: $(stage-dir)/data/fiveui/options.html \ - $(stage-dir)/data/fiveui/options.css \ - $(stage-dir)/data/fiveui/entry.css \ - $(stage-dir)/data/fiveui/ffcheck.js \ - $(stage-dir)/data/target/injected.css \ - $(stage-dir)/data/target/bundled.css \ - $(call stage-all,data/fiveui/images) \ - $(call stage-all,data/lib/codemirror) \ - $(call stage-path,$(jquery)) \ - $(call stage-all,data/lib/jshash) \ - $(stage-dir)/data/fiveui/injected/prelude.js \ - $(stage-dir)/data/fiveui/injected/jquery-plugins.js \ - $(stage-dir)/data/fiveui/injected/fiveui-injected-compute.js \ - $(stage-dir)/data/fiveui/injected/fiveui-injected-ui.js \ - $(stage-dir)/data/underscore.js \ - $(stage-dir)/data/backbone.js - -# Chrome Extension ############################################################# -# -# Use the staged artifacts to build the chrome extension in contexts/fiveui.crx - -chrome-dir := $(path)/chrome - -all: $(topdir)/fiveui.crx - -clean:: - $(RM) $(topdir)/fiveui.crx - -$(topdir)/fiveui.crx: $(build-dir)/fiveui.crx - $(call cmd,cp) - -# Create the chrome extension -$(build-dir)/fiveui.crx: \ - $(target-dir)/chrome-background.js \ - $(target-dir)/chrome-options.js \ - $(stage-dir)/manifest.json \ - $(stage-dir)/data/fiveui/chrome/background.html \ - $(stage-dir)/data/fiveui/chrome/chrome-port.js \ - $(stage-dir)/data/fiveui/chrome/chrome-injected-compute.js \ - $(stage-dir)/data/fiveui/chrome/chrome-injected-ui.js - $(call label,MAKECRX $(call drop-prefix,$@)) ( cd $(build-dir) \ - && $(topdir)/tools/bin/makecrx stage \ - $(topdir)/contexts/chrome/fiveui.pem fiveui \ - $(redir) ) - - -# install the extension manifest in the stage directory -$(stage-dir)/manifest.json: $(path)/manifest.json | $(stage-dir) - $(call cmd,cp) - -chrome-src := $(fiveui-dir)/chrome - -# the chrome-specific background javascript -$(target-dir)/chrome-background.js: $(background-deps) \ - $(chrome-src)/background.js \ - $(chrome-src)/chrome-port.js \ - | $(target-dir) - $(call cmd,compilejs) - - -# the chrome-specific options javascript -$(target-dir)/chrome-options.js: $(options-deps) \ - $(chrome-src)/ajax.js \ - $(chrome-src)/chrome-options.js \ - | $(target-dir) - $(call cmd,compilejs) - - -# Firefox Compilation ########################################################## - -firefox-dir := $(fiveui-dir)/firefox - -addon-sdk := $(topdir)/tools/addon-sdk - -all: $(topdir)/fiveui.xpi - -clean:: - $(RM) $(topdir)/fiveui.xpi - -$(topdir)/fiveui.xpi: $(build-dir)/fiveui.xpi - $(call cmd,cp) - - -# wrapper for setting up the environment for the running the cfx command -cfx = ( cd $(addon-sdk) $(redir) && \ - . bin/activate $(redir) && \ - cd $1 $(redir) && \ - cfx $2 $(redir) ) - -run-firefox: $(build-dir)/fiveui.xpi - $(call cfx,$(stage-dir),run) - -test-firefox: $(build-dir)/fiveui.xpi \ - $(stage-dir)/data/fiveui/firefox/test \ - $(call stage-all,data/fiveui/firefox/test) \ - | $(topdir)/profiles/firefox - $(call cfx,$(stage-dir),test -v -p $(topdir)/profiles/firefox) - -# build the actual extension -$(build-dir)/fiveui.xpi: \ - $(stage-dir)/package.json \ - $(target-dir)/firefox-main.js \ - $(target-dir)/firefox-options.js \ - $(call stage-path,$(path)/data/fiveui/firefox/firefox-injected-compute.js) \ - $(call stage-path,$(path)/data/fiveui/firefox/firefox-injected-ui.js) \ - $(call stage-path,$(path)/data/fiveui/firefox/icon-content.html) \ - $(call stage-path,$(path)/data/fiveui/firefox/icon-script.js) \ - $(call stage-path,$(path)/data/fiveui/firefox/options-icon.html) \ - $(call stage-path,$(path)/data/fiveui/firefox/options-script.js) \ - $(call stage-path,$(path)/data/fiveui/firefox/firefox-options.js) \ - | $(topdir)/profiles/firefox - $(call label,XPI $(call drop-prefix,$@))\ - $(call cfx,$(build-dir),xpi -p $(topdir)/profiles/firefox \ - --pkgdir=$(stage-dir) ) - -# stage the package description -$(stage-dir)/package.json: $(path)/package.json | $(stage-dir) - $(call cmd,cp) - -# build the main script -$(target-dir)/firefox-main.js: \ - $(firefox-dir)/main.js \ - $(firefox-dir)/storage.js \ - $(firefox-dir)/tabIds.js \ - $(firefox-dir)/ajax.js \ - $(fiveui-dir)/settings.js \ - $(fiveui-dir)/messenger.js \ - $(fiveui-dir)/rules.js \ - $(fiveui-dir)/background.js \ - $(fiveui-dir)/utils.js \ - $(fiveui-dir)/set.js \ - $(fiveui-dir)/state.js \ - $(fiveui-dir)/url-pat.js \ - | $(target-dir) - $(call cmd,compilejs) - - -# the chrome-specific options javascript -$(target-dir)/firefox-options.js: \ - $(lib-dir)/jquery/jquery-1.8.3.js \ - $(lib-dir)/underscore.js \ - $(lib-dir)/backbone.js \ - $(options-deps) \ - $(firefox-dir)/firefox-options.js \ - | $(target-dir) - $(call cmd,compilejs) diff --git a/contexts/chrome/.gitignore b/contexts/chrome/.gitignore deleted file mode 100644 index 3fe6a20..0000000 --- a/contexts/chrome/.gitignore +++ /dev/null @@ -1 +0,0 @@ -fiveui.pem diff --git a/contexts/data/fiveui/background.js b/contexts/data/fiveui/background.js deleted file mode 100644 index 284b443..0000000 --- a/contexts/data/fiveui/background.js +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Module : background.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -fiveui = fiveui || {}; - -(function() { -/** - * @constructor - * - * @param {!function(!string):!string} dataLoader - */ -fiveui.Background = function(settings, updateWidget, loadScripts, dataLoader) { - // Initialize a storage mechanism for FiveUI. - // Chrome utilizes HTML5's localStorage API as a backend, but other - // contexts (such as Firefox) would supply a different backend - // storage to the settings constructor. - // - // The data in settings is persisted across executions of the - // context and the plugin. It is used for long-term storage of user - // preferences, rule sets, and similarly long-lived FiveUI settings. - this.settings = settings; - - // the state of all managed tabs - this.state = new fiveui.State(settings); - - // how we communicate with the status widget - this.updateWidget = updateWidget; - - // how we signal the browser to load a content script - this.loadScripts = loadScripts; - - this.dataLoader = dataLoader; -}; - -fiveui.Background.prototype._registerComputeListeners = function(port, tabState){ - var bg = this; - port.on('ReportProblem', function(request) { - var problem = fiveui.Problem.fromJSON(request); - if(tabState.addProblem(problem) && tabState.uiPort != null) { - bg.updateWidget(tabState); - tabState.uiPort.emit('ShowProblem', problem); - } - }); - port.on('ReportStats', function (stats) { - if (tabState.addStats(stats) && tabState.uiPort != null) { - bg.updateWidget(tabState); - tabState.uiPort.emit('ShowStats', stats); - } - }); -}; - -fiveui.Background.prototype._registerUiListeners = function(port, tabState){ - var bg = this; - port.on('Position', function(request) { - tabState.winState.x = request.left; - tabState.winState.y = request.top; - }); - port.on('Size', function(request) { - tabState.winState.width = request.width; - tabState.winState.height = request.height; - }); - port.on('CloseUI', function(request) { - tabState.winState.closed = true; - }); - port.on('ClearProblems', function(request) { - tabState.clearProblems(); - bg.updateWidget(tabState); - }); - port.on('MaskRules', function(request) { - _.each(tabState.computePorts, function(cp) { - cp.emit('MaskRules', null); - }); - }); - port.on('UnmaskRules', function(request) { - _.each(tabState.computePorts, function(cp) { - cp.emit('UnmaskRules', null); - }); - }); -}; - -/** - * Accept a new connection from a content script. - */ -fiveui.Background.prototype.connect = function(tabId, port, url, isUiPort) { - - var tabState = this.state.acquireTabState(tabId); - - if (isUiPort) { - tabState.uiPort = port; - this._registerUiListeners(port, tabState); - port.emit('RestoreUI', tabState.toEmit()); - this.updateWidget(tabState); - } else { - tabState.computePorts.push(port); - this._registerComputeListeners(port, tabState); - - // get the rule set and send it down to the injected page: - var pat = this.settings.checkUrl(url); - if (!pat) { - console.err('could not find url pattern for tab.url, but one was strongly expected'); - } else { - var ruleSet = this.settings.getRuleSet(pat.rule_id); - - port.emit('SetRules', ruleSet); - } - } -}; - -/** - * @param {!number} tabId - * @param {!string} url - * @param {*} data - */ -fiveui.Background.prototype.pageLoad = function(tabId, url, data) { - var pat = this.settings.checkUrl(url); - - if (null == pat) { - this.updateWidget(null); - } else { - var tabState = this.state.acquireTabState(tabId); - tabState.computePorts = []; - - this.updateWidget(tabState); - - var dependencies = []; - var ruleSet = this.settings.getRuleSet(pat.rule_id); - - if (ruleSet && ruleSet.dependencies ) { - dependencies = ruleSet.dependencies; - } - - var computeScripts = _.flatten( - [ [ this.dataLoader('lib/jquery/jquery-1.8.3.js') - , this.dataLoader('fiveui/injected/prelude.js') - , this.dataLoader('lib/jshash/md5.js') - , this.dataLoader('fiveui/injected/jquery-plugins.js') - ] - , dependencies - , [ this.dataLoader('fiveui/injected/fiveui-injected-compute.js') - ] - ]); - this.loadScripts(tabId, computeScripts, true, data); - - var uiScripts = _.flatten( - [ this.dataLoader('target/injected.css') - , this.dataLoader('target/bundled.css') - , this.dataLoader('lib/jquery/jquery-1.8.3.js') - , this.dataLoader('lib/jquery/jquery-ui-1.9.2.custom.js') - , this.dataLoader('fiveui/injected/prelude.js') - , this.dataLoader('fiveui/injected/fiveui-injected-ui.js') - , this.dataLoader('fiveui/injected/jquery-plugins.js') - ]); - this.loadScripts(tabId, uiScripts, false, data); - } -}; - -/** - * Updates the widget according to the tab state of the specified tab. - * - * @param {!number} tabId Id of the tab that is currently active, and - * thus, dictating the widget display. - */ -fiveui.Background.prototype.activate = function(tabId) { - var tabState = this.state.getTabState(tabId); - this.updateWidget(tabState); -}; - -/** - * Stop tracking the state of a tab. - * - * @param {!number} tabId Id of the tab to free the state of. - */ -fiveui.Background.prototype.removeTab = function(tabId) { - this.state.removeTabState(tabId); -}; - -/** - * Request that the user interface be restored, if it is closed. - */ -fiveui.Background.prototype.showUI = function(tabId) { - var tabState = this.state.getTabState(tabId); - if(null == tabState) { - return; - } - - if(tabState.winState.closed) { - tabState.winState.closed = false; - tabState.uiPort.emit('ShowUI', null); - } -}; - -})(); diff --git a/contexts/data/fiveui/chan.js b/contexts/data/fiveui/chan.js deleted file mode 100644 index 47c6145..0000000 --- a/contexts/data/fiveui/chan.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Module : chan.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -/** - * @constructor - */ -fiveui.Chan = function() { - this.fns = {}; -}; - -_.extend(fiveui.Chan.prototype, { - - /** - * @param {!string} type - * @param {!function(*)} fn - */ - on: function(type, fn) { - this.fns[type] = fn; - }, - - /** - * @param {!string} type - * @param {*} data - */ - emit: function(type, data) { - this.chan.fns[type](data); - } - -}); - -})(); diff --git a/contexts/data/fiveui/chrome/ajax.js b/contexts/data/fiveui/chrome/ajax.js deleted file mode 100644 index 68ced39..0000000 --- a/contexts/data/fiveui/chrome/ajax.js +++ /dev/null @@ -1,39 +0,0 @@ - - -var fiveui = fiveui || {}; - -(function() { - -fiveui.ajax = fiveui.ajax || {}; - -/** - * Use jQuery to get the resource, calling the success or error continuations - * when the result is returned. This always retrieves as text, leaving any - * further processing to the success continuation. - */ -fiveui.ajax.get = function(url, options) { - - _.defaults(options, { - success:function() {}, - error: function() {} - }); - - jQuery.ajax(url, { - - dataType: 'text', - - success:function(text) { - // strip out everything else from the args - options.success(text); - }, - - error:function() { - // call with no context - options.error(); - }, - - }); - -}; - -})(); diff --git a/contexts/data/fiveui/chrome/background.html b/contexts/data/fiveui/chrome/background.html deleted file mode 100644 index ea90678..0000000 --- a/contexts/data/fiveui/chrome/background.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Background Page - - - - - - - diff --git a/contexts/data/fiveui/chrome/background.js b/contexts/data/fiveui/chrome/background.js deleted file mode 100644 index 7f74a33..0000000 --- a/contexts/data/fiveui/chrome/background.js +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Module : chrome/background.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Chrome Only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -fiveui.chrome = fiveui.chrome || {}; - -/** - * The primary entry point for the FiveUI Chrome background page. - */ -fiveui.chrome.background = function() { - - /** - * Inject code and resources into the specified tab's web page. - * - * @param {!number} tabid The id of the tab to load scripts into. - * @param {!Array.} inScripts The list of scripts to load in - * order. - * @param {!boolean} inFrames Whether or not to inject into iFrames. - * @return {void} - */ - var loadScripts = function(tabid, inScripts, inFrames) { - var chromeScripts = [dataLoader('fiveui/chrome/chrome-port.js')]; - if(inFrames) { - chromeScripts.push(dataLoader('fiveui/chrome/chrome-injected-compute.js')); - } else { - chromeScripts.push(dataLoader('fiveui/chrome/chrome-injected-ui.js')); - } - var scripts = _.flatten([chromeScripts, inScripts]); - - var end = function() {}; - - var loop = function() { - var next = loop; - if (scripts.length == 1) { - next = end; - } - - var script = scripts.shift(); - - // console.log('injecting: ' + script); - - if (/css$/.test(script)) { - chrome.tabs.insertCSS(tabid, { 'file' : script }, next); - } else { - chrome.tabs.executeScript(tabid, { 'file' : script }, next); - } - }; - - loop(); - }; - - /** - * Set the current widget icon. - * - * @param {!string} iconPath The local path to the icon to use. - * @return {void} - */ - var setIcon = function(iconPath) { - chrome.tabs.getSelected(null, - function(tab) { - chrome.browserAction.setIcon({ - path: iconPath, - tabId: tab.id - }); - }); - }; - - /** - * Change the text undearneath the fiveui icon. - * - * @param {!fiveui.TabState} tabState The tab state object to update. - * @return {void} - */ - var updateIconText = function(tabState) { - var tabId = tabState.tabId; - var probs = tabState.problems.length; - var text = ''; - if (probs > 0) { - if (probs > 99) { - text = '99+'; - } else { - text = probs.toString(); - } - } - chrome.browserAction.setBadgeText({ text: text, tabId: tabId }); - }; - - var updateWidget = function(tabState) { - if(null == tabState) { - setIcon('../images/fiveui-icon-disabled.png'); - } else { - setIcon('../images/fiveui-icon-enabled.png'); - updateIconText(tabState); - } - }; - - // launch the generic background script - var dataLoader = function (path) { - return "data/"+path; - }; - var settings = new fiveui.Settings(localStorage); - background = new fiveui.Background(settings, updateWidget, - loadScripts, dataLoader); - - // notify the generic background about a new content script connection. - chrome.extension.onConnect.addListener( - function(chPort) { - var port = new fiveui.ChromePort(chPort); - var tabId = chPort.sender.tab.id; - var url = chPort.sender.tab.url; - - background.connect(tabId, port, url, chPort.name == 'ui'); - }); - - - chrome.tabs.onCreated.addListener(function(tab) { - // console.log('in oncreated'); - if (tab.url) { - background.pageLoad(tab.id, tab.url); - } - }); - // check page load events against the generic background - chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { - if (changeInfo.status == 'complete') { - background.pageLoad(tabId, tab.url); - } - }); - - chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) { - background.removeTab(tabId); - }); - - // show the browser widget when the fiveui button is clicked. - chrome.browserAction.onClicked.addListener(function(tab) { - background.showUI(tab.id); - }); -}; - -// Add event listeners once the DOM has fully loaded by listening for the -// `DOMContentLoaded` event on the document, and adding your listeners to -// specific elements when it triggers. -jQuery(fiveui.chrome.background); - -})(); diff --git a/contexts/data/fiveui/chrome/chrome-injected-compute.js b/contexts/data/fiveui/chrome/chrome-injected-compute.js deleted file mode 100644 index a372913..0000000 --- a/contexts/data/fiveui/chrome/chrome-injected-compute.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Module : chrome/chrome-injected-compute.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Chrome Only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @return {{on: function(!string, function(*)), emit: function(!string, *)}} - */ -var obtainComputePort = function() { - return new fiveui.ChromePort(chrome.extension.connect({ name: 'compute' })); -}; diff --git a/contexts/data/fiveui/chrome/chrome-injected-ui.js b/contexts/data/fiveui/chrome/chrome-injected-ui.js deleted file mode 100644 index 939a62d..0000000 --- a/contexts/data/fiveui/chrome/chrome-injected-ui.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Module : chrome/chrome-injected-ui.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Chrome Only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @return {{on: function(!string, function(*)), emit: function(!string, *)}} - */ -var obtainPort = function() { - return new fiveui.ChromePort(chrome.extension.connect({ name: 'ui' })); -}; diff --git a/contexts/data/fiveui/chrome/chrome-options.js b/contexts/data/fiveui/chrome/chrome-options.js deleted file mode 100644 index 9abccea..0000000 --- a/contexts/data/fiveui/chrome/chrome-options.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Module : chrome/chrome-options.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Chrome Only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -fiveui.chrome = fiveui.chrome || {}; -fiveui.chrome.options = fiveui.chrome.options || {}; - - -_.extend(fiveui.chrome.options, { - init: function() { - var optionsChan = new fiveui.Chan(); - var storageChan = new fiveui.Chan(); - - optionsChan.chan = storageChan; - storageChan.chan = optionsChan; - - var settings = new fiveui.Settings(localStorage); - - fiveui.Settings.manager(storageChan, settings); - fiveui.options.init(optionsChan); - } -}); - -})(); diff --git a/contexts/data/fiveui/chrome/chrome-port.js b/contexts/data/fiveui/chrome/chrome-port.js deleted file mode 100644 index 8a5aeae..0000000 --- a/contexts/data/fiveui/chrome/chrome-port.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Module : chrome/chrome-port.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Chrome Only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -if (typeof goog != 'undefined') { - goog.provide('fiveui.ChromePort'); -} else { - var fiveui = fiveui || {}; -} - -/** - * @constructor - * @param {!{onMessage:Object,postMessage:function(*):void}} port The connection to manage. - */ -fiveui.ChromePort = function(port) { - var events = {}; - - this._port = port; - this._events = events; - - this._port.onMessage.addListener(function(obj) { - var evt = obj.type; - var cb = events[evt]; - if(null != evt && null != cb) { - cb(obj.payload); - } - }); -}; - -/** - * Listen to incoming messages. - * - * @param {!string} evt The event to listen for. - * @param {!function(*)} cb The callback to invoke. - * @return {void} - */ -fiveui.ChromePort.prototype.on = function(evt, cb) { - this._events[evt] = cb; -}; - -/** - * Send a message to the background. - * - * @param {!string} evt The event to fire. - * @param {?Object} obj The data to associate with the event. - * @return {void} - */ -fiveui.ChromePort.prototype.emit = function(evt, obj) { - // console.log('chromeport.emit: '+evt); - // console.log(obj); - this._port.postMessage({ type: evt, payload: obj }); - // console.log('chromeport.emit: '+evt+' done'); -}; diff --git a/contexts/data/fiveui/entry.css b/contexts/data/fiveui/entry.css deleted file mode 100644 index ec4791c..0000000 --- a/contexts/data/fiveui/entry.css +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Module : entry.css - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -ul.entries { - list-style: none; - padding-left: 5px; -} - -ul.entries li.entry { - border-top: 1px solid #CDCDCD; - margin-top: 5px; - padding-top: 10px; - padding-bottom: 10px; -} - -li.entry .error { - margin-top: 10px; - padding: 10px; - background-color: #FF4D4D; - color: #ffffff; -} - -ul.entries li.entry:first-child { - border-top: 0px; -} - -li.entry .button { - cursor: pointer; - cursor: hand; -} - -li.entry .editable { - padding: 5px; - border: 1px solid #CDCDCD; -} - -li.entry .placeholder { - font-style: italic; - color: #CDCDCD; -} diff --git a/contexts/data/fiveui/entry.js b/contexts/data/fiveui/entry.js deleted file mode 100644 index 025034a..0000000 --- a/contexts/data/fiveui/entry.js +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Module : entry.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -var fiveui = fiveui || {}; - -(function() { - -var editable = function(el, model, placeholder) { - - el.prop('contenteditable', true).addClass('editable'); - - // prevent newlines - el.on('keypress', function(e) { - return e.which != 13; - }); - - var addPlaceholder = function() { - el.addClass('placeholder') - .text(placeholder) - .one('click keypress paste', remPlaceholder); - }; - - var remPlaceholder = function() { - el.removeClass('placeholder').text(''); - }; - - // if the model is new, set the placeholder, and a listener to clear it - if(model.isNew()) { - addPlaceholder(); - } - - el.on('blur', function() { - if(_.isEmpty(el.text())) { - addPlaceholder(); - } - }); - - el.focus(); - -}; - - -/** UrlPat Entry Elements ****************************************************/ - -fiveui.UrlPatEntry = Backbone.View.extend({ - - tagName: 'li', - - className: 'entry', - - events: { - 'click span.save' : 'save', - 'click span.remove' : 'remove', - 'click span.edit' : 'edit', - }, - - initialize:function() { - this.listenTo(this.model, 'remove', function() { - this.$el.remove(); - this.stopListening(); - }); - }, - - viewTemplate: _.template( - [ '
' - , ' x' - , ' edit' - , ' <%= regex %>' - , ' <%= rule_name %>' - , '
' - ].join('')), - - render:function() { - var attrs = _.clone(this.model.attributes); - var ruleSet = this.options.rules.model.findWhere({ id: attrs.rule_id }) - attrs.rule_name = ruleSet.get('name'); - this.$el.html(this.viewTemplate(attrs)); - return this; - }, - - editTemplate: _.template( - [ '
' - , ' x' - , ' save' - , ' ' - , ' ' - , '
' - ].join('')), - - edit:function() { - var attrs = this.model.attributes; - this.$el.html(this.editTemplate(attrs)); - - this.$el.find('.rules').append(this.options.rules.render().$el); - editable(this.$el.find('.regex'), this.model, 'url pattern'); - return this; - }, - - remove: function() { - this.model.destroy(); - }, - - save:function() { - var regex = this.$el.find('.regex').text(); - var rule_id = parseInt(this.options.rules.$el.val()); - this.model.save({ regex : regex, rule_id : rule_id }, { - success: _.bind(this.render, this), - error: _.bind(this.edit, this) - }); - }, - -}); - - -/** Rule Set View ************************************************************/ - -fiveui.RulesView = Backbone.View.extend({ - - tagName: 'select', - - initialize:function() { - this.listenTo(this.model, 'sync', this.update); - this.listenTo(this.model, 'remove', this.update); - }, - - optionTemplate:_.template( - '' - ), - - update:function() { - if(this.model.length == 0) { - return this.remove(); - } else { - return this.render(); - } - }, - - remove:function() { - this.stopListening(); - this.$el.remove(); - - this.trigger('remove'); - - return this; - }, - - render:function() { - - var scope = this; - - this.$el.children().remove(); - - var text = this.model.foldl(function(body,ruleSet) { - return body + scope.optionTemplate(ruleSet.attributes); - }, ''); - - this.$el.html(text); - - return this; - }, - -}); - - -/** Rule Entry Elements ******************************************************/ - -fiveui.RuleSetEntry = Backbone.View.extend({ - - tagName: 'li', - - className: 'entry', - - events: { - 'click .save' : 'save', - 'click .remove' : 'remove', - 'click .edit' : 'edit', - 'click .reload' : 'reload', - }, - - viewTemplate: _.template( - [ '
' - , ' x' - , ' edit' - , ' reload' - , ' <%= name %>' - , '
' - ].join('')), - - render:function() { - var attrs = this.model.attributes; - this.$el.html(this.viewTemplate(attrs)); - return this; - }, - - editTemplate: _.template( - [ '
' - , ' x' - , ' save' - , ' <%= source %>' - , '
' - ].join('')), - - edit:function() { - var attrs = this.model.attributes; - this.$el.html(this.editTemplate(attrs)); - - editable(this.$el.find('.source'), this.model, - 'http://example.com/manifest.json') - - return this; - }, - - errorTemplate: _.template('
<%= message %>
'), - - editError:function(target, message) { - this.edit(); - - this.$el.append(this.errorTemplate({ message: message })); - - return this; - }, - - save: function() { - var source = this.$el.find('.source').text(); - this.model.set('source', source); - this.model.save({}, { - success: _.bind(this.render, this), - error: _.bind(this.editError, this) - }); - }, - - reload:function() { - this.model.save({}, { - success: _.bind(this.render, this), - error: _.bind(this.edit, this) - }); - }, - - remove:function() { - var self = this; - - this.model.destroy({ - wait:true, - - success:function() { - self.$el.remove(); - self.stopListening(); - }, - - error:function() { - console.log('communicate failure somehow...'); - } - }); - }, - -}); - -})(); diff --git a/contexts/data/fiveui/ffcheck.js b/contexts/data/fiveui/ffcheck.js deleted file mode 100644 index 2157ed0..0000000 --- a/contexts/data/fiveui/ffcheck.js +++ /dev/null @@ -1,3 +0,0 @@ -if (! /Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) { - window.onload=fiveui.chrome.options.init; -} diff --git a/contexts/data/fiveui/firefox/ajax.js b/contexts/data/fiveui/firefox/ajax.js deleted file mode 100644 index da95c38..0000000 --- a/contexts/data/fiveui/firefox/ajax.js +++ /dev/null @@ -1,37 +0,0 @@ - -var fiveui = fiveui || {}; -var Request = require('request').Request; - -(function() { - -fiveui.ajax = fiveui.ajax || {}; - -/** - * Use the request api to make an XHR request from the extension context. - * Behaves somewhat like the jQuery.ajax method, but only ever returns the text - * content of the response. - */ -fiveui.ajax.get = function(url, opts) { - - _.defaults(opts, { - success: function() {}, - error: function() {}, - }); - - Request({ - - url: url, - - onComplete:function(resp) { - if(resp.status == 200) { - opts.success(resp.text); - } else { - opts.error(); - } - }, - - }).get(); - -}; - -})(); diff --git a/contexts/data/fiveui/firefox/bootstrap.js b/contexts/data/fiveui/firefox/bootstrap.js deleted file mode 100644 index e7f0b34..0000000 --- a/contexts/data/fiveui/firefox/bootstrap.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Module : firefox/bootstrap.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; diff --git a/contexts/data/fiveui/firefox/firefox-injected-compute.js b/contexts/data/fiveui/firefox/firefox-injected-compute.js deleted file mode 100644 index 1f1dc48..0000000 --- a/contexts/data/fiveui/firefox/firefox-injected-compute.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Module : firefox/firefox-injected-compute.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Firefox only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @param {!string} css The css to inject. - */ -var addGlobalStyle = function(css) { - var head = document.getElementsByTagName('head')[0]; // find head element, which should exist - if (!head) { - head = document.createElement('head'); - - // XXX this is perhaps not reliable? - document.body.appendChild(head); - } - - var style = document.createElement('style'); // create - - - -
- - - - -
-
- - diff --git a/contexts/data/fiveui/firefox/icon-script.js b/contexts/data/fiveui/firefox/icon-script.js deleted file mode 100644 index 61545da..0000000 --- a/contexts/data/fiveui/firefox/icon-script.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Module : firefox/icon-script.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Firefox only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function() { - var updateBadgeText = function(text) { - $('#badge-text').text(text); - $('#badge-text').show(); - }; - - self.port.on('setEnabled', function(text) { - $('#disabled-img').hide(); - $('#enabled-img').show(); - if (text.length != 0) { - updateBadgeText(text); - } else { - $('#badge-text').hide(); - } - }); - self.port.on('setDisabled', function() { - $('#disabled-img').show(); - $('#enabled-img').hide(); - $('#badge-text').hide(); - }); - })(); diff --git a/contexts/data/fiveui/firefox/main.js b/contexts/data/fiveui/firefox/main.js deleted file mode 100644 index 2723c72..0000000 --- a/contexts/data/fiveui/firefox/main.js +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Module : firefox/main.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Firefox only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -_ = require('underscore'); -Backbone = require('backbone'); - -var fiveui = fiveui || {}; - -(function() { - -fiveui.firefox = fiveui.firefox || {}; - -const widgets = require("widget"); -const tabs = require("tabs"); -const data = require("self").data; -const pageMod = require("page-mod"); - -fiveui.firefox.main = function() { - var settings = new fiveui.Settings(new fiveui.firefox.StorageWrapper()); - var activeId = 0; - - // initialze the background functionality - - // the FiveUI button: - var icon = widgets.Widget({ - id: "FiveUI-Icon", - label: "FiveUI", - contentURL: data.url('fiveui/firefox/icon-content.html'), - contentScriptFile: [ - data.url('lib/jquery/jquery-1.8.3.js'), - data.url('fiveui/firefox/icon-script.js') - ], - onClick: function() { - background.showUI(activeId); - } - }); - - var optionsButton = widgets.Widget( - { id: "FiveUI-Options", - label: "FiveUI", - contentURL: data.url('fiveui/firefox/options-icon.html'), - contentScriptFile: [ - data.url('lib/jquery/jquery-1.8.3.js'), - data.url('fiveui/firefox/options-script.js') - ] - } - ); - - /** - * @param {?fiveui.TabState} tabState - */ - var updateWidget = function(tabState) { - if(null == tabState) { - icon.port.emit('setDisabled'); - icon.width = 16; - } else { - var problems = getProblemCount(tabState); - icon.port.emit('setEnabled', problems); - if (problems == 0){ - icon.width = 16; - } else { - icon.width = 24; - } - } - }; - - // store the contents of the injected css, so that we can inject it later - var injectedCSS = [ - data.load('target/injected.css'), - data.load('target/bundled.css') - ].join('\n'); - - /** - * Inject code and resources into the specified tab's web page. - * - * @param {!number} tabid The id of the tab to load scripts into. - * @param {!Array.} inScripts The list of scripts to load in - * order. - * @param {!boolean} inFrames Whether or not to inject into iFrames. - * @return {void} - */ - var loadScripts = function(tabId, inScripts, inFrames, tab) { - - if(inFrames) { - var firefoxScripts = [dataLoader('fiveui/firefox/firefox-injected-compute.js')]; - } else { - var firefoxScripts = [dataLoader('fiveui/firefox/firefox-injected-ui.js')]; - } - - // just scripts, css gets filtered out. - var scripts = _.filter(_.flatten([firefoxScripts, inScripts]), - function(script) { - console.log(script); - return script.search(/\.css$/i) == -1; - }); - - if (tab) { - var worker = tab.attach({ - contentScriptFile: scripts - }); - - background.connect(tabId, worker.port, tab.url, !inFrames); - worker.port.emit('injectCSS', injectedCSS); - } - }; - - var dataLoader = function(path) { - return data.url(path); - }; - - var background = new fiveui.Background(settings, updateWidget, - loadScripts, dataLoader); - - var tabIds = new fiveui.firefox.TabIds(); - - var handleNewTab = function(tab) { - var tabId = tabIds.allocate(); - - tab.on('activate', function() { - background.activate(tabId); - activeId = tabId; - }); - - tab.on('ready', function() { - background.pageLoad(tabId, tab.url, tab); - }); - - tab.on('close', function() { - tabIds.free(tabId); - background.removeTab(tabId); - }); - }; - - // handle existing tabs - _.each(tabs, handleNewTab); - - // manage new tab creation - tabs.on('open', handleNewTab); - - /** - * @param {!fiveui.TabState} tabstate - * @return {void} - */ - var getProblemCount = function(tabState){ - var tabId = tabState.tabId; - var probs = tabState.problems.length; - var text = ''; - if (probs > 0) { - if (probs > 99) { - text = '99+'; - } else { - text = probs.toString(); - } - } - return text; - }; - - var showOptions = function() { - // TODO does not make use of existing options tabs, if any are open: - tabs.open(data.url('fiveui/options.html')); - }; - - // set up a page-mod to be active on the options page, so that - // page can communicate with the add-on: - pageMod.PageMod( - { include: data.url('fiveui/options.html'), - contentScriptWhen: 'end', - contentScriptFile: [ - data.url("target/firefox-options.js") - ], - contentScript: "fiveui.firefox.options.init()", - onAttach: function (worker) { - fiveui.Settings.manager(worker.port, settings); - } - }); - - optionsButton.port.on('showOptions', showOptions); -}; - -exports.main = fiveui.firefox.main; - -})(); diff --git a/contexts/data/fiveui/firefox/options-icon.html b/contexts/data/fiveui/firefox/options-icon.html deleted file mode 100644 index 850b530..0000000 --- a/contexts/data/fiveui/firefox/options-icon.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - -
- - -
- - diff --git a/contexts/data/fiveui/firefox/options-script.js b/contexts/data/fiveui/firefox/options-script.js deleted file mode 100644 index 2008883..0000000 --- a/contexts/data/fiveui/firefox/options-script.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Module : firefox/options-script.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Firefox only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function() { - $('#options-div').click(function() { - //console.log('options-div handler'); - self.port.emit('showOptions'); - }); - })(); diff --git a/contexts/data/fiveui/firefox/storage.js b/contexts/data/fiveui/firefox/storage.js deleted file mode 100644 index 9aa51aa..0000000 --- a/contexts/data/fiveui/firefox/storage.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Module : firefox/storage.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Firefox only) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -if (typeof goog != 'undefined') { - goog.provide('fiveui.firefox.StorageWrapper'); -} else { - var fiveui = fiveui || {}; - fiveui.firefox = fiveui.firefox || {}; -} - -const ss = require('simple-storage'); - -/** - * A wraper around the Firefox Simple-Storage API to match the w3c Storage interface: - * http://dev.w3.org/html5/webstorage/#storage-0 - */ -fiveui.firefox.StorageWrapper = function() { - this.__defineGetter__('length', - function(){ - return Object.keys(ss.storage).length; - }); -}; - -fiveui.firefox.StorageWrapper.prototype.key = function(idx) { - return Object.keys(ss.storage)[idx]; -}; - -fiveui.firefox.StorageWrapper.prototype.getItem = function(key) { - return ss.storage[key]; -}; - -fiveui.firefox.StorageWrapper.prototype.setItem = function(key, value) { - ss.storage[key] = value; -}; - -fiveui.firefox.StorageWrapper.prototype.removeItem = function(key) { - var keys = Object.keys(ss.storage); - for(var i=0; i - - - - - - - - - - image/svg+xml - - - - - eugrafia - - - - - - - - - - - - - - - - - - - diff --git a/contexts/data/fiveui/images/attribution.txt b/contexts/data/fiveui/images/attribution.txt deleted file mode 100644 index fb8c49c..0000000 --- a/contexts/data/fiveui/images/attribution.txt +++ /dev/null @@ -1,3 +0,0 @@ -Gear_3.svg is used under a Creative Commons liscense. The svg was found here: - - - http://en.wikipedia.org/wiki/File:Gear_3.svg diff --git a/contexts/data/fiveui/images/down-arrow.png b/contexts/data/fiveui/images/down-arrow.png deleted file mode 100644 index 4fd7d54..0000000 Binary files a/contexts/data/fiveui/images/down-arrow.png and /dev/null differ diff --git a/contexts/data/fiveui/images/down-arrow.svg b/contexts/data/fiveui/images/down-arrow.svg deleted file mode 100644 index 6b4ba07..0000000 --- a/contexts/data/fiveui/images/down-arrow.svg +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/contexts/data/fiveui/images/errorCircle.png b/contexts/data/fiveui/images/errorCircle.png deleted file mode 100644 index d5c1dc0..0000000 Binary files a/contexts/data/fiveui/images/errorCircle.png and /dev/null differ diff --git a/contexts/data/fiveui/images/fiveui-icon-128.png b/contexts/data/fiveui/images/fiveui-icon-128.png deleted file mode 100644 index 1f0b6c4..0000000 Binary files a/contexts/data/fiveui/images/fiveui-icon-128.png and /dev/null differ diff --git a/contexts/data/fiveui/images/fiveui-icon-16.png b/contexts/data/fiveui/images/fiveui-icon-16.png deleted file mode 100644 index cc256e0..0000000 Binary files a/contexts/data/fiveui/images/fiveui-icon-16.png and /dev/null differ diff --git a/contexts/data/fiveui/images/fiveui-icon-48.png b/contexts/data/fiveui/images/fiveui-icon-48.png deleted file mode 100644 index 2d586fa..0000000 Binary files a/contexts/data/fiveui/images/fiveui-icon-48.png and /dev/null differ diff --git a/contexts/data/fiveui/images/fiveui-icon-disabled.png b/contexts/data/fiveui/images/fiveui-icon-disabled.png deleted file mode 100644 index 66b6a63..0000000 Binary files a/contexts/data/fiveui/images/fiveui-icon-disabled.png and /dev/null differ diff --git a/contexts/data/fiveui/images/fiveui-icon-enabled.png b/contexts/data/fiveui/images/fiveui-icon-enabled.png deleted file mode 100644 index 144f64e..0000000 Binary files a/contexts/data/fiveui/images/fiveui-icon-enabled.png and /dev/null differ diff --git a/contexts/data/fiveui/images/fiveui-icon-working.png b/contexts/data/fiveui/images/fiveui-icon-working.png deleted file mode 100644 index 94643c7..0000000 Binary files a/contexts/data/fiveui/images/fiveui-icon-working.png and /dev/null differ diff --git a/contexts/data/fiveui/images/right-arrow.png b/contexts/data/fiveui/images/right-arrow.png deleted file mode 100644 index 614e65d..0000000 Binary files a/contexts/data/fiveui/images/right-arrow.png and /dev/null differ diff --git a/contexts/data/fiveui/images/right-arrow.svg b/contexts/data/fiveui/images/right-arrow.svg deleted file mode 100644 index 192f654..0000000 --- a/contexts/data/fiveui/images/right-arrow.svg +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/contexts/data/fiveui/images/warningTriangle.png b/contexts/data/fiveui/images/warningTriangle.png deleted file mode 100644 index dac1d03..0000000 Binary files a/contexts/data/fiveui/images/warningTriangle.png and /dev/null differ diff --git a/contexts/data/fiveui/injected/fiveui-injected-compute.js b/contexts/data/fiveui/injected/fiveui-injected-compute.js deleted file mode 100644 index 7ae9848..0000000 --- a/contexts/data/fiveui/injected/fiveui-injected-compute.js +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Module : injected/fiveui-injected-compute.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function(){ - var guidGenerator = function () { - var S4 = function() { - return (((1+Math.random())*0x10000)|0).toString(16).substring(1); - }; - return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); - }; - - /** - * Storage namespace for in-browser logic - */ - var core = {}; - core.port = obtainComputePort(); - - /** - * Whether or not rules are fired when a dom change is detected. - */ - core.maskRules = false; - - /** - * Timeout (in miliseconds) for the dom to settle, before running the rules - * engine again. - */ - core.timeout = 500; - - /** - * Whether or not the rules thread should be started. - */ - core.scheduled = false; - - /** - * Start the process that checks for the need to run the rules, and - * reschedules when necessary. - */ - core.scheduleRules = function() { - core.lastEvent = new Date(); - - var check = function() { - var delta = new Date() - core.lastEvent; - if(delta > core.timeout && !core.maskRules) { - core.scheduled = false; - core.evaluate(core.rules.rules); - } else { - setTimeout(check, core.timeout); - } - }; - - if(!core.scheduled && !core.maskRules) { - core.scheduled = true; - check(); - } - }; - - core.port.on('MaskRules', function() { - core.maskRules = true; - }); - - core.port.on('UnmaskRules', function() { - core.maskRules = false; - }); - - core.reportProblem = function(prob) { - core.port.emit('ReportProblem', prob); - }; - - core.reportStats = function(stats) { - core.port.emit('ReportStats', stats); - }; - - core.hash = function(rule, name, node) { - var prob = { - name: name, - descr: rule.description, - url: window.location.href, - severity: 1, - xpath: core.getElementXPath(node) - }; - - var nodeParents = function(node) { - var parents = ''; - $(node).parents().each( - function (idx, elt) { - parents += elt.tagName; - parents += ">"; - }); - return parents; - }; - - var nodeHash = function(node) { - if (node == null) { - return ""; - } - - return nodeParents(node) + node.id + node.tagName; - }; - - var str = prob.name + prob.descr + prob.url + prob.severity - + name + nodeHash(node); - - prob.hash = hex_md5(str); // hex_md5() is from md5.js - - return prob; - }; - - /* The next two methods are provided under the following license: */ - /* Software License Agreement (BSD License) - - Copyright (c) 2007, Parakey Inc. - All rights reserved. - - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - - * Neither the name of Parakey Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of Parakey Inc. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - /** - * Gets an XPath for an element which describes its hierarchical location. - */ - core.getElementXPath = function(element) - { - if (element && element.id) - return '//*[@id="' + element.id + '"]'; - else - return core.getElementTreeXPath(element); - }; - - core.getElementTreeXPath = function(element) - { - var paths = []; - - // Use nodeName (instead of localName) so namespace prefix is included (if any). - for (; element && element.nodeType == 1; element = element.parentNode) - { - var index = 0; - for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling) - { - // Ignore document type declaration. - if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE) - continue; - - if (sibling.nodeName == element.nodeName) - ++index; - } - - var tagName = element.nodeName.toLowerCase(); - var pathIndex = (index ? "[" + (index+1) + "]" : ""); - paths.splice(0, 0, tagName + pathIndex); - } - - return paths.length ? "/" + paths.join("/") : null; - }; - - /* END of BSD licensed code */ - - core.evaluate = function(rs) { - var theRule = null; - var date = new Date(); - var stats = - { start: date.getTime() - , end: null - , numRules: 0 - , numElts: 0 - }; - fiveui.stats.numElts = 0; // reset stats element counter - - var report = function(name, node) { - var prob = core.hash(theRule, name, node); - var query = $(node); - if(!query.hasClass(prob.hash)) { - query.addClass(prob.hash); - core.reportProblem(prob); - } - }; - - for(var i=0; i= 0; - }; - - var handleDOMEvent = function(e){ - if ( !uicAttrEvent(e.target) && !underFiveUI(e.target) ) { - core.scheduleRules(); - } - }; - - context.addEventListener('DOMNodeInserted', handleDOMEvent); - context.addEventListener('DOMNodeRemoved', handleDOMEvent); - context.addEventListener('DOMSubtreeModified', handleDOMEvent); - context.addEventListener('DOMAttrModified', handleDOMEvent); - context.addEventListener('DOMNodeRemovedFromDocument', handleDOMEvent); - context.addEventListener('DOMNodeInsertedIntoDocument', handleDOMEvent); - context.addEventListener('DOMCharacterDataModified', handleDOMEvent); - context.addEventListener('DOMNodeInsertedIntoDocument', handleDOMEvent); - - context.addEventListener('DOMNodeInserted', - function(e) { - var eTagName = e.target.tagName; - if (eTagName == 'IFRAME' || eTagName == 'FRAME') { - e.target.onload = function() { - core.scheduleRules(); - registerDomListeners(e.target.contentDocument); - }; - } - }); - }; - - var registerBackendListeners = function(port) { - port.on('SetRules', function(payload) { - - var rules = payload.rules; - - core.rules = payload; - core.rules.rules = []; - - for(var i=0; i').attr('id', 'uic-dialog'); - - core.lockDepth = 0; - - core.lockMask = function() { - core.lockDepth = core.lockDepth + 1; - if(core.lockDepth == 1) { - core.port.emit('MaskRules', null); - } - }; - - core.unlockMask = function() { - core.lockDepth = core.lockDepth - 1; - if(core.lockDepth == 0) { - core.port.emit('UnmaskRules', null); - } - }; - - /** - * Due to the lack of a confirmation continuation with the port api, this - * function runs a continuation after 10ms of delivering the MaskRules - * message, then waits another 10ms before delivering the UnmaskRules - * message. The two delays seem to give a better chance that the - * continuation runs within the masked context. - */ - core.maskRules = function(body) { - core.lockMask(); - - setTimeout(function() { - body(); - setTimeout(function() { - core.unlockMask(); - }, 10); - }, 10); - }; - - core.highlightProblem = function(elt) { - core.maskRules(function() { - elt.css('background-color', 'rgba(255,0,0,0.3)') - .addClass('uic-problem'); - }); - }; - - core.maskProblem = function(elt) { - core.maskRules(function() { - elt.css('background-color', '') - .removeClass('uic-problem'); - }); - }; - - core.renderStats = function (stats) { - core.maskRules(function () { - var statsDiv, statsDetail; - statsDiv = $('#fiveui-stats'); - statsDiv.children().remove(); - statsDetail = $('' + - '' + - '
rules checked:' + stats.numRules + '
elements checked:' + stats.numElts + '
elapsed time (ms):' + (stats.end - stats.start) + '
'); - statsDiv.append(statsDetail); - }); - }; - - core.renderProblem = function(prob) { - core.maskRules(function() { - var probDiv = $('
'); - - - /** Problem Controls **/ - var prControls = $('
'); - probDiv.append(prControls); - - var prSeverity = $('
'); - prControls.append(prSeverity); - - if (1 == prob.severity) { - prSeverity.addClass('prSeverity-err'); - } else { - prSeverity.addClass('prSeverity-warn'); - } - - var prExpand = $('
'); - prControls.append(prExpand); - - /** Problem Content **/ - var prMessage = $('
'); - probDiv.append(prMessage); - - var prTitle = $('
'+prob.name+'
'); - prMessage.append(prTitle); - - var prDetails = $('
'); - prMessage.append(prDetails); - - var prDescr = $('

'+prob.descr+'

'); - prDetails.append(prDescr); - prDetails.hide(); - - $('#problemList').append(probDiv); - - prExpand.click( - function() { - var elt = $(this); - if(elt.is('.prExpand-down')) { - elt.removeClass('prExpand-down') - .addClass('prExpand-right'); - prDetails.hide(); - core.maskProblem(fiveui.query('.' + prob.hash)); - } else { - elt.addClass('prExpand-down') - .removeClass('prExpand-right'); - prDetails.show(); - core.highlightProblem(fiveui.query('.' + prob.hash)); - } - - return false; - }); - }); - }; - - var dragStop = function(evt,e) { - core.port.emit('Position', core.ui.parent().position()); - }; - - var resizeStop = function(evt,e) { - core.port.emit('Size', { width: core.ui.width(), height: core.ui.height() }); - }; - - var beforeClose = function(evt,e) { - core.port.emit('CloseUI'); - }; - - var registerBackendListeners = function(port) { - - port.on('ShowUI', function(unused) { - core.ui.dialog('open'); - }); - - - port.on('ShowProblem', function(problem) { - core.renderProblem(problem); - }); - - port.on('ShowStats', function(stats) { - core.renderStats(stats); - }); - - port.on('RestoreUI', function(state) { - core.ui.append($('
')); - - core.ui.append($('
')); - - var newDialog = core.ui.dialog({ title: 'FiveUI', - dragStop: dragStop, - resizeStop: resizeStop, - beforeClose: beforeClose, - position: [state.winState.x, state.winState.y], - width: state.winState.width, - height: state.winState.height, - autoOpen: false, - zIndex: 50000 - }); - newDialog.parent().attr('id', 'uic-top'); - - $('#controls').append($('
') - .button({ label: 'clear' })); - - $('#clearButton').click(function() { - $('#problemList').children().remove(); - port.emit('ClearProblems'); - core.renderStats(fiveui.stats.zero); - core.maskProblem(fiveui.query('.uic-problem')); - }); - - /////////////////////////////////////////// - // Add a button that causes a debuger break. - // - // handy for playing with Jquery on the dom. - // Note: This only works in Google Chrome. - $('#controls').append($('
') - .button({ label: 'break' })); - $('#breakButton').click(function() { - debugger; // - }); // - //////////////////////////////////////////// - - core.ui.append($('
')); - - if(!state.winState.closed) { - core.ui.dialog('open'); - } - - $(state.problems).each(function(ix,prob) { - core.renderProblem(prob); - }); - core.renderStats(state.stats); - }); - }; - - registerBackendListeners(core.port); -})(); diff --git a/contexts/data/fiveui/injected/injected.css b/contexts/data/fiveui/injected/injected.css deleted file mode 100644 index 2f50058..0000000 --- a/contexts/data/fiveui/injected/injected.css +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Module : injected/injected.css - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -.uic-problem { - background-color: rgba(255, 0, 0, 0.3); - border: 2px solid; - border-color: red; -} - -/* Reduce the JQuery UI spacing on the left of the dialog content. */ -#uic-dialog { - padding-left: 3px; - font-family: Courier; -} - -#uic-top { - font-family: Courier; -} - -.ui-dialog .ui-dialog-content { - /* overflow: hidden !important; */ - position: relative; -} - -#breakButton, #clearButton { - font-family: Courier; -} - -/* stats area style */ - -#fiveui-stats { - font-family: Courier; - font-size: 10px; - background-color: #F0F0F0; - border: 1px solid #DDDDDD; - border-style: groove; - padding: 3px; - height: auto; - width: 97%; - margin-top: 0.5em; - margin-bottom: 0.75em; -} - -.fiveui-table-number { - text-align: right; - color: blue; -} - -.fiveui-table-text { - text-align: left; - color: black; - padding-right: 3px; -} - -/* problem list style */ - -#problemList { - border-style: groove; - background: white; - - /* - position: absolute; - top: 95px; - bottom: 0px; - */ - - /* coarse estimate of width in most standard sizes */ - width: 97%; - - margin-top: 0.5em; - margin-bottom: 0.75em; - - overflow-y: scroll; -} - -.pr { - border-top: 1px solid #ddd; -} - -.pr:first-child { - border-top: 0px; -} - -.pr>.prControls { - float: left; - width: 2em; -} - -.pr>div.prControls>div { - padding: 0; - margin: 0; - width: 1em; - height: 1em; - float: left; - background-size: 1em 1em; - background-repeat:no-repeat; -} - -.prExpand { -} - -.prSeverity-err { - background-image: url(../images/errorCircle.png); -} - -.prSeverity-warn { - background-image: url(../images/warningTriangle.png); -} - -.prExpand-right { - background-image: url(../images/right-arrow.png); -} -.prExpand-down { - background-image: url(../images/down-arrow.png); -} - -.prMessage { - margin: 0; - margin-left: 2em; - padding: 0; -} - -.prTitle { - display: block; - margin: 0px; -} - -.prHead { - border-bottom: 1px solid #ccc; -} - -.prDetails { -} diff --git a/contexts/data/fiveui/injected/jquery-plugins.js b/contexts/data/fiveui/injected/jquery-plugins.js deleted file mode 100644 index 0f13c2a..0000000 --- a/contexts/data/fiveui/injected/jquery-plugins.js +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Module : injected/jquery-plugins.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -if (typeof goog != 'undefined') { - goog.provide('fiveui.jquery'); -} - -/** - * This module provides several useful jQuery plugins related to checking and reporting - * UI consistency issues. - * - * @namespace - */ -fiveui.jquery = fiveui.jquery || {}; - - -/** - * Wrapper for the :contains('text') selector - * - * @param {!String} text Text to select for - * @returns {!Object} A modified jQuery object - */ -fiveui.jquery.hasText = function (text) { - return this.filter(":contains('" + text + "')") -} - -/** - * Color checker plugin: filters for elements whose CSS color property is - * not in the given set. - * - * @description Note: This is a special case of fiveui.jquery.cssIsNot, i.e. - * $(..).notColorSet(set) == $(..).cssIsNot("color", set, fiveui.color.colorToHex) - * @see {fiveui.color.colorToHex} - * - * @param {String[]} cset A set of allowable color strings - * @returns {!Object} A modified jQuery object - */ -fiveui.jquery.notColorSet = function (cset) { - var allowable = {}; - for (var i = 0; i < cset.length; i += 1) { allowable[cset[i]] = true; } // array -> object - return this.filter(function (index) { - var color = fiveui.color.colorToHex($(this).css("color")); // .css("color") returns rgb(...) - return !(color in allowable); - }); -} - -/** - * General CSS propetry checker plugin - * - * @description This plugin filters for elements whose CSS property `prop` is not a member - * of the given array `cset`. The values checked are transformed using the - * optional given function `fn`. This may be used to normalize values that the - * browser returns so they can be compared to values in `cset`. - * - * @param {String} prop CSS property selector - * @param {String|String[]} set allowable values (either a string or an array of strings) - * @param {function(String):String} [fn] Function to apply to return values of $(this).css(prop), fn defaults to the identity function. - * @returns {Object} jQuery object - */ -fiveui.jquery.cssIsNot = function (prop, set, fn) { - var allowable = {}; - fn = fn || function (x) { return x; }; // default is Id - if (typeof set === "string") { - allowable[fn(set)] = true; - } - else { // assume `set` is an array of strings - for (var i = 0; i < set.length; i += 1) { allowable[fn(set[i])] = true; } // array -> object - } - return this.filter(function (index) { - var cssProp = fn($(this).css(prop)); - return !(cssProp in allowable); - }); -} - -/** - * Filter out elements that do not contain the attribute - * href=`href`. - * - * @param {String} href the href to look for - * @returns {Object} jQuery object - */ -fiveui.jquery.linksTo = function (href) { - return this.filter(function (index) { - var addr = $(this).attr("href"); - return (addr == href); - }); -} - -/** - * Visually highlight elements in the jQuery object. - * - * @description This plugin is useful mostly in the process of writing - * guidelines, for example the guideline developer can load a page, - * click the "Break" button on the FiveUI window, enter the browser's - * Javascript console, and run: - * - * @example > $5("p").hasText("foo").highlight(); - * - * @param {String} [hint] Highlighted border color, defaults to "red" - * @returns {!Object} A modified jQuery object - */ -fiveui.jquery.highlight = function (hint) { - hint = hint || "red"; // Default is "red" - return this.css("background-color", "rgba(255, 0, 0, 0.3)") - .css("border-style", "solid") - .css("border-color", hint); -} - -/** - * Returns a list of css properties that element in the jQuery - * object have. - * - * @description This plugin is useful for analysis of a given page when - * writing guielines. For example if the guideline developer wants to - * know what font sizes are used on a loaded page, they can run from the - * Javascript console: - * - * @example > $5("*").propDist("font-size", true); - * - * @param {String} prop CSS property to be inspected - * @param {boolean} [log] Boolean which enables console logging of the result; default is `false`. - * @returns {Object} A frequence map { "property": frequency } - */ -fiveui.jquery.propDist = function (prop, log) { - var res = {}; - log = log || false; - this.each(function (i, elt) { - var p = $(elt).css(prop); - if (p in res) { - res[p] += 1; - } - else { - res[p] = 1; - } - }); - if (log) { - console.log("Property distribution:"); - for (var p in res) { - console.log(" " + p + ": " + res[p]); - } - } - return res; -} - -/** - * Register the plugins. This adds methods to the jQuery.fn namespace. - */ -fiveui.jquery.init = function () { - for (fn in fiveui.jquery) { - f = fiveui.jquery[fn]; - if (jQuery.isFunction(f) && fn != "init") { - jQuery.fn[fn] = fiveui.jquery[fn]; - } - } -} -fiveui.jquery.init(); diff --git a/contexts/data/fiveui/injected/prelude.js b/contexts/data/fiveui/injected/prelude.js deleted file mode 100644 index 3f3b4f5..0000000 --- a/contexts/data/fiveui/injected/prelude.js +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Module : injected/prelude.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * The FiveUI Prelude. - * - * @description - * The prelude provides a collection of utilities to ease the - * conversion from human-readable guideline documents (such as the Web - * Accessibilty Guidelines, or Apple Human Interface Guidelines) to - * executable Rules. - * - * @namespace - */ -var fiveui = fiveui || {}; - -(function() { - -/** - * A global namespace for statistics collection. - * - * @namespace - */ -fiveui.stats = fiveui.stats || {}; -/** @global */ -fiveui.stats.numElts = 0; -/** @const */ -fiveui.stats.zero = { numRules: 0, start: 0, end: 0, numElts: 0 }; - -/** DOM Traversal ************************************************************/ - -/** - * fiveui.query is a wrapper around the jQuery $() function. - * - * @description - * fiveui.query recurses into iframes and frames, whereas $(...) stops - * when it encounters internal frames. - * - * Generally, rules written for FiveUI will want to cover the entire - * visible page, and as such, should use fiveui.query; however, $(...) - * is available if recursing into frames is not necessary. - * - * @param {String} sel The jQuery selector string. - * @param {Object} [context] The context to run the query within. This is often a DOM object/tree. - * @returns {Object} A jQuery object, suitable for chaining. - */ -fiveui.query = function (sel, context) { - var ctx = context || document; - var $results = jQuery(sel, ctx); - - jQuery('iframe, frame', ctx).each( - function(idx, elt) { - var $tempResults; - if (elt.contentDocument) { - try { - $tempResults = fiveui.query(sel, elt.contentDocument); - } catch (e) { - console.log("encoutered a non-cooperative iframe/frame at " + $(elt).attr("src")); - console.log(e.toString()); - $tempResults = []; - } - - $results = $results.add($tempResults); - } - } - ); - - $filteredResults = $results.not('#uic-top *') - .not('#uic-top') - .filter(':visible'); - - // update global stats - fiveui.stats.numElts += $filteredResults.length; - - return $filteredResults; -}; - -/** - * Provide a short alias for fiveui.query along the lines of the jQuery $ alias. - * - * @example $5("p").hasText("foo") -> jQuery object containing paragraph elements - * containing the text "foo" - *

- * - * @const - * - */ -var $5 = fiveui.query; - -/** Utilities ****************************************************************/ - -/** - * Determine if a given value is a string or not. - * - * @param {*} [o] A value of some type that may or may not be defined. - * @returns {!boolean} true if the object is a defined, non-null string, false - * otherwise. - */ -fiveui.isString = function(o) { - return typeof o == 'string'; -}; - - -/** - * String-specific utilities. - * - * @namespace - */ -fiveui.string = {}; - -/** - * Non-destructively removes whitespace from the start and end of a - * string. - * - * @param {String} [s] The string to trim of whitespace. - * @returns {String} The input string, without leading or trailing - * whitespace. Returns null if you gave it null. - */ -fiveui.string.trim = function(s) { - if (s) { - return s.replace(/^\s+|\s+$/g,""); - } - return s; -}; - -/** - * Tokenize a string on whitespace. - * - * @param {!String} s The string to tokenize. - * @returns {String[]>} An array of substrings. - */ -fiveui.string.tokens = function (s) { - var posLength = function(ar) { - return 1 <= ar.length; - }; - - return s.split(/\s/).filter(posLength); -}; - - -/** - * A simple heuristic check to see if a string is in Title Case. - * - * @description - * This does not perform an exhaustive gramatical analysis, and as - * such, it is prone to generating false-positives in some cases. In - * particular, it only has a short 'white list' of articles, - * conjections, and prepositions that are allowed to be in lower case. - * - * @param {!String} str The string to check. - * @returns {!boolean} true if the string is in title case, false if - * it is not. - */ -fiveui.string.isTitleCase = function(str) { - var exception = function(str) { - var exceptions = [ 'a', 'an', 'the' // articles - , 'and', 'but', 'for', 'not', 'or' // conjuctions - , 'in', 'on' // short prepositions - , 'to' ]; - return exceptions.indexOf(str.toLowerCase()) != -1; - }; - - if ( !fiveui.word.capitalized(str[0]) ) { - return false; - } - - var tokens = fiveui.string.tokens(str); - for (var i=1; i < tokens.length; ++i) { - if (!exception(tokens[i]) && !fiveui.word.capitalized(tokens[i])) { - return false; - } - } - return true; -}; - -/** - * Utilities for word-specific processing. - * - * @description The fiveui.word namespace focuses on tools for working directly - * with words in the sense of natural languages, rather than general - * strings (as is the case for the fiveui.string namespace). - * - * @namespace - */ -fiveui.word = {}; - -/** - * Check to see if a sting begins with a capital letter. - * - * @param {!String} word The string to check for capitalization. - * @returns {!boolean} - */ -fiveui.word.capitalized = function(word) { - return fiveui.isString(word) && word.search(/^[A-Z]/, word) >= 0; -}; - -/** - * Check to see if a sting consists entirely of capital letters. - * - * @param {!String} word The string to check for capitalization. - * @returns {!boolean} - */ -fiveui.word.allCaps = function(word) { - return fiveui.isString(word) - && word.search(/^\w/, word) >= 0 - && (word == word.toUpperCase()); -}; - - -/** - * Utilities for dealing with color. - * - * @namespace - */ -fiveui.color = {}; - -/** - * Color check compiler. It is recommended to use the jQuery plugin - * fiveui.jquery.cssIsNot instead. - * - * @param {!String} selector The HTML element selector to check. - * @param {String[]} colorSet An array of strings containing the HEX values of - * colors in the desired color set. - * @returns {!function()} A function which checks the rule - * @see fiveui.jquery.cssIsNot - */ -fiveui.color.colorCheck = function (selector, colorSet) { - var allowable, i, fnStr, forEachFuncStr; - allowable = {}; - for (i = 0; i < colorSet.length; i += 1) { allowable[colorSet[i]] = true; } - forEachFuncStr = 'function (j, elt) {\n' - + ' var allowable = ' + JSON.stringify(allowable) + ';\n' - + ' var color = fiveui.color.colorToHex($(elt).css("color"));\n' - + ' if (!(color in allowable)) {\n' - + ' report("Disallowed color " + color + " in element matching " + ' + JSON.stringify(selector) + ', $(elt));\n' - + ' }\n' - + '}\n'; - fnStr = 'function () { fiveui.query("' + selector + '").each(' + forEachFuncStr + '); }'; - return eval('false||'+fnStr); // the `false||` trick is required for eval to parse a - // function expression ?!? -}; - -/** - * Covert rgb colors to hex and abreviated hex colors to their full 3 byte - * form. - * - * In case there are parse errors during the conversion, i.e. color values - * that are not understood, the input is returned unchanged. - * - * @param {!String} color The color string to convert. This should be either of the form rgb(...) or #... - * @returns {!String} The color string in #XXXXXX form - * @throws {ParseError} if the rgb color string cannot be parsed - */ -fiveui.color.colorToHex = function(color) { - var have, need; - if (color.substr(0, 1) === '#') { - if (color.length === 7) { - return color; - } - else { // deal with #0 or #F7 cases - var have = color.length - 1; - var haveDigits = color.substr(1, color.length); - var need = 6 - have; - var reps = Math.ceil(need / have); - var i, strColor; - for (i = 0, stdColor = color; i < reps; i += 1) { stdColor += haveDigits; } - return stdColor.substr(0, 7); - } - } - - var digits = /rgba?\((\d+), (\d+), (\d+)/.exec(color); - if (!digits) { - return color; // in case there is a parse error, we just - // return the input unchanged - } - - var red = parseInt(digits[1]); - var green = parseInt(digits[2]); - var blue = parseInt(digits[3]); - - var rgb = blue | (green << 8) | (red << 16); - if (rgb === 0) { - return '#000000'; // normalized form - } - else { - return '#' + rgb.toString(16).toUpperCase(); - } -}; - - -/** - * Utilities for dealing with fonts. - * - * @namespace - */ -fiveui.font = {}; - -/** - * Extracts the font-family, font-size (in px, as an int), and font-weight - * from a jQuery object. - * - * @param {!Object} jElt A jQuery object to extract font info from - * @returns {!Object} An object with properties: 'family', 'size', and 'weight' - * @throws {ParseError} if the font size cannot be parsed - */ -fiveui.font.getFont = function (jElt) { - var res = {}; - var size = jElt.css('font-size'); - if(size.length > 0) { - var psize = /(\d+)/.exec(size); - if(!psize) { - throw { - name: 'ParseError', - message: 'Could not parse font size: ' + jElt.css('font-size') - }; - } - else { - res.size = psize - } - } else { - res.size = ''; - } - res.family = jElt.css('font-family'); - res.weight = jElt.css('font-weight').toString(); - // normalize reporting of the following two synonyms - if (res.weight === '400') { res.weight = 'normal'; } - if (res.weight === '700') { res.weight = 'bold'; } - return res; -}; - -/** - * Validate a font property object extracted using fiveui.font.getFont(). - * - * @description The `allow` parameter should be an object whose top level properties are - * (partial) font family names (e.g. 'Verdana'). For each font family name - * there should be an object whose properties are font weights (e.g. 'bold'), - * and for each font weight there should be an array of allowable sizes - * (e.g. [10, 11, 12]). - * - * The `font` parameter should be an object containing 'family', 'weight', and - * 'size' properties. These are returned by @see fiveui.font.getFont(). - * - * @example > allow = { 'Verdana': { 'bold': [10, 12], 'normal': [10, 12]}}; - * > font = { family: 'Verdana Arial sans-serif', size: "10", weight: "normal" }; - * > fiveui.font.validate(allow, font) -> true - * - * @param {!Object} allow Object containing allowable font sets (see description and examples) - * @param {!Object} font object to check - * @param font.family A partial font family name (e.g. 'Verdana') - * @param font.weight A font weight (e.g. 'bold') - * @param font.size A font size string (e.g. "10") - * @returns {!boolean} - */ -fiveui.font.validate = function (allow, font) { - var x; - for (x in allow) { // loop over allowed font family keywords - if (font.family.indexOf(x) !== -1) { break; } - else { return false; } - } - return (font.weight in allow[x] && allow[x][font.weight].indexOf(parseInt(font.size)) != -1); -}; - -/** - * Functions outside the fiveui namespace that can be called during rule - * evaluation. - */ - -/** - *

Report a problem to FiveUI.

- * - * @description - *

report is used to indicate that a guideline has been violated. - * Invocations should provide a short (1-line) string description of - * the problem, as well as a reference to the element of the DOM that - * violated the guideline.

- * - *

The second parameter is not strictly required, but we strongly - * suggest providing a node if at all possible, as that is used to - * visually highlight the problematic areas of the DOM at runtime. - * Debugging a guideline violation becomes much more difficult without - * the visual indicator.

- * - * @function - * @param {!String} desc The description of the problem to report. - * @param {?Node} node The node in the DOM that caused the problem. - * @name report - */ - -/** - * JSON.stringify is included here for extension and ruleset debugging - * purposes. It is used by the jQuery pluggin jQuery.fn.log. - */ -var JSON = JSON || {}; -JSON.stringify = JSON.stringify || function (obj) { - var t = typeof (obj); - if (t != "object" || obj === null) { - // simple data type - if (t == "string") obj = '"'+obj+'"'; - return String(obj); - } - else { - // recurse array or object - var n, v, json = [], arr = (obj && obj.constructor == Array); - for (n in obj) { - v = obj[n]; t = typeof(v); - if (t == "string") v = '"'+v+'"'; - else if (t == "object" && v !== null) v = JSON.stringify(v); - json.push((arr ? "" : '"' + n + '":') + String(v)); - } - return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}"); - } -}; - -})(); diff --git a/contexts/data/fiveui/messenger.js b/contexts/data/fiveui/messenger.js deleted file mode 100644 index fc1962c..0000000 --- a/contexts/data/fiveui/messenger.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Module : messenger.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -/** - * @constructor - * @param {{on: function(!string, function(*)), emit: function(!string, *)}} - * channel The object containing on and emit. - */ -fiveui.Messenger = function(channel) { - this.callbacks = {}; - this.handlers = {}; - - this.channel = channel; - this.channel.on(fiveui.Messenger.type, _.bind(this._handler, this)); -}; - -fiveui.Messenger.type = "fiveui_messaging_type"; - -_.extend(fiveui.Messenger.prototype, { - - /** - * @param {!string} type The message type to send. - * @param {?Object} data The payload (which can be null). - * @param {?function(?Object)} callback An optional callback to be - * invoked in response. - */ - send: function(type, data, callback){ - var id = null; - if (callback) { - id = this._newId(); - this.callbacks[id] = callback; - } - - var payload = new fiveui.Messenger.Payload(false, type, data, id); - this.channel.emit(fiveui.Messenger.type, payload); - }, - - /** - * Register a handler for the specified message type. - * - * @param {!string} type The message type. - * @param {!function(*)} callback The function to call when a message - * of the specified type is received. - */ - register: function(type, callback) { - if(null == this.handlers[type]) { - this.handlers[type] = []; - } - this.handlers[type].push(callback); - }, - - _handler: function(payload) { - if (payload.isCallback && payload.id != null) { - // this is a callback invocation, lookup the callback and invoke it: - this.callbacks[payload.id](payload.data); - - // remove the callback: - this._remove(payload.id); - } else { - // look up a handler and invoke it, passing in the response fn: - var hs = this.handlers[payload.type]; - if (hs && hs.length > 0) { - - // this is a new incomming message. - // create a response function: - var respond = function(respData) { - this.channel.emit(fiveui.Messenger.type, - new fiveui.Messenger.Payload(true, payload.type, respData, payload.id)); - }; - - // iterate over the handlers, invoking them with the response callback. - _.each(hs, function(h) { - h(payload.data, _.bind(respond, this)); - }, this); - } - } - }, - - /** - * Remove a callback from the map of callbacks. - * - * @param {!number} callbackId The id of the callback to remove. - */ - _remove: function(callbackId) { - delete this.callbacks[callbackId]; - }, - - /** - * @return {!number} The next unique id for a callback. - */ - _newId: function() { - var list = Object.keys(this.callbacks); - return fiveui.utils.getNewId(list); - } - -}); - -/** - * @constructor - * @param {!boolean} isCallback True if this is in response to a - * message, false if this is requesting a callback. - * @param {!string} type - * @param {?Object} data - * @param {!number} id Callback id to invoke, or in which this is a response. - */ -fiveui.Messenger.Payload = function(isCallback, type, data, id) { - this.isCallback = isCallback; - this.type = type; - this.id = id; - this.__defineGetter__('data', function() { - return JSON.parse(this.rawData); - }); - this.__defineSetter__('data', function(obj){ - this.rawData = JSON.stringify(obj); - }); - this.data = data; -}; - -})(); diff --git a/contexts/data/fiveui/options.css b/contexts/data/fiveui/options.css deleted file mode 100644 index efe7d05..0000000 --- a/contexts/data/fiveui/options.css +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Module : options.css - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -html body, body { - font-family: Arial, sans-serif; - margin: 0; - padding: 0; -} - -#content { - float: left; -} - -div#icon { - float: right; - opacity: 0.25; - background-image: url(images/fiveui-icon-128.png); - background-repeat: no-repeat; - background-position-x: 16px; - background-position: 0px 16px; - width: 128px; - height: 160px; - margin: 0; - padding: 0; - z-index: -1; -} - -#navbar-container { - background: -linear-gradient(left, #EAEEF3, #EAEEF3 97%, #D3D7DB); - background: -moz-linear-gradient(left, #EAEEF3, #EAEEF3 97%, #D3D7DB); - background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #EAEEF3), -webkit-linear-gradient(left, #EAEEF3, #EAEEF3 97%, #D3D7DB); - position: absolute; - top: 0px; - left: 0px; - bottom: 0px; - width: 20%; - float: left; -} - -#navbar-container>nav>div { - cursor: pointer; - border: 0px; -} - -#navbar-content-title { - font-size: 200%; - font-weight: normal; - color: #53637D; - padding-right: 1em; - padding-bottom: 0.5em; - text-align: end; - text-shadow: white 0 1px 2px; -} - -nav { - text-align: right; -} - -nav div { - padding-right: 0.5em; - color: #426DC9; - font-size: 14px; - height: 16px; - padding-bottom: 7px; - padding-left: 0px; - padding-right: 24px; - padding-top: 7px; - text-align: end; - text-shadow: white 0px 1px 1px; -} - -nav .selected { - background: -linear-gradient(left, #BBCEE9, #BBCEE9 97%, #AABEDC); - background: -moz-linear-gradient(left, #BBCEE9, #BBCEE9 97%, #AABEDC); - background: -webkit-linear-gradient(left, #BBCEE9, #BBCEE9 97%, #AABEDC); - border-bottom: 1px solid #8FAAD9; - border-top: 1px solid #8FAAD9; - color: black; - text-shadow: #BBCEE9 0 1px 1px; -} - -#content>section .selected { -} - -#content>section { - position: absolute; - left: 20%; - width: 50em; - margin-left: 2em; -} - -#content > section > section > h3 { - display: table-cell; - width: 130px; - padding-right: 10px; - padding-top: 17px; -} - -#content > section > section > h3 + div { - padding-bottom: 20px; - display: table-cell; -} - -div.title { - font-size: 200%; - border-bottom: 1px solid #EEEEEE; -} - -.displayList { - float: left; - width: 50%; -} - -#upDownGroup button { - display: block -} - -#upDownGroup { - margin-top: auto; - margin-bottom: auto; - float: left; -} - -.buttons { - display: inline; -} diff --git a/contexts/data/fiveui/options.html b/contexts/data/fiveui/options.html deleted file mode 100644 index 8994a69..0000000 --- a/contexts/data/fiveui/options.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - Five UI - - - - - - - - - - - - -
- - - -
-
-
URL Patterns
-
-
    -
    - -
    -
    -
    - -
    -
    Rule Sets
    -
    -
      -
      - -
      -
      -
      - -
      -
      Basics
      -
      -

      Window

      -
      -
      - -
      -
      -
      -
      -
      - - - diff --git a/contexts/data/fiveui/options.js b/contexts/data/fiveui/options.js deleted file mode 100644 index 2b29f8d..0000000 --- a/contexts/data/fiveui/options.js +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Module : options.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - - -/***************************************************************** - * - * Misc. utility functions - * - ****************************************************************/ - -var setClickHandler = function(sel, fn, scope) { - var boundFn = fn; - if (scope) { - boundFn = _.bind(fn, scope); - } - - sel.on('click', boundFn) -}; - -/** - * @param {!string} selectEltId The id of the select element to - * search for selected items. - * @return {!Array.} An array of 'value' entries from the - * selected elements. This may be empty, but it will not be null. - */ -var findSelectedIds = function(elt) { - var opts = elt.find('option:checked'); - return _.map(opts, function(o) { return o.value; }); -}; - - -fiveui.options = fiveui.options || {}; - -/** - * @param {{on: function(!string, function(*)), emit: function(!string, *)}} port - */ -fiveui.options.init = function(port) { - - var msg = new fiveui.Messenger(port); - var update = new fiveui.UpdateManager(msg); - - ruleSets = new fiveui.RuleSets([], { url: msg }); - urlPats = new fiveui.UrlPats([], { url: msg }); - - - /** UrlPat list entries ****************************************************/ - - var urlPatEntries = jQuery('#urlPatEntries'); - var addUrlPat = jQuery('#addUrlPat'); - - addUrlPat.prop('disabled', true); - - addUrlPat.on('click', function() { - urlPats.add(new fiveui.UrlPatModel({}, { url : msg })); - }); - - // when a new rule set is sync'd, make sure that the add url pattern button is - // enabled. - ruleSets.on('sync', function() { - if(ruleSets.length > 0) { - addUrlPat.prop('disabled', false); - } - }); - - // when a rule set is destroyed, and the collection is now empty, disable the - // add url pattern button. - ruleSets.on('destroy', function(model,col) { - if(col.length <= 0) { - addUrlPat.prop('disabled', true); - } - }); - - // handle new url patterns being added to the collection. - urlPats.on('add', function(model) { - var view = new fiveui.UrlPatEntry({ - model: model, - rules: new fiveui.RulesView({ model: ruleSets }) - }); - urlPatEntries.append(view.$el); - - if(model.isNew()) { - view.edit(); - } else { - view.render(); - } - }); - - - /** RuleSet list entries ***************************************************/ - - var ruleSetEntries = jQuery('#ruleSetEntries'); - - // handle clicks to the 'add' button on the rule sets page - jQuery('#addRsButton').on('click', function() { - ruleSets.add(new fiveui.RuleSetModel({}, { url : msg })); - }); - - // render a ruleset added to the collection - ruleSets.on('add', function(model) { - var entry = new fiveui.RuleSetEntry({ model: model }) - ruleSetEntries.append(entry.$el); - - if(model.isNew()) { - entry.edit(); - } else { - addUrlPat.prop('disabled', false); - entry.render(); - } - }); - - - /** Basics *****************************************************************/ - - var windowDisplayDefault = jQuery('#windowDisplayDefault'); - - windowDisplayDefault.on('change', function() { - msg.send('setDisplayDefault', windowDisplayDefault.prop('checked')) - }); - - - /** Tab Management *********************************************************/ - - /** - * Select a tab header by Element reference. - * - * @param {!Element} clicked The navigation element to focus. - * @return {void} - */ - var selectNav = function(clicked) { - var nav = clicked.parent(); - - nav.find('div.selected', nav).removeClass('selected'); - - jQuery('div.editorPane').hide(); - - clicked.addClass('selected'); - }; - - /** - * Focus a tab, by Element reference. - * - * @param {!Element} el The tab element to focus. - * @return {void} - */ - var selectSection = function(el) { - var cont = el.parent(); - - // hide all sections - cont.find('>section').removeClass('selected').hide(); - - // display this section - el.addClass('selected').show(); - }; - - /** - * A combination of selectNav and selectSection that will first lookup the - * elements associated with a tab, then return a new function that when - * called, will focus both the navigation element, and the tab it controls. - * - * @param {!string} id The id of the tab to focus. - * @return {function()} - */ - var select = function(id) { - var sel = jQuery(id); - return function() { - selectNav(jQuery(this)); - selectSection(sel); - }; - }; - - // listen to click events on navigation elements - setClickHandler(jQuery('#url-defaults'), select('#tab-url-defaults')); - setClickHandler(jQuery('#rule-sets'), select('#tab-rule-sets')); - setClickHandler(jQuery('#basics'), select('#tab-basics')); - - // select the url patterns tab by default - selectNav(jQuery('#url-defaults')); - selectSection(jQuery('#tab-url-defaults')); - - - /** Pre-populate UI elements ***********************************************/ - - msg.send('getDisplayDefault', null, function(def) { - jQuery('#windowDisplayDefault').prop('checked', def); - }); - - // pre-populate the rule set and url pattern lists - ruleSets.fetch({ - success:function() { - urlPats.fetch(); - } - }); -}; - -})(); diff --git a/contexts/data/fiveui/rules.js b/contexts/data/fiveui/rules.js deleted file mode 100644 index 68d821d..0000000 --- a/contexts/data/fiveui/rules.js +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Module : rules.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -/** - * @constructor - * @param {!string} module A Javascript module that defines the rule. - */ -fiveui.Rule = function(module) { - this.module = module; -}; - -fiveui.Rule.defaults = function(obj) { - return _.defaults(obj, { - module: '', - }); -}; - -/** - * Create a Rule from a JSON object. - * - * @param {!Object} obj The object to take settings from. - * @return {!fiveui.Rule} A populated Rule object. - */ -fiveui.Rule.fromJSON = function(obj) { - return new fiveui.Rule(obj.module); -}; - -/** - * @constructor - * @param {!number} id The unique RuleSet identifier. - * @param {!string} name A human-readable name for this RuleSet. - * @param {!string} desc A human-readable description of the Rule Set. - * @param {!string} source The url where the manifest can be retrieved - * @param {!Array.} rules An Array of Rules. - * @param {?Array.} deps Dependencies that this RuleSet requires. - */ -fiveui.RuleSet = function(id, name, desc, source, rules, deps) { - this.id = id; - this.name = name; - this.description = desc; - this.source = source; - this.rules = rules || []; - this.dependencies = deps || []; -}; - -/** - * Create a Rule Setfrom a JSON object. - * - * @param {!number} id A unique id for the rehydrated Rule. - * @param {!Object} obj The object to take settings from. - * @return {!fiveui.RuleSet} A populated RuleSet object. - */ -fiveui.RuleSet.fromJSON = function(id, obj) { - var rules = (/** @type {!Array.} */ - _.map(obj.rules, fiveui.Rule.fromJSON)); - - return new fiveui.RuleSet(id, obj.name, obj.description, obj.source, - rules, obj.dependencies); -}; - - -fiveui.RuleSet.defaults = function(obj) { - return _.defaults(obj, { - name: '', - description: '', - rules: [], - dependencies: [] - }); -}; - - -/** - * Options is an object that can contain a success and error continuation. - */ -fiveui.RuleSet.load = function(manifest_url, options) { - - _.defaults(options, { - success: function() {}, - error: function() { throw "failed when loading url"; } - }); - - var match = manifest_url.match(/\/[^\/]*$/); - - if(match) { - var base_url = manifest_url.substring(0,match.index); - - // iterate over rules, retrieving the - var loadRules = function(manifest, rules) { - - if(rules.length == 0) { - options.success(manifest); - } else { - - // XXX there's likely problems here, how should we make sure that the - // url is what we expect? - var rule_file = fiveui.Rule.defaults(rules.pop()); - var rule_url = base_url + '/' + rule_file; - - fiveui.ajax.get(rule_url, { - - success: function(text) { - manifest.rules.push(new fiveui.Rule(text)); - loadRules(manifest, rules); - }, - - error: options.error - }); - - } - }; - - // fetch the manifest, and load its rules - fiveui.ajax.get(manifest_url, { - - success: function(text) { - try { - var manifest = JSON.parse(fiveui.utils.filterJSON(text,'json')); - - } catch(e) { - // XXX incoming error continuation is empty - // (and we may have syntax error details in e) - options.error(); - return; - } - - fiveui.RuleSet.defaults(manifest); - - var rules = manifest.rules; - manifest.rules = []; - loadRules(manifest, rules); - }, - - error: options.error, - }); - - - } else { - options.error("unable to parse manifest url"); - } - -}; - - -/******************************************************************************* - * Models for RuleSet - ******************************************************************************/ - -/** - * The model for an single set of rules. - */ -fiveui.RuleSetModel = Backbone.Model.extend({ - - defaults: { - id: null, - name: '', - description: '', - source: '', - rules: [], - dependencies: [], - }, - - sync: function(method, model, options) { - - _.defaults(options, { - success:function() {}, - error: function() {} - }); - - var msg = this.url; - var id = model.get('id'); - var source = model.get('source'); - - switch(method) { - - case 'update': - case 'create': - var rsMethod = method == 'update' ? 'updateRuleSet' : 'addRuleSet'; - - msg.send('loadRuleSet', source, function(obj) { - if(obj) { - obj.id = id; - obj.source = source; - - msg.send(rsMethod, obj, options.success); - } else { - options.error('failed to load manifest'); - } - }); - break; - - case 'delete': - msg.send('remRuleSet', id, function(obj) { - if(obj.removed) { - options.success(); - } else { - options.error(); - } - }); - break; - - case 'read': - msg.send('getRuleSet', id, function(rs) { - model.set({ - title: rs.name, - descr: rs.description, - source: rs.source, - }); - }); - break; - - default: - break; - } - } - -}, { - - /** - * Generate a RuleSetModel from a RuleSet - */ - fromRuleSet: function(ruleSet,msg) { - return new fiveui.RuleSetModel({ - id: ruleSet.id, - name: ruleSet.name, - description: ruleSet.description, - rules: ruleSet.rules, - dependencies:ruleSet.dependencies, - source: ruleSet.source, - }, { url : msg }); - }, - -}); - - -/** - * The model for a collection of rule sets - */ -fiveui.RuleSets = Backbone.Collection.extend({ - - model: fiveui.RuleSetModel, - - sync: function(method, collection, options) { - _.defaults(options, { - success:function() {}, - error:function() {} - }); - - var self = this; - var msg = this.url; - - switch(method) { - - case 'read': - msg.send('getRuleSets', null, function(ruleSets) { - options.success(_.map(ruleSets, function(rs) { - return fiveui.RuleSetModel.fromRuleSet(rs, msg); - })); - }); - break; - - } - } - -}); - - -})(); diff --git a/contexts/data/fiveui/selenium/selenium-injected-compute.js b/contexts/data/fiveui/selenium/selenium-injected-compute.js deleted file mode 100644 index d0327b3..0000000 --- a/contexts/data/fiveui/selenium/selenium-injected-compute.js +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Module : selenium/selenium-injected-compute.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Not Portable (Selenium-specific) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Init FiveUI, if necessary: -if (typeof fiveui == 'undefined') { - fiveui = {}; -} - -/** - * @return {{on: function(!string, function(*)), emit: function(!string, *)}} - */ -var obtainComputePort = function() { - fiveui.selPort = new fiveui.SeleniumPort(); - return fiveui.selPort; -}; - -/** - * @constructor - */ -fiveui.SeleniumPort = function() { - this._events = {}; - this._messages = []; -}; - -/** - * Listen to incoming messages. - * - * @param {!string} evt The event to listen for. - * @param {!function(*)} cb The callback to invoke. - * @return {void} - */ -fiveui.SeleniumPort.prototype.on = function(evt, cb) { - this._events[evt] = cb; -}; - -/** - * Send a message to the background. - * - * @param {!string} evt The event to fire. - * @param {?Object} obj The data to associate with the event. - * @return {void} - */ -fiveui.SeleniumPort.prototype.emit = function(evt, obj) { - this._messages.push({ type: evt, payload: obj }); -}; - -/** - * Send a message to the injected script. - * - * @param {!string} evt The event to fire. - * @param {?Object} obj The data to associate with the event. - */ -fiveui.SeleniumPort.prototype.send = function(evt, obj) { - if (this._events[evt]) { - this._events[evt](obj); - } -}; - -/** - * Check to see if any messages have been generated. - * - * @param {[String]} type Message type to filter for (default: no filter) - * @return {!Array.<{string, Object}>} - */ -fiveui.SeleniumPort.prototype.query = function (type) { - var msgs = []; - var i; - - if (!type) { - msgs = this._messages; - } - else { - for (i=0; i < this._messages.length; i += 1) { - console.log(this._messages); - if (this._messages[i].type === type) { - msgs.push(this._messages[i]); - } - } - } - - // flush the read messages: - this._messages = []; - - // return the new messages to the backend: - return msgs; -}; diff --git a/contexts/data/fiveui/set.js b/contexts/data/fiveui/set.js deleted file mode 100644 index 7015a3e..0000000 --- a/contexts/data/fiveui/set.js +++ /dev/null @@ -1,58 +0,0 @@ - - -(function() { - -Set = function() { - this.elems = {}; -}; - -_.extend(Set.prototype, { - - add: function(obj) { - var hash = this._getHash(obj); - if(this.elems[hash] == undefined) { - this.elems[hash] = obj; - } - }, - - remove: function(obj) { - var hash = this._getHash(obj); - if(this.elems[hash]) { - delete this.elems[hash]; - } - }, - - member: function(obj) { - var hash = this._getHash(obj); - return !!this.elems[hash]; - }, - - contains: function(obj) { - return this.member(obj); - }, - - size: function () { - return _.size(this.elems); - }, - - isEmpty: function() { - return this.size() == 0; - }, - - each: function(k, cxt) { - _.each(this.elems, k, cxt); - }, - - _getHash: function(obj) { - var str = obj.toString(); - - // the same hash function that java uses for String.hashCode - return _.reduce(str, function(hash, c) { - hash = ((hash << 5) - hash) + c.charCodeAt(); - return hash & hash; - }, 0); - } - -}); - -})(); diff --git a/contexts/data/fiveui/settings.js b/contexts/data/fiveui/settings.js deleted file mode 100644 index c284db8..0000000 --- a/contexts/data/fiveui/settings.js +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Module : settings.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -/** - * Create a new instance of the Settings object - * - * @constructor - * @param {!Storage} store The Storage instance to use. - */ -fiveui.Settings = function(store) { - this.store = store; -}; - -_.extend(fiveui.Settings.prototype, { - - /** - * Retrieve an object associated with the key. - * - * @param {!string} key The key to look up. - * @return {?Object} The returned JavaScript object. - */ - get: function(key) { - var value = this.store.getItem(key); - if (value == null) { - return null; - } else { - return JSON.parse(value); - } - }, - - /** - * Store an object with the given key. - * - * @param {string} key the key. - * @param {Object} value the value. - * @return {void} - */ - set: function(key, value) { - this.store.setItem(key, JSON.stringify(value)); - }, - - /** - * @param {string} key The local storage entry to remove. - * @return {void} - */ - remove: function(key) { - this.store.removeItem(key); - }, - - /** - * Set the display default. - * - * @param {!boolean} def Whether or not to display the FiveUI Window - * when problems are reported. - */ - setDisplayDefault: function(def) { - this.set('displayDefault', def); - }, - - /** - * Get the display default. - * - * @return {!boolean} true to show the window as soon as problems are - * reported, false otherwise. - */ - getDisplayDefault: function() { - var def = this.get('displayDefault'); - - // double negation to normalize funny things like null - return !!def; - }, - - /** - * Add a mapping from url patterns to RuleSets (via rule set ids) - * - * @param {!string} url_pat A regular expression (actually, a glob) to match URLs against. - * @param {!number} rule_id The id of the RuleSet to use with any matching URL. - * @return {!number} The id of the new url pattern. - */ - addUrl: function(url_pat, rule_id) { - var pats = this.getUrls(); - - var new_id = fiveui.utils.getNewId(pats); - - this.updateUrl(new_id, url_pat, rule_id); - - // add it to the patterns list - pats.push(new_id); - this.set('urls', pats); - - return new_id; - }, - - updateUrl: function(id, url_pat, rule_id) { - this.set('urls.' + id, new fiveui.UrlPat(id, url_pat, rule_id)); - return id; - }, - - /** - * Retrieve the list of url patterns. - * - * @return {Array.} An ordered list of the currently active - * url patterns. - */ - getUrls: function() { - return (/** @type {Array.} */ this.get('urls')) || []; - }, - - /** - * Retrieve a specific url pattern. - * - * @param {!number} url_id The id of the url pattern to retrieve. - * @return {?fiveui.UrlPat} The matching UrlPat or null, - * if no pattern exists for url_id. - */ - getUrlPat: function(url_id) { - return /** @type {?fiveui.UrlPat} */ this.getById(url_id, 'urls', fiveui.UrlPat.fromJSON); - }, - - /** - * Remove a UrlPat from the persistent storage. - * - * @param {!number} pat_id The id of the UrlPat to remove. - * @return {void} - */ - remUrlPat: function(pat_id) { - this.remById(pat_id, 'urls'); - }, - - /** - * @param {!string} url A url to compare against the list of ordered - * url patterns in local storage. - * @return {?fiveui.UrlPat} The matching pattern, or null, if no - * mapping was found. - */ - checkUrl: function(url) { - var pats = this.getUrls(); - - // check for a possible match - for (var i = 0; i < pats.length; ++i) { - var pat = this.getUrlPat(pats[i]); - if (pat.match(url)) { - return pat; - } - } - - return null; - }, - - /** - * Retrieve the list of rule sets. - * - * @return {!Array.} An ordered list of the configured rule sets. - */ - getRuleSets: function() { - return (/** @type {!Array.} */ this.get('ruleSet')) || []; - }, - - - /** - * @param {!Object} ruleSet The new rule set, as an anonymous JSON object. - * @return {!fiveui.RuleSet} The new RuleSet object. - */ - addRuleSet: function(ruleSet) { - var ids = this.getRuleSets(); - var id = fiveui.utils.getNewId(ids); - - var newRS = this.updateRuleSet(id, ruleSet); - ids.push(id); - this.set('ruleSet', ids); - - return newRS; - }, - - /** - * Change a rule set without generating a new id. - * - * @param {!number} ruleSetId The id of the ruleset that is being modified. - * @param {!Object} ruleSet The rule set, as an anonymous JSON object. - * @return {!fiveui.RuleSet} The new RuleSet object. - */ - updateRuleSet: function(ruleSetId, ruleSet) { - var newRS = fiveui.RuleSet.fromJSON(ruleSetId, ruleSet); - this.set('ruleSet.'+ruleSetId, newRS); - return newRS; - }, - - /** - * @param {!number} id The id of the RuleSet to retrieve. - * @return {?fiveui.RuleSet} The RuleSet, or null, if no RuleSet was found. - */ - getRuleSet: function(id) { - return /** @type {?fiveui.RuleSet} */ this.getById(id, 'ruleSet', fiveui.RuleSet.fromJSON); - }, - - /** - * @param {!number} id The id of the rule set to remove. - * @return {!Array.} null if the remove succeeded, otherwise, - * returns the list of UrlPats that use this - * rule set, if any. - */ - remRuleSet: function(id) { - var matches = _.map(this.getRuleSetUrlPats(id), function(id) { - return this.getUrlPat(id); - }, this); - - if (0 == matches.length) { - this.remById(id, 'ruleSet'); - } - - return matches; - }, - - /** - * @param {!number} ruleSetId The rule set to retrieve url patterns for. - * @return {Array.} Url pattern ids associated with this rule set. - */ - getRuleSetUrlPats: function(ruleSetId) { - var urls = this.getUrls(); - var patIds = []; - - _.each(urls, function(patId) { - var pat = this.getUrlPat(patId); - if(pat.rule_id == ruleSetId) { - patIds.push(patId); - } - }, this); - - return patIds; - }, - - /** - * @param {!number} id The nuber of the element to retrieve. - * @param {!string} listName The name of the portion of the localstorage hierarchy to search for id. - * @param {!function(number, !Object): *} fromJSON A deserialization function. - * - * @return {*} Either null, or the result of fromJSON. - */ - getById: function(id, listName, fromJSON) { - var obj = this.get(listName + '.' + id); - if (!obj) { - return null; - } - - return fromJSON(id, obj); - }, - - /** - * @param {!number} id The nuber of the element to retrieve. - * @param {!string} listName The name of the portion of the - * localstorage hierarchy to search for id. - */ - remById: function(id, listName) { - // remove it from the list of ids: - var ids = this.get(listName) || []; - - for (var i = 0; i < ids.length; ++i) { - if (ids[i] == id) { - ids.splice(i, 1); - this.set(listName, ids); - this.remove(listName + '.' + id); - break; - } - } - } -}); - - -/** - * @param {!fiveui.Chan} chan - * @param {!fiveui.Settings} settings - * @return {void} - */ -fiveui.Settings.manager = function(chan, settings) { - - var msg = new fiveui.Messenger(chan); - - msg.register('addRuleSet', function(ruleSet,respond){ - var newRS = settings.addRuleSet(ruleSet); - respond(newRS); - }); - - msg.register('updateRuleSet', function(updatedRS,respond){ - var newRS = settings.updateRuleSet(updatedRS.id, updatedRS); - respond(newRS); - }); - - msg.register('remRuleSet', function(ruleSetId, respond) { - var pats = settings.remRuleSet(ruleSetId); - respond({ - id: ruleSetId, - pats: pats, - removed: pats.length == 0 - }); - }); - - msg.register('getRuleSetUrlPats', function(ruleSetId, respond) { - var pats = settings.getUrls(); - var patIds = []; - - _.each(pats, function(patId) { - var pat = settings.getUrlPat(patId); - if(pat.rule_id == ruleSetId) { - patIds.push(patId); - } - }); - - respond(patIds); - }); - - // Retrieve the manifest, and return the object to the caller. Invokes the - // caller with `null` when the manifest fails to load. - msg.register('loadRuleSet', function(url, respond) { - fiveui.RuleSet.load(url, { - success:respond, - - error:function() { - respond(null); - }, - }); - }); - - msg.register('getRuleSet', function(ruleSetId, respond){ - respond(settings.getRuleSet(ruleSetId)); - }); - - msg.register('getRuleSets', function(unused, respond) { - var ruleSets = _.map(settings.getRuleSets(), - _.bind(settings.getRuleSet, settings)); - respond(ruleSets); - }); - - msg.register('getUrlPats', function(unused, respond){ - respond(_.map(settings.getUrls(), _.bind(settings.getUrlPat, settings))); - }); - - msg.register('addUrlPat', function(url, respond){ - var urlId = settings.addUrl(url.regex, url.rule_id); - respond(settings.getUrlPat(urlId)); - }); - - msg.register('updateUrlPat', function(pat, respond) { - var obj = settings.getUrlPat(pat.id); - settings.updateUrl(pat.id, pat.regex, pat.rule_id); - respond(pat); - }); - - msg.register('getUrlPat', function(urlPatId, respond){ - respond(settings.getUrlPat(urlPatId)); - }); - - msg.register('remUrlPat', function(urlPatId, respond){ - settings.remUrlPat(urlPatId); - respond(true); - }); - - msg.register('setDisplayDefault', function(def) { - settings.setDisplayDefault(def); - }); - - msg.register('getDisplayDefault', function(ignored, respond) { - respond(settings.getDisplayDefault()); - }); - -}; - -})(); diff --git a/contexts/data/fiveui/state.js b/contexts/data/fiveui/state.js deleted file mode 100644 index 226a439..0000000 --- a/contexts/data/fiveui/state.js +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Module : state.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -/** - * @constructor - * @param {!number} x The x-offset of the embedded dialog. - * @param {!number} y The y-offset the dialog. - * @param {!number} width The width of the dalog. - * @param {!number} height The width of the dalog. - * @param {!boolean} closed True if the window is closed, false if it is open. - */ -fiveui.WinState = function(x, y, width, height, closed) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - this.closed = closed; -}; - -/** - * @constructor - * @param {string} name The name of the rule that this problem represents. - * @param {string} descr Short description of the problem. - * @param {string} url The url that the problem occurred at. - * @param {number} severity The severity of the problem - */ -fiveui.Problem = function(name, descr, url, severity, hash) { - this.name = name || ''; - this.descr = descr || ''; - this.url = url || ''; - this.severity = severity || 0; - this.hash = hash; -}; - -/** - * @param {!Object} obj The JSON object to use as a template for a problem. - * @return {!fiveui.Problem} The problem that the object represents. - */ -fiveui.Problem.fromJSON = function(obj) { - return new fiveui.Problem(obj.name, obj.descr, obj.url, obj.severity, obj.hash); -}; - -/** - * @constructor - * @param {fiveui.WinState} winState The location of the FiveUI windown in - * the injected page. Null if the window - * is hidden. - * @param {fiveui.ChromePort} uiPort The port used to communicate with - * the corresponding tab. - */ -fiveui.TabState = function(tabId, winState, uiPort) { - this.tabId = tabId; - this.winState = winState; - this.uiPort = uiPort; - this.computePorts = []; - this.problems = []; - this.seenProblems = new Set(); - this.stats = {}; -}; - -_.extend(fiveui.TabState.prototype, { - - addProblem: function(prob) { - if(!this.seenProblems.contains(prob.hash)) { - this.problems.push(prob); - this.seenProblems.add(prob.hash); - return true; - } - else { - return false; - } - }, - - addStats: function (stats) { - this.stats = stats; - return true; - }, - - clearProblems: function() { - this.problems = []; - this.seenProblems = new Set(); - }, - - clearStats: function() { - for (var p in fiveui.stats.zero) { this.stats[p] = fiveui.stats.zero[p]; } - }, - - /* - * Returns a copy of only the attributes in a TabState that are needed for - * interpage communication. - */ - toEmit: function() { - return { winState: this.winState, problems: this.problems, stats: this.stats }; - } - -}); - -/** - * @constructor - * @param {!fiveui.Settings} settings The settings object to obtain - * defaults from. - */ -fiveui.State = function(settings) { - this.tabs = {}; - this.settings = settings; -}; - -_.extend(fiveui.State.prototype, { - - /** - * @param {!number} tabId The id of the tab to retrieve state for. - * - * @return {?fiveui.TabState} The stored state of the tab, or null, if - * no state exists for the requested tab. - */ - getTabState: function(tabId) { - return this.tabs[tabId] || null; - }, - - /** - * Like getTabState, but creates an initial tab state if none exists. - * - * @param {!number} tabId The id of the tab to retrieve state for. - * @param {!fiveui.ChromePort} port The port to use for communication - * with the corresponding tab. - * @return {!fiveui.TabState} Either an initial state if none existed, or the - * state that exists already. - */ - acquireTabState: function(tabId, port) { - var ts = this.getTabState(tabId); - - if(null == ts) { - var closed = ! this.settings.getDisplayDefault(); - - // in the future, get these defaults from the settings instance. - var ws = new fiveui.WinState(10, 10, 300, 300, closed); - ts = new fiveui.TabState(tabId, ws, port); - this.setTabState(ts); - } - - return ts; - }, - - /** - * @param {!fiveui.TabState} ts The state to store. - * @return {void} - */ - setTabState: function(ts) { - this.tabs[ts.tabId] = ts; - }, - - /** - * Update the state of a tab, if and only if the tabId exists in the state. - * - * @param {!number} tabId The id of the tab to store state for. - * @param {function(fiveui.TabState): fiveui.TabState} fn A function - * that modifies the tab state. - * - * @return {void} - */ - adjust: function(tabId, fn) { - var tState = this.getTabState(tabId); - if (tState) { - this.tabs[tabId] = fn(tState); - } - }, - - /** - * Remove the state of a tab. - * - * @param {!number} tabId The id of the tab to remove the state of. - * @return {void} - */ - removeTabState: function(tabId) { - delete this.tabs[tabId]; - } - -}); - -})(); diff --git a/contexts/data/fiveui/update-manager.js b/contexts/data/fiveui/update-manager.js deleted file mode 100644 index 8013d2f..0000000 --- a/contexts/data/fiveui/update-manager.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Module : update-manager.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function() { - - -fiveui.UpdateManager = function(msg) { - var manager = this; - - // fired when the rule set gets updated - msg.register('updateRuleSet', function(newRuleSet) { - manager.trigger('updateRuleSet.' + newRuleSet.id, false, newRuleSet); - - // update the associated url patterns - msg.send('getRuleSetPatIds', null, function(patIds) { - _.each(patIds, function(patId) { - manager.trigger('updateUrlPat.' + patId); - }); - }); - }); - - // fired when the url pat gets removed - msg.register('remUrlPat', function(id) { - var evt = 'remUrlPat.' + id; - manager.trigger(evt); - manager.off(evt); - }); - -}; - -_.extend(fiveui.UpdateManager.prototype, Backbone.Events); - -})(); diff --git a/contexts/data/fiveui/url-pat.js b/contexts/data/fiveui/url-pat.js deleted file mode 100644 index d723021..0000000 --- a/contexts/data/fiveui/url-pat.js +++ /dev/null @@ -1,140 +0,0 @@ - -(function() { - -/** - * Create a new Url Pattern to map urls to Rule Sets. - * - * @constructor - * @param {!number} id New id for this UrlPat. - * @param {!string} regex The pattern that is used to match Urls. - * @param {!number} rule_id Unique id of the RuleSet to use for matching URLs. - */ -fiveui.UrlPat = function(id, regex, rule_id) { - this.id = id; - this.regex = regex; - this.rule_id = rule_id; -}; - -/** - * Create a Url Pattern from a JSON object. - * - * @param {!number} id The id to use for the restored object. - * @param {!Object} obj The object to take settings from. - * @return {!fiveui.UrlPat} A populated UrlPat object. - */ -fiveui.UrlPat.fromJSON = function(id, obj) { - return new fiveui.UrlPat(id, obj.regex, obj.rule_id); -}; - -/** - * Create a regular expression from a globbed pattern. - * - * @param {!string} str The globbed url. - * @return {!RegExp} A compiled regular expression. - */ -fiveui.UrlPat.compile = function(str) { - var regex = str.replace(/\./g, '\.') - .replace(/\*/g, '.*'); - return new RegExp(regex); -}; - -/** - * Test a string Url against the regular expression held in a Url Pattern. - * - * @param {!string} url The Url the string to test. - * @return {!boolean} If the Url matched the regular expression. - */ -fiveui.UrlPat.prototype.match = function(url) { - var pat = fiveui.UrlPat.compile(this.regex); - return pat.test(url); -}; - - - -fiveui.UrlPatModel = Backbone.Model.extend({ - - defaults: { - id: null, - regex: '', - rule_id: null, - }, - - sync:function(method, model, options) { - _.defaults(options, { - success:function() {}, - error:function() {} - }); - - var msg = model.url; - var id = model.get('id'); - - switch(method) { - case 'read': - msg.send('getUrlPat', id, function(pat) { - model.set(pat); - options.success(); - }); - break; - - case 'update': - msg.send('updateUrlPat', _.clone(model.attributes), options.success); - break; - - case 'create': - msg.send('addUrlPat', _.clone(model.attributes), options.success); - break; - - case 'delete': - msg.send('remUrlPat', id, function(res) { - if(res) { - options.success({}); - } else { - options.error({}); - } - }); - break; - } - } - -}, { - - fromUrlPat: function(pat, msg) { - return new fiveui.UrlPatModel({ - id: pat.id, - regex: pat.regex, - rule_id: pat.rule_id - }, { url : msg }); - } - -}); - - -fiveui.UrlPats = Backbone.Collection.extend({ - - model: fiveui.UrlPatModel, - - sync:function(method, collection, options) { - - _.defaults(options, { - success:function() {}, - error:function() {} - }); - - var msg = this.url; - - switch(method) { - - case 'read': - msg.send('getUrlPats', null, function(pats) { - options.success(_.map(pats, function(pat) { - return fiveui.UrlPatModel.fromUrlPat(pat, msg); - })); - }); - break; - } - - } - -}); - -})(); diff --git a/contexts/data/fiveui/utils.js b/contexts/data/fiveui/utils.js deleted file mode 100644 index 0ab3128..0000000 --- a/contexts/data/fiveui/utils.js +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Module : utils.js - * Copyright : (c) 2011-2012, Galois, Inc. - * - * Maintainer : - * Stability : Provisional - * Portability: Portable - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fiveui = fiveui || {}; - -(function() { - -fiveui.utils = fiveui.utils || {}; - -/** - * Chooses a function based on the current browser. - */ -fiveui.utils.pick = function (mozFn, chrFn) { - if (typeof chrome != 'undefined' ) { - return chrFn; - } else { - return mozFn; - } -}; - -/** - * Create a browser-independent settings object. This uses different - * backing storage depending on the browser: - * - * - Firefox: simple-storage - * - Chrome: localStorage - * - * @return {!fiveui.Settings} A settings object that will persist data - * between browser invocations. - */ -// fiveui.utils.getSettings = fiveui.utils.pick( -// function() { -// // var ss = require('simple-storage'); -// var ss = {storage: {}}; // XXX hack, obviously. - -// var storageWrapper = new fiveui.utils.StorageWrapper(ss.storage); -// return new fiveui.Settings(storageWrapper); -// }, -// function() { -// return new fiveui.Settings(localStorage); -// }); - -/** - * Get an ID by adding one to the max id in current use. - * - * @param {Array.} list the list of ids that the new id must - * not conflict with. - * @return {!number} A unique id for UrlPats. - */ -fiveui.utils.getNewId = function(list) { - // make sure we have a non-null, non-empty list: - if (list === null || list.length == 0) { - return 0; - } else { - return 1 + Math.max.apply(Math, list); - } -}; - - -/** - * Remove c-style comments - * - * There's probably a faster way to do this. - */ -var removeComments = function(data) { - - var state = 0; - var toEOL = 1; - var toEOC = 2; - - var sanitized = ''; - var len = data.length; - var s = 0, e = 0; - - for(; e < len; ++e) { - switch(state) { - case toEOL: - if(data[e] == '\n') { - state = 0; - s = e + 1; - } - break; - - case toEOC: - if(data[e] == '*' && data[e+1] == '/') { - state = 0; - s = e + 2; - e = e + 1; - } - break; - - default: - if(data[e] == '/') { - if(data[e+1] == '/') { - sanitized = sanitized + data.substring(s,e); - state = toEOL; - e = e + 1; - } else if(data[e+1] == '*') { - sanitized = sanitized + data.substring(s,e); - state = toEOC; - e = e + 1; - } - } - break; - } - } - - if(state == 0 && s < e) { - sanitized = sanitized + data.substring(s,e); - } - - return sanitized; -}; - - -/** - * Filter out comments, and other things that aren't appropriate in JSON. - */ -fiveui.utils.filterJSON = function(data, type) { - if(type == 'json') { - return removeComments(data); - } else { - return data; - } -}; - -})(); diff --git a/contexts/data/lib/backbone.js b/contexts/data/lib/backbone.js deleted file mode 100644 index 3512d42..0000000 --- a/contexts/data/lib/backbone.js +++ /dev/null @@ -1,1571 +0,0 @@ -// Backbone.js 1.0.0 - -// (c) 2010-2013 Jeremy Ashkenas, DocumentCloud Inc. -// Backbone may be freely distributed under the MIT license. -// For all details and documentation: -// http://backbonejs.org - -(function(){ - - // Initial Setup - // ------------- - - // Save a reference to the global object (`window` in the browser, `exports` - // on the server). - var root = this; - - // Save the previous value of the `Backbone` variable, so that it can be - // restored later on, if `noConflict` is used. - var previousBackbone = root.Backbone; - - // Create local references to array methods we'll want to use later. - var array = []; - var push = array.push; - var slice = array.slice; - var splice = array.splice; - - // The top-level namespace. All public Backbone classes and modules will - // be attached to this. Exported for both the browser and the server. - var Backbone; - if (typeof exports !== 'undefined') { - Backbone = exports; - } else { - Backbone = root.Backbone = {}; - } - - // Current version of the library. Keep in sync with `package.json`. - Backbone.VERSION = '1.0.0'; - - // Require Underscore, if we're on the server, and it's not already present. - var _ = root._; - if (!_ && (typeof require !== 'undefined')) _ = require('underscore'); - - // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns - // the `$` variable. - Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$; - - // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable - // to its previous owner. Returns a reference to this Backbone object. - Backbone.noConflict = function() { - root.Backbone = previousBackbone; - return this; - }; - - // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option - // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and - // set a `X-Http-Method-Override` header. - Backbone.emulateHTTP = false; - - // Turn on `emulateJSON` to support legacy servers that can't deal with direct - // `application/json` requests ... will encode the body as - // `application/x-www-form-urlencoded` instead and will send the model in a - // form param named `model`. - Backbone.emulateJSON = false; - - // Backbone.Events - // --------------- - - // A module that can be mixed in to *any object* in order to provide it with - // custom events. You may bind with `on` or remove with `off` callback - // functions to an event; `trigger`-ing an event fires all callbacks in - // succession. - // - // var object = {}; - // _.extend(object, Backbone.Events); - // object.on('expand', function(){ alert('expanded'); }); - // object.trigger('expand'); - // - var Events = Backbone.Events = { - - // Bind an event to a `callback` function. Passing `"all"` will bind - // the callback to all events fired. - on: function(name, callback, context) { - if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; - this._events || (this._events = {}); - var events = this._events[name] || (this._events[name] = []); - events.push({callback: callback, context: context, ctx: context || this}); - return this; - }, - - // Bind an event to only be triggered a single time. After the first time - // the callback is invoked, it will be removed. - once: function(name, callback, context) { - if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; - var self = this; - var once = _.once(function() { - self.off(name, once); - callback.apply(this, arguments); - }); - once._callback = callback; - return this.on(name, once, context); - }, - - // Remove one or many callbacks. If `context` is null, removes all - // callbacks with that function. If `callback` is null, removes all - // callbacks for the event. If `name` is null, removes all bound - // callbacks for all events. - off: function(name, callback, context) { - var retain, ev, events, names, i, l, j, k; - if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; - if (!name && !callback && !context) { - this._events = {}; - return this; - } - - names = name ? [name] : _.keys(this._events); - for (i = 0, l = names.length; i < l; i++) { - name = names[i]; - if (events = this._events[name]) { - this._events[name] = retain = []; - if (callback || context) { - for (j = 0, k = events.length; j < k; j++) { - ev = events[j]; - if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || - (context && context !== ev.context)) { - retain.push(ev); - } - } - } - if (!retain.length) delete this._events[name]; - } - } - - return this; - }, - - // Trigger one or many events, firing all bound callbacks. Callbacks are - // passed the same arguments as `trigger` is, apart from the event name - // (unless you're listening on `"all"`, which will cause your callback to - // receive the true name of the event as the first argument). - trigger: function(name) { - if (!this._events) return this; - var args = slice.call(arguments, 1); - if (!eventsApi(this, 'trigger', name, args)) return this; - var events = this._events[name]; - var allEvents = this._events.all; - if (events) triggerEvents(events, args); - if (allEvents) triggerEvents(allEvents, arguments); - return this; - }, - - // Tell this object to stop listening to either specific events ... or - // to every object it's currently listening to. - stopListening: function(obj, name, callback) { - var listeners = this._listeners; - if (!listeners) return this; - var deleteListener = !name && !callback; - if (typeof name === 'object') callback = this; - if (obj) (listeners = {})[obj._listenerId] = obj; - for (var id in listeners) { - listeners[id].off(name, callback, this); - if (deleteListener) delete this._listeners[id]; - } - return this; - } - - }; - - // Regular expression used to split event strings. - var eventSplitter = /\s+/; - - // Implement fancy features of the Events API such as multiple event - // names `"change blur"` and jQuery-style event maps `{change: action}` - // in terms of the existing API. - var eventsApi = function(obj, action, name, rest) { - if (!name) return true; - - // Handle event maps. - if (typeof name === 'object') { - for (var key in name) { - obj[action].apply(obj, [key, name[key]].concat(rest)); - } - return false; - } - - // Handle space separated event names. - if (eventSplitter.test(name)) { - var names = name.split(eventSplitter); - for (var i = 0, l = names.length; i < l; i++) { - obj[action].apply(obj, [names[i]].concat(rest)); - } - return false; - } - - return true; - }; - - // A difficult-to-believe, but optimized internal dispatch function for - // triggering events. Tries to keep the usual cases speedy (most internal - // Backbone events have 3 arguments). - var triggerEvents = function(events, args) { - var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; - switch (args.length) { - case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; - case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; - case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; - case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; - default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); - } - }; - - var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; - - // Inversion-of-control versions of `on` and `once`. Tell *this* object to - // listen to an event in another object ... keeping track of what it's - // listening to. - _.each(listenMethods, function(implementation, method) { - Events[method] = function(obj, name, callback) { - var listeners = this._listeners || (this._listeners = {}); - var id = obj._listenerId || (obj._listenerId = _.uniqueId('l')); - listeners[id] = obj; - if (typeof name === 'object') callback = this; - obj[implementation](name, callback, this); - return this; - }; - }); - - // Aliases for backwards compatibility. - Events.bind = Events.on; - Events.unbind = Events.off; - - // Allow the `Backbone` object to serve as a global event bus, for folks who - // want global "pubsub" in a convenient place. - _.extend(Backbone, Events); - - // Backbone.Model - // -------------- - - // Backbone **Models** are the basic data object in the framework -- - // frequently representing a row in a table in a database on your server. - // A discrete chunk of data and a bunch of useful, related methods for - // performing computations and transformations on that data. - - // Create a new model with the specified attributes. A client id (`cid`) - // is automatically generated and assigned for you. - var Model = Backbone.Model = function(attributes, options) { - var defaults; - var attrs = attributes || {}; - options || (options = {}); - this.cid = _.uniqueId('c'); - this.attributes = {}; - _.extend(this, _.pick(options, modelOptions)); - if (options.parse) attrs = this.parse(attrs, options) || {}; - if (defaults = _.result(this, 'defaults')) { - attrs = _.defaults({}, attrs, defaults); - } - this.set(attrs, options); - this.changed = {}; - this.initialize.apply(this, arguments); - }; - - // A list of options to be attached directly to the model, if provided. - var modelOptions = ['url', 'urlRoot', 'collection']; - - // Attach all inheritable methods to the Model prototype. - _.extend(Model.prototype, Events, { - - // A hash of attributes whose current and previous value differ. - changed: null, - - // The value returned during the last failed validation. - validationError: null, - - // The default name for the JSON `id` attribute is `"id"`. MongoDB and - // CouchDB users may want to set this to `"_id"`. - idAttribute: 'id', - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Return a copy of the model's `attributes` object. - toJSON: function(options) { - return _.clone(this.attributes); - }, - - // Proxy `Backbone.sync` by default -- but override this if you need - // custom syncing semantics for *this* particular model. - sync: function() { - return Backbone.sync.apply(this, arguments); - }, - - // Get the value of an attribute. - get: function(attr) { - return this.attributes[attr]; - }, - - // Get the HTML-escaped value of an attribute. - escape: function(attr) { - return _.escape(this.get(attr)); - }, - - // Returns `true` if the attribute contains a value that is not null - // or undefined. - has: function(attr) { - return this.get(attr) != null; - }, - - // Set a hash of model attributes on the object, firing `"change"`. This is - // the core primitive operation of a model, updating the data and notifying - // anyone who needs to know about the change in state. The heart of the beast. - set: function(key, val, options) { - var attr, attrs, unset, changes, silent, changing, prev, current; - if (key == null) return this; - - // Handle both `"key", value` and `{key: value}` -style arguments. - if (typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - options || (options = {}); - - // Run validation. - if (!this._validate(attrs, options)) return false; - - // Extract attributes and options. - unset = options.unset; - silent = options.silent; - changes = []; - changing = this._changing; - this._changing = true; - - if (!changing) { - this._previousAttributes = _.clone(this.attributes); - this.changed = {}; - } - current = this.attributes, prev = this._previousAttributes; - - // Check for changes of `id`. - if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; - - // For each `set` attribute, update or delete the current value. - for (attr in attrs) { - val = attrs[attr]; - if (!_.isEqual(current[attr], val)) changes.push(attr); - if (!_.isEqual(prev[attr], val)) { - this.changed[attr] = val; - } else { - delete this.changed[attr]; - } - unset ? delete current[attr] : current[attr] = val; - } - - // Trigger all relevant attribute changes. - if (!silent) { - if (changes.length) this._pending = true; - for (var i = 0, l = changes.length; i < l; i++) { - this.trigger('change:' + changes[i], this, current[changes[i]], options); - } - } - - // You might be wondering why there's a `while` loop here. Changes can - // be recursively nested within `"change"` events. - if (changing) return this; - if (!silent) { - while (this._pending) { - this._pending = false; - this.trigger('change', this, options); - } - } - this._pending = false; - this._changing = false; - return this; - }, - - // Remove an attribute from the model, firing `"change"`. `unset` is a noop - // if the attribute doesn't exist. - unset: function(attr, options) { - return this.set(attr, void 0, _.extend({}, options, {unset: true})); - }, - - // Clear all attributes on the model, firing `"change"`. - clear: function(options) { - var attrs = {}; - for (var key in this.attributes) attrs[key] = void 0; - return this.set(attrs, _.extend({}, options, {unset: true})); - }, - - // Determine if the model has changed since the last `"change"` event. - // If you specify an attribute name, determine if that attribute has changed. - hasChanged: function(attr) { - if (attr == null) return !_.isEmpty(this.changed); - return _.has(this.changed, attr); - }, - - // Return an object containing all the attributes that have changed, or - // false if there are no changed attributes. Useful for determining what - // parts of a view need to be updated and/or what attributes need to be - // persisted to the server. Unset attributes will be set to undefined. - // You can also pass an attributes object to diff against the model, - // determining if there *would be* a change. - changedAttributes: function(diff) { - if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; - var val, changed = false; - var old = this._changing ? this._previousAttributes : this.attributes; - for (var attr in diff) { - if (_.isEqual(old[attr], (val = diff[attr]))) continue; - (changed || (changed = {}))[attr] = val; - } - return changed; - }, - - // Get the previous value of an attribute, recorded at the time the last - // `"change"` event was fired. - previous: function(attr) { - if (attr == null || !this._previousAttributes) return null; - return this._previousAttributes[attr]; - }, - - // Get all of the attributes of the model at the time of the previous - // `"change"` event. - previousAttributes: function() { - return _.clone(this._previousAttributes); - }, - - // Fetch the model from the server. If the server's representation of the - // model differs from its current attributes, they will be overridden, - // triggering a `"change"` event. - fetch: function(options) { - options = options ? _.clone(options) : {}; - if (options.parse === void 0) options.parse = true; - var model = this; - var success = options.success; - options.success = function(resp) { - if (!model.set(model.parse(resp, options), options)) return false; - if (success) success(model, resp, options); - model.trigger('sync', model, resp, options); - }; - wrapError(this, options); - return this.sync('read', this, options); - }, - - // Set a hash of model attributes, and sync the model to the server. - // If the server returns an attributes hash that differs, the model's - // state will be `set` again. - save: function(key, val, options) { - var attrs, method, xhr, attributes = this.attributes; - - // Handle both `"key", value` and `{key: value}` -style arguments. - if (key == null || typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - // If we're not waiting and attributes exist, save acts as `set(attr).save(null, opts)`. - if (attrs && (!options || !options.wait) && !this.set(attrs, options)) return false; - - options = _.extend({validate: true}, options); - - // Do not persist invalid models. - if (!this._validate(attrs, options)) return false; - - // Set temporary attributes if `{wait: true}`. - if (attrs && options.wait) { - this.attributes = _.extend({}, attributes, attrs); - } - - // After a successful server-side save, the client is (optionally) - // updated with the server-side state. - if (options.parse === void 0) options.parse = true; - var model = this; - var success = options.success; - options.success = function(resp) { - // Ensure attributes are restored during synchronous saves. - model.attributes = attributes; - var serverAttrs = model.parse(resp, options); - if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs); - if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { - return false; - } - if (success) success(model, resp, options); - model.trigger('sync', model, resp, options); - }; - wrapError(this, options); - - method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); - if (method === 'patch') options.attrs = attrs; - xhr = this.sync(method, this, options); - - // Restore attributes. - if (attrs && options.wait) this.attributes = attributes; - - return xhr; - }, - - // Destroy this model on the server if it was already persisted. - // Optimistically removes the model from its collection, if it has one. - // If `wait: true` is passed, waits for the server to respond before removal. - destroy: function(options) { - options = options ? _.clone(options) : {}; - var model = this; - var success = options.success; - - var destroy = function() { - model.trigger('destroy', model, model.collection, options); - }; - - options.success = function(resp) { - if (options.wait || model.isNew()) destroy(); - if (success) success(model, resp, options); - if (!model.isNew()) model.trigger('sync', model, resp, options); - }; - - if (this.isNew()) { - options.success(); - return false; - } - wrapError(this, options); - - var xhr = this.sync('delete', this, options); - if (!options.wait) destroy(); - return xhr; - }, - - // Default URL for the model's representation on the server -- if you're - // using Backbone's restful methods, override this to change the endpoint - // that will be called. - url: function() { - var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError(); - if (this.isNew()) return base; - return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id); - }, - - // **parse** converts a response into the hash of attributes to be `set` on - // the model. The default implementation is just to pass the response along. - parse: function(resp, options) { - return resp; - }, - - // Create a new model with identical attributes to this one. - clone: function() { - return new this.constructor(this.attributes); - }, - - // A model is new if it has never been saved to the server, and lacks an id. - isNew: function() { - return this.id == null; - }, - - // Check if the model is currently in a valid state. - isValid: function(options) { - return this._validate({}, _.extend(options || {}, { validate: true })); - }, - - // Run validation against the next complete set of model attributes, - // returning `true` if all is well. Otherwise, fire an `"invalid"` event. - _validate: function(attrs, options) { - if (!options.validate || !this.validate) return true; - attrs = _.extend({}, this.attributes, attrs); - var error = this.validationError = this.validate(attrs, options) || null; - if (!error) return true; - this.trigger('invalid', this, error, _.extend(options || {}, {validationError: error})); - return false; - } - - }); - - // Underscore methods that we want to implement on the Model. - var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit']; - - // Mix in each Underscore method as a proxy to `Model#attributes`. - _.each(modelMethods, function(method) { - Model.prototype[method] = function() { - var args = slice.call(arguments); - args.unshift(this.attributes); - return _[method].apply(_, args); - }; - }); - - // Backbone.Collection - // ------------------- - - // If models tend to represent a single row of data, a Backbone Collection is - // more analagous to a table full of data ... or a small slice or page of that - // table, or a collection of rows that belong together for a particular reason - // -- all of the messages in this particular folder, all of the documents - // belonging to this particular author, and so on. Collections maintain - // indexes of their models, both in order, and for lookup by `id`. - - // Create a new **Collection**, perhaps to contain a specific type of `model`. - // If a `comparator` is specified, the Collection will maintain - // its models in sort order, as they're added and removed. - var Collection = Backbone.Collection = function(models, options) { - options || (options = {}); - if (options.url) this.url = options.url; - if (options.model) this.model = options.model; - if (options.comparator !== void 0) this.comparator = options.comparator; - this._reset(); - this.initialize.apply(this, arguments); - if (models) this.reset(models, _.extend({silent: true}, options)); - }; - - // Default options for `Collection#set`. - var setOptions = {add: true, remove: true, merge: true}; - var addOptions = {add: true, merge: false, remove: false}; - - // Define the Collection's inheritable methods. - _.extend(Collection.prototype, Events, { - - // The default model for a collection is just a **Backbone.Model**. - // This should be overridden in most cases. - model: Model, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // The JSON representation of a Collection is an array of the - // models' attributes. - toJSON: function(options) { - return this.map(function(model){ return model.toJSON(options); }); - }, - - // Proxy `Backbone.sync` by default. - sync: function() { - return Backbone.sync.apply(this, arguments); - }, - - // Add a model, or list of models to the set. - add: function(models, options) { - return this.set(models, _.defaults(options || {}, addOptions)); - }, - - // Remove a model, or a list of models from the set. - remove: function(models, options) { - models = _.isArray(models) ? models.slice() : [models]; - options || (options = {}); - var i, l, index, model; - for (i = 0, l = models.length; i < l; i++) { - model = this.get(models[i]); - if (!model) continue; - delete this._byId[model.id]; - delete this._byId[model.cid]; - index = this.indexOf(model); - this.models.splice(index, 1); - this.length--; - if (!options.silent) { - options.index = index; - model.trigger('remove', model, this, options); - } - this._removeReference(model); - } - return this; - }, - - // Update a collection by `set`-ing a new list of models, adding new ones, - // removing models that are no longer present, and merging models that - // already exist in the collection, as necessary. Similar to **Model#set**, - // the core operation for updating the data contained by the collection. - set: function(models, options) { - options = _.defaults(options || {}, setOptions); - if (options.parse) models = this.parse(models, options); - if (!_.isArray(models)) models = models ? [models] : []; - var i, l, model, attrs, existing, sort; - var at = options.at; - var sortable = this.comparator && (at == null) && options.sort !== false; - var sortAttr = _.isString(this.comparator) ? this.comparator : null; - var toAdd = [], toRemove = [], modelMap = {}; - - // Turn bare objects into model references, and prevent invalid models - // from being added. - for (i = 0, l = models.length; i < l; i++) { - if (!(model = this._prepareModel(models[i], options))) continue; - - // If a duplicate is found, prevent it from being added and - // optionally merge it into the existing model. - if (existing = this.get(model)) { - if (options.remove) modelMap[existing.cid] = true; - if (options.merge) { - existing.set(model.attributes, options); - if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true; - } - - // This is a new model, push it to the `toAdd` list. - } else if (options.add) { - toAdd.push(model); - - // Listen to added models' events, and index models for lookup by - // `id` and by `cid`. - model.on('all', this._onModelEvent, this); - this._byId[model.cid] = model; - if (model.id != null) this._byId[model.id] = model; - } - } - - // Remove nonexistent models if appropriate. - if (options.remove) { - for (i = 0, l = this.length; i < l; ++i) { - if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model); - } - if (toRemove.length) this.remove(toRemove, options); - } - - // See if sorting is needed, update `length` and splice in new models. - if (toAdd.length) { - if (sortable) sort = true; - this.length += toAdd.length; - if (at != null) { - splice.apply(this.models, [at, 0].concat(toAdd)); - } else { - push.apply(this.models, toAdd); - } - } - - // Silently sort the collection if appropriate. - if (sort) this.sort({silent: true}); - - if (options.silent) return this; - - // Trigger `add` events. - for (i = 0, l = toAdd.length; i < l; i++) { - (model = toAdd[i]).trigger('add', model, this, options); - } - - // Trigger `sort` if the collection was sorted. - if (sort) this.trigger('sort', this, options); - return this; - }, - - // When you have more items than you want to add or remove individually, - // you can reset the entire set with a new list of models, without firing - // any granular `add` or `remove` events. Fires `reset` when finished. - // Useful for bulk operations and optimizations. - reset: function(models, options) { - options || (options = {}); - for (var i = 0, l = this.models.length; i < l; i++) { - this._removeReference(this.models[i]); - } - options.previousModels = this.models; - this._reset(); - this.add(models, _.extend({silent: true}, options)); - if (!options.silent) this.trigger('reset', this, options); - return this; - }, - - // Add a model to the end of the collection. - push: function(model, options) { - model = this._prepareModel(model, options); - this.add(model, _.extend({at: this.length}, options)); - return model; - }, - - // Remove a model from the end of the collection. - pop: function(options) { - var model = this.at(this.length - 1); - this.remove(model, options); - return model; - }, - - // Add a model to the beginning of the collection. - unshift: function(model, options) { - model = this._prepareModel(model, options); - this.add(model, _.extend({at: 0}, options)); - return model; - }, - - // Remove a model from the beginning of the collection. - shift: function(options) { - var model = this.at(0); - this.remove(model, options); - return model; - }, - - // Slice out a sub-array of models from the collection. - slice: function(begin, end) { - return this.models.slice(begin, end); - }, - - // Get a model from the set by id. - get: function(obj) { - if (obj == null) return void 0; - return this._byId[obj.id != null ? obj.id : obj.cid || obj]; - }, - - // Get the model at the given index. - at: function(index) { - return this.models[index]; - }, - - // Return models with matching attributes. Useful for simple cases of - // `filter`. - where: function(attrs, first) { - if (_.isEmpty(attrs)) return first ? void 0 : []; - return this[first ? 'find' : 'filter'](function(model) { - for (var key in attrs) { - if (attrs[key] !== model.get(key)) return false; - } - return true; - }); - }, - - // Return the first model with matching attributes. Useful for simple cases - // of `find`. - findWhere: function(attrs) { - return this.where(attrs, true); - }, - - // Force the collection to re-sort itself. You don't need to call this under - // normal circumstances, as the set will maintain sort order as each item - // is added. - sort: function(options) { - if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); - options || (options = {}); - - // Run sort based on type of `comparator`. - if (_.isString(this.comparator) || this.comparator.length === 1) { - this.models = this.sortBy(this.comparator, this); - } else { - this.models.sort(_.bind(this.comparator, this)); - } - - if (!options.silent) this.trigger('sort', this, options); - return this; - }, - - // Figure out the smallest index at which a model should be inserted so as - // to maintain order. - sortedIndex: function(model, value, context) { - value || (value = this.comparator); - var iterator = _.isFunction(value) ? value : function(model) { - return model.get(value); - }; - return _.sortedIndex(this.models, model, iterator, context); - }, - - // Pluck an attribute from each model in the collection. - pluck: function(attr) { - return _.invoke(this.models, 'get', attr); - }, - - // Fetch the default set of models for this collection, resetting the - // collection when they arrive. If `reset: true` is passed, the response - // data will be passed through the `reset` method instead of `set`. - fetch: function(options) { - options = options ? _.clone(options) : {}; - if (options.parse === void 0) options.parse = true; - var success = options.success; - var collection = this; - options.success = function(resp) { - var method = options.reset ? 'reset' : 'set'; - collection[method](resp, options); - if (success) success(collection, resp, options); - collection.trigger('sync', collection, resp, options); - }; - wrapError(this, options); - return this.sync('read', this, options); - }, - - // Create a new instance of a model in this collection. Add the model to the - // collection immediately, unless `wait: true` is passed, in which case we - // wait for the server to agree. - create: function(model, options) { - options = options ? _.clone(options) : {}; - if (!(model = this._prepareModel(model, options))) return false; - if (!options.wait) this.add(model, options); - var collection = this; - var success = options.success; - options.success = function(resp) { - if (options.wait) collection.add(model, options); - if (success) success(model, resp, options); - }; - model.save(null, options); - return model; - }, - - // **parse** converts a response into a list of models to be added to the - // collection. The default implementation is just to pass it through. - parse: function(resp, options) { - return resp; - }, - - // Create a new collection with an identical list of models as this one. - clone: function() { - return new this.constructor(this.models); - }, - - // Private method to reset all internal state. Called when the collection - // is first initialized or reset. - _reset: function() { - this.length = 0; - this.models = []; - this._byId = {}; - }, - - // Prepare a hash of attributes (or other model) to be added to this - // collection. - _prepareModel: function(attrs, options) { - if (attrs instanceof Model) { - if (!attrs.collection) attrs.collection = this; - return attrs; - } - options || (options = {}); - options.collection = this; - var model = new this.model(attrs, options); - if (!model._validate(attrs, options)) { - this.trigger('invalid', this, attrs, options); - return false; - } - return model; - }, - - // Internal method to sever a model's ties to a collection. - _removeReference: function(model) { - if (this === model.collection) delete model.collection; - model.off('all', this._onModelEvent, this); - }, - - // Internal method called every time a model in the set fires an event. - // Sets need to update their indexes when models change ids. All other - // events simply proxy through. "add" and "remove" events that originate - // in other collections are ignored. - _onModelEvent: function(event, model, collection, options) { - if ((event === 'add' || event === 'remove') && collection !== this) return; - if (event === 'destroy') this.remove(model, options); - if (model && event === 'change:' + model.idAttribute) { - delete this._byId[model.previous(model.idAttribute)]; - if (model.id != null) this._byId[model.id] = model; - } - this.trigger.apply(this, arguments); - } - - }); - - // Underscore methods that we want to implement on the Collection. - // 90% of the core usefulness of Backbone Collections is actually implemented - // right here: - var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl', - 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select', - 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', - 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest', - 'tail', 'drop', 'last', 'without', 'indexOf', 'shuffle', 'lastIndexOf', - 'isEmpty', 'chain']; - - // Mix in each Underscore method as a proxy to `Collection#models`. - _.each(methods, function(method) { - Collection.prototype[method] = function() { - var args = slice.call(arguments); - args.unshift(this.models); - return _[method].apply(_, args); - }; - }); - - // Underscore methods that take a property name as an argument. - var attributeMethods = ['groupBy', 'countBy', 'sortBy']; - - // Use attributes instead of properties. - _.each(attributeMethods, function(method) { - Collection.prototype[method] = function(value, context) { - var iterator = _.isFunction(value) ? value : function(model) { - return model.get(value); - }; - return _[method](this.models, iterator, context); - }; - }); - - // Backbone.View - // ------------- - - // Backbone Views are almost more convention than they are actual code. A View - // is simply a JavaScript object that represents a logical chunk of UI in the - // DOM. This might be a single item, an entire list, a sidebar or panel, or - // even the surrounding frame which wraps your whole app. Defining a chunk of - // UI as a **View** allows you to define your DOM events declaratively, without - // having to worry about render order ... and makes it easy for the view to - // react to specific changes in the state of your models. - - // Creating a Backbone.View creates its initial element outside of the DOM, - // if an existing element is not provided... - var View = Backbone.View = function(options) { - this.cid = _.uniqueId('view'); - this._configure(options || {}); - this._ensureElement(); - this.initialize.apply(this, arguments); - this.delegateEvents(); - }; - - // Cached regex to split keys for `delegate`. - var delegateEventSplitter = /^(\S+)\s*(.*)$/; - - // List of view options to be merged as properties. - var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; - - // Set up all inheritable **Backbone.View** properties and methods. - _.extend(View.prototype, Events, { - - // The default `tagName` of a View's element is `"div"`. - tagName: 'div', - - // jQuery delegate for element lookup, scoped to DOM elements within the - // current view. This should be prefered to global lookups where possible. - $: function(selector) { - return this.$el.find(selector); - }, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // **render** is the core function that your view should override, in order - // to populate its element (`this.el`), with the appropriate HTML. The - // convention is for **render** to always return `this`. - render: function() { - return this; - }, - - // Remove this view by taking the element out of the DOM, and removing any - // applicable Backbone.Events listeners. - remove: function() { - this.$el.remove(); - this.stopListening(); - return this; - }, - - // Change the view's element (`this.el` property), including event - // re-delegation. - setElement: function(element, delegate) { - if (this.$el) this.undelegateEvents(); - this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); - this.el = this.$el[0]; - if (delegate !== false) this.delegateEvents(); - return this; - }, - - // Set callbacks, where `this.events` is a hash of - // - // *{"event selector": "callback"}* - // - // { - // 'mousedown .title': 'edit', - // 'click .button': 'save' - // 'click .open': function(e) { ... } - // } - // - // pairs. Callbacks will be bound to the view, with `this` set properly. - // Uses event delegation for efficiency. - // Omitting the selector binds the event to `this.el`. - // This only works for delegate-able events: not `focus`, `blur`, and - // not `change`, `submit`, and `reset` in Internet Explorer. - delegateEvents: function(events) { - if (!(events || (events = _.result(this, 'events')))) return this; - this.undelegateEvents(); - for (var key in events) { - var method = events[key]; - if (!_.isFunction(method)) method = this[events[key]]; - if (!method) continue; - - var match = key.match(delegateEventSplitter); - var eventName = match[1], selector = match[2]; - method = _.bind(method, this); - eventName += '.delegateEvents' + this.cid; - if (selector === '') { - this.$el.on(eventName, method); - } else { - this.$el.on(eventName, selector, method); - } - } - return this; - }, - - // Clears all callbacks previously bound to the view with `delegateEvents`. - // You usually don't need to use this, but may wish to if you have multiple - // Backbone views attached to the same DOM element. - undelegateEvents: function() { - this.$el.off('.delegateEvents' + this.cid); - return this; - }, - - // Performs the initial configuration of a View with a set of options. - // Keys with special meaning *(e.g. model, collection, id, className)* are - // attached directly to the view. See `viewOptions` for an exhaustive - // list. - _configure: function(options) { - if (this.options) options = _.extend({}, _.result(this, 'options'), options); - _.extend(this, _.pick(options, viewOptions)); - this.options = options; - }, - - // Ensure that the View has a DOM element to render into. - // If `this.el` is a string, pass it through `$()`, take the first - // matching element, and re-assign it to `el`. Otherwise, create - // an element from the `id`, `className` and `tagName` properties. - _ensureElement: function() { - if (!this.el) { - var attrs = _.extend({}, _.result(this, 'attributes')); - if (this.id) attrs.id = _.result(this, 'id'); - if (this.className) attrs['class'] = _.result(this, 'className'); - var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs); - this.setElement($el, false); - } else { - this.setElement(_.result(this, 'el'), false); - } - } - - }); - - // Backbone.sync - // ------------- - - // Override this function to change the manner in which Backbone persists - // models to the server. You will be passed the type of request, and the - // model in question. By default, makes a RESTful Ajax request - // to the model's `url()`. Some possible customizations could be: - // - // * Use `setTimeout` to batch rapid-fire updates into a single request. - // * Send up the models as XML instead of JSON. - // * Persist models via WebSockets instead of Ajax. - // - // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests - // as `POST`, with a `_method` parameter containing the true HTTP method, - // as well as all requests with the body as `application/x-www-form-urlencoded` - // instead of `application/json` with the model in a param named `model`. - // Useful when interfacing with server-side languages like **PHP** that make - // it difficult to read the body of `PUT` requests. - Backbone.sync = function(method, model, options) { - var type = methodMap[method]; - - // Default options, unless specified. - _.defaults(options || (options = {}), { - emulateHTTP: Backbone.emulateHTTP, - emulateJSON: Backbone.emulateJSON - }); - - // Default JSON-request options. - var params = {type: type, dataType: 'json'}; - - // Ensure that we have a URL. - if (!options.url) { - params.url = _.result(model, 'url') || urlError(); - } - - // Ensure that we have the appropriate request data. - if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { - params.contentType = 'application/json'; - params.data = JSON.stringify(options.attrs || model.toJSON(options)); - } - - // For older servers, emulate JSON by encoding the request into an HTML-form. - if (options.emulateJSON) { - params.contentType = 'application/x-www-form-urlencoded'; - params.data = params.data ? {model: params.data} : {}; - } - - // For older servers, emulate HTTP by mimicking the HTTP method with `_method` - // And an `X-HTTP-Method-Override` header. - if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { - params.type = 'POST'; - if (options.emulateJSON) params.data._method = type; - var beforeSend = options.beforeSend; - options.beforeSend = function(xhr) { - xhr.setRequestHeader('X-HTTP-Method-Override', type); - if (beforeSend) return beforeSend.apply(this, arguments); - }; - } - - // Don't process data on a non-GET request. - if (params.type !== 'GET' && !options.emulateJSON) { - params.processData = false; - } - - // If we're sending a `PATCH` request, and we're in an old Internet Explorer - // that still has ActiveX enabled by default, override jQuery to use that - // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8. - if (params.type === 'PATCH' && window.ActiveXObject && - !(window.external && window.external.msActiveXFilteringEnabled)) { - params.xhr = function() { - return new ActiveXObject("Microsoft.XMLHTTP"); - }; - } - - // Make the request, allowing the user to override any Ajax options. - var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); - model.trigger('request', model, xhr, options); - return xhr; - }; - - // Map from CRUD to HTTP for our default `Backbone.sync` implementation. - var methodMap = { - 'create': 'POST', - 'update': 'PUT', - 'patch': 'PATCH', - 'delete': 'DELETE', - 'read': 'GET' - }; - - // Set the default implementation of `Backbone.ajax` to proxy through to `$`. - // Override this if you'd like to use a different library. - Backbone.ajax = function() { - return Backbone.$.ajax.apply(Backbone.$, arguments); - }; - - // Backbone.Router - // --------------- - - // Routers map faux-URLs to actions, and fire events when routes are - // matched. Creating a new one sets its `routes` hash, if not set statically. - var Router = Backbone.Router = function(options) { - options || (options = {}); - if (options.routes) this.routes = options.routes; - this._bindRoutes(); - this.initialize.apply(this, arguments); - }; - - // Cached regular expressions for matching named param parts and splatted - // parts of route strings. - var optionalParam = /\((.*?)\)/g; - var namedParam = /(\(\?)?:\w+/g; - var splatParam = /\*\w+/g; - var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; - - // Set up all inheritable **Backbone.Router** properties and methods. - _.extend(Router.prototype, Events, { - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Manually bind a single named route to a callback. For example: - // - // this.route('search/:query/p:num', 'search', function(query, num) { - // ... - // }); - // - route: function(route, name, callback) { - if (!_.isRegExp(route)) route = this._routeToRegExp(route); - if (_.isFunction(name)) { - callback = name; - name = ''; - } - if (!callback) callback = this[name]; - var router = this; - Backbone.history.route(route, function(fragment) { - var args = router._extractParameters(route, fragment); - callback && callback.apply(router, args); - router.trigger.apply(router, ['route:' + name].concat(args)); - router.trigger('route', name, args); - Backbone.history.trigger('route', router, name, args); - }); - return this; - }, - - // Simple proxy to `Backbone.history` to save a fragment into the history. - navigate: function(fragment, options) { - Backbone.history.navigate(fragment, options); - return this; - }, - - // Bind all defined routes to `Backbone.history`. We have to reverse the - // order of the routes here to support behavior where the most general - // routes can be defined at the bottom of the route map. - _bindRoutes: function() { - if (!this.routes) return; - this.routes = _.result(this, 'routes'); - var route, routes = _.keys(this.routes); - while ((route = routes.pop()) != null) { - this.route(route, this.routes[route]); - } - }, - - // Convert a route string into a regular expression, suitable for matching - // against the current location hash. - _routeToRegExp: function(route) { - route = route.replace(escapeRegExp, '\\$&') - .replace(optionalParam, '(?:$1)?') - .replace(namedParam, function(match, optional){ - return optional ? match : '([^\/]+)'; - }) - .replace(splatParam, '(.*?)'); - return new RegExp('^' + route + '$'); - }, - - // Given a route, and a URL fragment that it matches, return the array of - // extracted decoded parameters. Empty or unmatched parameters will be - // treated as `null` to normalize cross-browser behavior. - _extractParameters: function(route, fragment) { - var params = route.exec(fragment).slice(1); - return _.map(params, function(param) { - return param ? decodeURIComponent(param) : null; - }); - } - - }); - - // Backbone.History - // ---------------- - - // Handles cross-browser history management, based on either - // [pushState](http://diveintohtml5.info/history.html) and real URLs, or - // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) - // and URL fragments. If the browser supports neither (old IE, natch), - // falls back to polling. - var History = Backbone.History = function() { - this.handlers = []; - _.bindAll(this, 'checkUrl'); - - // Ensure that `History` can be used outside of the browser. - if (typeof window !== 'undefined') { - this.location = window.location; - this.history = window.history; - } - }; - - // Cached regex for stripping a leading hash/slash and trailing space. - var routeStripper = /^[#\/]|\s+$/g; - - // Cached regex for stripping leading and trailing slashes. - var rootStripper = /^\/+|\/+$/g; - - // Cached regex for detecting MSIE. - var isExplorer = /msie [\w.]+/; - - // Cached regex for removing a trailing slash. - var trailingSlash = /\/$/; - - // Has the history handling already been started? - History.started = false; - - // Set up all inheritable **Backbone.History** properties and methods. - _.extend(History.prototype, Events, { - - // The default interval to poll for hash changes, if necessary, is - // twenty times a second. - interval: 50, - - // Gets the true hash value. Cannot use location.hash directly due to bug - // in Firefox where location.hash will always be decoded. - getHash: function(window) { - var match = (window || this).location.href.match(/#(.*)$/); - return match ? match[1] : ''; - }, - - // Get the cross-browser normalized URL fragment, either from the URL, - // the hash, or the override. - getFragment: function(fragment, forcePushState) { - if (fragment == null) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname; - var root = this.root.replace(trailingSlash, ''); - if (!fragment.indexOf(root)) fragment = fragment.substr(root.length); - } else { - fragment = this.getHash(); - } - } - return fragment.replace(routeStripper, ''); - }, - - // Start the hash change handling, returning `true` if the current URL matches - // an existing route, and `false` otherwise. - start: function(options) { - if (History.started) throw new Error("Backbone.history has already been started"); - History.started = true; - - // Figure out the initial configuration. Do we need an iframe? - // Is pushState desired ... is it available? - this.options = _.extend({}, {root: '/'}, this.options, options); - this.root = this.options.root; - this._wantsHashChange = this.options.hashChange !== false; - this._wantsPushState = !!this.options.pushState; - this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - var fragment = this.getFragment(); - var docMode = document.documentMode; - var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); - - // Normalize root to always include a leading and trailing slash. - this.root = ('/' + this.root + '/').replace(rootStripper, '/'); - - if (oldIE && this._wantsHashChange) { - this.iframe = Backbone.$('' : ''); - inst._keyEvent = false; - return html; - }, - - /* Generate the month and year header. */ - _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, - secondary, monthNames, monthNamesShort) { - var changeMonth = this._get(inst, 'changeMonth'); - var changeYear = this._get(inst, 'changeYear'); - var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); - var html = '
      '; - var monthHtml = ''; - // month selection - if (secondary || !changeMonth) - monthHtml += '' + monthNames[drawMonth] + ''; - else { - var inMinYear = (minDate && minDate.getFullYear() == drawYear); - var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); - monthHtml += ''; - } - if (!showMonthAfterYear) - html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); - // year selection - if ( !inst.yearshtml ) { - inst.yearshtml = ''; - if (secondary || !changeYear) - html += '' + drawYear + ''; - else { - // determine range of years to display - var years = this._get(inst, 'yearRange').split(':'); - var thisYear = new Date().getFullYear(); - var determineYear = function(value) { - var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : - (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : - parseInt(value, 10))); - return (isNaN(year) ? thisYear : year); - }; - var year = determineYear(years[0]); - var endYear = Math.max(year, determineYear(years[1] || '')); - year = (minDate ? Math.max(year, minDate.getFullYear()) : year); - endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); - inst.yearshtml += ''; - - html += inst.yearshtml; - inst.yearshtml = null; - } - } - html += this._get(inst, 'yearSuffix'); - if (showMonthAfterYear) - html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; - html += '
      '; // Close datepicker_header - return html; - }, - - /* Adjust one of the date sub-fields. */ - _adjustInstDate: function(inst, offset, period) { - var year = inst.drawYear + (period == 'Y' ? offset : 0); - var month = inst.drawMonth + (period == 'M' ? offset : 0); - var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + - (period == 'D' ? offset : 0); - var date = this._restrictMinMax(inst, - this._daylightSavingAdjust(new Date(year, month, day))); - inst.selectedDay = date.getDate(); - inst.drawMonth = inst.selectedMonth = date.getMonth(); - inst.drawYear = inst.selectedYear = date.getFullYear(); - if (period == 'M' || period == 'Y') - this._notifyChange(inst); - }, - - /* Ensure a date is within any min/max bounds. */ - _restrictMinMax: function(inst, date) { - var minDate = this._getMinMaxDate(inst, 'min'); - var maxDate = this._getMinMaxDate(inst, 'max'); - var newDate = (minDate && date < minDate ? minDate : date); - newDate = (maxDate && newDate > maxDate ? maxDate : newDate); - return newDate; - }, - - /* Notify change of month/year. */ - _notifyChange: function(inst) { - var onChange = this._get(inst, 'onChangeMonthYear'); - if (onChange) - onChange.apply((inst.input ? inst.input[0] : null), - [inst.selectedYear, inst.selectedMonth + 1, inst]); - }, - - /* Determine the number of months to show. */ - _getNumberOfMonths: function(inst) { - var numMonths = this._get(inst, 'numberOfMonths'); - return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); - }, - - /* Determine the current maximum date - ensure no time components are set. */ - _getMinMaxDate: function(inst, minMax) { - return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); - }, - - /* Find the number of days in a given month. */ - _getDaysInMonth: function(year, month) { - return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); - }, - - /* Find the day of the week of the first of a month. */ - _getFirstDayOfMonth: function(year, month) { - return new Date(year, month, 1).getDay(); - }, - - /* Determines if we should allow a "next/prev" month display change. */ - _canAdjustMonth: function(inst, offset, curYear, curMonth) { - var numMonths = this._getNumberOfMonths(inst); - var date = this._daylightSavingAdjust(new Date(curYear, - curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); - if (offset < 0) - date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); - return this._isInRange(inst, date); - }, - - /* Is the given date in the accepted range? */ - _isInRange: function(inst, date) { - var minDate = this._getMinMaxDate(inst, 'min'); - var maxDate = this._getMinMaxDate(inst, 'max'); - return ((!minDate || date.getTime() >= minDate.getTime()) && - (!maxDate || date.getTime() <= maxDate.getTime())); - }, - - /* Provide the configuration settings for formatting/parsing. */ - _getFormatConfig: function(inst) { - var shortYearCutoff = this._get(inst, 'shortYearCutoff'); - shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : - new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); - return {shortYearCutoff: shortYearCutoff, - dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), - monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; - }, - - /* Format the given date for display. */ - _formatDate: function(inst, day, month, year) { - if (!day) { - inst.currentDay = inst.selectedDay; - inst.currentMonth = inst.selectedMonth; - inst.currentYear = inst.selectedYear; - } - var date = (day ? (typeof day == 'object' ? day : - this._daylightSavingAdjust(new Date(year, month, day))) : - this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); - return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); - } -}); - -/* - * Bind hover events for datepicker elements. - * Done via delegate so the binding only occurs once in the lifetime of the parent div. - * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. - */ -function bindHover(dpDiv) { - var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; - return dpDiv.delegate(selector, 'mouseout', function() { - $(this).removeClass('ui-state-hover'); - if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover'); - if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover'); - }) - .delegate(selector, 'mouseover', function(){ - if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { - $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); - $(this).addClass('ui-state-hover'); - if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover'); - if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover'); - } - }); -} - -/* jQuery extend now ignores nulls! */ -function extendRemove(target, props) { - $.extend(target, props); - for (var name in props) - if (props[name] == null || props[name] == undefined) - target[name] = props[name]; - return target; -}; - -/* Invoke the datepicker functionality. - @param options string - a command, optionally followed by additional parameters or - Object - settings for attaching new datepicker functionality - @return jQuery object */ -$.fn.datepicker = function(options){ - - /* Verify an empty collection wasn't passed - Fixes #6976 */ - if ( !this.length ) { - return this; - } - - /* Initialise the date picker. */ - if (!$.datepicker.initialized) { - $(document).mousedown($.datepicker._checkExternalClick). - find(document.body).append($.datepicker.dpDiv); - $.datepicker.initialized = true; - } - - var otherArgs = Array.prototype.slice.call(arguments, 1); - if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) - return $.datepicker['_' + options + 'Datepicker']. - apply($.datepicker, [this[0]].concat(otherArgs)); - if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') - return $.datepicker['_' + options + 'Datepicker']. - apply($.datepicker, [this[0]].concat(otherArgs)); - return this.each(function() { - typeof options == 'string' ? - $.datepicker['_' + options + 'Datepicker']. - apply($.datepicker, [this].concat(otherArgs)) : - $.datepicker._attachDatepicker(this, options); - }); -}; - -$.datepicker = new Datepicker(); // singleton instance -$.datepicker.initialized = false; -$.datepicker.uuid = new Date().getTime(); -$.datepicker.version = "1.9.2"; - -// Workaround for #4055 -// Add another global to avoid noConflict issues with inline event handlers -window['DP_jQuery_' + dpuuid] = $; - -})(jQuery); -(function( $, undefined ) { - -var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ", - sizeRelatedOptions = { - buttons: true, - height: true, - maxHeight: true, - maxWidth: true, - minHeight: true, - minWidth: true, - width: true - }, - resizableRelatedOptions = { - maxHeight: true, - maxWidth: true, - minHeight: true, - minWidth: true - }; - -$.widget("ui.dialog", { - version: "1.9.2", - options: { - autoOpen: true, - buttons: {}, - closeOnEscape: true, - closeText: "close", - dialogClass: "", - draggable: true, - hide: null, - height: "auto", - maxHeight: false, - maxWidth: false, - minHeight: 150, - minWidth: 150, - modal: false, - position: { - my: "center", - at: "center", - of: window, - collision: "fit", - // ensure that the titlebar is never outside the document - using: function( pos ) { - var topOffset = $( this ).css( pos ).offset().top; - if ( topOffset < 0 ) { - $( this ).css( "top", pos.top - topOffset ); - } - } - }, - resizable: true, - show: null, - stack: true, - title: "", - width: 300, - zIndex: 1000 - }, - - _create: function() { - this.originalTitle = this.element.attr( "title" ); - // #5742 - .attr() might return a DOMElement - if ( typeof this.originalTitle !== "string" ) { - this.originalTitle = ""; - } - this.oldPosition = { - parent: this.element.parent(), - index: this.element.parent().children().index( this.element ) - }; - this.options.title = this.options.title || this.originalTitle; - var that = this, - options = this.options, - - title = options.title || " ", - uiDialog, - uiDialogTitlebar, - uiDialogTitlebarClose, - uiDialogTitle, - uiDialogButtonPane; - - uiDialog = ( this.uiDialog = $( "
      " ) ) - .addClass( uiDialogClasses + options.dialogClass ) - .css({ - display: "none", - outline: 0, // TODO: move to stylesheet - zIndex: options.zIndex - }) - // setting tabIndex makes the div focusable - .attr( "tabIndex", -1) - .keydown(function( event ) { - if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && - event.keyCode === $.ui.keyCode.ESCAPE ) { - that.close( event ); - event.preventDefault(); - } - }) - .mousedown(function( event ) { - that.moveToTop( false, event ); - }) - .appendTo( "body" ); - - this.element - .show() - .removeAttr( "title" ) - .addClass( "ui-dialog-content ui-widget-content" ) - .appendTo( uiDialog ); - - uiDialogTitlebar = ( this.uiDialogTitlebar = $( "
      " ) ) - .addClass( "ui-dialog-titlebar ui-widget-header " + - "ui-corner-all ui-helper-clearfix" ) - .bind( "mousedown", function() { - // Dialog isn't getting focus when dragging (#8063) - uiDialog.focus(); - }) - .prependTo( uiDialog ); - - uiDialogTitlebarClose = $( "" ) - .addClass( "ui-dialog-titlebar-close ui-corner-all" ) - .attr( "role", "button" ) - .click(function( event ) { - event.preventDefault(); - that.close( event ); - }) - .appendTo( uiDialogTitlebar ); - - ( this.uiDialogTitlebarCloseText = $( "" ) ) - .addClass( "ui-icon ui-icon-closethick" ) - .text( options.closeText ) - .appendTo( uiDialogTitlebarClose ); - - uiDialogTitle = $( "" ) - .uniqueId() - .addClass( "ui-dialog-title" ) - .html( title ) - .prependTo( uiDialogTitlebar ); - - uiDialogButtonPane = ( this.uiDialogButtonPane = $( "
      " ) ) - .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); - - ( this.uiButtonSet = $( "
      " ) ) - .addClass( "ui-dialog-buttonset" ) - .appendTo( uiDialogButtonPane ); - - uiDialog.attr({ - role: "dialog", - "aria-labelledby": uiDialogTitle.attr( "id" ) - }); - - uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection(); - this._hoverable( uiDialogTitlebarClose ); - this._focusable( uiDialogTitlebarClose ); - - if ( options.draggable && $.fn.draggable ) { - this._makeDraggable(); - } - if ( options.resizable && $.fn.resizable ) { - this._makeResizable(); - } - - this._createButtons( options.buttons ); - this._isOpen = false; - - if ( $.fn.bgiframe ) { - uiDialog.bgiframe(); - } - - // prevent tabbing out of modal dialogs - this._on( uiDialog, { keydown: function( event ) { - if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) { - return; - } - - var tabbables = $( ":tabbable", uiDialog ), - first = tabbables.filter( ":first" ), - last = tabbables.filter( ":last" ); - - if ( event.target === last[0] && !event.shiftKey ) { - first.focus( 1 ); - return false; - } else if ( event.target === first[0] && event.shiftKey ) { - last.focus( 1 ); - return false; - } - }}); - }, - - _init: function() { - if ( this.options.autoOpen ) { - this.open(); - } - }, - - _destroy: function() { - var next, - oldPosition = this.oldPosition; - - if ( this.overlay ) { - this.overlay.destroy(); - } - this.uiDialog.hide(); - this.element - .removeClass( "ui-dialog-content ui-widget-content" ) - .hide() - .appendTo( "body" ); - this.uiDialog.remove(); - - if ( this.originalTitle ) { - this.element.attr( "title", this.originalTitle ); - } - - next = oldPosition.parent.children().eq( oldPosition.index ); - // Don't try to place the dialog next to itself (#8613) - if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { - next.before( this.element ); - } else { - oldPosition.parent.append( this.element ); - } - }, - - widget: function() { - return this.uiDialog; - }, - - close: function( event ) { - var that = this, - maxZ, thisZ; - - if ( !this._isOpen ) { - return; - } - - if ( false === this._trigger( "beforeClose", event ) ) { - return; - } - - this._isOpen = false; - - if ( this.overlay ) { - this.overlay.destroy(); - } - - if ( this.options.hide ) { - this._hide( this.uiDialog, this.options.hide, function() { - that._trigger( "close", event ); - }); - } else { - this.uiDialog.hide(); - this._trigger( "close", event ); - } - - $.ui.dialog.overlay.resize(); - - // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) - if ( this.options.modal ) { - maxZ = 0; - $( ".ui-dialog" ).each(function() { - if ( this !== that.uiDialog[0] ) { - thisZ = $( this ).css( "z-index" ); - if ( !isNaN( thisZ ) ) { - maxZ = Math.max( maxZ, thisZ ); - } - } - }); - $.ui.dialog.maxZ = maxZ; - } - - return this; - }, - - isOpen: function() { - return this._isOpen; - }, - - // the force parameter allows us to move modal dialogs to their correct - // position on open - moveToTop: function( force, event ) { - var options = this.options, - saveScroll; - - if ( ( options.modal && !force ) || - ( !options.stack && !options.modal ) ) { - return this._trigger( "focus", event ); - } - - if ( options.zIndex > $.ui.dialog.maxZ ) { - $.ui.dialog.maxZ = options.zIndex; - } - if ( this.overlay ) { - $.ui.dialog.maxZ += 1; - $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ; - this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ ); - } - - // Save and then restore scroll - // Opera 9.5+ resets when parent z-index is changed. - // http://bugs.jqueryui.com/ticket/3193 - saveScroll = { - scrollTop: this.element.scrollTop(), - scrollLeft: this.element.scrollLeft() - }; - $.ui.dialog.maxZ += 1; - this.uiDialog.css( "z-index", $.ui.dialog.maxZ ); - this.element.attr( saveScroll ); - this._trigger( "focus", event ); - - return this; - }, - - open: function() { - if ( this._isOpen ) { - return; - } - - var hasFocus, - options = this.options, - uiDialog = this.uiDialog; - - this._size(); - this._position( options.position ); - uiDialog.show( options.show ); - this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null; - this.moveToTop( true ); - - // set focus to the first tabbable element in the content area or the first button - // if there are no tabbable elements, set focus on the dialog itself - hasFocus = this.element.find( ":tabbable" ); - if ( !hasFocus.length ) { - hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); - if ( !hasFocus.length ) { - hasFocus = uiDialog; - } - } - hasFocus.eq( 0 ).focus(); - - this._isOpen = true; - this._trigger( "open" ); - - return this; - }, - - _createButtons: function( buttons ) { - var that = this, - hasButtons = false; - - // if we already have a button pane, remove it - this.uiDialogButtonPane.remove(); - this.uiButtonSet.empty(); - - if ( typeof buttons === "object" && buttons !== null ) { - $.each( buttons, function() { - return !(hasButtons = true); - }); - } - if ( hasButtons ) { - $.each( buttons, function( name, props ) { - var button, click; - props = $.isFunction( props ) ? - { click: props, text: name } : - props; - // Default to a non-submitting button - props = $.extend( { type: "button" }, props ); - // Change the context for the click callback to be the main element - click = props.click; - props.click = function() { - click.apply( that.element[0], arguments ); - }; - button = $( "", props ) - .appendTo( that.uiButtonSet ); - if ( $.fn.button ) { - button.button(); - } - }); - this.uiDialog.addClass( "ui-dialog-buttons" ); - this.uiDialogButtonPane.appendTo( this.uiDialog ); - } else { - this.uiDialog.removeClass( "ui-dialog-buttons" ); - } - }, - - _makeDraggable: function() { - var that = this, - options = this.options; - - function filteredUi( ui ) { - return { - position: ui.position, - offset: ui.offset - }; - } - - this.uiDialog.draggable({ - cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", - handle: ".ui-dialog-titlebar", - containment: "document", - start: function( event, ui ) { - $( this ) - .addClass( "ui-dialog-dragging" ); - that._trigger( "dragStart", event, filteredUi( ui ) ); - }, - drag: function( event, ui ) { - that._trigger( "drag", event, filteredUi( ui ) ); - }, - stop: function( event, ui ) { - options.position = [ - ui.position.left - that.document.scrollLeft(), - ui.position.top - that.document.scrollTop() - ]; - $( this ) - .removeClass( "ui-dialog-dragging" ); - that._trigger( "dragStop", event, filteredUi( ui ) ); - $.ui.dialog.overlay.resize(); - } - }); - }, - - _makeResizable: function( handles ) { - handles = (handles === undefined ? this.options.resizable : handles); - var that = this, - options = this.options, - // .ui-resizable has position: relative defined in the stylesheet - // but dialogs have to use absolute or fixed positioning - position = this.uiDialog.css( "position" ), - resizeHandles = typeof handles === 'string' ? - handles : - "n,e,s,w,se,sw,ne,nw"; - - function filteredUi( ui ) { - return { - originalPosition: ui.originalPosition, - originalSize: ui.originalSize, - position: ui.position, - size: ui.size - }; - } - - this.uiDialog.resizable({ - cancel: ".ui-dialog-content", - containment: "document", - alsoResize: this.element, - maxWidth: options.maxWidth, - maxHeight: options.maxHeight, - minWidth: options.minWidth, - minHeight: this._minHeight(), - handles: resizeHandles, - start: function( event, ui ) { - $( this ).addClass( "ui-dialog-resizing" ); - that._trigger( "resizeStart", event, filteredUi( ui ) ); - }, - resize: function( event, ui ) { - that._trigger( "resize", event, filteredUi( ui ) ); - }, - stop: function( event, ui ) { - $( this ).removeClass( "ui-dialog-resizing" ); - options.height = $( this ).height(); - options.width = $( this ).width(); - that._trigger( "resizeStop", event, filteredUi( ui ) ); - $.ui.dialog.overlay.resize(); - } - }) - .css( "position", position ) - .find( ".ui-resizable-se" ) - .addClass( "ui-icon ui-icon-grip-diagonal-se" ); - }, - - _minHeight: function() { - var options = this.options; - - if ( options.height === "auto" ) { - return options.minHeight; - } else { - return Math.min( options.minHeight, options.height ); - } - }, - - _position: function( position ) { - var myAt = [], - offset = [ 0, 0 ], - isVisible; - - if ( position ) { - // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( - // if (typeof position == 'string' || $.isArray(position)) { - // myAt = $.isArray(position) ? position : position.split(' '); - - if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { - myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ]; - if ( myAt.length === 1 ) { - myAt[ 1 ] = myAt[ 0 ]; - } - - $.each( [ "left", "top" ], function( i, offsetPosition ) { - if ( +myAt[ i ] === myAt[ i ] ) { - offset[ i ] = myAt[ i ]; - myAt[ i ] = offsetPosition; - } - }); - - position = { - my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + - myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), - at: myAt.join( " " ) - }; - } - - position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); - } else { - position = $.ui.dialog.prototype.options.position; - } - - // need to show the dialog to get the actual offset in the position plugin - isVisible = this.uiDialog.is( ":visible" ); - if ( !isVisible ) { - this.uiDialog.show(); - } - this.uiDialog.position( position ); - if ( !isVisible ) { - this.uiDialog.hide(); - } - }, - - _setOptions: function( options ) { - var that = this, - resizableOptions = {}, - resize = false; - - $.each( options, function( key, value ) { - that._setOption( key, value ); - - if ( key in sizeRelatedOptions ) { - resize = true; - } - if ( key in resizableRelatedOptions ) { - resizableOptions[ key ] = value; - } - }); - - if ( resize ) { - this._size(); - } - if ( this.uiDialog.is( ":data(resizable)" ) ) { - this.uiDialog.resizable( "option", resizableOptions ); - } - }, - - _setOption: function( key, value ) { - var isDraggable, isResizable, - uiDialog = this.uiDialog; - - switch ( key ) { - case "buttons": - this._createButtons( value ); - break; - case "closeText": - // ensure that we always pass a string - this.uiDialogTitlebarCloseText.text( "" + value ); - break; - case "dialogClass": - uiDialog - .removeClass( this.options.dialogClass ) - .addClass( uiDialogClasses + value ); - break; - case "disabled": - if ( value ) { - uiDialog.addClass( "ui-dialog-disabled" ); - } else { - uiDialog.removeClass( "ui-dialog-disabled" ); - } - break; - case "draggable": - isDraggable = uiDialog.is( ":data(draggable)" ); - if ( isDraggable && !value ) { - uiDialog.draggable( "destroy" ); - } - - if ( !isDraggable && value ) { - this._makeDraggable(); - } - break; - case "position": - this._position( value ); - break; - case "resizable": - // currently resizable, becoming non-resizable - isResizable = uiDialog.is( ":data(resizable)" ); - if ( isResizable && !value ) { - uiDialog.resizable( "destroy" ); - } - - // currently resizable, changing handles - if ( isResizable && typeof value === "string" ) { - uiDialog.resizable( "option", "handles", value ); - } - - // currently non-resizable, becoming resizable - if ( !isResizable && value !== false ) { - this._makeResizable( value ); - } - break; - case "title": - // convert whatever was passed in o a string, for html() to not throw up - $( ".ui-dialog-title", this.uiDialogTitlebar ) - .html( "" + ( value || " " ) ); - break; - } - - this._super( key, value ); - }, - - _size: function() { - /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content - * divs will both have width and height set, so we need to reset them - */ - var nonContentHeight, minContentHeight, autoHeight, - options = this.options, - isVisible = this.uiDialog.is( ":visible" ); - - // reset content sizing - this.element.show().css({ - width: "auto", - minHeight: 0, - height: 0 - }); - - if ( options.minWidth > options.width ) { - options.width = options.minWidth; - } - - // reset wrapper sizing - // determine the height of all the non-content elements - nonContentHeight = this.uiDialog.css({ - height: "auto", - width: options.width - }) - .outerHeight(); - minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); - - if ( options.height === "auto" ) { - // only needed for IE6 support - if ( $.support.minHeight ) { - this.element.css({ - minHeight: minContentHeight, - height: "auto" - }); - } else { - this.uiDialog.show(); - autoHeight = this.element.css( "height", "auto" ).height(); - if ( !isVisible ) { - this.uiDialog.hide(); - } - this.element.height( Math.max( autoHeight, minContentHeight ) ); - } - } else { - this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); - } - - if (this.uiDialog.is( ":data(resizable)" ) ) { - this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); - } - } -}); - -$.extend($.ui.dialog, { - uuid: 0, - maxZ: 0, - - getTitleId: function($el) { - var id = $el.attr( "id" ); - if ( !id ) { - this.uuid += 1; - id = this.uuid; - } - return "ui-dialog-title-" + id; - }, - - overlay: function( dialog ) { - this.$el = $.ui.dialog.overlay.create( dialog ); - } -}); - -$.extend( $.ui.dialog.overlay, { - instances: [], - // reuse old instances due to IE memory leak with alpha transparency (see #5185) - oldInstances: [], - maxZ: 0, - events: $.map( - "focus,mousedown,mouseup,keydown,keypress,click".split( "," ), - function( event ) { - return event + ".dialog-overlay"; - } - ).join( " " ), - create: function( dialog ) { - if ( this.instances.length === 0 ) { - // prevent use of anchors and inputs - // we use a setTimeout in case the overlay is created from an - // event that we're going to be cancelling (see #2804) - setTimeout(function() { - // handle $(el).dialog().dialog('close') (see #4065) - if ( $.ui.dialog.overlay.instances.length ) { - $( document ).bind( $.ui.dialog.overlay.events, function( event ) { - // stop events if the z-index of the target is < the z-index of the overlay - // we cannot return true when we don't want to cancel the event (#3523) - if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) { - return false; - } - }); - } - }, 1 ); - - // handle window resize - $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize ); - } - - var $el = ( this.oldInstances.pop() || $( "
      " ).addClass( "ui-widget-overlay" ) ); - - // allow closing by pressing the escape key - $( document ).bind( "keydown.dialog-overlay", function( event ) { - var instances = $.ui.dialog.overlay.instances; - // only react to the event if we're the top overlay - if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el && - dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && - event.keyCode === $.ui.keyCode.ESCAPE ) { - - dialog.close( event ); - event.preventDefault(); - } - }); - - $el.appendTo( document.body ).css({ - width: this.width(), - height: this.height() - }); - - if ( $.fn.bgiframe ) { - $el.bgiframe(); - } - - this.instances.push( $el ); - return $el; - }, - - destroy: function( $el ) { - var indexOf = $.inArray( $el, this.instances ), - maxZ = 0; - - if ( indexOf !== -1 ) { - this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] ); - } - - if ( this.instances.length === 0 ) { - $( [ document, window ] ).unbind( ".dialog-overlay" ); - } - - $el.height( 0 ).width( 0 ).remove(); - - // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) - $.each( this.instances, function() { - maxZ = Math.max( maxZ, this.css( "z-index" ) ); - }); - this.maxZ = maxZ; - }, - - height: function() { - var scrollHeight, - offsetHeight; - // handle IE - if ( $.ui.ie ) { - scrollHeight = Math.max( - document.documentElement.scrollHeight, - document.body.scrollHeight - ); - offsetHeight = Math.max( - document.documentElement.offsetHeight, - document.body.offsetHeight - ); - - if ( scrollHeight < offsetHeight ) { - return $( window ).height() + "px"; - } else { - return scrollHeight + "px"; - } - // handle "good" browsers - } else { - return $( document ).height() + "px"; - } - }, - - width: function() { - var scrollWidth, - offsetWidth; - // handle IE - if ( $.ui.ie ) { - scrollWidth = Math.max( - document.documentElement.scrollWidth, - document.body.scrollWidth - ); - offsetWidth = Math.max( - document.documentElement.offsetWidth, - document.body.offsetWidth - ); - - if ( scrollWidth < offsetWidth ) { - return $( window ).width() + "px"; - } else { - return scrollWidth + "px"; - } - // handle "good" browsers - } else { - return $( document ).width() + "px"; - } - }, - - resize: function() { - /* If the dialog is draggable and the user drags it past the - * right edge of the window, the document becomes wider so we - * need to stretch the overlay. If the user then drags the - * dialog back to the left, the document will become narrower, - * so we need to shrink the overlay to the appropriate size. - * This is handled by shrinking the overlay before setting it - * to the full document size. - */ - var $overlays = $( [] ); - $.each( $.ui.dialog.overlay.instances, function() { - $overlays = $overlays.add( this ); - }); - - $overlays.css({ - width: 0, - height: 0 - }).css({ - width: $.ui.dialog.overlay.width(), - height: $.ui.dialog.overlay.height() - }); - } -}); - -$.extend( $.ui.dialog.overlay.prototype, { - destroy: function() { - $.ui.dialog.overlay.destroy( this.$el ); - } -}); - -}( jQuery ) ); -(function( $, undefined ) { - -var mouseHandled = false; - -$.widget( "ui.menu", { - version: "1.9.2", - defaultElement: "
      "+(o[0]>0&&I==o[1]-1?'
      ':""):""),F+=U}B+=F}return B+=x+($.ui.ie6&&!e.inline?'':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='
      ',h="";if(s||!a)h+=''+o[t]+"";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='"}l||(c+=h+(s||!a||!f?" ":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+=''+n+"";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?" ":"")+h),c+="
      ",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&tr?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.2",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.2",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||" ",s,o,u,a,f;s=(this.uiDialog=e("
      ")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),o=(this.uiDialogTitlebar=e("
      ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").bind("mousedown",function(){s.focus()}).prependTo(s),u=e("").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(o),(this.uiDialogTitlebarCloseText=e("")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u),a=e("").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o),f=(this.uiDialogButtonPane=e("
      ")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),(this.uiButtonSet=e("
      ")).addClass("ui-dialog-buttonset").appendTo(f),s.attr({role:"dialog","aria-labelledby":a.attr("id")}),o.find("*").add(o).disableSelection(),this._hoverable(u),this._focusable(u),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n=this,r=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(r=!0)}),r?(e.each(t,function(t,r){var i,s;r=e.isFunction(r)?{click:r,text:t}:r,r=e.extend({type:"button"},r),s=r.click,r.click=function(){s.apply(n.element[0],arguments)},i=e("",r).appendTo(n.uiButtonSet),e.fn.button&&i.button()}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)):this.uiDialog.removeClass("ui-dialog-buttons")},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s)),e.ui.dialog.overlay.resize()}})},_makeResizable:function(n){function u(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}n=n===t?this.options.resizable:n;var r=this,i=this.options,s=this.uiDialog.css("position"),o=typeof n=="string"?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:o,start:function(t,n){e(this).addClass("ui-dialog-resizing"),r._trigger("resizeStart",t,u(n))},resize:function(e,t){r._trigger("resize",e,u(t))},stop:function(t,n){e(this).removeClass("ui-dialog-resizing"),i.height=e(this).height(),i.width=e(this).width(),r._trigger("resizeStop",t,u(n)),e.ui.dialog.overlay.resize()}}).css("position",s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(t){var n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()},_setOptions:function(t){var n=this,s={},o=!1;e.each(t,function(e,t){n._setOption(e,t),e in r&&(o=!0),e in i&&(s[e]=t)}),o&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",s)},_setOption:function(t,r){var i,s,o=this.uiDialog;switch(t){case"buttons":this._createButtons(r);break;case"closeText":this.uiDialogTitlebarCloseText.text(""+r);break;case"dialogClass":o.removeClass(this.options.dialogClass).addClass(n+r);break;case"disabled":r?o.addClass("ui-dialog-disabled"):o.removeClass("ui-dialog-disabled");break;case"draggable":i=o.is(":data(draggable)"),i&&!r&&o.draggable("destroy"),!i&&r&&this._makeDraggable();break;case"position":this._position(r);break;case"resizable":s=o.is(":data(resizable)"),s&&!r&&o.resizable("destroy"),s&&typeof r=="string"&&o.resizable("option","handles",r),!s&&r!==!1&&this._makeResizable(r);break;case"title":e(".ui-dialog-title",this.uiDialogTitlebar).html(""+(r||" "))}this._super(t,r)},_size:function(){var t,n,r,i=this.options,s=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),i.minWidth>i.width&&(i.width=i.minWidth),t=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),n=Math.max(0,i.minHeight-t),i.height==="auto"?e.support.minHeight?this.element.css({minHeight:n,height:"auto"}):(this.uiDialog.show(),r=this.element.css("height","auto").height(),s||this.uiDialog.hide(),this.element.height(Math.max(r,n))):this.element.height(Math.max(i.height-t,0)),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),e.extend(e.ui.dialog,{uuid:0,maxZ:0,getTitleId:function(e){var t=e.attr("id");return t||(this.uuid+=1,t=this.uuid),"ui-dialog-title-"+t},overlay:function(t){this.$el=e.ui.dialog.overlay.create(t)}}),e.extend(e.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(e){return e+".dialog-overlay"}).join(" "),create:function(t){this.instances.length===0&&(setTimeout(function(){e.ui.dialog.overlay.instances.length&&e(document).bind(e.ui.dialog.overlay.events,function(t){if(e(t.target).zIndex()").addClass("ui-widget-overlay");return e(document).bind("keydown.dialog-overlay",function(r){var i=e.ui.dialog.overlay.instances;i.length!==0&&i[i.length-1]===n&&t.options.closeOnEscape&&!r.isDefaultPrevented()&&r.keyCode&&r.keyCode===e.ui.keyCode.ESCAPE&&(t.close(r),r.preventDefault())}),n.appendTo(document.body).css({width:this.width(),height:this.height()}),e.fn.bgiframe&&n.bgiframe(),this.instances.push(n),n},destroy:function(t){var n=e.inArray(t,this.instances),r=0;n!==-1&&this.oldInstances.push(this.instances.splice(n,1)[0]),this.instances.length===0&&e([document,window]).unbind(".dialog-overlay"),t.height(0).width(0).remove(),e.each(this.instances,function(){r=Math.max(r,this.css("z-index"))}),this.maxZ=r},height:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),n=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),t",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()
      ").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return e===t?this._value():(this._setOption("value",e),this)},_setOption:function(e,t){e==="value"&&(this.options.value=t,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),this._super(e,t)},_value:function(){var e=this.options.value;return typeof e!="number"&&(e=0),Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var e=this.value(),t=this._percentage();this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),this.valueDiv.toggle(e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(t.toFixed(0)+"%"),this.element.attr("aria-valuenow",e)}})})(jQuery);(function(e,t){var n=5;e.widget("ui.slider",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var t,r,i=this.options,s=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),o="",u=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(i.disabled?" ui-slider-disabled ui-disabled":"")),this.range=e([]),i.range&&(i.range===!0&&(i.values||(i.values=[this._valueMin(),this._valueMin()]),i.values.length&&i.values.length!==2&&(i.values=[i.values[0],i.values[0]])),this.range=e("
      ").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(i.range==="min"||i.range==="max"?" ui-slider-range-"+i.range:""))),r=i.values&&i.values.length||1;for(t=s.length;tn&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e){function t(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.widget("ui.spinner",{version:"1.9.2",defaultElement:"",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""+""+""+""+""},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e1&&e.href.replace(r,"")===location.href.replace(r,"").replace(/\s/g,"%20")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options,r=n.active,i=location.hash.substring(1);this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(r===null){i&&this.tabs.each(function(t,n){if(e(n).attr("aria-controls")===i)return r=t,!1}),r===null&&(r=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(r===null||r===-1)r=this.tabs.length?0:!1}r!==!1&&(r=this.tabs.index(this.tabs.eq(r)),r===-1&&(r=n.collapsible?!1:0)),n.active=r,!n.collapsible&&n.active===!1&&this.anchors.length&&(n.active=0),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
      ").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"Loading…"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"
    • #{label}
    • "},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"
      "},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r,i,s=this._superApply(arguments);return s?(e==="beforeActivate"?(r=n.newTab.length?n.newTab:n.oldTab,i=n.newPanel.length?n.newPanel:n.oldPanel,s=this._super("select",t,{tab:r.find(".ui-tabs-anchor")[0],panel:i[0],index:r.closest("li").index()})):e==="activate"&&n.newTab.length&&(s=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),s):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.2",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("
      ").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("
      ").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery);jQuery.effects||function(e,t){var n=e.uiBackCompat!==!1,r="ui-effects-";e.effects={effect:{}},function(t,n){function p(e,t,n){var r=a[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[];i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(l){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i;if(t&&t.length&&t[0]&&t[t[0]]){i=t.length;while(i--)r=t[i],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.2",save:function(e,t){for(var n=0;n
      ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function a(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,s=t.mode;(r.is(":hidden")?s==="hide":s==="show")?u():o.call(r[0],t,u)}var t=i.apply(this,arguments),r=t.mode,s=t.queue,o=e.effects.effect[t.effect],u=!o&&n&&e.effects[t.effect];return e.fx.off||!o&&!u?r?this[r](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):o?s===!1?this.each(a):this.queue(s||"fx",a):u.call(this,{options:t,duration:t.duration,callback:t.complete,mode:t.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h
      ").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u,outerHeight:a.outerHeight*u,outerWidth:a.outerWidth*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r,i,s,o=e(this),u=["position","top","bottom","left","right","width","height","overflow","opacity"],a=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],l=["fontSize"],c=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),d=t.restore||p!=="effect",v=t.scale||"both",m=t.origin||["middle","center"],g=o.css("position"),y=d?u:a,b={height:0,width:0,outerHeight:0,outerWidth:0};p==="show"&&o.show(),r={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},t.mode==="toggle"&&p==="show"?(o.from=t.to||b,o.to=t.from||r):(o.from=t.from||(p==="show"?b:r),o.to=t.to||(p==="hide"?b:r)),s={from:{y:o.from.height/r.height,x:o.from.width/r.width},to:{y:o.to.height/r.height,x:o.to.width/r.width}};if(v==="box"||v==="both")s.from.y!==s.to.y&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,s.from.y,o.from),o.to=e.effects.setTransition(o,c,s.to.y,o.to)),s.from.x!==s.to.x&&(y=y.concat(h),o.from=e.effects.setTransition(o,h,s.from.x,o.from),o.to=e.effects.setTransition(o,h,s.to.x,o.to));(v==="content"||v==="both")&&s.from.y!==s.to.y&&(y=y.concat(l).concat(f),o.from=e.effects.setTransition(o,l,s.from.y,o.from),o.to=e.effects.setTransition(o,l,s.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(i=e.effects.getBaseline(m,r),o.from.top=(r.outerHeight-o.outerHeight())*i.y,o.from.left=(r.outerWidth-o.outerWidth())*i.x,o.to.top=(r.outerHeight-o.to.outerHeight)*i.y,o.to.left=(r.outerWidth-o.to.outerWidth)*i.x),o.css(o.from);if(v==="content"||v==="both")c=c.concat(["marginTop","marginBottom"]).concat(l),h=h.concat(["marginLeft","marginRight"]),f=u.concat(c).concat(h),o.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()};d&&e.effects.save(n,f),n.from={height:r.height*s.from.y,width:r.width*s.from.x,outerHeight:r.outerHeight*s.from.y,outerWidth:r.outerWidth*s.from.x},n.to={height:r.height*s.to.y,width:r.width*s.to.x,outerHeight:r.height*s.to.y,outerWidth:r.width*s.to.x},s.from.y!==s.to.y&&(n.from=e.effects.setTransition(n,c,s.from.y,n.from),n.to=e.effects.setTransition(n,c,s.to.y,n.to)),s.from.x!==s.to.x&&(n.from=e.effects.setTransition(n,h,s.from.x,n.from),n.to=e.effects.setTransition(n,h,s.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){d&&e.effects.restore(n,f)})});o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o.to.opacity===0&&o.css("opacity",o.from.opacity),p==="hide"&&o.hide(),e.effects.restore(o,y),d||(g==="static"?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,n){var r=parseInt(n,10),i=e?o.to.left:o.to.top;return n==="auto"?i+"px":r+i+"px"})})),e.effects.removeWrapper(o),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e('
      ').appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery); \ No newline at end of file diff --git a/contexts/data/lib/jquery/jquery-ui.js b/contexts/data/lib/jquery/jquery-ui.js deleted file mode 120000 index 072d3a5..0000000 --- a/contexts/data/lib/jquery/jquery-ui.js +++ /dev/null @@ -1 +0,0 @@ -jquery-ui-1.9.2.custom.min.js \ No newline at end of file diff --git a/contexts/data/lib/jquery/jquery.js b/contexts/data/lib/jquery/jquery.js deleted file mode 120000 index 6217889..0000000 --- a/contexts/data/lib/jquery/jquery.js +++ /dev/null @@ -1 +0,0 @@ -jquery-1.8.3.js \ No newline at end of file diff --git a/contexts/data/lib/jshash/md5.js b/contexts/data/lib/jshash/md5.js deleted file mode 100755 index 8773a96..0000000 --- a/contexts/data/lib/jshash/md5.js +++ /dev/null @@ -1,379 +0,0 @@ -/* - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - -/* - * Configurable variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - */ -var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ -var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ - -/* - * These are the functions you'll usually want to call - * They take string arguments and return either hex or base-64 encoded strings - */ -function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); } -function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); } -function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); } -function hex_hmac_md5(k, d) - { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } -function b64_hmac_md5(k, d) - { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } -function any_hmac_md5(k, d, e) - { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } - -/* - * Perform a simple self-test to see if the VM is working - */ -function md5_vm_test() -{ - return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72"; -} - -/* - * Calculate the MD5 of a raw string - */ -function rstr_md5(s) -{ - return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); -} - -/* - * Calculate the HMAC-MD5, of a key and some data (raw strings) - */ -function rstr_hmac_md5(key, data) -{ - var bkey = rstr2binl(key); - if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); - - var ipad = Array(16), opad = Array(16); - for(var i = 0; i < 16; i++) - { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - - var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); - return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); -} - -/* - * Convert a raw string to a hex string - */ -function rstr2hex(input) -{ - try { hexcase } catch(e) { hexcase=0; } - var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; - var output = ""; - var x; - for(var i = 0; i < input.length; i++) - { - x = input.charCodeAt(i); - output += hex_tab.charAt((x >>> 4) & 0x0F) - + hex_tab.charAt( x & 0x0F); - } - return output; -} - -/* - * Convert a raw string to a base-64 string - */ -function rstr2b64(input) -{ - try { b64pad } catch(e) { b64pad=''; } - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var output = ""; - var len = input.length; - for(var i = 0; i < len; i += 3) - { - var triplet = (input.charCodeAt(i) << 16) - | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) - | (i + 2 < len ? input.charCodeAt(i+2) : 0); - for(var j = 0; j < 4; j++) - { - if(i * 8 + j * 6 > input.length * 8) output += b64pad; - else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); - } - } - return output; -} - -/* - * Convert a raw string to an arbitrary string encoding - */ -function rstr2any(input, encoding) -{ - var divisor = encoding.length; - var i, j, q, x, quotient; - - /* Convert to an array of 16-bit big-endian values, forming the dividend */ - var dividend = Array(Math.ceil(input.length / 2)); - for(i = 0; i < dividend.length; i++) - { - dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); - } - - /* - * Repeatedly perform a long division. The binary array forms the dividend, - * the length of the encoding is the divisor. Once computed, the quotient - * forms the dividend for the next step. All remainders are stored for later - * use. - */ - var full_length = Math.ceil(input.length * 8 / - (Math.log(encoding.length) / Math.log(2))); - var remainders = Array(full_length); - for(j = 0; j < full_length; j++) - { - quotient = Array(); - x = 0; - for(i = 0; i < dividend.length; i++) - { - x = (x << 16) + dividend[i]; - q = Math.floor(x / divisor); - x -= q * divisor; - if(quotient.length > 0 || q > 0) - quotient[quotient.length] = q; - } - remainders[j] = x; - dividend = quotient; - } - - /* Convert the remainders to the output string */ - var output = ""; - for(i = remainders.length - 1; i >= 0; i--) - output += encoding.charAt(remainders[i]); - - return output; -} - -/* - * Encode a string as utf-8. - * For efficiency, this assumes the input is valid utf-16. - */ -function str2rstr_utf8(input) -{ - var output = ""; - var i = -1; - var x, y; - - while(++i < input.length) - { - /* Decode utf-16 surrogate pairs */ - x = input.charCodeAt(i); - y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; - if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) - { - x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); - i++; - } - - /* Encode output as utf-8 */ - if(x <= 0x7F) - output += String.fromCharCode(x); - else if(x <= 0x7FF) - output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), - 0x80 | ( x & 0x3F)); - else if(x <= 0xFFFF) - output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), - 0x80 | ((x >>> 6 ) & 0x3F), - 0x80 | ( x & 0x3F)); - else if(x <= 0x1FFFFF) - output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), - 0x80 | ((x >>> 12) & 0x3F), - 0x80 | ((x >>> 6 ) & 0x3F), - 0x80 | ( x & 0x3F)); - } - return output; -} - -/* - * Encode a string as utf-16 - */ -function str2rstr_utf16le(input) -{ - var output = ""; - for(var i = 0; i < input.length; i++) - output += String.fromCharCode( input.charCodeAt(i) & 0xFF, - (input.charCodeAt(i) >>> 8) & 0xFF); - return output; -} - -function str2rstr_utf16be(input) -{ - var output = ""; - for(var i = 0; i < input.length; i++) - output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, - input.charCodeAt(i) & 0xFF); - return output; -} - -/* - * Convert a raw string to an array of little-endian words - * Characters >255 have their high-byte silently ignored. - */ -function rstr2binl(input) -{ - var output = Array(input.length >> 2); - for(var i = 0; i < output.length; i++) - output[i] = 0; - for(var i = 0; i < input.length * 8; i += 8) - output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32); - return output; -} - -/* - * Convert an array of little-endian words to a string - */ -function binl2rstr(input) -{ - var output = ""; - for(var i = 0; i < input.length * 32; i += 8) - output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF); - return output; -} - -/* - * Calculate the MD5 of an array of little-endian words, and a bit length. - */ -function binl_md5(x, len) -{ - /* append padding */ - x[len >> 5] |= 0x80 << ((len) % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - - for(var i = 0; i < x.length; i += 16) - { - var olda = a; - var oldb = b; - var oldc = c; - var oldd = d; - - a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); - d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); - c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); - b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); - a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); - d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); - c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); - b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); - a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); - d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); - c = md5_ff(c, d, a, b, x[i+10], 17, -42063); - b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); - a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); - d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); - c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); - b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); - - a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); - d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); - c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); - b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); - a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); - d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); - c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); - b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); - a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); - d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); - c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); - b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); - a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); - d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); - c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); - b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); - - a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); - d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); - c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); - b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); - a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); - d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); - c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); - b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); - a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); - d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); - c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); - b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); - a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); - d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); - c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); - b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); - - a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); - d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); - c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); - b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); - a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); - d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); - c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); - b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); - a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); - d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); - c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); - b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); - a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); - d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); - c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); - b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - } - return Array(a, b, c, d); -} - -/* - * These functions implement the four basic operations the algorithm uses. - */ -function md5_cmn(q, a, b, x, s, t) -{ - return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); -} -function md5_ff(a, b, c, d, x, s, t) -{ - return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); -} -function md5_gg(a, b, c, d, x, s, t) -{ - return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); -} -function md5_hh(a, b, c, d, x, s, t) -{ - return md5_cmn(b ^ c ^ d, a, b, x, s, t); -} -function md5_ii(a, b, c, d, x, s, t) -{ - return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); -} - -/* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ -function safe_add(x, y) -{ - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); -} - -/* - * Bitwise rotate a 32-bit number to the left. - */ -function bit_rol(num, cnt) -{ - return (num << cnt) | (num >>> (32 - cnt)); -} diff --git a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/MIT.LICENSE b/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/MIT.LICENSE deleted file mode 100644 index 1eb9b49..0000000 --- a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/MIT.LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-2010 Pivotal Labs - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine-html.js b/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine-html.js deleted file mode 100644 index 046cb5c..0000000 --- a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine-html.js +++ /dev/null @@ -1,188 +0,0 @@ -jasmine.TrivialReporter = function(doc) { - this.document = doc || document; - this.suiteDivs = {}; - this.logRunningSpecs = false; -}; - -jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { el.appendChild(child); } - } - } - - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; -}; - -jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { - var showPassed, showSkipped; - - this.outerDiv = this.createDom('div', { className: 'jasmine_reporter', id: 'TrivialReporter' }, - this.createDom('div', { className: 'banner' }, - this.createDom('div', { className: 'logo' }, - this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"), - this.createDom('span', { className: 'version' }, runner.env.versionString())), - this.createDom('div', { className: 'options' }, - "Show ", - showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), - showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") - ) - ), - - this.runnerDiv = this.createDom('div', { className: 'runner running' }, - this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), - this.runnerMessageSpan = this.createDom('span', {}, "Running..."), - this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) - ); - - this.document.body.appendChild(this.outerDiv); - - var suites = runner.suites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - var suiteDiv = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), - this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); - this.suiteDivs[suite.id] = suiteDiv; - var parentDiv = this.outerDiv; - if (suite.parentSuite) { - parentDiv = this.suiteDivs[suite.parentSuite.id]; - } - parentDiv.appendChild(suiteDiv); - } - - this.startedAt = new Date(); - - var self = this; - showPassed.onclick = function(evt) { - if (showPassed.checked) { - self.outerDiv.className += ' show-passed'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); - } - }; - - showSkipped.onclick = function(evt) { - if (showSkipped.checked) { - self.outerDiv.className += ' show-skipped'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); - } - }; -}; - -jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { - var results = runner.results(); - var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; - this.runnerDiv.setAttribute("class", className); - //do it twice for IE - this.runnerDiv.setAttribute("className", className); - var specs = runner.specs(); - var specCount = 0; - for (var i = 0; i < specs.length; i++) { - if (this.specFilter(specs[i])) { - specCount++; - } - } - var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); - message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; - this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); - - this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); -}; - -jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { - var results = suite.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.totalCount == 0) { // todo: change this to check results.skipped - status = 'skipped'; - } - this.suiteDivs[suite.id].className += " " + status; -}; - -jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { - if (this.logRunningSpecs) { - this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } -}; - -jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { - var results = spec.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - var specDiv = this.createDom('div', { className: 'spec ' + status }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(spec.getFullName()), - title: spec.getFullName() - }, spec.description)); - - - var resultItems = results.getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); - } - } - } - - if (messagesDiv.childNodes.length > 0) { - specDiv.appendChild(messagesDiv); - } - - this.suiteDivs[spec.suite.id].appendChild(specDiv); -}; - -jasmine.TrivialReporter.prototype.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie - } - } -}; - -jasmine.TrivialReporter.prototype.getLocation = function() { - return this.document.location; -}; - -jasmine.TrivialReporter.prototype.specFilter = function(spec) { - var paramMap = {}; - var params = this.getLocation().search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - if (!paramMap["spec"]) return true; - return spec.getFullName().indexOf(paramMap["spec"]) == 0; -}; diff --git a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.css b/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.css deleted file mode 100644 index 6583fe7..0000000 --- a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.css +++ /dev/null @@ -1,166 +0,0 @@ -body { - font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; -} - - -.jasmine_reporter a:visited, .jasmine_reporter a { - color: #303; -} - -.jasmine_reporter a:hover, .jasmine_reporter a:active { - color: blue; -} - -.run_spec { - float:right; - padding-right: 5px; - font-size: .8em; - text-decoration: none; -} - -.jasmine_reporter { - margin: 0 5px; -} - -.banner { - color: #303; - background-color: #fef; - padding: 5px; -} - -.logo { - float: left; - font-size: 1.1em; - padding-left: 5px; -} - -.logo .version { - font-size: .6em; - padding-left: 1em; -} - -.runner.running { - background-color: yellow; -} - - -.options { - text-align: right; - font-size: .8em; -} - - - - -.suite { - border: 1px outset gray; - margin: 5px 0; - padding-left: 1em; -} - -.suite .suite { - margin: 5px; -} - -.suite.passed { - background-color: #dfd; -} - -.suite.failed { - background-color: #fdd; -} - -.spec { - margin: 5px; - padding-left: 1em; - clear: both; -} - -.spec.failed, .spec.passed, .spec.skipped { - padding-bottom: 5px; - border: 1px solid gray; -} - -.spec.failed { - background-color: #fbb; - border-color: red; -} - -.spec.passed { - background-color: #bfb; - border-color: green; -} - -.spec.skipped { - background-color: #bbb; -} - -.messages { - border-left: 1px dashed gray; - padding-left: 1em; - padding-right: 1em; -} - -.passed { - background-color: #cfc; - display: none; -} - -.failed { - background-color: #fbb; -} - -.skipped { - color: #777; - background-color: #eee; - display: none; -} - - -/*.resultMessage {*/ - /*white-space: pre;*/ -/*}*/ - -.resultMessage span.result { - display: block; - line-height: 2em; - color: black; -} - -.resultMessage .mismatch { - color: black; -} - -.stackTrace { - white-space: pre; - font-size: .8em; - margin-left: 10px; - max-height: 5em; - overflow: auto; - border: 1px inset red; - padding: 1em; - background: #eef; -} - -.finished-at { - padding-left: 1em; - font-size: .6em; -} - -.show-passed .passed, -.show-skipped .skipped { - display: block; -} - - -#jasmine_content { - position:fixed; - right: 100%; -} - -.runner { - border: 1px solid gray; - display: block; - margin: 5px 0; - padding: 2px 0 2px 10px; -} diff --git a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.js b/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.js deleted file mode 100644 index 63e415d..0000000 --- a/contexts/data/lib/phantomjs_jasmine/jasmine-1.0.2/jasmine.js +++ /dev/null @@ -1,2421 +0,0 @@ -/** - * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. - * - * @namespace - */ -var jasmine = {}; - -/** - * @private - */ -jasmine.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); -}; - -/** - * Use jasmine.undefined instead of undefined, since undefined is just - * a plain old variable and may be redefined by somebody else. - * - * @private - */ -jasmine.undefined = jasmine.___undefined___; - -/** - * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. - * - */ -jasmine.DEFAULT_UPDATE_INTERVAL = 250; - -/** - * Default timeout interval in milliseconds for waitsFor() blocks. - */ -jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; - -jasmine.getGlobal = function() { - function getGlobal() { - return this; - } - - return getGlobal(); -}; - -/** - * Allows for bound functions to be compared. Internal use only. - * - * @ignore - * @private - * @param base {Object} bound 'this' for the function - * @param name {Function} function to find - */ -jasmine.bindOriginal_ = function(base, name) { - var original = base[name]; - if (original.apply) { - return function() { - return original.apply(base, arguments); - }; - } else { - // IE support - return jasmine.getGlobal()[name]; - } -}; - -jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); -jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); -jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); -jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); - -jasmine.MessageResult = function(values) { - this.type = 'log'; - this.values = values; - this.trace = new Error(); // todo: test better -}; - -jasmine.MessageResult.prototype.toString = function() { - var text = ""; - for(var i = 0; i < this.values.length; i++) { - if (i > 0) text += " "; - if (jasmine.isString_(this.values[i])) { - text += this.values[i]; - } else { - text += jasmine.pp(this.values[i]); - } - } - return text; -}; - -jasmine.ExpectationResult = function(params) { - this.type = 'expect'; - this.matcherName = params.matcherName; - this.passed_ = params.passed; - this.expected = params.expected; - this.actual = params.actual; - - this.message = this.passed_ ? 'Passed.' : params.message; - this.trace = this.passed_ ? '' : new Error(this.message); -}; - -jasmine.ExpectationResult.prototype.toString = function () { - return this.message; -}; - -jasmine.ExpectationResult.prototype.passed = function () { - return this.passed_; -}; - -/** - * Getter for the Jasmine environment. Ensures one gets created - */ -jasmine.getEnv = function() { - return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isArray_ = function(value) { - return jasmine.isA_("Array", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isString_ = function(value) { - return jasmine.isA_("String", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isNumber_ = function(value) { - return jasmine.isA_("Number", value); -}; - -/** - * @ignore - * @private - * @param {String} typeName - * @param value - * @returns {Boolean} - */ -jasmine.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; -}; - -/** - * Pretty printer for expecations. Takes any object and turns it into a human-readable string. - * - * @param value {Object} an object to be outputted - * @returns {String} - */ -jasmine.pp = function(value) { - var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; -}; - -/** - * Returns true if the object is a DOM Node. - * - * @param {Object} obj object to check - * @returns {Boolean} - */ -jasmine.isDomNode = function(obj) { - return obj['nodeType'] > 0; -}; - -/** - * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - * - * @example - * // don't care about which function is passed in, as long as it's a function - * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); - * - * @param {Class} clazz - * @returns matchable object of the type clazz - */ -jasmine.any = function(clazz) { - return new jasmine.Matchers.Any(clazz); -}; - -/** - * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. - * - * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine - * expectation syntax. Spies can be checked if they were called or not and what the calling params were. - * - * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). - * - * Spies are torn down at the end of every spec. - * - * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. - * - * @example - * // a stub - * var myStub = jasmine.createSpy('myStub'); // can be used anywhere - * - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // actual foo.not will not be called, execution stops - * spyOn(foo, 'not'); - - // foo.not spied upon, execution will continue to implementation - * spyOn(foo, 'not').andCallThrough(); - * - * // fake example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // foo.not(val) will return val - * spyOn(foo, 'not').andCallFake(function(value) {return value;}); - * - * // mock example - * foo.not(7 == 7); - * expect(foo.not).toHaveBeenCalled(); - * expect(foo.not).toHaveBeenCalledWith(true); - * - * @constructor - * @see spyOn, jasmine.createSpy, jasmine.createSpyObj - * @param {String} name - */ -jasmine.Spy = function(name) { - /** - * The name of the spy, if provided. - */ - this.identity = name || 'unknown'; - /** - * Is this Object a spy? - */ - this.isSpy = true; - /** - * The actual function this spy stubs. - */ - this.plan = function() { - }; - /** - * Tracking of the most recent call to the spy. - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy.mostRecentCall.args = [1, 2]; - */ - this.mostRecentCall = {}; - - /** - * Holds arguments for each call to the spy, indexed by call count - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy(7, 8); - * mySpy.mostRecentCall.args = [7, 8]; - * mySpy.argsForCall[0] = [1, 2]; - * mySpy.argsForCall[1] = [7, 8]; - */ - this.argsForCall = []; - this.calls = []; -}; - -/** - * Tells a spy to call through to the actual implemenatation. - * - * @example - * var foo = { - * bar: function() { // do some stuff } - * } - * - * // defining a spy on an existing property: foo.bar - * spyOn(foo, 'bar').andCallThrough(); - */ -jasmine.Spy.prototype.andCallThrough = function() { - this.plan = this.originalValue; - return this; -}; - -/** - * For setting the return value of a spy. - * - * @example - * // defining a spy from scratch: foo() returns 'baz' - * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); - * - * // defining a spy on an existing property: foo.bar() returns 'baz' - * spyOn(foo, 'bar').andReturn('baz'); - * - * @param {Object} value - */ -jasmine.Spy.prototype.andReturn = function(value) { - this.plan = function() { - return value; - }; - return this; -}; - -/** - * For throwing an exception when a spy is called. - * - * @example - * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' - * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); - * - * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' - * spyOn(foo, 'bar').andThrow('baz'); - * - * @param {String} exceptionMsg - */ -jasmine.Spy.prototype.andThrow = function(exceptionMsg) { - this.plan = function() { - throw exceptionMsg; - }; - return this; -}; - -/** - * Calls an alternate implementation when a spy is called. - * - * @example - * var baz = function() { - * // do some stuff, return something - * } - * // defining a spy from scratch: foo() calls the function baz - * var foo = jasmine.createSpy('spy on foo').andCall(baz); - * - * // defining a spy on an existing property: foo.bar() calls an anonymnous function - * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); - * - * @param {Function} fakeFunc - */ -jasmine.Spy.prototype.andCallFake = function(fakeFunc) { - this.plan = fakeFunc; - return this; -}; - -/** - * Resets all of a spy's the tracking variables so that it can be used again. - * - * @example - * spyOn(foo, 'bar'); - * - * foo.bar(); - * - * expect(foo.bar.callCount).toEqual(1); - * - * foo.bar.reset(); - * - * expect(foo.bar.callCount).toEqual(0); - */ -jasmine.Spy.prototype.reset = function() { - this.wasCalled = false; - this.callCount = 0; - this.argsForCall = []; - this.calls = []; - this.mostRecentCall = {}; -}; - -jasmine.createSpy = function(name) { - - var spyObj = function() { - spyObj.wasCalled = true; - spyObj.callCount++; - var args = jasmine.util.argsToArray(arguments); - spyObj.mostRecentCall.object = this; - spyObj.mostRecentCall.args = args; - spyObj.argsForCall.push(args); - spyObj.calls.push({object: this, args: args}); - return spyObj.plan.apply(this, arguments); - }; - - var spy = new jasmine.Spy(name); - - for (var prop in spy) { - spyObj[prop] = spy[prop]; - } - - spyObj.reset(); - - return spyObj; -}; - -/** - * Determines whether an object is a spy. - * - * @param {jasmine.Spy|Object} putativeSpy - * @returns {Boolean} - */ -jasmine.isSpy = function(putativeSpy) { - return putativeSpy && putativeSpy.isSpy; -}; - -/** - * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something - * large in one call. - * - * @param {String} baseName name of spy class - * @param {Array} methodNames array of names of methods to make spies - */ -jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length == 0) { - throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); - } - return obj; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the current spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.log = function() { - var spec = jasmine.getEnv().currentSpec; - spec.log.apply(spec, arguments); -}; - -/** - * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. - * - * @example - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops - * - * @see jasmine.createSpy - * @param obj - * @param methodName - * @returns a Jasmine spy that can be chained with all spy methods - */ -var spyOn = function(obj, methodName) { - return jasmine.getEnv().currentSpec.spyOn(obj, methodName); -}; - -/** - * Creates a Jasmine spec that will be added to the current suite. - * - * // TODO: pending tests - * - * @example - * it('should be true', function() { - * expect(true).toEqual(true); - * }); - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var it = function(desc, func) { - return jasmine.getEnv().it(desc, func); -}; - -/** - * Creates a disabled Jasmine spec. - * - * A convenience method that allows existing specs to be disabled temporarily during development. - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var xit = function(desc, func) { - return jasmine.getEnv().xit(desc, func); -}; - -/** - * Starts a chain for a Jasmine expectation. - * - * It is passed an Object that is the actual value and should chain to one of the many - * jasmine.Matchers functions. - * - * @param {Object} actual Actual value to test against and expected value - */ -var expect = function(actual) { - return jasmine.getEnv().currentSpec.expect(actual); -}; - -/** - * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. - * - * @param {Function} func Function that defines part of a jasmine spec. - */ -var runs = function(func) { - jasmine.getEnv().currentSpec.runs(func); -}; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -var waits = function(timeout) { - jasmine.getEnv().currentSpec.waits(timeout); -}; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); -}; - -/** - * A function that is called before each spec in a suite. - * - * Used for spec setup, including validating assumptions. - * - * @param {Function} beforeEachFunction - */ -var beforeEach = function(beforeEachFunction) { - jasmine.getEnv().beforeEach(beforeEachFunction); -}; - -/** - * A function that is called after each spec in a suite. - * - * Used for restoring any state that is hijacked during spec execution. - * - * @param {Function} afterEachFunction - */ -var afterEach = function(afterEachFunction) { - jasmine.getEnv().afterEach(afterEachFunction); -}; - -/** - * Defines a suite of specifications. - * - * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared - * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization - * of setup in some tests. - * - * @example - * // TODO: a simple suite - * - * // TODO: a simple suite with a nested describe block - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var describe = function(description, specDefinitions) { - return jasmine.getEnv().describe(description, specDefinitions); -}; - -/** - * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var xdescribe = function(description, specDefinitions) { - return jasmine.getEnv().xdescribe(description, specDefinitions); -}; - - -// Provide the XMLHttpRequest class for IE 5.x-6.x: -jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - try { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - } catch(e) { - } - try { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - } catch(e) { - } - try { - return new ActiveXObject("Msxml2.XMLHTTP"); - } catch(e) { - } - try { - return new ActiveXObject("Microsoft.XMLHTTP"); - } catch(e) { - } - throw new Error("This browser does not support XMLHttpRequest."); -} : XMLHttpRequest; -/** - * @namespace - */ -jasmine.util = {}; - -/** - * Declare that a child class inherit it's prototype from the parent class. - * - * @private - * @param {Function} childClass - * @param {Function} parentClass - */ -jasmine.util.inherit = function(childClass, parentClass) { - /** - * @private - */ - var subclass = function() { - }; - subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass; -}; - -jasmine.util.formatException = function(e) { - var lineNumber; - if (e.line) { - lineNumber = e.line; - } - else if (e.lineNumber) { - lineNumber = e.lineNumber; - } - - var file; - - if (e.sourceURL) { - file = e.sourceURL; - } - else if (e.fileName) { - file = e.fileName; - } - - var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); - - if (file && lineNumber) { - message += ' in ' + file + ' (line ' + lineNumber + ')'; - } - - return message; -}; - -jasmine.util.htmlEscape = function(str) { - if (!str) return str; - return str.replace(/&/g, '&') - .replace(//g, '>'); -}; - -jasmine.util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); - return arrayOfArgs; -}; - -jasmine.util.extend = function(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; -}; - -/** - * Environment for Jasmine - * - * @constructor - */ -jasmine.Env = function() { - this.currentSpec = null; - this.currentSuite = null; - this.currentRunner_ = new jasmine.Runner(this); - - this.reporter = new jasmine.MultiReporter(); - - this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; - this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; - this.lastUpdate = 0; - this.specFilter = function() { - return true; - }; - - this.nextSpecId_ = 0; - this.nextSuiteId_ = 0; - this.equalityTesters_ = []; - - // wrap matchers - this.matchersClass = function() { - jasmine.Matchers.apply(this, arguments); - }; - jasmine.util.inherit(this.matchersClass, jasmine.Matchers); - - jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); -}; - - -jasmine.Env.prototype.setTimeout = jasmine.setTimeout; -jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; -jasmine.Env.prototype.setInterval = jasmine.setInterval; -jasmine.Env.prototype.clearInterval = jasmine.clearInterval; - -/** - * @returns an object containing jasmine version build info, if set. - */ -jasmine.Env.prototype.version = function () { - if (jasmine.version_) { - return jasmine.version_; - } else { - throw new Error('Version not set'); - } -}; - -/** - * @returns string containing jasmine version build info, if set. - */ -jasmine.Env.prototype.versionString = function() { - if (jasmine.version_) { - var version = this.version(); - return version.major + "." + version.minor + "." + version.build + " revision " + version.revision; - } else { - return "version unknown"; - } -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSpecId = function () { - return this.nextSpecId_++; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSuiteId = function () { - return this.nextSuiteId_++; -}; - -/** - * Register a reporter to receive status updates from Jasmine. - * @param {jasmine.Reporter} reporter An object which will receive status updates. - */ -jasmine.Env.prototype.addReporter = function(reporter) { - this.reporter.addReporter(reporter); -}; - -jasmine.Env.prototype.execute = function() { - this.currentRunner_.execute(); -}; - -jasmine.Env.prototype.describe = function(description, specDefinitions) { - var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); - - var parentSuite = this.currentSuite; - if (parentSuite) { - parentSuite.add(suite); - } else { - this.currentRunner_.add(suite); - } - - this.currentSuite = suite; - - var declarationError = null; - try { - specDefinitions.call(suite); - } catch(e) { - declarationError = e; - } - - this.currentSuite = parentSuite; - - if (declarationError) { - this.it("encountered a declaration exception", function() { - throw declarationError; - }); - } - - return suite; -}; - -jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { - if (this.currentSuite) { - this.currentSuite.beforeEach(beforeEachFunction); - } else { - this.currentRunner_.beforeEach(beforeEachFunction); - } -}; - -jasmine.Env.prototype.currentRunner = function () { - return this.currentRunner_; -}; - -jasmine.Env.prototype.afterEach = function(afterEachFunction) { - if (this.currentSuite) { - this.currentSuite.afterEach(afterEachFunction); - } else { - this.currentRunner_.afterEach(afterEachFunction); - } - -}; - -jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { - return { - execute: function() { - } - }; -}; - -jasmine.Env.prototype.it = function(description, func) { - var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.add(spec); - this.currentSpec = spec; - - if (func) { - spec.runs(func); - } - - return spec; -}; - -jasmine.Env.prototype.xit = function(desc, func) { - return { - id: this.nextSpecId(), - runs: function() { - } - }; -}; - -jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { - if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { - return true; - } - - a.__Jasmine_been_here_before__ = b; - b.__Jasmine_been_here_before__ = a; - - var hasKey = function(obj, keyName) { - return obj != null && obj[keyName] !== jasmine.undefined; - }; - - for (var property in b) { - if (!hasKey(a, property) && hasKey(b, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - } - for (property in a) { - if (!hasKey(b, property) && hasKey(a, property)) { - mismatchKeys.push("expected missing key '" + property + "', but present in actual."); - } - } - for (property in b) { - if (property == '__Jasmine_been_here_before__') continue; - if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); - } - } - - if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { - mismatchValues.push("arrays were not the same length"); - } - - delete a.__Jasmine_been_here_before__; - delete b.__Jasmine_been_here_before__; - return (mismatchKeys.length == 0 && mismatchValues.length == 0); -}; - -jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; - - for (var i = 0; i < this.equalityTesters_.length; i++) { - var equalityTester = this.equalityTesters_[i]; - var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); - if (result !== jasmine.undefined) return result; - } - - if (a === b) return true; - - if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { - return (a == jasmine.undefined && b == jasmine.undefined); - } - - if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { - return a === b; - } - - if (a instanceof Date && b instanceof Date) { - return a.getTime() == b.getTime(); - } - - if (a instanceof jasmine.Matchers.Any) { - return a.matches(b); - } - - if (b instanceof jasmine.Matchers.Any) { - return b.matches(a); - } - - if (jasmine.isString_(a) && jasmine.isString_(b)) { - return (a == b); - } - - if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { - return (a == b); - } - - if (typeof a === "object" && typeof b === "object") { - return this.compareObjects_(a, b, mismatchKeys, mismatchValues); - } - - //Straight check - return (a === b); -}; - -jasmine.Env.prototype.contains_ = function(haystack, needle) { - if (jasmine.isArray_(haystack)) { - for (var i = 0; i < haystack.length; i++) { - if (this.equals_(haystack[i], needle)) return true; - } - return false; - } - return haystack.indexOf(needle) >= 0; -}; - -jasmine.Env.prototype.addEqualityTester = function(equalityTester) { - this.equalityTesters_.push(equalityTester); -}; -/** No-op base class for Jasmine reporters. - * - * @constructor - */ -jasmine.Reporter = function() { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerResults = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecStarting = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecResults = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.log = function(str) { -}; - -/** - * Blocks are functions with executable code that make up a spec. - * - * @constructor - * @param {jasmine.Env} env - * @param {Function} func - * @param {jasmine.Spec} spec - */ -jasmine.Block = function(env, func, spec) { - this.env = env; - this.func = func; - this.spec = spec; -}; - -jasmine.Block.prototype.execute = function(onComplete) { - try { - this.func.apply(this.spec); - } catch (e) { - this.spec.fail(e); - } - onComplete(); -}; -/** JavaScript API reporter. - * - * @constructor - */ -jasmine.JsApiReporter = function() { - this.started = false; - this.finished = false; - this.suites_ = []; - this.results_ = {}; -}; - -jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { - this.started = true; - var suites = runner.topLevelSuites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - this.suites_.push(this.summarize_(suite)); - } -}; - -jasmine.JsApiReporter.prototype.suites = function() { - return this.suites_; -}; - -jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { - var isSuite = suiteOrSpec instanceof jasmine.Suite; - var summary = { - id: suiteOrSpec.id, - name: suiteOrSpec.description, - type: isSuite ? 'suite' : 'spec', - children: [] - }; - - if (isSuite) { - var children = suiteOrSpec.children(); - for (var i = 0; i < children.length; i++) { - summary.children.push(this.summarize_(children[i])); - } - } - return summary; -}; - -jasmine.JsApiReporter.prototype.results = function() { - return this.results_; -}; - -jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { - return this.results_[specId]; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { - this.finished = true; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { - this.results_[spec.id] = { - messages: spec.results().getItems(), - result: spec.results().failedCount > 0 ? "failed" : "passed" - }; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.log = function(str) { -}; - -jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ - var results = {}; - for (var i = 0; i < specIds.length; i++) { - var specId = specIds[i]; - results[specId] = this.summarizeResult_(this.results_[specId]); - } - return results; -}; - -jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ - var summaryMessages = []; - var messagesLength = result.messages.length; - for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { - var resultMessage = result.messages[messageIndex]; - summaryMessages.push({ - text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, - passed: resultMessage.passed ? resultMessage.passed() : true, - type: resultMessage.type, - message: resultMessage.message, - trace: { - stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined - } - }); - } - - return { - result : result.result, - messages : summaryMessages - }; -}; - -/** - * @constructor - * @param {jasmine.Env} env - * @param actual - * @param {jasmine.Spec} spec - */ -jasmine.Matchers = function(env, actual, spec, opt_isNot) { - this.env = env; - this.actual = actual; - this.spec = spec; - this.isNot = opt_isNot || false; - this.reportWasCalled_ = false; -}; - -// todo: @deprecated as of Jasmine 0.11, remove soon [xw] -jasmine.Matchers.pp = function(str) { - throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); -}; - -// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] -jasmine.Matchers.prototype.report = function(result, failing_message, details) { - throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); -}; - -jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { - for (var methodName in prototype) { - if (methodName == 'report') continue; - var orig = prototype[methodName]; - matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); - } -}; - -jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { - return function() { - var matcherArgs = jasmine.util.argsToArray(arguments); - var result = matcherFunction.apply(this, arguments); - - if (this.isNot) { - result = !result; - } - - if (this.reportWasCalled_) return result; - - var message; - if (!result) { - if (this.message) { - message = this.message.apply(this, arguments); - if (jasmine.isArray_(message)) { - message = message[this.isNot ? 1 : 0]; - } - } else { - var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; - if (matcherArgs.length > 0) { - for (var i = 0; i < matcherArgs.length; i++) { - if (i > 0) message += ","; - message += " " + jasmine.pp(matcherArgs[i]); - } - } - message += "."; - } - } - var expectationResult = new jasmine.ExpectationResult({ - matcherName: matcherName, - passed: result, - expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], - actual: this.actual, - message: message - }); - this.spec.addMatcherResult(expectationResult); - return jasmine.undefined; - }; -}; - - - - -/** - * toBe: compares the actual to the expected using === - * @param expected - */ -jasmine.Matchers.prototype.toBe = function(expected) { - return this.actual === expected; -}; - -/** - * toNotBe: compares the actual to the expected using !== - * @param expected - * @deprecated as of 1.0. Use not.toBe() instead. - */ -jasmine.Matchers.prototype.toNotBe = function(expected) { - return this.actual !== expected; -}; - -/** - * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. - * - * @param expected - */ -jasmine.Matchers.prototype.toEqual = function(expected) { - return this.env.equals_(this.actual, expected); -}; - -/** - * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual - * @param expected - * @deprecated as of 1.0. Use not.toNotEqual() instead. - */ -jasmine.Matchers.prototype.toNotEqual = function(expected) { - return !this.env.equals_(this.actual, expected); -}; - -/** - * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes - * a pattern or a String. - * - * @param expected - */ -jasmine.Matchers.prototype.toMatch = function(expected) { - return new RegExp(expected).test(this.actual); -}; - -/** - * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch - * @param expected - * @deprecated as of 1.0. Use not.toMatch() instead. - */ -jasmine.Matchers.prototype.toNotMatch = function(expected) { - return !(new RegExp(expected).test(this.actual)); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeDefined = function() { - return (this.actual !== jasmine.undefined); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeUndefined = function() { - return (this.actual === jasmine.undefined); -}; - -/** - * Matcher that compares the actual to null. - */ -jasmine.Matchers.prototype.toBeNull = function() { - return (this.actual === null); -}; - -/** - * Matcher that boolean not-nots the actual. - */ -jasmine.Matchers.prototype.toBeTruthy = function() { - return !!this.actual; -}; - - -/** - * Matcher that boolean nots the actual. - */ -jasmine.Matchers.prototype.toBeFalsy = function() { - return !this.actual; -}; - - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called. - */ -jasmine.Matchers.prototype.toHaveBeenCalled = function() { - if (arguments.length > 0) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to have been called.", - "Expected spy " + this.actual.identity + " not to have been called." - ]; - }; - - return this.actual.wasCalled; -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ -jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was not called. - * - * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead - */ -jasmine.Matchers.prototype.wasNotCalled = function() { - if (arguments.length > 0) { - throw new Error('wasNotCalled does not take arguments'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to not have been called.", - "Expected spy " + this.actual.identity + " to have been called." - ]; - }; - - return !this.actual.wasCalled; -}; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. - * - * @example - * - */ -jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - this.message = function() { - if (this.actual.callCount == 0) { - // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] - return [ - "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", - "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was." - ]; - } else { - return [ - "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), - "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) - ]; - } - }; - - return this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; - -/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasNotCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", - "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" - ] - }; - - return !this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** - * Matcher that checks that the expected item is an element in the actual Array. - * - * @param {Object} expected - */ -jasmine.Matchers.prototype.toContain = function(expected) { - return this.env.contains_(this.actual, expected); -}; - -/** - * Matcher that checks that the expected item is NOT an element in the actual Array. - * - * @param {Object} expected - * @deprecated as of 1.0. Use not.toNotContain() instead. - */ -jasmine.Matchers.prototype.toNotContain = function(expected) { - return !this.env.contains_(this.actual, expected); -}; - -jasmine.Matchers.prototype.toBeLessThan = function(expected) { - return this.actual < expected; -}; - -jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { - return this.actual > expected; -}; - -/** - * Matcher that checks that the expected exception was thrown by the actual. - * - * @param {String} expected - */ -jasmine.Matchers.prototype.toThrow = function(expected) { - var result = false; - var exception; - if (typeof this.actual != 'function') { - throw new Error('Actual is not a function'); - } - try { - this.actual(); - } catch (e) { - exception = e; - } - if (exception) { - result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); - } - - var not = this.isNot ? "not " : ""; - - this.message = function() { - if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { - return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' '); - } else { - return "Expected function to throw an exception."; - } - }; - - return result; -}; - -jasmine.Matchers.Any = function(expectedClass) { - this.expectedClass = expectedClass; -}; - -jasmine.Matchers.Any.prototype.matches = function(other) { - if (this.expectedClass == String) { - return typeof other == 'string' || other instanceof String; - } - - if (this.expectedClass == Number) { - return typeof other == 'number' || other instanceof Number; - } - - if (this.expectedClass == Function) { - return typeof other == 'function' || other instanceof Function; - } - - if (this.expectedClass == Object) { - return typeof other == 'object'; - } - - return other instanceof this.expectedClass; -}; - -jasmine.Matchers.Any.prototype.toString = function() { - return ''; -}; - -/** - * @constructor - */ -jasmine.MultiReporter = function() { - this.subReporters_ = []; -}; -jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); - -jasmine.MultiReporter.prototype.addReporter = function(reporter) { - this.subReporters_.push(reporter); -}; - -(function() { - var functionNames = [ - "reportRunnerStarting", - "reportRunnerResults", - "reportSuiteResults", - "reportSpecStarting", - "reportSpecResults", - "log" - ]; - for (var i = 0; i < functionNames.length; i++) { - var functionName = functionNames[i]; - jasmine.MultiReporter.prototype[functionName] = (function(functionName) { - return function() { - for (var j = 0; j < this.subReporters_.length; j++) { - var subReporter = this.subReporters_[j]; - if (subReporter[functionName]) { - subReporter[functionName].apply(subReporter, arguments); - } - } - }; - })(functionName); - } -})(); -/** - * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults - * - * @constructor - */ -jasmine.NestedResults = function() { - /** - * The total count of results - */ - this.totalCount = 0; - /** - * Number of passed results - */ - this.passedCount = 0; - /** - * Number of failed results - */ - this.failedCount = 0; - /** - * Was this suite/spec skipped? - */ - this.skipped = false; - /** - * @ignore - */ - this.items_ = []; -}; - -/** - * Roll up the result counts. - * - * @param result - */ -jasmine.NestedResults.prototype.rollupCounts = function(result) { - this.totalCount += result.totalCount; - this.passedCount += result.passedCount; - this.failedCount += result.failedCount; -}; - -/** - * Adds a log message. - * @param values Array of message parts which will be concatenated later. - */ -jasmine.NestedResults.prototype.log = function(values) { - this.items_.push(new jasmine.MessageResult(values)); -}; - -/** - * Getter for the results: message & results. - */ -jasmine.NestedResults.prototype.getItems = function() { - return this.items_; -}; - -/** - * Adds a result, tracking counts (total, passed, & failed) - * @param {jasmine.ExpectationResult|jasmine.NestedResults} result - */ -jasmine.NestedResults.prototype.addResult = function(result) { - if (result.type != 'log') { - if (result.items_) { - this.rollupCounts(result); - } else { - this.totalCount++; - if (result.passed()) { - this.passedCount++; - } else { - this.failedCount++; - } - } - } - this.items_.push(result); -}; - -/** - * @returns {Boolean} True if everything below passed - */ -jasmine.NestedResults.prototype.passed = function() { - return this.passedCount === this.totalCount; -}; -/** - * Base class for pretty printing for expectation results. - */ -jasmine.PrettyPrinter = function() { - this.ppNestLevel_ = 0; -}; - -/** - * Formats a value in a nice, human-readable string. - * - * @param value - */ -jasmine.PrettyPrinter.prototype.format = function(value) { - if (this.ppNestLevel_ > 40) { - throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); - } - - this.ppNestLevel_++; - try { - if (value === jasmine.undefined) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === jasmine.getGlobal()) { - this.emitScalar(''); - } else if (value instanceof jasmine.Matchers.Any) { - this.emitScalar(value.toString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (jasmine.isSpy(value)) { - this.emitScalar("spy on " + value.identity); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (value.__Jasmine_been_here_before__) { - this.emitScalar(''); - } else if (jasmine.isArray_(value) || typeof value == 'object') { - value.__Jasmine_been_here_before__ = true; - if (jasmine.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); - } - delete value.__Jasmine_been_here_before__; - } else { - this.emitScalar(value.toString()); - } - } finally { - this.ppNestLevel_--; - } -}; - -jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (property == '__Jasmine_been_here_before__') continue; - fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false); - } -}; - -jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; - -jasmine.StringPrettyPrinter = function() { - jasmine.PrettyPrinter.call(this); - - this.string = ''; -}; -jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); - -jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); -}; - -jasmine.StringPrettyPrinter.prototype.emitString = function(value) { - this.append("'" + value + "'"); -}; - -jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { - this.append('[ '); - for (var i = 0; i < array.length; i++) { - if (i > 0) { - this.append(', '); - } - this.format(array[i]); - } - this.append(' ]'); -}; - -jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { - var self = this; - this.append('{ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.append(property); - self.append(' : '); - if (isGetter) { - self.append(''); - } else { - self.format(obj[property]); - } - }); - - this.append(' }'); -}; - -jasmine.StringPrettyPrinter.prototype.append = function(value) { - this.string += value; -}; -jasmine.Queue = function(env) { - this.env = env; - this.blocks = []; - this.running = false; - this.index = 0; - this.offset = 0; - this.abort = false; -}; - -jasmine.Queue.prototype.addBefore = function(block) { - this.blocks.unshift(block); -}; - -jasmine.Queue.prototype.add = function(block) { - this.blocks.push(block); -}; - -jasmine.Queue.prototype.insertNext = function(block) { - this.blocks.splice((this.index + this.offset + 1), 0, block); - this.offset++; -}; - -jasmine.Queue.prototype.start = function(onComplete) { - this.running = true; - this.onComplete = onComplete; - this.next_(); -}; - -jasmine.Queue.prototype.isRunning = function() { - return this.running; -}; - -jasmine.Queue.LOOP_DONT_RECURSE = true; - -jasmine.Queue.prototype.next_ = function() { - var self = this; - var goAgain = true; - - while (goAgain) { - goAgain = false; - - if (self.index < self.blocks.length && !this.abort) { - var calledSynchronously = true; - var completedSynchronously = false; - - var onComplete = function () { - if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { - completedSynchronously = true; - return; - } - - if (self.blocks[self.index].abort) { - self.abort = true; - } - - self.offset = 0; - self.index++; - - var now = new Date().getTime(); - if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { - self.env.lastUpdate = now; - self.env.setTimeout(function() { - self.next_(); - }, 0); - } else { - if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { - goAgain = true; - } else { - self.next_(); - } - } - }; - self.blocks[self.index].execute(onComplete); - - calledSynchronously = false; - if (completedSynchronously) { - onComplete(); - } - - } else { - self.running = false; - if (self.onComplete) { - self.onComplete(); - } - } - } -}; - -jasmine.Queue.prototype.results = function() { - var results = new jasmine.NestedResults(); - for (var i = 0; i < this.blocks.length; i++) { - if (this.blocks[i].results) { - results.addResult(this.blocks[i].results()); - } - } - return results; -}; - - -/** - * Runner - * - * @constructor - * @param {jasmine.Env} env - */ -jasmine.Runner = function(env) { - var self = this; - self.env = env; - self.queue = new jasmine.Queue(env); - self.before_ = []; - self.after_ = []; - self.suites_ = []; -}; - -jasmine.Runner.prototype.execute = function() { - var self = this; - if (self.env.reporter.reportRunnerStarting) { - self.env.reporter.reportRunnerStarting(this); - } - self.queue.start(function () { - self.finishCallback(); - }); -}; - -jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.splice(0,0,beforeEachFunction); -}; - -jasmine.Runner.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.splice(0,0,afterEachFunction); -}; - - -jasmine.Runner.prototype.finishCallback = function() { - this.env.reporter.reportRunnerResults(this); -}; - -jasmine.Runner.prototype.addSuite = function(suite) { - this.suites_.push(suite); -}; - -jasmine.Runner.prototype.add = function(block) { - if (block instanceof jasmine.Suite) { - this.addSuite(block); - } - this.queue.add(block); -}; - -jasmine.Runner.prototype.specs = function () { - var suites = this.suites(); - var specs = []; - for (var i = 0; i < suites.length; i++) { - specs = specs.concat(suites[i].specs()); - } - return specs; -}; - -jasmine.Runner.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Runner.prototype.topLevelSuites = function() { - var topLevelSuites = []; - for (var i = 0; i < this.suites_.length; i++) { - if (!this.suites_[i].parentSuite) { - topLevelSuites.push(this.suites_[i]); - } - } - return topLevelSuites; -}; - -jasmine.Runner.prototype.results = function() { - return this.queue.results(); -}; -/** - * Internal representation of a Jasmine specification, or test. - * - * @constructor - * @param {jasmine.Env} env - * @param {jasmine.Suite} suite - * @param {String} description - */ -jasmine.Spec = function(env, suite, description) { - if (!env) { - throw new Error('jasmine.Env() required'); - } - if (!suite) { - throw new Error('jasmine.Suite() required'); - } - var spec = this; - spec.id = env.nextSpecId ? env.nextSpecId() : null; - spec.env = env; - spec.suite = suite; - spec.description = description; - spec.queue = new jasmine.Queue(env); - - spec.afterCallbacks = []; - spec.spies_ = []; - - spec.results_ = new jasmine.NestedResults(); - spec.results_.description = description; - spec.matchersClass = null; -}; - -jasmine.Spec.prototype.getFullName = function() { - return this.suite.getFullName() + ' ' + this.description + '.'; -}; - - -jasmine.Spec.prototype.results = function() { - return this.results_; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.Spec.prototype.log = function() { - return this.results_.log(arguments); -}; - -jasmine.Spec.prototype.runs = function (func) { - var block = new jasmine.Block(this.env, func, this); - this.addToQueue(block); - return this; -}; - -jasmine.Spec.prototype.addToQueue = function (block) { - if (this.queue.isRunning()) { - this.queue.insertNext(block); - } else { - this.queue.add(block); - } -}; - -/** - * @param {jasmine.ExpectationResult} result - */ -jasmine.Spec.prototype.addMatcherResult = function(result) { - this.results_.addResult(result); -}; - -jasmine.Spec.prototype.expect = function(actual) { - var positive = new (this.getMatchersClass_())(this.env, actual, this); - positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); - return positive; -}; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -jasmine.Spec.prototype.waits = function(timeout) { - var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); - this.addToQueue(waitsFunc); - return this; -}; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - var latchFunction_ = null; - var optional_timeoutMessage_ = null; - var optional_timeout_ = null; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - switch (typeof arg) { - case 'function': - latchFunction_ = arg; - break; - case 'string': - optional_timeoutMessage_ = arg; - break; - case 'number': - optional_timeout_ = arg; - break; - } - } - - var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); - this.addToQueue(waitsForFunc); - return this; -}; - -jasmine.Spec.prototype.fail = function (e) { - var expectationResult = new jasmine.ExpectationResult({ - passed: false, - message: e ? jasmine.util.formatException(e) : 'Exception' - }); - this.results_.addResult(expectationResult); -}; - -jasmine.Spec.prototype.getMatchersClass_ = function() { - return this.matchersClass || this.env.matchersClass; -}; - -jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { - var parent = this.getMatchersClass_(); - var newMatchersClass = function() { - parent.apply(this, arguments); - }; - jasmine.util.inherit(newMatchersClass, parent); - jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); - this.matchersClass = newMatchersClass; -}; - -jasmine.Spec.prototype.finishCallback = function() { - this.env.reporter.reportSpecResults(this); -}; - -jasmine.Spec.prototype.finish = function(onComplete) { - this.removeAllSpies(); - this.finishCallback(); - if (onComplete) { - onComplete(); - } -}; - -jasmine.Spec.prototype.after = function(doAfter) { - if (this.queue.isRunning()) { - this.queue.add(new jasmine.Block(this.env, doAfter, this)); - } else { - this.afterCallbacks.unshift(doAfter); - } -}; - -jasmine.Spec.prototype.execute = function(onComplete) { - var spec = this; - if (!spec.env.specFilter(spec)) { - spec.results_.skipped = true; - spec.finish(onComplete); - return; - } - - this.env.reporter.reportSpecStarting(this); - - spec.env.currentSpec = spec; - - spec.addBeforesAndAftersToQueue(); - - spec.queue.start(function () { - spec.finish(onComplete); - }); -}; - -jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { - var runner = this.env.currentRunner(); - var i; - - for (var suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); - } - } - for (i = 0; i < runner.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); - } - for (i = 0; i < this.afterCallbacks.length; i++) { - this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); - } - for (suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); - } - } - for (i = 0; i < runner.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); - } -}; - -jasmine.Spec.prototype.explodes = function() { - throw 'explodes function should not have been called'; -}; - -jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { - if (obj == jasmine.undefined) { - throw "spyOn could not find an object to spy upon for " + methodName + "()"; - } - - if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { - throw methodName + '() method does not exist'; - } - - if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { - throw new Error(methodName + ' has already been spied upon'); - } - - var spyObj = jasmine.createSpy(methodName); - - this.spies_.push(spyObj); - spyObj.baseObj = obj; - spyObj.methodName = methodName; - spyObj.originalValue = obj[methodName]; - - obj[methodName] = spyObj; - - return spyObj; -}; - -jasmine.Spec.prototype.removeAllSpies = function() { - for (var i = 0; i < this.spies_.length; i++) { - var spy = this.spies_[i]; - spy.baseObj[spy.methodName] = spy.originalValue; - } - this.spies_ = []; -}; - -/** - * Internal representation of a Jasmine suite. - * - * @constructor - * @param {jasmine.Env} env - * @param {String} description - * @param {Function} specDefinitions - * @param {jasmine.Suite} parentSuite - */ -jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - var self = this; - self.id = env.nextSuiteId ? env.nextSuiteId() : null; - self.description = description; - self.queue = new jasmine.Queue(env); - self.parentSuite = parentSuite; - self.env = env; - self.before_ = []; - self.after_ = []; - self.children_ = []; - self.suites_ = []; - self.specs_ = []; -}; - -jasmine.Suite.prototype.getFullName = function() { - var fullName = this.description; - for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - fullName = parentSuite.description + ' ' + fullName; - } - return fullName; -}; - -jasmine.Suite.prototype.finish = function(onComplete) { - this.env.reporter.reportSuiteResults(this); - this.finished = true; - if (typeof(onComplete) == 'function') { - onComplete(); - } -}; - -jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.unshift(beforeEachFunction); -}; - -jasmine.Suite.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.unshift(afterEachFunction); -}; - -jasmine.Suite.prototype.results = function() { - return this.queue.results(); -}; - -jasmine.Suite.prototype.add = function(suiteOrSpec) { - this.children_.push(suiteOrSpec); - if (suiteOrSpec instanceof jasmine.Suite) { - this.suites_.push(suiteOrSpec); - this.env.currentRunner().addSuite(suiteOrSpec); - } else { - this.specs_.push(suiteOrSpec); - } - this.queue.add(suiteOrSpec); -}; - -jasmine.Suite.prototype.specs = function() { - return this.specs_; -}; - -jasmine.Suite.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Suite.prototype.children = function() { - return this.children_; -}; - -jasmine.Suite.prototype.execute = function(onComplete) { - var self = this; - this.queue.start(function () { - self.finish(onComplete); - }); -}; -jasmine.WaitsBlock = function(env, timeout, spec) { - this.timeout = timeout; - jasmine.Block.call(this, env, null, spec); -}; - -jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); - -jasmine.WaitsBlock.prototype.execute = function (onComplete) { - this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); - this.env.setTimeout(function () { - onComplete(); - }, this.timeout); -}; -/** - * A block which waits for some condition to become true, with timeout. - * - * @constructor - * @extends jasmine.Block - * @param {jasmine.Env} env The Jasmine environment. - * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. - * @param {Function} latchFunction A function which returns true when the desired condition has been met. - * @param {String} message The message to display if the desired condition hasn't been met within the given time period. - * @param {jasmine.Spec} spec The Jasmine spec. - */ -jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { - this.timeout = timeout || env.defaultTimeoutInterval; - this.latchFunction = latchFunction; - this.message = message; - this.totalTimeSpentWaitingForLatch = 0; - jasmine.Block.call(this, env, null, spec); -}; -jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); - -jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; - -jasmine.WaitsForBlock.prototype.execute = function(onComplete) { - this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); - var latchFunctionResult; - try { - latchFunctionResult = this.latchFunction.apply(this.spec); - } catch (e) { - this.spec.fail(e); - onComplete(); - return; - } - - if (latchFunctionResult) { - onComplete(); - } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { - var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); - this.spec.fail({ - name: 'timeout', - message: message - }); - - this.abort = true; - onComplete(); - } else { - this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; - var self = this; - this.env.setTimeout(function() { - self.execute(onComplete); - }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); - } -}; -// Mock setTimeout, clearTimeout -// Contributed by Pivotal Computer Systems, www.pivotalsf.com - -jasmine.FakeTimer = function() { - this.reset(); - - var self = this; - self.setTimeout = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); - return self.timeoutsMade; - }; - - self.setInterval = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); - return self.timeoutsMade; - }; - - self.clearTimeout = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - - self.clearInterval = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - -}; - -jasmine.FakeTimer.prototype.reset = function() { - this.timeoutsMade = 0; - this.scheduledFunctions = {}; - this.nowMillis = 0; -}; - -jasmine.FakeTimer.prototype.tick = function(millis) { - var oldMillis = this.nowMillis; - var newMillis = oldMillis + millis; - this.runFunctionsWithinRange(oldMillis, newMillis); - this.nowMillis = newMillis; -}; - -jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { - var scheduledFunc; - var funcsToRun = []; - for (var timeoutKey in this.scheduledFunctions) { - scheduledFunc = this.scheduledFunctions[timeoutKey]; - if (scheduledFunc != jasmine.undefined && - scheduledFunc.runAtMillis >= oldMillis && - scheduledFunc.runAtMillis <= nowMillis) { - funcsToRun.push(scheduledFunc); - this.scheduledFunctions[timeoutKey] = jasmine.undefined; - } - } - - if (funcsToRun.length > 0) { - funcsToRun.sort(function(a, b) { - return a.runAtMillis - b.runAtMillis; - }); - for (var i = 0; i < funcsToRun.length; ++i) { - try { - var funcToRun = funcsToRun[i]; - this.nowMillis = funcToRun.runAtMillis; - funcToRun.funcToCall(); - if (funcToRun.recurring) { - this.scheduleFunction(funcToRun.timeoutKey, - funcToRun.funcToCall, - funcToRun.millis, - true); - } - } catch(e) { - } - } - this.runFunctionsWithinRange(oldMillis, nowMillis); - } -}; - -jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { - this.scheduledFunctions[timeoutKey] = { - runAtMillis: this.nowMillis + millis, - funcToCall: funcToCall, - recurring: recurring, - timeoutKey: timeoutKey, - millis: millis - }; -}; - -/** - * @namespace - */ -jasmine.Clock = { - defaultFakeTimer: new jasmine.FakeTimer(), - - reset: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.reset(); - }, - - tick: function(millis) { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.tick(millis); - }, - - runFunctionsWithinRange: function(oldMillis, nowMillis) { - jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); - }, - - scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { - jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); - }, - - useMock: function() { - if (!jasmine.Clock.isInstalled()) { - var spec = jasmine.getEnv().currentSpec; - spec.after(jasmine.Clock.uninstallMock); - - jasmine.Clock.installMock(); - } - }, - - installMock: function() { - jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; - }, - - uninstallMock: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.installed = jasmine.Clock.real; - }, - - real: { - setTimeout: jasmine.getGlobal().setTimeout, - clearTimeout: jasmine.getGlobal().clearTimeout, - setInterval: jasmine.getGlobal().setInterval, - clearInterval: jasmine.getGlobal().clearInterval - }, - - assertInstalled: function() { - if (!jasmine.Clock.isInstalled()) { - throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); - } - }, - - isInstalled: function() { - return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; - }, - - installed: null -}; -jasmine.Clock.installed = jasmine.Clock.real; - -//else for IE support -jasmine.getGlobal().setTimeout = function(funcToCall, millis) { - if (jasmine.Clock.installed.setTimeout.apply) { - return jasmine.Clock.installed.setTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.setTimeout(funcToCall, millis); - } -}; - -jasmine.getGlobal().setInterval = function(funcToCall, millis) { - if (jasmine.Clock.installed.setInterval.apply) { - return jasmine.Clock.installed.setInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.setInterval(funcToCall, millis); - } -}; - -jasmine.getGlobal().clearTimeout = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearTimeout(timeoutKey); - } -}; - -jasmine.getGlobal().clearInterval = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearInterval(timeoutKey); - } -}; - - -jasmine.version_= { - "major": 1, - "minor": 0, - "build": 2, - "revision": 1298837858 -}; diff --git a/contexts/data/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js b/contexts/data/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js deleted file mode 100644 index c326ded..0000000 --- a/contexts/data/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js +++ /dev/null @@ -1,204 +0,0 @@ -(function() { - - if (! jasmine) { - throw new Exception("jasmine library does not exist in global namespace!"); - } - - function elapsed(startTime, endTime) { - return (endTime - startTime)/1000; - } - - function ISODateString(d) { - function pad(n) { return n < 10 ? '0'+n : n; } - - return d.getFullYear() + '-' - + pad(d.getMonth()+1) +'-' - + pad(d.getDate()) + 'T' - + pad(d.getHours()) + ':' - + pad(d.getMinutes()) + ':' - + pad(d.getSeconds()); - } - - function trim(str) { - return str.replace(/^\s+/, "" ).replace(/\s+$/, "" ); - } - - function escapeInvalidXmlChars(str) { - return str.replace(/\&/g, "&") - .replace(//g, ">") - .replace(/\"/g, """) - .replace(/\'/g, "'"); - } - - /** - * PhantomJS Reporter generates JUnit XML for the given spec run. - * Allows the test results to be used in java based CI. - * It appends some DOM elements/containers, so that a PhantomJS script can pick that up. - * - * @param {boolean} consolidate whether to save nested describes within the - * same file as their parent; default: true - * @param {boolean} useDotNotation whether to separate suite names with - * dots rather than spaces (ie "Class.init" not - * "Class init"); default: true - */ - var PhantomJSReporter = function(consolidate, useDotNotation) { - this.consolidate = consolidate === jasmine.undefined ? true : consolidate; - this.useDotNotation = useDotNotation === jasmine.undefined ? true : useDotNotation; - }; - - PhantomJSReporter.prototype = { - reportRunnerStarting: function(runner) { - this.log("Runner Started."); - }, - - reportSpecStarting: function(spec) { - spec.startTime = new Date(); - - if (! spec.suite.startTime) { - spec.suite.startTime = spec.startTime; - } - - this.log(spec.suite.description + ' : ' + spec.description + ' ... '); - }, - - reportSpecResults: function(spec) { - var results = spec.results(); - spec.didFail = !results.passed(); - spec.status = spec.didFail ? 'Failed.' : 'Passed.'; - if (results.skipped) { - spec.status = 'Skipped.'; - } - this.log(spec.status); - - spec.duration = elapsed(spec.startTime, new Date()); - spec.output = ''; - - var failure = ""; - var failures = 0; - var resultItems = results.getItems(); - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'expect' && result.passed && !result.passed()) { - failures += 1; - failure += (failures + ": " + escapeInvalidXmlChars(result.message) + " "); - } - } - if (failure) { - spec.output += "" + trim(failure) + ""; - } - spec.output += ""; - }, - - reportSuiteResults: function(suite) { - var results = suite.results(); - var specs = suite.specs(); - var specOutput = ""; - // for JUnit results, let's only include directly failed tests (not nested suites') - var failedCount = 0; - - suite.status = results.passed() ? 'Passed.' : 'Failed.'; - suite.statusPassed = results.passed(); - if (results.totalCount === 0) { // todo: change this to check results.skipped - suite.status = 'Skipped.'; - } - - // if a suite has no (active?) specs, reportSpecStarting is never called - // and thus the suite has no startTime -- account for that here - suite.startTime = suite.startTime || new Date(); - suite.duration = elapsed(suite.startTime, new Date()); - - for (var i = 0; i < specs.length; i++) { - failedCount += specs[i].didFail ? 1 : 0; - specOutput += "\n " + specs[i].output; - } - suite.output = '\n'; - suite.output += specOutput; - suite.output += "\n"; - this.log(suite.description + ": " + results.passedCount + " of " + results.totalCount + " expectations passed."); - }, - - reportRunnerResults: function(runner) { - this.log("Runner Finished."); - var suites = runner.suites(), - passed = true; - for (var i = 0; i < suites.length; i++) { - var suite = suites[i], - filename = 'TEST-' + this.getFullName(suite, true) + '.xml', - output = ''; - - passed = !suite.statusPassed ? false : passed; - - // if we are consolidating, only write out top-level suites - if (this.consolidate && suite.parentSuite) { - continue; - } - else if (this.consolidate) { - output += "\n"; - output += this.getNestedOutput(suite); - output += "\n"; - this.createSuiteResultContainer(filename, output); - } - else { - output += suite.output; - this.createSuiteResultContainer(filename, output); - } - } - this.createTestFinishedContainer(passed); - }, - - getNestedOutput: function(suite) { - var output = suite.output; - for (var i = 0; i < suite.suites().length; i++) { - output += this.getNestedOutput(suite.suites()[i]); - } - return output; - }, - - createSuiteResultContainer: function(filename, xmloutput) { - jasmine.phantomjsXMLReporterResults = jasmine.phantomjsXMLReporterResults || []; - jasmine.phantomjsXMLReporterResults.push({ - "xmlfilename" : filename, - "xmlbody" : xmloutput - }); - }, - - createTestFinishedContainer: function(passed) { - jasmine.phantomjsXMLReporterPassed = passed - }, - - getFullName: function(suite, isFilename) { - var fullName; - if (this.useDotNotation) { - fullName = suite.description; - for (var parentSuite = suite.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - fullName = parentSuite.description + '.' + fullName; - } - } - else { - fullName = suite.getFullName(); - } - - // Either remove or escape invalid XML characters - if (isFilename) { - return fullName.replace(/[^\w]/g, ""); - } - return escapeInvalidXmlChars(fullName); - }, - - log: function(str) { - var console = jasmine.getGlobal().console; - - if (console && console.log) { - console.log(str); - } - } - }; - - // export public - jasmine.PhantomJSReporter = PhantomJSReporter; -})(); diff --git a/contexts/data/lib/phantomjs_jasmine/jasmine_favicon.png b/contexts/data/lib/phantomjs_jasmine/jasmine_favicon.png deleted file mode 100644 index 218f3b4..0000000 Binary files a/contexts/data/lib/phantomjs_jasmine/jasmine_favicon.png and /dev/null differ diff --git a/contexts/data/lib/phantomjs_jasmine/phantomjs_jasminexml_runner.js b/contexts/data/lib/phantomjs_jasmine/phantomjs_jasminexml_runner.js deleted file mode 100644 index 8804a29..0000000 --- a/contexts/data/lib/phantomjs_jasmine/phantomjs_jasminexml_runner.js +++ /dev/null @@ -1,59 +0,0 @@ -var htmlrunner, - resultdir, - page, - fs; - -phantom.injectJs("utils/core.js") - -if ( phantom.args.length !== 2 ) { - console.log("Usage: phantom_test_runner.js HTML_RUNNER RESULT_DIR"); - phantom.exit(); -} else { - htmlrunner = phantom.args[0]; - resultdir = phantom.args[1]; - page = require("webpage").create(); - fs = require("fs"); - - // Echo the output of the tests to the Standard Output - page.onConsoleMessage = function(msg, source, linenumber) { - console.log(msg); - }; - - page.open(htmlrunner, function(status) { - if (status === "success") { - utils.core.waitfor(function() { // wait for this to be true - return page.evaluate(function() { - return typeof(jasmine.phantomjsXMLReporterPassed) !== "undefined"; - }); - }, function() { // once done... - // Retrieve the result of the tests - var f = null, i, len; - suitesResults = page.evaluate(function(){ - return jasmine.phantomjsXMLReporterResults; - }); - - // Save the result of the tests in files - for ( i = 0, len = suitesResults.length; i < len; ++i ) { - try { - f = fs.open(resultdir + '/' + suitesResults[i]["xmlfilename"], "w"); - f.write(suitesResults[i]["xmlbody"]); - f.close(); - } catch (e) { - console.log(e); - console.log("phantomjs> Unable to save result of Suite '"+ suitesResults[i]["xmlfilename"] +"'"); - } - } - - // Return the correct exit status. '0' only if all the tests passed - phantom.exit(page.evaluate(function(){ - return jasmine.phantomjsXMLReporterPassed ? 0 : 1; //< exit(0) is success, exit(1) is failure - })); - }, function() { // or, once it timesout... - phantom.exit(1); - }); - } else { - console.log("phantomjs> Could not load '" + htmlrunner + "'."); - phantom.exit(1); - } - }); -} diff --git a/contexts/data/lib/phantomjs_jasmine/utils/core.js b/contexts/data/lib/phantomjs_jasmine/utils/core.js deleted file mode 100644 index 8441e13..0000000 --- a/contexts/data/lib/phantomjs_jasmine/utils/core.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Collection of Core JavaScript utility functionalities. - */ - -// Namespace "utils.core" -var utils = utils || {}; -utils.core = utils.core || {}; - -/** - * Wait until the test condition is true or a timeout occurs. Useful for waiting - * on a server response or for a ui change (fadeIn, etc.) to occur. - * - * @param check javascript condition that evaluates to a boolean. - * @param onTestPass what to do when 'check' condition is fulfilled. - * @param onTimeout what to do when 'check' condition is not fulfilled and 'timeoutMs' has passed - * @param timeoutMs the max amount of time to wait. Default value is 3 seconds - * @param freqMs how frequently to repeat 'check'. Default value is 250 milliseconds - */ -utils.core.waitfor = function(check, onTestPass, onTimeout, timeoutMs, freqMs) { - var timeoutMs = timeoutMs || 3000, //< Default Timeout is 3s - freqMs = freqMs || 250, //< Default Freq is 250ms - start = Date.now(), - condition = false, - timer = setTimeout(function() { - var elapsedMs = Date.now() - start; - if ((elapsedMs < timeoutMs) && !condition) { - // If not time-out yet and condition not yet fulfilled - condition = check(elapsedMs); - timer = setTimeout(arguments.callee, freqMs); - } else { - clearTimeout(timer); //< house keeping - if (!condition) { - // If condition still not fulfilled (timeout but condition is 'false') - onTimeout(elapsedMs); - } else { - // Condition fulfilled (timeout and/or condition is 'true') - onTestPass(elapsedMs); - } - } - }, freqMs); -}; \ No newline at end of file diff --git a/contexts/data/lib/underscore.js b/contexts/data/lib/underscore.js deleted file mode 100644 index 32ca0c1..0000000 --- a/contexts/data/lib/underscore.js +++ /dev/null @@ -1,1227 +0,0 @@ -// Underscore.js 1.4.4 -// =================== - -// > http://underscorejs.org -// > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. -// > Underscore may be freely distributed under the MIT license. - -// Baseline setup -// -------------- -(function() { - - // Establish the root object, `window` in the browser, or `global` on the server. - var root = this; - - // Save the previous value of the `_` variable. - var previousUnderscore = root._; - - // Establish the object that gets returned to break out of a loop iteration. - var breaker = {}; - - // Save bytes in the minified (but not gzipped) version: - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; - - // Create quick reference variables for speed access to core prototypes. - var push = ArrayProto.push, - slice = ArrayProto.slice, - concat = ArrayProto.concat, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - - // All **ECMAScript 5** native function implementations that we hope to use - // are declared here. - var - nativeForEach = ArrayProto.forEach, - nativeMap = ArrayProto.map, - nativeReduce = ArrayProto.reduce, - nativeReduceRight = ArrayProto.reduceRight, - nativeFilter = ArrayProto.filter, - nativeEvery = ArrayProto.every, - nativeSome = ArrayProto.some, - nativeIndexOf = ArrayProto.indexOf, - nativeLastIndexOf = ArrayProto.lastIndexOf, - nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeBind = FuncProto.bind; - - // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - - // Export the Underscore object for **Node.js**, with - // backwards-compatibility for the old `require()` API. If we're in - // the browser, add `_` as a global object via a string identifier, - // for Closure Compiler "advanced" mode. - if (typeof exports !== 'undefined') { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root._ = _; - } - - // Current version. - _.VERSION = '1.4.4'; - - // Collection Functions - // -------------------- - - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles objects with the built-in `forEach`, arrays, and raw objects. - // Delegates to **ECMAScript 5**'s native `forEach` if available. - var each = _.each = _.forEach = function(obj, iterator, context) { - if (obj == null) return; - if (nativeForEach && obj.forEach === nativeForEach) { - obj.forEach(iterator, context); - } else if (obj.length === +obj.length) { - for (var i = 0, l = obj.length; i < l; i++) { - if (iterator.call(context, obj[i], i, obj) === breaker) return; - } - } else { - for (var key in obj) { - if (_.has(obj, key)) { - if (iterator.call(context, obj[key], key, obj) === breaker) return; - } - } - } - }; - - // Return the results of applying the iterator to each element. - // Delegates to **ECMAScript 5**'s native `map` if available. - _.map = _.collect = function(obj, iterator, context) { - var results = []; - if (obj == null) return results; - if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); - each(obj, function(value, index, list) { - results[results.length] = iterator.call(context, value, index, list); - }); - return results; - }; - - var reduceError = 'Reduce of empty array with no initial value'; - - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. - _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { - var initial = arguments.length > 2; - if (obj == null) obj = []; - if (nativeReduce && obj.reduce === nativeReduce) { - if (context) iterator = _.bind(iterator, context); - return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); - } - each(obj, function(value, index, list) { - if (!initial) { - memo = value; - initial = true; - } else { - memo = iterator.call(context, memo, value, index, list); - } - }); - if (!initial) throw new TypeError(reduceError); - return memo; - }; - - // The right-associative version of reduce, also known as `foldr`. - // Delegates to **ECMAScript 5**'s native `reduceRight` if available. - _.reduceRight = _.foldr = function(obj, iterator, memo, context) { - var initial = arguments.length > 2; - if (obj == null) obj = []; - if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { - if (context) iterator = _.bind(iterator, context); - return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); - } - var length = obj.length; - if (length !== +length) { - var keys = _.keys(obj); - length = keys.length; - } - each(obj, function(value, index, list) { - index = keys ? keys[--length] : --length; - if (!initial) { - memo = obj[index]; - initial = true; - } else { - memo = iterator.call(context, memo, obj[index], index, list); - } - }); - if (!initial) throw new TypeError(reduceError); - return memo; - }; - - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, iterator, context) { - var result; - any(obj, function(value, index, list) { - if (iterator.call(context, value, index, list)) { - result = value; - return true; - } - }); - return result; - }; - - // Return all the elements that pass a truth test. - // Delegates to **ECMAScript 5**'s native `filter` if available. - // Aliased as `select`. - _.filter = _.select = function(obj, iterator, context) { - var results = []; - if (obj == null) return results; - if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); - each(obj, function(value, index, list) { - if (iterator.call(context, value, index, list)) results[results.length] = value; - }); - return results; - }; - - // Return all the elements for which a truth test fails. - _.reject = function(obj, iterator, context) { - return _.filter(obj, function(value, index, list) { - return !iterator.call(context, value, index, list); - }, context); - }; - - // Determine whether all of the elements match a truth test. - // Delegates to **ECMAScript 5**'s native `every` if available. - // Aliased as `all`. - _.every = _.all = function(obj, iterator, context) { - iterator || (iterator = _.identity); - var result = true; - if (obj == null) return result; - if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); - each(obj, function(value, index, list) { - if (!(result = result && iterator.call(context, value, index, list))) return breaker; - }); - return !!result; - }; - - // Determine if at least one element in the object matches a truth test. - // Delegates to **ECMAScript 5**'s native `some` if available. - // Aliased as `any`. - var any = _.some = _.any = function(obj, iterator, context) { - iterator || (iterator = _.identity); - var result = false; - if (obj == null) return result; - if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); - each(obj, function(value, index, list) { - if (result || (result = iterator.call(context, value, index, list))) return breaker; - }); - return !!result; - }; - - // Determine if the array or object contains a given value (using `===`). - // Aliased as `include`. - _.contains = _.include = function(obj, target) { - if (obj == null) return false; - if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; - return any(obj, function(value) { - return value === target; - }); - }; - - // Invoke a method (with arguments) on every item in a collection. - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - return (isFunc ? method : value[method]).apply(value, args); - }); - }; - - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, function(value){ return value[key]; }); - }; - - // Convenience version of a common use case of `filter`: selecting only objects - // containing specific `key:value` pairs. - _.where = function(obj, attrs, first) { - if (_.isEmpty(attrs)) return first ? null : []; - return _[first ? 'find' : 'filter'](obj, function(value) { - for (var key in attrs) { - if (attrs[key] !== value[key]) return false; - } - return true; - }); - }; - - // Convenience version of a common use case of `find`: getting the first object - // containing specific `key:value` pairs. - _.findWhere = function(obj, attrs) { - return _.where(obj, attrs, true); - }; - - // Return the maximum element or (element-based computation). - // Can't optimize arrays of integers longer than 65,535 elements. - // See: https://bugs.webkit.org/show_bug.cgi?id=80797 - _.max = function(obj, iterator, context) { - if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { - return Math.max.apply(Math, obj); - } - if (!iterator && _.isEmpty(obj)) return -Infinity; - var result = {computed : -Infinity, value: -Infinity}; - each(obj, function(value, index, list) { - var computed = iterator ? iterator.call(context, value, index, list) : value; - computed >= result.computed && (result = {value : value, computed : computed}); - }); - return result.value; - }; - - // Return the minimum element (or element-based computation). - _.min = function(obj, iterator, context) { - if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { - return Math.min.apply(Math, obj); - } - if (!iterator && _.isEmpty(obj)) return Infinity; - var result = {computed : Infinity, value: Infinity}; - each(obj, function(value, index, list) { - var computed = iterator ? iterator.call(context, value, index, list) : value; - computed < result.computed && (result = {value : value, computed : computed}); - }); - return result.value; - }; - - // Shuffle an array. - _.shuffle = function(obj) { - var rand; - var index = 0; - var shuffled = []; - each(obj, function(value) { - rand = _.random(index++); - shuffled[index - 1] = shuffled[rand]; - shuffled[rand] = value; - }); - return shuffled; - }; - - // An internal function to generate lookup iterators. - var lookupIterator = function(value) { - return _.isFunction(value) ? value : function(obj){ return obj[value]; }; - }; - - // Sort the object's values by a criterion produced by an iterator. - _.sortBy = function(obj, value, context) { - var iterator = lookupIterator(value); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value : value, - index : index, - criteria : iterator.call(context, value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index < right.index ? -1 : 1; - }), 'value'); - }; - - // An internal function used for aggregate "group by" operations. - var group = function(obj, value, context, behavior) { - var result = {}; - var iterator = lookupIterator(value || _.identity); - each(obj, function(value, index) { - var key = iterator.call(context, value, index, obj); - behavior(result, key, value); - }); - return result; - }; - - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = function(obj, value, context) { - return group(obj, value, context, function(result, key, value) { - (_.has(result, key) ? result[key] : (result[key] = [])).push(value); - }); - }; - - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = function(obj, value, context) { - return group(obj, value, context, function(result, key) { - if (!_.has(result, key)) result[key] = 0; - result[key]++; - }); - }; - - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iterator, context) { - iterator = iterator == null ? _.identity : lookupIterator(iterator); - var value = iterator.call(context, obj); - var low = 0, high = array.length; - while (low < high) { - var mid = (low + high) >>> 1; - iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; - } - return low; - }; - - // Safely convert anything iterable into a real, live array. - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (obj.length === +obj.length) return _.map(obj, _.identity); - return _.values(obj); - }; - - // Return the number of elements in an object. - _.size = function(obj) { - if (obj == null) return 0; - return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; - }; - - // Array Functions - // --------------- - - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; - }; - - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. The **guard** check allows it to work with - // `_.map`. - _.initial = function(array, n, guard) { - return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); - }; - - // Get the last element of an array. Passing **n** will return the last N - // values in the array. The **guard** check allows it to work with `_.map`. - _.last = function(array, n, guard) { - if (array == null) return void 0; - if ((n != null) && !guard) { - return slice.call(array, Math.max(array.length - n, 0)); - } else { - return array[array.length - 1]; - } - }; - - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. The **guard** - // check allows it to work with `_.map`. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, (n == null) || guard ? 1 : n); - }; - - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array, _.identity); - }; - - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, output) { - each(input, function(value) { - if (_.isArray(value)) { - shallow ? push.apply(output, value) : flatten(value, shallow, output); - } else { - output.push(value); - } - }); - return output; - }; - - // Return a completely flattened version of an array. - _.flatten = function(array, shallow) { - return flatten(array, shallow, []); - }; - - // Return a version of the array that does not contain the specified value(s). - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iterator, context) { - if (_.isFunction(isSorted)) { - context = iterator; - iterator = isSorted; - isSorted = false; - } - var initial = iterator ? _.map(array, iterator, context) : array; - var results = []; - var seen = []; - each(initial, function(value, index) { - if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { - seen.push(value); - results.push(array[index]); - } - }); - return results; - }; - - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = function() { - return _.uniq(concat.apply(ArrayProto, arguments)); - }; - - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - var rest = slice.call(arguments, 1); - return _.filter(_.uniq(array), function(item) { - return _.every(rest, function(other) { - return _.indexOf(other, item) >= 0; - }); - }); - }; - - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = function(array) { - var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); - return _.filter(array, function(value){ return !_.contains(rest, value); }); - }; - - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = function() { - var args = slice.call(arguments); - var length = _.max(_.pluck(args, 'length')); - var results = new Array(length); - for (var i = 0; i < length; i++) { - results[i] = _.pluck(args, "" + i); - } - return results; - }; - - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - if (list == null) return {}; - var result = {}; - for (var i = 0, l = list.length; i < l; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; - }; - - // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), - // we need this function. Return the position of the first occurrence of an - // item in an array, or -1 if the item is not included in the array. - // Delegates to **ECMAScript 5**'s native `indexOf` if available. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = function(array, item, isSorted) { - if (array == null) return -1; - var i = 0, l = array.length; - if (isSorted) { - if (typeof isSorted == 'number') { - i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); - } else { - i = _.sortedIndex(array, item); - return array[i] === item ? i : -1; - } - } - if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); - for (; i < l; i++) if (array[i] === item) return i; - return -1; - }; - - // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. - _.lastIndexOf = function(array, item, from) { - if (array == null) return -1; - var hasIndex = from != null; - if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { - return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); - } - var i = (hasIndex ? from : array.length); - while (i--) if (array[i] === item) return i; - return -1; - }; - - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (arguments.length <= 1) { - stop = start || 0; - start = 0; - } - step = arguments[2] || 1; - - var len = Math.max(Math.ceil((stop - start) / step), 0); - var idx = 0; - var range = new Array(len); - - while(idx < len) { - range[idx++] = start; - start += step; - } - - return range; - }; - - // Function (ahem) Functions - // ------------------ - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if - // available. - _.bind = function(func, context) { - if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - var args = slice.call(arguments, 2); - return function() { - return func.apply(context, args.concat(slice.call(arguments))); - }; - }; - - // Partially apply a function by creating a version that has had some of its - // arguments pre-filled, without changing its dynamic `this` context. - _.partial = function(func) { - var args = slice.call(arguments, 1); - return function() { - return func.apply(this, args.concat(slice.call(arguments))); - }; - }; - - // Bind all of an object's methods to that object. Useful for ensuring that - // all callbacks defined on an object belong to it. - _.bindAll = function(obj) { - var funcs = slice.call(arguments, 1); - if (funcs.length === 0) funcs = _.functions(obj); - each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); - return obj; - }; - - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memo = {}; - hasher || (hasher = _.identity); - return function() { - var key = hasher.apply(this, arguments); - return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); - }; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function(){ return func.apply(null, args); }, wait); - }; - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = function(func) { - return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); - }; - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. - _.throttle = function(func, wait) { - var context, args, timeout, result; - var previous = 0; - var later = function() { - previous = new Date; - timeout = null; - result = func.apply(context, args); - }; - return function() { - var now = new Date; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0) { - clearTimeout(timeout); - timeout = null; - previous = now; - result = func.apply(context, args); - } else if (!timeout) { - timeout = setTimeout(later, remaining); - } - return result; - }; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, result; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) result = func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) result = func.apply(context, args); - return result; - }; - }; - - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = function(func) { - var ran = false, memo; - return function() { - if (ran) return memo; - ran = true; - memo = func.apply(this, arguments); - func = null; - return memo; - }; - }; - - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return function() { - var args = [func]; - push.apply(args, arguments); - return wrapper.apply(this, args); - }; - }; - - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var funcs = arguments; - return function() { - var args = arguments; - for (var i = funcs.length - 1; i >= 0; i--) { - args = [funcs[i].apply(this, args)]; - } - return args[0]; - }; - }; - - // Returns a function that will only be executed after being called N times. - _.after = function(times, func) { - if (times <= 0) return func(); - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - - // Object Functions - // ---------------- - - // Retrieve the names of an object's properties. - // Delegates to **ECMAScript 5**'s native `Object.keys` - _.keys = nativeKeys || function(obj) { - if (obj !== Object(obj)) throw new TypeError('Invalid object'); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; - return keys; - }; - - // Retrieve the values of an object's properties. - _.values = function(obj) { - var values = []; - for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); - return values; - }; - - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var pairs = []; - for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); - return pairs; - }; - - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; - return result; - }; - - // Return a sorted list of the function names available on the object. - // Aliased as `methods` - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); - } - return names.sort(); - }; - - // Extend a given object with all the properties in passed-in object(s). - _.extend = function(obj) { - each(slice.call(arguments, 1), function(source) { - if (source) { - for (var prop in source) { - obj[prop] = source[prop]; - } - } - }); - return obj; - }; - - // Return a copy of the object only containing the whitelisted properties. - _.pick = function(obj) { - var copy = {}; - var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); - each(keys, function(key) { - if (key in obj) copy[key] = obj[key]; - }); - return copy; - }; - - // Return a copy of the object without the blacklisted properties. - _.omit = function(obj) { - var copy = {}; - var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); - for (var key in obj) { - if (!_.contains(keys, key)) copy[key] = obj[key]; - } - return copy; - }; - - // Fill in a given object with default properties. - _.defaults = function(obj) { - each(slice.call(arguments, 1), function(source) { - if (source) { - for (var prop in source) { - if (obj[prop] == null) obj[prop] = source[prop]; - } - } - }); - return obj; - }; - - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - - // Internal recursive comparison function for `isEqual`. - var eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. - if (a === b) return a !== 0 || 1 / a == 1 / b; - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) return a === b; - // Unwrap any wrapped objects. - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className != toString.call(b)) return false; - switch (className) { - // Strings, numbers, dates, and booleans are compared by value. - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return a == String(b); - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for - // other numeric values. - return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a == +b; - // RegExps are compared by their source patterns and flags. - case '[object RegExp]': - return a.source == b.source && - a.global == b.global && - a.multiline == b.multiline && - a.ignoreCase == b.ignoreCase; - } - if (typeof a != 'object' || typeof b != 'object') return false; - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] == a) return bStack[length] == b; - } - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - var size = 0, result = true; - // Recursively compare objects and arrays. - if (className == '[object Array]') { - // Compare array lengths to determine if a deep comparison is necessary. - size = a.length; - result = size == b.length; - if (result) { - // Deep compare the contents, ignoring non-numeric properties. - while (size--) { - if (!(result = eq(a[size], b[size], aStack, bStack))) break; - } - } - } else { - // Objects with different constructors are not equivalent, but `Object`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && - _.isFunction(bCtor) && (bCtor instanceof bCtor))) { - return false; - } - // Deep compare objects. - for (var key in a) { - if (_.has(a, key)) { - // Count the expected number of properties. - size++; - // Deep compare each member. - if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; - } - } - // Ensure that both objects contain the same number of properties. - if (result) { - for (key in b) { - if (_.has(b, key) && !(size--)) break; - } - result = !size; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return result; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b, [], []); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) return true; - if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; - for (var key in obj) if (_.has(obj, key)) return false; - return true; - }; - - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) == '[object Array]'; - }; - - // Is a given variable an object? - _.isObject = function(obj) { - return obj === Object(obj); - }; - - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. - each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) == '[object ' + name + ']'; - }; - }); - - // Define a fallback version of the method in browsers (ahem, IE), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return !!(obj && _.has(obj, 'callee')); - }; - } - - // Optimize `isFunction` if appropriate. - if (typeof (/./) !== 'function') { - _.isFunction = function(obj) { - return typeof obj === 'function'; - }; - } - - // Is a given object a finite number? - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; - - // Is the given value `NaN`? (NaN is the only number which does not equal itself). - _.isNaN = function(obj) { - return _.isNumber(obj) && obj != +obj; - }; - - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; - }; - - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; - - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; - - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return hasOwnProperty.call(obj, key); - }; - - // Utility Functions - // ----------------- - - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - - // Keep the identity function around for default iterators. - _.identity = function(value) { - return value; - }; - - // Run a function **n** times. - _.times = function(n, iterator, context) { - var accum = Array(n); - for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); - return accum; - }; - - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - - // List of HTML entities for escaping. - var entityMap = { - escape: { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '/': '/' - } - }; - entityMap.unescape = _.invert(entityMap.escape); - - // Regexes containing the keys and values listed immediately above. - var entityRegexes = { - escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), - unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') - }; - - // Functions for escaping and unescaping strings to/from HTML interpolation. - _.each(['escape', 'unescape'], function(method) { - _[method] = function(string) { - if (string == null) return ''; - return ('' + string).replace(entityRegexes[method], function(match) { - return entityMap[method][match]; - }); - }; - }); - - // If the value of the named property is a function then invoke it; - // otherwise, return it. - _.result = function(object, property) { - if (object == null) return null; - var value = object[property]; - return _.isFunction(value) ? value.call(object) : value; - }; - - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - each(_.functions(obj), function(name){ - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return result.call(this, func.apply(_, args)); - }; - }); - }; - - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\t': 't', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - _.template = function(text, data, settings) { - var render; - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = new RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset) - .replace(escaper, function(match) { return '\\' + escapes[match]; }); - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } - if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } - if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - index = offset + match.length; - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + "return __p;\n"; - - try { - render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - if (data) return render(data, _); - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled function source as a convenience for precompilation. - template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; - - return template; - }; - - // Add a "chain" function, which will delegate to the wrapper. - _.chain = function(obj) { - return _(obj).chain(); - }; - - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. - - // Helper function to continue chaining intermediate results. - var result = function(obj) { - return this._chain ? _(obj).chain() : obj; - }; - - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); - - // Add all mutator Array functions to the wrapper. - each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; - return result.call(this, obj); - }; - }); - - // Add all accessor Array functions to the wrapper. - each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result.call(this, method.apply(this._wrapped, arguments)); - }; - }); - - _.extend(_.prototype, { - - // Start chaining a wrapped Underscore object. - chain: function() { - this._chain = true; - return this; - }, - - // Extracts the result from a wrapped and chained object. - value: function() { - return this._wrapped; - } - - }); - -}).call(this); diff --git a/contexts/data/tests/PhantomJSJasmineRunner.html b/contexts/data/tests/PhantomJSJasmineRunner.html deleted file mode 100644 index b240f46..0000000 --- a/contexts/data/tests/PhantomJSJasmineRunner.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - Jasmine Test Runner - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contexts/data/tests/README.md b/contexts/data/tests/README.md deleted file mode 100644 index dbd8435..0000000 --- a/contexts/data/tests/README.md +++ /dev/null @@ -1,30 +0,0 @@ -Running Tests -============= - -The Javascript unit tests for FiveUI can be run in one of two ways, manually in -your browser, or in a headless context (better for automation/continuous -integration). - -In Browser ----------- - -Start a local webserver at the FiveUI project root ($FIVEUI_ROOT) and load -`contexts/data/tests/SpecRunner.html`. - -Headless --------- - -Install [phantomjs](http://phantomjs.org/) on your system. - - - Debian/Ubuntu: apt-get install phantomjs - - Fedora: yum install phantomjs - - Mac OSX: brew install phantomjs - -Run: - - $ cd contexts/data - $ phantomjs lib/phantomjs_jasmine/phantomjs_jasminexml_runner.js \ - tests/PhantomJSJasmineRunner.html tests/reports/ - -XML test reports will be generated in -`$FIVEUI_ROOT/contexts/data/tests/reports/`. diff --git a/contexts/data/tests/SpecRunner.html b/contexts/data/tests/SpecRunner.html deleted file mode 100644 index 4a7ec8c..0000000 --- a/contexts/data/tests/SpecRunner.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - Jasmine Spec Runner v2.0.0-alpha - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contexts/data/tests/mock-storage.js b/contexts/data/tests/mock-storage.js deleted file mode 100644 index 71c667f..0000000 --- a/contexts/data/tests/mock-storage.js +++ /dev/null @@ -1,20 +0,0 @@ - -var MockStorage = function() { - this.store = {}; -}; - -_.extend(MockStorage.prototype, { - - getItem: function(key) { - return this.store[key]; - }, - - setItem: function(key,value) { - this.store[key] = value; - }, - - removeItem: function(key,value) { - delete this.store[key]; - }, - -}); diff --git a/contexts/data/tests/specs/messenger.js b/contexts/data/tests/specs/messenger.js deleted file mode 100644 index 12bd9e1..0000000 --- a/contexts/data/tests/specs/messenger.js +++ /dev/null @@ -1,96 +0,0 @@ - -describe('fiveui.Messenger', function() { - - var chan1 = null; - var chan2 = null; - - var m1 = null; - var m2 = null; - - - beforeEach(function() { - chan1 = new fiveui.Chan(); - chan2 = new fiveui.Chan(); - - chan2.chan = chan1; - chan1.chan = chan2 - - m1 = new fiveui.Messenger(chan1); - m2 = new fiveui.Messenger(chan2); - }); - - - afterEach(function() { - delete m1; - delete chan1; - - delete m2; - delete chan2; - }); - - - it('registers a simple callback', function() { - var got = []; - - m1.register('count', function(n) { - got.push(n); - }); - - m2.send('count', 1); - m2.send('count', 2); - - expect(got).toEqual([1,2]); - }); - - - it('supports respond callbacks when sending', function() { - var m1got = []; - var m2got = []; - - m1.register('count', function(n, respond){ - m1got.push(n); - respond(n); - }); - - m2.send('count', 1, function(n) { - m2got.push(n); - }); - - expect(m1got.length).toBe(m2got.length); - }); - - - it('doesn\'t invoke callbacks for null data', function() { - var m1got = []; - - m1.register('count', function(n) { - m1got.push(n); - }); - - m2.send('count', null); - - expect(m1got[0]).toBe(null); - }); - - - it('is able to send rules', function() { - var ruleIn = new fiveui.Rule(42, 'testRule', - 'see: http://test.description/', - 'function() { console.log("fail"); }'); - - var got = []; - m1.register('rule', function(r){ - got.push(r); - }); - - m2.send('rule', ruleIn); - expect(got.length).toBe(1); - - var ruleOut = got[0]; - expect(ruleIn.id).toBe(ruleOut.id); - expect(ruleIn.name).toBe(ruleOut.name); - expect(ruleIn.description).toBe(ruleOut.description); - expect(ruleIn.ruleStr).toBe(ruleOut.ruleStr); - }); - -}); diff --git a/contexts/data/tests/specs/prelude.js b/contexts/data/tests/specs/prelude.js deleted file mode 100644 index 31510e7..0000000 --- a/contexts/data/tests/specs/prelude.js +++ /dev/null @@ -1,157 +0,0 @@ - -describe('prelude', function() { - - var addTestSet = function(fn, tests) { - _.each(tests, function(test) { - it(test[0], function() { - expect(fn(test[1])).toEqual(test[2]); - }); - }); - }; - - addTestSet(fiveui.isString,[ - // name , input , oracle - ['isString: undefined', undefined, false], - ['isString: null' , null, false], - ['isString: a string' , 'str', true] - ]); - - addTestSet(fiveui.string.trim, [ - ['string.trim leading space' , ' str', 'str'], - ['string.trim on null' , null, null], - ['string.trim trailing space' , 'str ', 'str'], - ['string.trim trailing tab' , 'str \t ', 'str'], - ['string.trim mixed & interior', ' this is a str \t ', 'this is a str'] - ]); - - addTestSet(fiveui.word.capitalized, [ - ['capitalize: empty string' , '', false], - ['capitalize: a space' , ' ', false], - ['capitalize: whitespace' , '\t ', false], - ['capitalize: lowercase' , 'test', false], - ['capitalize: N-token' , 'a test', false], - ['capitalize: leading space' , ' test', false], - ['capitalize: 1-token - leading cap' , 'Test', true], - ['capitalize: N-token - leading cap' , 'A test', true], - ['capitalize: N-token - one cap' , 'this is a Test', false], - ['capitalize: N-token - one cap, punc' , 'this, is a Test.', false], - ['capitalize: N-token - all leading caps' , 'This Test', true], - ['capitalize: all caps' , 'TEST', true], - ['capitalize: N-token - all caps' , 'A TEST', true] - ]); - - addTestSet(fiveui.word.allCaps, [ - ['allCaps: empty string' , '', false], - ['allCaps: a space' , ' ', false], - ['allCaps: whitespace' , '\t ', false], - ['allCaps: lowercase' , 'test', false], - ['allCaps: N-token' , 'a test', false], - ['allCaps: leading space' , ' test', false], - ['allCaps: all caps' , 'TEST', true], - ['allCaps: N-token - all caps' , 'A TEST', true], - ['allCaps: 1-token - leading cap' , 'Test', false], - ['allCaps: N-token - leading cap' , 'A test', false], - ['allCaps: N-token - one cap , punc' , 'this, is a Test.', false], - ['allCaps: N-token - all caps , punc' , 'THIS, IS A TEST.', true] - ]); - - var testTokenize = function(spec) { - it(spec[0], function() { - var result = fiveui.string.tokens(spec[1]); - var oracle = spec[2]; - - expect(result.length).toBe(oracle.length); - - _.each(result, function(r, i) { - expect(r).toEqual(oracle[i]); - }) - }); - }; - - _.each([ - ['tokenize: empty string' , '', []], - ['tokenize: a space' , ' ', []], - ['tokenize: whitespace' , '\t ', []], - ['tokenize: lowercase' , 'test', ['test']], - ['tokenize: N-token' , 'a test', ['a', 'test']], - ['tokenize: N-token - more spaces', 'a test', ['a', 'test']], - ['tokenize: leading spaces' , ' test', ['test']], - ['tokenize: trailing spaces', 'test ', ['test']], - ['tokenize: N-token' , 'this is a test', ['this', 'is', 'a', 'test']], - ['tokenize: N-token - punc' , 'this, is a test.', ['this,', 'is', 'a', 'test.']] - ], testTokenize); - - it('colorCheck returns a function', function() { - expect(typeof fiveui.color.colorCheck('', [])).toEqual('function'); - }); - - addTestSet(fiveui.color.colorToHex, [ - ['colorToHex: full white' , '#000000', '#000000'], - ['colorToHex: abreviated white 1' , '#0', '#000000'], - ['colorToHex: abreviated white 2' , '#00', '#000000'], - ['colorToHex: black' , '#FFFFFF', '#FFFFFF'], - ['colorToHex: abreviated black' , '#FF', '#FFFFFF'], - ['colorToHex: abreviated C7 grey' , '#C7', '#C7C7C7'], - ['colorToHex: rgb(0, 0, 0)' , 'rgb(0, 0, 0)', '#000000'], - ['colorToHex: rgb(255, 255, 255)' , 'rgb(255, 255, 255)', '#FFFFFF'], - ['colorToHex: rgb(222, 173, 190)' , 'rgb(222, 173, 190)', '#DEADBE'], - ['colorToHex: rgba(255, 255, 255, 100)', 'rgba(255, 255, 255, 100)', '#FFFFFF'] // alpha is ignored - ]); - - var getFontTests = [ - // CSS ID, Family, Weight, Size - ['#getFontTest1', 'Arial', 'normal', '12'], - ['#getFontTest2', 'Arial sans-serif', 'normal', '12'], - ['#getFontTest3', 'Arial', 'bold', '12'], - // this case deals with an unparsable font-size parameter, which yields an - // empty size field on the result structure. - ['#getFontTest4', 'Verdana', 'bold', ''] - ]; - - - var getFontTestsDom = jQuery( - '

      FontTest1

      ' - +'

      FontTest2

      ' - +'

      FontTest3

      ' - +'

      FontTest4

      ' - +'
      ' - ); - - _.each(getFontTests, function (spec) { - it(spec[0], function() { - var jElt = getFontTestsDom.find(spec[0]); - var font = fiveui.font.getFont(jElt); - expect(font.family.indexOf(spec[1])).not.toBe(-1); - expect(font.weight.indexOf(spec[2])).not.toBe(-1); - expect(font.size.indexOf(spec[3])).not.toBe(-1); - }); - }); - - var validateTests = - // name, allow, font, oracle - [ ['a:verdana-bold-10 f:verdana+sans-bold-10', {'Verdana':{'bold':[10]}}, - {'family':'Verdana sans-serif', 'weight':'bold', 'size':'10'}, - true ] - , ['a:verdana-normal-12 f:verdana+sans-bold-10', {'Verdana':{'normal':[12]}}, - {'family':'Verdana sans-serif', 'weight':'bold', 'size':'10'}, - false ] - , ['a:arial-normal-12 f:verdana+sans-bold-10', {'Arial':{'normal':[12]}}, - {'family':'Verdana sans-serif', 'weight':'bold', 'size':'10'}, - false ] - , ['a:verdana-normal-10,12,14 f:verdana-normal-14', {'Verdana':{'normal':[10, 12, 14]}}, - {'family':'Verdana', 'weight':'normal', 'size':'14'}, - true ] - , ['a:verdana-normal,bold-12 f:verdana-bold-12', {'Verdana':{'normal':[12], 'bold':[12]}}, - {'family':'Verdana', 'weight':'bold', 'size':'12'}, - true ] - , ['a:verdana,arial-normal-12 f:arial-normal-12', {'Verdana':{'normal':[12]}, 'Arial':{'normal':[12]}}, - {'family':'Arial', 'weight':'normal', 'size':'12'}, - false ] - ]; - _.each(validateTests, function (spec) { - it(spec[0], function () { - expect(fiveui.font.validate(spec[1], spec[2])).toEqual(spec[3]); - }); - }); - -}); diff --git a/contexts/data/tests/specs/rules.js b/contexts/data/tests/specs/rules.js deleted file mode 100644 index b9db6b3..0000000 --- a/contexts/data/tests/specs/rules.js +++ /dev/null @@ -1,64 +0,0 @@ - -describe('fiveui.Rules', function() { - - it('round trips via JSON', function() { - - var ruleIn = new fiveui.Rule(42, 'testRule', - 'see: http://test.description/', - 'function() { console.log("fail"); }'); - - var jsonRule = JSON.stringify(ruleIn); - - var ruleOut = fiveui.Rule.fromJSON(JSON.parse(jsonRule)); - - expect(ruleOut.id).toBe(ruleIn.id); - expect(ruleOut.name).toBe(ruleIn.name); - expect(ruleOut.description).toBe(ruleIn.description); - expect(ruleOut.ruleStr).toBe(ruleIn.ruleStr); - }); - - -}); - - -describe('fiveui.RuleSet', function() { - - it('round trips via JSON, without deps', function() { - - var rule1 = new fiveui.Rule(42, 'r1', 'desc1', 'rule txt1'); - var rule2 = new fiveui.Rule(43, 'r2', 'desc2', 'rule txt2'); - - var ruleSet = new fiveui.RuleSet(42, 'rule set', 'desc', '', [rule1, rule2]); - - var jsonSet = JSON.stringify(ruleSet); - var restoredSet = fiveui.RuleSet.fromJSON(42, JSON.parse(jsonSet)); - - expect(restoredSet.id).toBe(ruleSet.id); - expect(restoredSet.name).toBe(ruleSet.name); - expect(restoredSet.description).toBe(ruleSet.description); - expect(restoredSet.source).toEqual(ruleSet.source); - expect(restoredSet.rules).toEqual(ruleSet.rules); - expect(restoredSet.dependencies.length).toBe(0); - - - }); - - it('round trips via JSON, with deps', function() { - - var rule1 = new fiveui.Rule(42, 'r1', 'desc1', 'rule txt1'); - var rule2 = new fiveui.Rule(43, 'r2', 'desc2', 'rule txt2'); - - var ruleSet = new fiveui.RuleSet(42, 'rule set', 'desc', [rule1, rule2], - '', ['dep1.js', 'dep2.js']); - - var jsonSet = JSON.stringify(ruleSet); - var restoredSet = fiveui.RuleSet.fromJSON(42, JSON.parse(jsonSet)); - - expect(restoredSet.id).toBe(ruleSet.id); - expect(restoredSet.name).toBe(ruleSet.name); - expect(restoredSet.description).toBe(ruleSet.description); - expect(restoredSet.rules.length).toBe(ruleSet.rules.length); - expect(restoredSet.dependencies).toEqual(ruleSet.dependencies); - }); - -}); diff --git a/contexts/data/tests/specs/set.js b/contexts/data/tests/specs/set.js deleted file mode 100644 index a0dfb71..0000000 --- a/contexts/data/tests/specs/set.js +++ /dev/null @@ -1,24 +0,0 @@ - -describe('Set', function() { - - it('tests membership', function() { - var set = new Set(); - set.add(1); - expect(set.member(1)).toBe(true); - }); - - it('allows multiple inserts', function() { - var set = new Set(); - - set.add(1); - set.add(1); - - expect(set.size()).toBe(1); - }); - - it('fails the membership test for things that aren\'t in the set', function() { - var set = new Set(); - expect(set.member(1)).toBe(false); - }); - -}); diff --git a/contexts/data/tests/specs/settings.js b/contexts/data/tests/specs/settings.js deleted file mode 100644 index a89b532..0000000 --- a/contexts/data/tests/specs/settings.js +++ /dev/null @@ -1,87 +0,0 @@ - -describe('fiveui.Settings', function() { - - var settings; - - beforeEach(function() { - settings = new fiveui.Settings(new MockStorage()); - }); - - - it('doesn\'t hold on to removed keys', function() { - var key = 'key'; - var value = 'value'; - var id = settings.set(key, value); - settings.remove(key); - - var result = settings.get(id); - expect(result).toBe(null); - }); - - - it('round trips values through set/get', function() { - var key = 'key'; - var value = 'value'; - - settings.set(key, value); - expect(settings.get(key)).toEqual(value); - }); - - it('round trips rules through addUrl', function() { - // somewhat random rule id - var ruleId = Math.floor(Math.random() * 101); - var urlPat = 'http://.*'; - var urlId = settings.addUrl(urlPat, ruleId); - var result = settings.getUrlPat(urlId); - - expect(result.regex).toBe(urlPat); - expect(result.rule_id).toBe(ruleId); - }); - - it('matches urls when there\s a valid pattern registered', function() { - var newId = 42; - settings.addUrl('http://.*', newId); - expect(settings.checkUrl('http://foo').rule_id).toBe(newId); - }); - - it('doesn\'t match urls when there are no patterns registered', function() { - expect(settings.checkUrl('http://foo')).toBe(null); - }); - - it('removes rules successfully', function() { - var obj = { - id: 17, - name: 'rs', - description: '', - rules: [] - }; - - var rs = settings.addRuleSet(obj); - expect(rs).not.toBe(null); - - var rsCount1 = settings.getRuleSets().length; - settings.remRuleSet(rs.id); - var rsCount2 = settings.getRuleSets().length; - expect(rsCount1).toEqual(rsCount2 + 1); - - rs = settings.getRuleSet(rs.id); - expect(rs).toBe(null); - }); - - it('is unable to remove rules that are in use', function() { - var obj = { - id: 17, - name: 'rs', - description: '', - rules: [] - }; - - var rs = settings.addRuleSet(obj); - expect(rs).not.toBe(null); - - var urlPatId = settings.addUrl('*', rs.id); - rs = settings.getRuleSet(rs.id); - expect(rs).not.toBe(null); - }); - -}); diff --git a/contexts/data/tests/specs/state.js b/contexts/data/tests/specs/state.js deleted file mode 100644 index 65ff0b1..0000000 --- a/contexts/data/tests/specs/state.js +++ /dev/null @@ -1,29 +0,0 @@ - -describe('fiveui.state', function() { - - var storage, state; - - beforeEach(function() { - storage = new MockStorage(); - state = new fiveui.State(storage); - }); - - it('cannot retrieve a tab that doesn\'t exist', function() { - expect(storage.getItem(42)).toBe(undefined); - expect(state.getTabState(42)).toBe(null); - }); - - it('manages the window location', function() { - var testId = 42; - var winState = new fiveui.WinState(0,1,10,15); - var tabState = new fiveui.TabState(testId,winState); - var oracle = new fiveui.TabState(testId,new fiveui.WinState(0,1,10,15)); - - state.setTabState(tabState); - var result = state.getTabState(testId); - _.each(result,function(val,key) { - expect(val).toEqual(oracle[key]); - }); - }); - -}); diff --git a/contexts/data/tests/specs/utils.js b/contexts/data/tests/specs/utils.js deleted file mode 100644 index f4ed399..0000000 --- a/contexts/data/tests/specs/utils.js +++ /dev/null @@ -1,20 +0,0 @@ - -describe('fiveui.utils', function() { - - describe('fiveui.utils.getNewId', function() { - - it('returns 0 when no elements are given', function() { - expect(fiveui.utils.getNewId([])).toBe(0); - }); - - it('returns 1, when 0 is given', function() { - expect(fiveui.utils.getNewId([0])).toBe(1); - }); - - it('ignores order when finding the maximum element', function() { - expect(fiveui.utils.getNewId([2,1])).toBe(3); - }); - - }); - -}); diff --git a/contexts/manifest.json b/contexts/manifest.json deleted file mode 100644 index 584f5d0..0000000 --- a/contexts/manifest.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "manifest_version": 2, - - "name": "Five UI", - "version": "0.2", - "description": "UI Constraint Checker", - - "icons": { "16": "data/fiveui/images/fiveui-icon-16.png", - "48": "data/fiveui/images/fiveui-icon-48.png", - "128": "data/fiveui/images/fiveui-icon-128.png" - }, - - "background": { - "persistent": true, - "page": "data/fiveui/chrome/background.html" - }, - - "options_page": "data/fiveui/options.html", - - "browser_action": { - "default_icon": "data/fiveui/images/fiveui-icon-disabled.png", - "default_title": "Five UI" - }, - "permissions": [ - "tabs", "http://*/*", "https://*/*", "history" - ], - - // We have to relax the content security policy to allow rules to be evaluated: - "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" -} diff --git a/contexts/package.json b/contexts/package.json deleted file mode 100644 index eea95f1..0000000 --- a/contexts/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "fiveui", - "fullName": "Five UI", - "license": "BSD 3", - "author": "Galois (http://galois.com)", - "contributors": [ "Rogan Creswick ", - "Trevor Elliot ", - "Benjamin Jones " - ], - "version": "0.2", - "id": "jid1-oquzbbbog1fmxq", - "description": "UI Constraint Checker", - "lib": "data/", - "main": "target/firefox-main", - "tests": "data/fiveui/firefox/test" -} diff --git a/doc/build.mk b/doc/build.mk index f62ef54..f628a6c 100644 --- a/doc/build.mk +++ b/doc/build.mk @@ -60,7 +60,7 @@ $(eval $(call stage-doc-dir,$(path)/images)) doc: $(jsdoc-dir)/index.html $(jsdoc-dir)/index.html: \ - $(topdir)/contexts/data/fiveui/injected/prelude.js \ - $(topdir)/contexts/data/fiveui/injected/jquery-plugins.js \ + $(topdir)/src/js/fiveui/injected/prelude.js \ + $(topdir)/src/js/fiveui/injected/jquery-plugins.js \ | $(build-dir) $(call label,JSDOC)$(topdir)/tools/bin/jsdoc $^ $(redir) diff --git a/exampleData/ruleSets/colorRules/backgroundCheck.js b/exampleData/ruleSets/colorRules/backgroundCheck.js index 4ce7043..98df08c 100644 --- a/exampleData/ruleSets/colorRules/backgroundCheck.js +++ b/exampleData/ruleSets/colorRules/backgroundCheck.js @@ -8,11 +8,11 @@ exports.description = exports.rule = function() { var allow = '#00 #FF #3D #F7 #C2 #B4 #4E'.split(' '); - report("broken"); + this.report("broken"); $5(':visible') .cssIsNot('background-color', allow, fiveui.color.colorToHex) .each(function(i, elt) { var color = fiveui.color.colorToHex($(elt).css('background-color')); - report('non-standard background color: ' + color, $(elt)); + this.report('non-standard background color: ' + color, $(elt)); }); }; diff --git a/exampleData/ruleSets/colorRules/foregroundCheck.js b/exampleData/ruleSets/colorRules/foregroundCheck.js index 5b1e04b..2cf2b5f 100644 --- a/exampleData/ruleSets/colorRules/foregroundCheck.js +++ b/exampleData/ruleSets/colorRules/foregroundCheck.js @@ -11,6 +11,6 @@ exports.rule = function() { .cssIsNot('color', allow, fiveui.color.colorToHex) .each(function(i, elt) { var color = fiveui.color.colorToHex($(elt).css('color')); - report('foreground color: ' + color, elt); + this.report('foreground color: ' + color, elt); }); }; diff --git a/src/js/chrome/background.html b/src/js/chrome/background.html new file mode 100644 index 0000000..8ca54fd --- /dev/null +++ b/src/js/chrome/background.html @@ -0,0 +1,38 @@ + + + + + Background Page + + + + + + + + + + + + + + diff --git a/src/js/chrome/build.mk b/src/js/chrome/build.mk new file mode 100644 index 0000000..b93cc6f --- /dev/null +++ b/src/js/chrome/build.mk @@ -0,0 +1,48 @@ + + +# Chrome Extension ############################################################# + +all: $(build-dir)/fiveui.crx + +chrome-dir := $(path) + +chrome-build := $(build-dir)/chrome + + +# Generic Extension Parts ###################################################### + +# pull in the base fiveui extension +$(eval $(call stage-fiveui,$(chrome-build),$(build-dir)/fiveui.crx)) + + +# Chrome File Staging ########################################################## + +# copy over scripts from the chrome extension +$(chrome-build)/data/js/%: $(chrome-dir)/js/% | $(chrome-build)/data/js + $(call cmd,cp) + +$(chrome-build)/data/injected/%: $(chrome-dir)/injected/% | $(chrome-build)/data/injected + $(call cmd,cp) + +$(chrome-build)/data/%: $(chrome-dir)/% | $(chrome-build)/data + $(call cmd,cp) + +$(chrome-build)/%: $(chrome-dir)/% | $(chrome-build) + $(call cmd,cp) + +$(chrome-build): | $(build-dir) + $(call cmd,mkdir) + + +# Packaging #################################################################### + +# generate the executable after copying over all files +$(build-dir)/fiveui.crx: $(chrome-build)/manifest.json \ + $(chrome-build)/data/background.html \ + $(chrome-build)/data/js/platform-port.js \ + $(chrome-build)/data/js/platform-background.js \ + | $(chrome-build) + $(call label,MAKECRX $(call drop-prefix,$@)) ( cd $(build-dir) \ + && $(topdir)/tools/bin/makecrx $(chrome-build) \ + $(topdir)/fiveui.pem fiveui \ + $(redir) ) diff --git a/src/js/chrome/injected/platform-compute.js b/src/js/chrome/injected/platform-compute.js new file mode 100644 index 0000000..a372913 --- /dev/null +++ b/src/js/chrome/injected/platform-compute.js @@ -0,0 +1,27 @@ +/* + * Module : chrome/chrome-injected-compute.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Chrome Only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @return {{on: function(!string, function(*)), emit: function(!string, *)}} + */ +var obtainComputePort = function() { + return new fiveui.ChromePort(chrome.extension.connect({ name: 'compute' })); +}; diff --git a/src/js/chrome/injected/platform-ui.js b/src/js/chrome/injected/platform-ui.js new file mode 100644 index 0000000..939a62d --- /dev/null +++ b/src/js/chrome/injected/platform-ui.js @@ -0,0 +1,27 @@ +/* + * Module : chrome/chrome-injected-ui.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Chrome Only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @return {{on: function(!string, function(*)), emit: function(!string, *)}} + */ +var obtainPort = function() { + return new fiveui.ChromePort(chrome.extension.connect({ name: 'ui' })); +}; diff --git a/src/js/chrome/js/platform-ajax.js b/src/js/chrome/js/platform-ajax.js new file mode 100644 index 0000000..68ced39 --- /dev/null +++ b/src/js/chrome/js/platform-ajax.js @@ -0,0 +1,39 @@ + + +var fiveui = fiveui || {}; + +(function() { + +fiveui.ajax = fiveui.ajax || {}; + +/** + * Use jQuery to get the resource, calling the success or error continuations + * when the result is returned. This always retrieves as text, leaving any + * further processing to the success continuation. + */ +fiveui.ajax.get = function(url, options) { + + _.defaults(options, { + success:function() {}, + error: function() {} + }); + + jQuery.ajax(url, { + + dataType: 'text', + + success:function(text) { + // strip out everything else from the args + options.success(text); + }, + + error:function() { + // call with no context + options.error(); + }, + + }); + +}; + +})(); diff --git a/src/js/chrome/js/platform-background.js b/src/js/chrome/js/platform-background.js new file mode 100644 index 0000000..6ffecf8 --- /dev/null +++ b/src/js/chrome/js/platform-background.js @@ -0,0 +1,165 @@ +/* + * Module : chrome/background.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Chrome Only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var fiveui = fiveui || {}; + +(function() { + +fiveui.chrome = fiveui.chrome || {}; + +/** + * The primary entry point for the FiveUI Chrome background page. + */ +fiveui.chrome.background = function() { + + /** + * Inject code and resources into the specified tab's web page. + * + * @param {!number} tabid The id of the tab to load scripts into. + * @param {!Array.} inScripts The list of scripts to load in + * order. + * @param {!boolean} inFrames Whether or not to inject into iFrames. + * @return {void} + */ + var loadScripts = function(tabid, inScripts, inFrames) { + var chromeScripts = [dataLoader('js/platform-port.js')]; + if(inFrames) { + chromeScripts.push(dataLoader('injected/platform-compute.js')); + } else { + chromeScripts.push(dataLoader('injected/platform-ui.js')); + } + var scripts = _.flatten([chromeScripts, inScripts]); + + var end = function() {}; + + var loop = function() { + var next = loop; + if (scripts.length == 1) { + next = end; + } + + var script = scripts.shift(); + + // console.log('injecting: ' + script); + + if (/css$/.test(script)) { + chrome.tabs.insertCSS(tabid, { 'file' : script }, next); + } else { + chrome.tabs.executeScript(tabid, { 'file' : script }, next); + } + }; + + loop(); + }; + + /** + * Set the current widget icon. + * + * @param {!string} iconPath The local path to the icon to use. + * @return {void} + */ + var setIcon = function(iconPath) { + chrome.tabs.getSelected(null, + function(tab) { + chrome.browserAction.setIcon({ + path: iconPath, + tabId: tab.id + }); + }); + }; + + /** + * Change the text undearneath the fiveui icon. + * + * @param {!fiveui.TabState} tabState The tab state object to update. + * @return {void} + */ + var updateIconText = function(tabState) { + var tabId = tabState.tabId; + var probs = tabState.problems.length; + var text = ''; + if (probs > 0) { + if (probs > 99) { + text = '99+'; + } else { + text = probs.toString(); + } + } + chrome.browserAction.setBadgeText({ text: text, tabId: tabId }); + }; + + var updateWidget = function(tabState) { + if(null == tabState) { + setIcon('images/fiveui-icon-disabled.png'); + } else { + setIcon('images/fiveui-icon-enabled.png'); + updateIconText(tabState); + } + }; + + // launch the generic background script + var dataLoader = function (path) { + return "data/"+path; + }; + var settings = new fiveui.Settings(localStorage); + background = new fiveui.Background(settings, updateWidget, + loadScripts, dataLoader); + + // notify the generic background about a new content script connection. + chrome.extension.onConnect.addListener( + function(chPort) { + var port = new fiveui.ChromePort(chPort); + var tabId = chPort.sender.tab.id; + var url = chPort.sender.tab.url; + + background.connect(tabId, port, url, chPort.name == 'ui'); + }); + + + chrome.tabs.onCreated.addListener(function(tab) { + // console.log('in oncreated'); + if (tab.url) { + background.pageLoad(tab.id, tab.url); + } + }); + // check page load events against the generic background + chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { + if (changeInfo.status == 'complete') { + background.pageLoad(tabId, tab.url); + } + }); + + chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) { + background.removeTab(tabId); + }); + + // show the browser widget when the fiveui button is clicked. + chrome.browserAction.onClicked.addListener(function(tab) { + background.showUI(tab.id); + }); +}; + +// Add event listeners once the DOM has fully loaded by listening for the +// `DOMContentLoaded` event on the document, and adding your listeners to +// specific elements when it triggers. +fiveui.chrome.background(); + +})(); diff --git a/src/js/chrome/js/platform-options.js b/src/js/chrome/js/platform-options.js new file mode 100644 index 0000000..b049122 --- /dev/null +++ b/src/js/chrome/js/platform-options.js @@ -0,0 +1,48 @@ +/* + * Module : chrome/chrome-options.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Chrome Only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var fiveui = fiveui || {}; + +(function() { + +fiveui.chrome = fiveui.chrome || {}; +fiveui.chrome.options = fiveui.chrome.options || {}; + + +_.extend(fiveui.chrome.options, { + init: function() { + var optionsChan = new fiveui.Chan(); + var storageChan = new fiveui.Chan(); + + optionsChan.chan = storageChan; + storageChan.chan = optionsChan; + + var settings = new fiveui.Settings(localStorage); + + fiveui.Settings.manager(storageChan, settings); + fiveui.options.init(optionsChan); + } +}); + +// run the init function when the page loads +jQuery(fiveui.chrome.options.init); + +})(); diff --git a/src/js/chrome/js/platform-port.js b/src/js/chrome/js/platform-port.js new file mode 100644 index 0000000..8a5aeae --- /dev/null +++ b/src/js/chrome/js/platform-port.js @@ -0,0 +1,70 @@ +/* + * Module : chrome/chrome-port.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Chrome Only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +if (typeof goog != 'undefined') { + goog.provide('fiveui.ChromePort'); +} else { + var fiveui = fiveui || {}; +} + +/** + * @constructor + * @param {!{onMessage:Object,postMessage:function(*):void}} port The connection to manage. + */ +fiveui.ChromePort = function(port) { + var events = {}; + + this._port = port; + this._events = events; + + this._port.onMessage.addListener(function(obj) { + var evt = obj.type; + var cb = events[evt]; + if(null != evt && null != cb) { + cb(obj.payload); + } + }); +}; + +/** + * Listen to incoming messages. + * + * @param {!string} evt The event to listen for. + * @param {!function(*)} cb The callback to invoke. + * @return {void} + */ +fiveui.ChromePort.prototype.on = function(evt, cb) { + this._events[evt] = cb; +}; + +/** + * Send a message to the background. + * + * @param {!string} evt The event to fire. + * @param {?Object} obj The data to associate with the event. + * @return {void} + */ +fiveui.ChromePort.prototype.emit = function(evt, obj) { + // console.log('chromeport.emit: '+evt); + // console.log(obj); + this._port.postMessage({ type: evt, payload: obj }); + // console.log('chromeport.emit: '+evt+' done'); +}; diff --git a/src/js/chrome/manifest.json b/src/js/chrome/manifest.json new file mode 100644 index 0000000..9202276 --- /dev/null +++ b/src/js/chrome/manifest.json @@ -0,0 +1,30 @@ +{ + "manifest_version": 2, + + "name": "Five UI", + "version": "0.2", + "description": "UI Constraint Checker", + + "icons": { "16": "data/images/fiveui-icon-16.png", + "48": "data/images/fiveui-icon-48.png", + "128": "data/images/fiveui-icon-128.png" + }, + + "background": { + "persistent": true, + "page": "data/background.html" + }, + + "options_page": "data/options.html", + + "browser_action": { + "default_icon": "data/images/fiveui-icon-disabled.png", + "default_title": "Five UI" + }, + "permissions": [ + "tabs", "http://*/*", "https://*/*", "history" + ], + + // We have to relax the content security policy to allow rules to be evaluated: + "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" +} diff --git a/src/js/firefox/build.mk b/src/js/firefox/build.mk new file mode 100644 index 0000000..4696930 --- /dev/null +++ b/src/js/firefox/build.mk @@ -0,0 +1,102 @@ + +# Firefox Extension ############################################################ + +all: $(build-dir)/firefox.xpi + +firefox-dir := $(path) + +firefox-build := $(build-dir)/firefox + +$(firefox-build): | $(build-dir) + $(call cmd,mkdir) + + +# Generic Extension ############################################################ + +$(eval $(call stage-fiveui,$(firefox-build),stage-firefox)) + + +# Firefox File Staging ######################################################### + +# copy in firefox scripts +$(firefox-build)/data/js/%: $(firefox-dir)/js/% | $(firefox-build)/data/js + $(call cmd,cp) + +# copy in firefox scripts +$(firefox-build)/data/injected/%: $(firefox-dir)/injected/% \ + | $(firefox-build)/data/injected + $(call cmd,cp) + +$(firefox-build)/data/icons/%: $(firefox-dir)/icons/% \ + | $(firefox-build)/data/icons + $(call cmd,cp) + +$(firefox-build)/data/icons: | $(firefox-build)/data + $(call cmd,mkdir) + +$(firefox-build)/data/%: $(firefox-dir)/lib/% | $(firefox-build)/data + $(call cmd,cp) + + +$(firefox-build)/%: $(firefox-dir)/% | $(firefox-build) + $(call cmd,cp) + + +# Wrapper Compilation ########################################################## + +# In order to turn a number of different javascript modules into a single one, +# we just concatenate them all together. This should be fine, as all of the +# modules we define just provide functions, or register callbacks. +quiet_cmd_compilejs = JSC $(call drop-prefix,$@) + cmd_compilejs = cat $^ > $@ + +# we have to build one big source for the firefox main.js, as we can't really +# share reuse the CommonJS module system in the chrome version. +$(firefox-build)/data/main.js: \ + $(firefox-dir)/lib/main.js \ + $(fiveui-dir)/js/set.js \ + $(fiveui-dir)/js/url-pat.js \ + $(fiveui-dir)/js/url-pat.js \ + $(fiveui-dir)/js/settings.js \ + $(fiveui-dir)/js/messenger.js \ + $(fiveui-dir)/js/state.js \ + $(fiveui-dir)/js/utils.js \ + $(fiveui-dir)/js/rules.js \ + $(fiveui-dir)/js/background.js \ + | $(firefox-build)/data + $(call cmd,compilejs) + + +# Packaging #################################################################### + +addon-sdk := $(topdir)/tools/addon-sdk + +# wrapper for setting up the environment for the running the cfx command +cfx = ( cd $(addon-sdk) $(redir) && \ + . bin/activate $(redir) && \ + cd $1 $(redir) && \ + cfx $2 $(redir) ) + +.PHONY: stage-firefox +stage-firefox: \ + $(firefox-build)/package.json \ + $(firefox-build)/data/main.js \ + $(firefox-build)/data/ajax.js \ + $(firefox-build)/data/storage-wrapper.js \ + $(firefox-build)/data/tabIds.js \ + $(firefox-build)/data/icons/fiveui-icon.html \ + $(firefox-build)/data/icons/fiveui-icon.js \ + $(firefox-build)/data/icons/options-icon.html \ + $(firefox-build)/data/icons/options-icon.js \ + | $(firefox-build) + +$(build-dir)/firefox.xpi: stage-firefox + $(call label,XPI $(call drop-prefix,$@))\ + $(call cfx,$(build-dir),xpi -p $(topdir)/profiles/firefox \ + --pkgdir=$(firefox-build) ) + + +# Testing ###################################################################### + +run-firefox: stage-firefox + $(call label,RUNFF)$(call cfx,$(firefox-build),run) diff --git a/src/js/firefox/icons/fiveui-icon.html b/src/js/firefox/icons/fiveui-icon.html new file mode 100644 index 0000000..d943367 --- /dev/null +++ b/src/js/firefox/icons/fiveui-icon.html @@ -0,0 +1,82 @@ + + + + + + + +
      + + + + +
      +
      + + diff --git a/src/js/firefox/icons/fiveui-icon.js b/src/js/firefox/icons/fiveui-icon.js new file mode 100644 index 0000000..61545da --- /dev/null +++ b/src/js/firefox/icons/fiveui-icon.js @@ -0,0 +1,42 @@ +/* + * Module : firefox/icon-script.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Firefox only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function() { + var updateBadgeText = function(text) { + $('#badge-text').text(text); + $('#badge-text').show(); + }; + + self.port.on('setEnabled', function(text) { + $('#disabled-img').hide(); + $('#enabled-img').show(); + if (text.length != 0) { + updateBadgeText(text); + } else { + $('#badge-text').hide(); + } + }); + self.port.on('setDisabled', function() { + $('#disabled-img').show(); + $('#enabled-img').hide(); + $('#badge-text').hide(); + }); + })(); diff --git a/src/js/firefox/icons/options-icon.html b/src/js/firefox/icons/options-icon.html new file mode 100644 index 0000000..850b530 --- /dev/null +++ b/src/js/firefox/icons/options-icon.html @@ -0,0 +1,31 @@ + + + + +
      + + +
      + + diff --git a/src/js/firefox/icons/options-icon.js b/src/js/firefox/icons/options-icon.js new file mode 100644 index 0000000..2008883 --- /dev/null +++ b/src/js/firefox/icons/options-icon.js @@ -0,0 +1,27 @@ +/* + * Module : firefox/options-script.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Firefox only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function() { + $('#options-div').click(function() { + //console.log('options-div handler'); + self.port.emit('showOptions'); + }); + })(); diff --git a/src/js/firefox/injected/platform-compute.js b/src/js/firefox/injected/platform-compute.js new file mode 100644 index 0000000..1f1dc48 --- /dev/null +++ b/src/js/firefox/injected/platform-compute.js @@ -0,0 +1,55 @@ +/* + * Module : firefox/firefox-injected-compute.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Not Portable (Firefox only) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @param {!string} css The css to inject. + */ +var addGlobalStyle = function(css) { + var head = document.getElementsByTagName('head')[0]; // find head element, which should exist + if (!head) { + head = document.createElement('head'); + + // XXX this is perhaps not reliable? + document.body.appendChild(head); + } + + var style = document.createElement('style'); // create