diff --git a/.envrc b/.envrc deleted file mode 100644 index c29849a..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake ./flake/flake.nix diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 4f6df06..8696088 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -14,7 +14,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [windows-latest, macos-latest] steps: - name: Checkout code @@ -33,7 +33,7 @@ jobs: - name: Check clippy lints run: cargo clippy --all-targets --all-features -- -D warnings - - name: Install dependencies + - name: Install Rust dependencies run: cargo fetch - name: Build diff --git a/.gitignore b/.gitignore index f579414..82dae74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,51 @@ +# Environment files +.env +.envrc /.direnv + +# Build artifacts /target +**/*.rs.bk + +# Lock files Cargo.lock -export.json -parsed_osm_data.txt + +# IDE/editor files +.idea/ +/.vscode/ +/*.swp +*.iml +*.suo +*.ntvs* +*.njsproj +*.sln +*.ps1 + +# System files +.DS_Store +Thumbs.db +*.tmp +*.log + +# Generated files +/export.json +/parsed_osm_data.txt +/gen/ +/build/ +*.rmeta +*.dSYM + +# Tauri specific +flake/ +capabilities/ +gen/ + +# Miscellaneous +*.bak +*.old +*.orig + +# Ignore all in flake directory except specific files +/flake/* +!/flake/flake.nix +!/flake/flake.lock diff --git a/Cargo.toml b/Cargo.toml index d95eeec..4cc0676 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "arnis" -version = "2.0.0" +version = "2.1.0" edition = "2021" description = "Arnis - Generate real life cities in Minecraft" homepage = "https://github.com/louis-e/arnis" @@ -11,9 +11,13 @@ readme = "README.md" [profile.release] lto = true +[build-dependencies] +tauri-build = { version = "2", features = [] } + [dependencies] clap = { version = "4.1", features = ["derive"] } colored = "2.1.0" +dirs = "4.0.0" fastanvil = "0.31.0" fastnbt = "2.5.0" fnv = "1.0.7" @@ -24,6 +28,11 @@ nalgebra = "0.33.0" once_cell = "1.19.0" rand = "0.8.5" reqwest = { version = "0.12.7", features = ["blocking", "json"] } +rfd = "0.15.0" semver = "1.0.23" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +tauri = { version = "2", features = [] } +tauri-plugin-dialog = "2.0.0" +tauri-plugin-shell = "2" +tokio = { version = "1.42.0", features = ["full"] } diff --git a/README.md b/README.md index 8068d3f..33ac30d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

-# Arnis [![CI Build Status](https://github.com/louis-e/arnis/actions/workflows/ci-build.yml/badge.svg)](https://github.com/louis-e/arnis/actions) +# Arnis [![CI Build Status](https://github.com/louis-e/arnis/actions/workflows/ci-build.yml/badge.svg)](https://github.com/louis-e/arnis/actions) [GitHub Release](https://github.com/louis-e/arnis/releases) [GitHub Downloads (all assets, all releases](https://github.com/louis-e/arnis/releases) This open source project written in Rust generates any chosen location from the real world in Minecraft Java Edition with a high level of detail. @@ -13,6 +13,28 @@ By leveraging geospatial data from OpenStreetMap and utilizing the powerful capa Arnis is designed to handle large-scale data and generate rich, immersive environments that bring real-world cities, landmarks, and natural features into the Minecraft universe. Whether you're looking to replicate your hometown, explore urban environments, or simply build something unique and realistic, Arnis offers a comprehensive toolset to achieve your vision. +## :keyboard: Usage +
+Download the [latest release](https://github.com/louis-e/arnis/releases/) or [compile](#trophy-open-source) the project on your own. + +Make sure to generate a new flat world in advance in Minecraft. Then choose your area in Arnis using the rectangle tool and select your Minecraft world - then simply click on 'Start Generation'! +The world will always be generated starting from the coordinates 0 0 0. + +
+ +Alternatively you can also run Arnis the old fashioned way in the command line. + +```arnis.exe --path="C:/YOUR_PATH/.minecraft/saves/worldname" --bbox="min_lng,min_lat,max_lng,max_lat"``` + +The --bbox parameter specifies the bounding box coordinates in the format: min_lng,min_lat,max_lng,max_lat. Use --path to specify the location of the Minecraft world. + +
+Use http://bboxfinder.com/ to draw a rectangle of your wanted area. Then copy the four box coordinates as shown below and use them as the input for the --bbox parameter. Try starting with a small area since large areas take a lot of computing power and time to process.
+ +Note: This might not be working right now since the console gets suppressed. + +
+ ## :floppy_disk: How it works ![CLI Generation](https://github.com/louis-e/arnis/blob/main/gitassets/cli.gif?raw=true) @@ -26,19 +48,6 @@ The raw data obtained from the API *[(see FAQ)](#question-faq)* includes each el 5. Generate Ground Layer: A ground layer is generated based on the provided scale factors to provide a base for the entire Minecraft world. This step ensures all areas have an appropriate foundation (e.g., grass and dirt layers). 6. Save the Minecraft World: All the modified chunks are saved back to the Minecraft region files. -## :keyboard: Usage -Get the [latest release](https://github.com/louis-e/arnis/releases/) or [compile](#trophy-open-source) the project on your own. -#### Run: ```arnis.exe --path="C:/YOUR_PATH/.minecraft/saves/worldname" --bbox="min_lng,min_lat,max_lng,max_lat"``` - -### How to find your bbox coordinates -Use http://bboxfinder.com/ to draw a rectangle of your wanted area. Then copy the four box coordinates as shown below and use them as the input for the --bbox parameter. -![How to find area](https://github.com/louis-e/arnis/blob/main/gitassets/bbox-finder.png?raw=true) -The world will always be generated starting from the coordinates 0 0 0. Try starting with a small area since large areas take a lot of computing power and time to process. - -Manually generate a new Minecraft world (preferably a flat world) before running the script. -The --bbox parameter specifies the bounding box coordinates in the format: min_lng,min_lat,max_lng,max_lat. -Use --path to specify the location of the Minecraft world. - ## :question: FAQ - *Wasn't this written in Python before?*
Yes! Arnis was initially developed in Python, which benefited from Python's open-source friendliness and ease of readability. This is why we strive for clear, well-documented code in the Rust port of this project to find the right balance. I decided to port the project to Rust to learn more about it and push the algorithm's performance further. We were nearing the limits of optimization in Python, and Rust's capabilities allow for even better performance and efficiency. The old Python implementation is still available in the python-legacy branch. @@ -51,7 +60,6 @@ The project is named after the smallest city in Germany, Arnis[^2]. The city's s ## :memo: ToDo and Known Bugs Feel free to choose an item from the To-Do or Known Bugs list, or bring your own idea to the table. Bug reports shall be raised as a Github issue. Contributions are highly welcome and appreciated! -- [ ] Design and implement a GUI - [ ] Memory optimization - [ ] Fix Github Action Workflow for releasing Linux & MacOS Binary - [ ] Evaluate and implement multithreaded region saving @@ -67,6 +75,7 @@ Feel free to choose an item from the To-Do or Known Bugs list, or bring your own - [ ] Evaluate and implement elevation - [ ] Generate a few big cities using high performance hardware and make them available to download - [ ] Implement memory mapped storing of chunks to reduce memory usage +- [x] Design and implement a GUI - [x] Fix faulty empty chunks ([https://github.com/owengage/fastnbt/issues/120](https://github.com/owengage/fastnbt/issues/120)) (workaround found) ## :trophy: Open Source @@ -81,6 +90,7 @@ Feel free to choose an item from the To-Do or Known Bugs list, or bring your own This project is open source and welcomes contributions from everyone! Whether you're interested in fixing bugs, improving performance, adding new features, or enhancing documentation, your input is valuable. Simply fork the repository, make your changes, and submit a pull request. We encourage discussions and suggestions to ensure the project remains modular, optimized, and easy to use for the community. You can use the parameter --debug to get a more detailed output of the processed values, which can be helpful for debugging and development. Contributions of all levels are appreciated, and your efforts help improve this tool for everyone. Build and run it using: ```cargo run --release -- --path="C:/YOUR_PATH/.minecraft/saves/worldname" --bbox="min_lng,min_lat,max_lng,max_lat"```
+For the GUI: ```cargo run --release```
After your pull request was merged, I will take care of regularly creating update releases which will include your changes. diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..d860e1e --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/gui-src/css/bbox.css b/gui-src/css/bbox.css new file mode 100644 index 0000000..4d541c4 --- /dev/null +++ b/gui-src/css/bbox.css @@ -0,0 +1,347 @@ +html, +body, +#map { + height: 100%; + width: 100%; + padding: 0px; + margin: 0px; + font-family: "Courier New", Courier, monospace; +} + +#info-box { + position: absolute; + width: 100%; + height: auto; + bottom: 0; + border: 0 0 7px 0; + z-index: 10000; +} + +#coord-format { + position: absolute; + bottom: 0; + right: 15; +} + +#coord-format .bboxlabel { + width: 100%; +} + +#coord-format form { + margin-bottom: 10px; +} + +#info img { + vertical-align: middle; + height: 16px; + width: auto; + opacity: 0.6; +} + +#info img:hover { + opacity: 1; + cursor: pointer; +} + +#info-toggle ul { + margin: 0 0 0 20px; + padding: 0; +} + +#info-toggle ul li { + display: inline-block; + padding: 4px 7px 0; + background-color: rgba(230, 230, 230, 0.4); + border-top-left-radius: 3px; + border-top-right-radius: 3px; + font-weight: 900; + cursor: pointer; +} + +#info-toggle ul li.active { + background-color: rgba(255, 255, 255, 0.8); +} + +#info-toggle-button { + background-color: rgba(0, 0, 0, 0.7) !important; + color: #fff; +} + +#info-toggle-button:hover { + background-color: #f4f4f4; +} + +#projlabel, +#wgslabel { + display: inline-block; + color: #333; + z-index: 10000; +} + +#projcoords { + display: none; +} + +.coords { + text-align: left; + padding: 7px 0; + background-color: rgba(255, 255, 255, 0.8); +} + +#bbounds, +#mbounds, +#mcenter { + font-size: small; + display: block; + z-index: 10000; + padding: 2px 0; +} + +#mouse, +#tile, +#zoom { + display: inline-block; +} + +.bboxlabel { + font-size: small; + font-weight: bold; + z-index: 10000; + background-color: black; + color: white; + text-align: center; + display: inline-block; + padding-left: 2px; + width: 60px; +} + +.bboxllpos, +.bboxllpossmall, +.bboxprojpos, +.bboxprojpossmall, +.tilesmall, +.zoomsmall { + font-size: small; + font-weight: bold; + color: black; + display: inline-block; + padding-left: 5px; +} + +.bboxllpos { + width: 350px; +} + +.bboxllpossmall { + width: 200px; +} + +.bboxprojpos { + width: 450px; +} + +.bboxprojpossmall { + width: 250px; +} + +.tilesmall { + width: 60px; +} + +.zoomsmall { + width: 20px; +} + +#map-ui-proj { + position: absolute; + top: 460px; + left: 10px; + list-style: none; + margin: 0; + padding: 0; + z-index: 100; +} + +#map-ui-proj a { + font: normal 13px/18px 'Helvetica Neue', Helvetica, sans-serif; + background: #FFF; + color: #3C4E5A; + display: block; + margin: 0; + padding: 0; + border: 1px solid #BBB; + border-bottom-width: 0; + min-width: 75px; + padding: 2px; + text-decoration: none; + text-align: center; +} + +#map-ui-proj a:hover { + background: #ECF5FA; +} + +#map-ui-proj li:last-child a { + border-bottom-width: 1px; + -webkit-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; +} + +#map-ui-proj li:first-child a { + -webkit-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; +} + +#map-ui-proj a.active { + background: #3887BE; + border-color: #3887BE; + border-top-color: #FFF; + color: #FFF; +} + +.epsglabel { + font-size: small; + font-weight: bold; + background-color: black; + color: white; + z-index: 10000; +} + +#map-ui { + position: absolute; + top: 330px; + left: 12px; + list-style: none; + margin: 0; + padding: 0; + z-index: 100; +} + +#map-ui a { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 30px; + height: 30px; + line-height: 30px; + display: block; + text-align: center; + text-decoration: none; + color: black; + background-image: url('css/maps/images/bbox-sprites.png'); + background-repeat: no-repeat; +} + +#map-ui a:hover { + background-color: #ECF5FA; +} + +#map-ui li:last-child a { + border-bottom-width: 1px; + -webkit-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + background-position: -33px -2px; +} + +#map-ui li:last-child a.enabled { + border-bottom-width: 1px; + -webkit-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + background-position: -278px -2px; +} + +#map-ui li:first-child a { + -webkit-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; +} + +#create-geojson a.enabled { + background-position: -248px -2px; +} + +#create-geojson a { + background-position: -2px -2px; +} + +#geolocation a { + background-position: -186px -2px; +} + +#geolocation a.active { + background-position: -63px -2px; +} + +#help a.enabled { + background-position: -342px -2px; +} + +#help a { + background-position: -93px -2px; +} + +.zeroclipboard-is-hover { + opacity: 1 !important; +} + +.leaflet-sidebar textarea { + /* display: none; */ + height: 95%; + width: 100%; + border: 1; + padding: 2em; + resize: none; + -webkit-box-sizing: border-box; + /* Safari/Chrome, other WebKit */ + -moz-box-sizing: border-box; + /* Firefox, other Gecko */ + box-sizing: border-box; + /* Opera/IE 8+ */ +} + +.leaflet-sidebar button { + font-size: large; +} + +.leaflet-sidebar .close { + z-index: 10001; +} + +.ui-autocomplete { + max-height: 180px; + overflow-y: auto; + /* prevent horizontal scrollbar */ + overflow-x: hidden; +} + +/* IE 6 doesn't support max-height + * we use height instead, but this forces the menu to always be this tall + */ +* html .ui-autocomplete { + height: 180px; +} + + +.unblurred.leaflet-tile-loaded { + + -moz-filter: blur(0) sepia(0) invert(0); + -webkit-filter: blur(0) sepia(0) invert(0); + filter: blur(0) sepia(0) invert(0); + + -moz-transition: all 1s ease; + -webkit-transition: all 1s ease; + transition: all 1s ease; +} + + + +.blurred.leaflet-tile-loaded { + + -moz-filter: blur(1px) sepia(1) invert(1); + -moz-transition: all 1s ease; + + -webkit-filter: blur(1px) sepia(1) invert(1); + -webkit-transition: all 1s ease; + + filter: blur(1px) sepia(1) invert(1); + transition: all 1s ease; + +} \ No newline at end of file diff --git a/gui-src/css/libs/ui-lightness/images/animated-overlay.gif b/gui-src/css/libs/ui-lightness/images/animated-overlay.gif new file mode 100644 index 0000000..d441f75 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/animated-overlay.gif differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/gui-src/css/libs/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100644 index 0000000..2730942 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/gui-src/css/libs/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png new file mode 100644 index 0000000..6ba64c1 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_flat_10_000000_40x100.png b/gui-src/css/libs/ui-lightness/images/ui-bg_flat_10_000000_40x100.png new file mode 100644 index 0000000..89ea269 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_flat_10_000000_40x100.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png b/gui-src/css/libs/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png new file mode 100644 index 0000000..9d6e124 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png b/gui-src/css/libs/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png new file mode 100644 index 0000000..2582d56 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png b/gui-src/css/libs/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000..0359b12 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/gui-src/css/libs/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png new file mode 100644 index 0000000..8fa8f9f Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/gui-src/css/libs/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png new file mode 100644 index 0000000..1f8238f Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/gui-src/css/libs/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png new file mode 100644 index 0000000..dcbf47c Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-icons_222222_256x240.png b/gui-src/css/libs/ui-lightness/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000..c1cb117 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-icons_222222_256x240.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-icons_228ef1_256x240.png b/gui-src/css/libs/ui-lightness/images/ui-icons_228ef1_256x240.png new file mode 100644 index 0000000..3a0140c Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-icons_228ef1_256x240.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-icons_ef8c08_256x240.png b/gui-src/css/libs/ui-lightness/images/ui-icons_ef8c08_256x240.png new file mode 100644 index 0000000..036ee07 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-icons_ef8c08_256x240.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-icons_ffd27a_256x240.png b/gui-src/css/libs/ui-lightness/images/ui-icons_ffd27a_256x240.png new file mode 100644 index 0000000..8b6c058 Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-icons_ffd27a_256x240.png differ diff --git a/gui-src/css/libs/ui-lightness/images/ui-icons_ffffff_256x240.png b/gui-src/css/libs/ui-lightness/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000..4f624bb Binary files /dev/null and b/gui-src/css/libs/ui-lightness/images/ui-icons_ffffff_256x240.png differ diff --git a/gui-src/css/libs/ui-lightness/jquery-ui-1.10.3.custom.css b/gui-src/css/libs/ui-lightness/jquery-ui-1.10.3.custom.css new file mode 100644 index 0000000..91f12a1 --- /dev/null +++ b/gui-src/css/libs/ui-lightness/jquery-ui-1.10.3.custom.css @@ -0,0 +1,1177 @@ +/*! jQuery UI - v1.10.3 - 2013-11-13 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px +* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted black; +} +.ui-accordion .ui-accordion-header { + display: block; + cursor: pointer; + position: relative; + margin-top: 2px; + padding: .5em .5em .5em .7em; + min-height: 0; /* support: IE7 */ +} +.ui-accordion .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-noicons { + padding-left: .7em; +} +.ui-accordion .ui-accordion-icons .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-header .ui-accordion-header-icon { + position: absolute; + left: .5em; + top: 50%; + margin-top: -8px; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + overflow: auto; +} +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +.ui-button { + display: inline-block; + position: relative; + padding: 0; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + overflow: visible; /* removes extra width in IE */ +} +.ui-button, +.ui-button:link, +.ui-button:visited, +.ui-button:hover, +.ui-button:active { + text-decoration: none; +} +/* to make room for the icon, a width needs to be set here */ +.ui-button-icon-only { + width: 2.2em; +} +/* button elements seem to need a little more width */ +button.ui-button-icon-only { + width: 2.4em; +} +.ui-button-icons-only { + width: 3.4em; +} +button.ui-button-icons-only { + width: 3.7em; +} + +/* button text element */ +.ui-button .ui-button-text { + display: block; + line-height: normal; +} +.ui-button-text-only .ui-button-text { + padding: .4em 1em; +} +.ui-button-icon-only .ui-button-text, +.ui-button-icons-only .ui-button-text { + padding: .4em; + text-indent: -9999999px; +} +.ui-button-text-icon-primary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 1em .4em 2.1em; +} +.ui-button-text-icon-secondary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 2.1em .4em 1em; +} +.ui-button-text-icons .ui-button-text { + padding-left: 2.1em; + padding-right: 2.1em; +} +/* no icon support for input elements, provide padding by default */ +input.ui-button { + padding: .4em 1em; +} + +/* button icon element(s) */ +.ui-button-icon-only .ui-icon, +.ui-button-text-icon-primary .ui-icon, +.ui-button-text-icon-secondary .ui-icon, +.ui-button-text-icons .ui-icon, +.ui-button-icons-only .ui-icon { + position: absolute; + top: 50%; + margin-top: -8px; +} +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; +} +.ui-button-text-icon-primary .ui-button-icon-primary, +.ui-button-text-icons .ui-button-icon-primary, +.ui-button-icons-only .ui-button-icon-primary { + left: .5em; +} +.ui-button-text-icon-secondary .ui-button-icon-secondary, +.ui-button-text-icons .ui-button-icon-secondary, +.ui-button-icons-only .ui-button-icon-secondary { + right: .5em; +} + +/* button sets */ +.ui-buttonset { + margin-right: 7px; +} +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: -.3em; +} + +/* workarounds */ +/* reset extra padding in Firefox, see h5bp.com/l */ +input.ui-button::-moz-focus-inner, +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-datepicker { + width: 17em; + padding: .2em .2em 0; + display: none; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; +} +.ui-datepicker .ui-datepicker-prev, +.ui-datepicker .ui-datepicker-next { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; +} +.ui-datepicker .ui-datepicker-prev-hover, +.ui-datepicker .ui-datepicker-next-hover { + top: 1px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; +} +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; +} +.ui-datepicker .ui-datepicker-prev span, +.ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month-year { + width: 100%; +} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 49%; +} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td span, +.ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} + +/* RTL support */ +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, +.ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} +.ui-dialog { + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 21px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-menu { + list-style: none; + padding: 2px; + margin: 0; + display: block; + outline: none; +} +.ui-menu .ui-menu { + margin-top: -3px; + position: absolute; +} +.ui-menu .ui-menu-item { + margin: 0; + padding: 0; + width: 100%; + /* support: IE10, see #8844 */ + list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); +} +.ui-menu .ui-menu-divider { + margin: 5px -2px 5px -2px; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-menu-item a { + text-decoration: none; + display: block; + padding: 2px .4em; + line-height: 1.5; + min-height: 0; /* support: IE7 */ + font-weight: normal; +} +.ui-menu .ui-menu-item a.ui-state-focus, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} + +.ui-menu .ui-state-disabled { + font-weight: normal; + margin: .4em 0 .2em; + line-height: 1.5; +} +.ui-menu .ui-state-disabled a { + cursor: default; +} + +/* icon support */ +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item a { + position: relative; + padding-left: 2em; +} + +/* left-aligned */ +.ui-menu .ui-icon { + position: absolute; + top: .2em; + left: .2em; +} + +/* right-aligned */ +.ui-menu .ui-menu-icon { + position: static; + float: right; +} +.ui-progressbar { + height: 2em; + text-align: left; + overflow: hidden; +} +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; +} +.ui-progressbar .ui-progressbar-overlay { + background: url("images/animated-overlay.gif"); + height: 100%; + filter: alpha(opacity=25); + opacity: 0.25; +} +.ui-progressbar-indeterminate .ui-progressbar-value { + background-image: none; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +/* For IE8 - See #6727 */ +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} + +.ui-slider-horizontal { + height: .8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.3em; + margin-left: -.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.3em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} +.ui-spinner { + position: relative; + display: inline-block; + overflow: hidden; + padding: 0; + vertical-align: middle; +} +.ui-spinner-input { + border: none; + background: none; + color: inherit; + padding: 0; + margin: .2em 0; + vertical-align: middle; + margin-left: .4em; + margin-right: 22px; +} +.ui-spinner-button { + width: 16px; + height: 50%; + font-size: .5em; + padding: 0; + margin: 0; + text-align: center; + position: absolute; + cursor: default; + display: block; + overflow: hidden; + right: 0; +} +/* more specificity required here to overide default borders */ +.ui-spinner a.ui-spinner-button { + border-top: none; + border-bottom: none; + border-right: none; +} +/* vertical centre icon */ +.ui-spinner .ui-icon { + position: absolute; + margin-top: -8px; + top: 50%; + left: 0; +} +.ui-spinner-up { + top: 0; +} +.ui-spinner-down { + bottom: 0; +} + +/* TR overrides */ +.ui-spinner .ui-icon-triangle-1-s { + /* need to fix icons sprite */ + background-position: -65px -16px; +} +.ui-tabs { + position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + padding: .2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px .2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav li a { + float: left; + padding: .5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active a, +.ui-tabs .ui-tabs-nav li.ui-state-disabled a, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading a { + cursor: text; +} +.ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; +} +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; + -webkit-box-shadow: 0 0 5px #aaa; + box-shadow: 0 0 5px #aaa; +} +body .ui-tooltip { + border-width: 2px; +} + +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif; + font-size: 1.1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif; + font-size: 1em; +} +.ui-widget-content { + border: 1px solid #dddddd; + background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; + color: #333333; +} +.ui-widget-content a { + color: #333333; +} +.ui-widget-header { + border: 1px solid #e78f08; + background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; + color: #ffffff; + font-weight: bold; +} +.ui-widget-header a { + color: #ffffff; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { + border: 1px solid #cccccc; + background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; + font-weight: bold; + color: #1c94c4; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited { + color: #1c94c4; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { + border: 1px solid #fbcb09; + background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; + font-weight: bold; + color: #c77405; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited { + color: #c77405; + text-decoration: none; +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active { + border: 1px solid #fbd850; + background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; + font-weight: bold; + color: #eb8f00; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #eb8f00; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #fed22f; + background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; + color: #363636; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #cd0a0a; + background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; + color: #ffffff; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #ffffff; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #ffffff; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* For IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url(images/ui-icons_222222_256x240.png); +} +.ui-widget-header .ui-icon { + background-image: url(images/ui-icons_ffffff_256x240.png); +} +.ui-state-default .ui-icon { + background-image: url(images/ui-icons_ef8c08_256x240.png); +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon { + background-image: url(images/ui-icons_ef8c08_256x240.png); +} +.ui-state-active .ui-icon { + background-image: url(images/ui-icons_ef8c08_256x240.png); +} +.ui-state-highlight .ui-icon { + background-image: url(images/ui-icons_228ef1_256x240.png); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url(images/ui-icons_ffd27a_256x240.png); +} + +/* positioning */ +.ui-icon-blank { background-position: 16px 16px; } +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 4px; +} + +/* Overlays */ +.ui-widget-overlay { + background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; + opacity: .5; + filter: Alpha(Opacity=50); +} +.ui-widget-shadow { + margin: -5px 0 0 -5px; + padding: 5px; + background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; + opacity: .2; + filter: Alpha(Opacity=20); + border-radius: 5px; +} diff --git a/gui-src/css/libs/ui-lightness/jquery-ui-1.10.3.custom.min.css b/gui-src/css/libs/ui-lightness/jquery-ui-1.10.3.custom.min.css new file mode 100644 index 0000000..5916296 --- /dev/null +++ b/gui-src/css/libs/ui-lightness/jquery-ui-1.10.3.custom.min.css @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.10.3 - 2013-11-13 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px +* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_228ef1_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px} \ No newline at end of file diff --git a/gui-src/css/maps/images/bbox-sprites.png b/gui-src/css/maps/images/bbox-sprites.png new file mode 100644 index 0000000..4393aba Binary files /dev/null and b/gui-src/css/maps/images/bbox-sprites.png differ diff --git a/gui-src/css/maps/images/bbox-sprites.svg b/gui-src/css/maps/images/bbox-sprites.svg new file mode 100644 index 0000000..14a4fcc --- /dev/null +++ b/gui-src/css/maps/images/bbox-sprites.svg @@ -0,0 +1,505 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui-src/css/maps/images/icons-404040.png b/gui-src/css/maps/images/icons-404040.png new file mode 100644 index 0000000..054afd8 Binary files /dev/null and b/gui-src/css/maps/images/icons-404040.png differ diff --git a/gui-src/css/maps/images/icons-404040@2x.png b/gui-src/css/maps/images/icons-404040@2x.png new file mode 100644 index 0000000..c1e8a7e Binary files /dev/null and b/gui-src/css/maps/images/icons-404040@2x.png differ diff --git a/gui-src/css/maps/images/icons-ffffff.png b/gui-src/css/maps/images/icons-ffffff.png new file mode 100644 index 0000000..fc9abb9 Binary files /dev/null and b/gui-src/css/maps/images/icons-ffffff.png differ diff --git a/gui-src/css/maps/images/icons-ffffff@2x.png b/gui-src/css/maps/images/icons-ffffff@2x.png new file mode 100644 index 0000000..cbcfefe Binary files /dev/null and b/gui-src/css/maps/images/icons-ffffff@2x.png differ diff --git a/gui-src/css/maps/images/icons.svg b/gui-src/css/maps/images/icons.svg new file mode 100644 index 0000000..ab590a3 --- /dev/null +++ b/gui-src/css/maps/images/icons.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + diff --git a/gui-src/css/maps/images/spritesheet - Kopie.png b/gui-src/css/maps/images/spritesheet - Kopie.png new file mode 100644 index 0000000..0138093 Binary files /dev/null and b/gui-src/css/maps/images/spritesheet - Kopie.png differ diff --git a/gui-src/css/maps/images/spritesheet-2x.png b/gui-src/css/maps/images/spritesheet-2x.png new file mode 100644 index 0000000..1525c9f Binary files /dev/null and b/gui-src/css/maps/images/spritesheet-2x.png differ diff --git a/gui-src/css/maps/images/spritesheet.png b/gui-src/css/maps/images/spritesheet.png new file mode 100644 index 0000000..0138093 Binary files /dev/null and b/gui-src/css/maps/images/spritesheet.png differ diff --git a/gui-src/css/maps/images/spritesheet.svg b/gui-src/css/maps/images/spritesheet.svg new file mode 100644 index 0000000..5948eee --- /dev/null +++ b/gui-src/css/maps/images/spritesheet.svg @@ -0,0 +1,297 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui-src/css/maps/leaflet.css b/gui-src/css/maps/leaflet.css new file mode 100644 index 0000000..1232550 --- /dev/null +++ b/gui-src/css/maps/leaflet.css @@ -0,0 +1,478 @@ +/* required styles */ + +.leaflet-map-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-pane, +.leaflet-tile-container, +.leaflet-overlay-pane, +.leaflet-shadow-pane, +.leaflet-marker-pane, +.leaflet-popup-pane, +.leaflet-overlay-pane svg, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + -ms-touch-action: none; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container img { + max-width: none !important; + } +/* stupid Android 2 doesn't understand "max-width: none" properly */ +.leaflet-container img.leaflet-image-layer { + max-width: 15000px !important; + } +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-tile-pane { z-index: 2; } +.leaflet-objects-pane { z-index: 3; } +.leaflet-overlay-pane { z-index: 4; } +.leaflet-shadow-pane { z-index: 5; } +.leaflet-marker-pane { z-index: 6; } +.leaflet-popup-pane { z-index: 7; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 7; + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile, +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-tile-loaded, +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } + +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile, +.leaflet-touching .leaflet-zoom-animated { + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-clickable { + cursor: pointer; + } +.leaflet-container { + cursor: -webkit-grab; + cursor: -moz-grab; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-container, +.leaflet-dragging .leaflet-clickable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + } + + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; + } +.leaflet-container a { + color: #0078A8; + } +.leaflet-container a.leaflet-active { + outline: 2px solid orange; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } + + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } +.leaflet-control-zoom-out { + font-size: 20px; + } + +.leaflet-touch .leaflet-control-zoom-in { + font-size: 22px; + } +.leaflet-touch .leaflet-control-zoom-out { + font-size: 24px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover { + text-decoration: underline; + } +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: content-box; + box-sizing: content-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; + } +.leaflet-popup-content p { + margin: 18px 0; + } +.leaflet-popup-tip-container { + margin: 0 auto; + width: 40px; + height: 20px; + position: relative; + overflow: hidden; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #c3c3c3; + text-decoration: none; + font-weight: bold; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover { + color: #999; + } +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } diff --git a/gui-src/css/maps/leaflet.draw.css b/gui-src/css/maps/leaflet.draw.css new file mode 100644 index 0000000..f1a8776 --- /dev/null +++ b/gui-src/css/maps/leaflet.draw.css @@ -0,0 +1,248 @@ +/* ================================================================== */ +/* Toolbars +/* ================================================================== */ + +.leaflet-draw-section { + position: relative; +} + +.leaflet-draw-toolbar { + margin-top: 12px; +} + +.leaflet-draw-toolbar-top { + margin-top: 0; +} + +.leaflet-draw-toolbar-notop a:first-child { + border-top-right-radius: 0; +} + +.leaflet-draw-toolbar-nobottom a:last-child { + border-bottom-right-radius: 0; +} + +.leaflet-draw-toolbar a { + background-image: url('images/spritesheet.png'); + background-repeat: no-repeat; +} + +.leaflet-retina .leaflet-draw-toolbar a { + background-image: url('images/spritesheet-2x.png'); + background-size: 210px 30px; +} + +.leaflet-draw a { + display: block; + text-align: center; + text-decoration: none; +} + +/* ================================================================== */ +/* Toolbar actions menu +/* ================================================================== */ + +.leaflet-draw-actions { + display: none; + list-style: none; + margin: 0; + padding: 0; + position: absolute; + left: 26px; /* leaflet-draw-toolbar.left + leaflet-draw-toolbar.width */ + top: 0; +} + +.leaflet-right .leaflet-draw-actions { + right:26px; + left:auto; +} + +.leaflet-draw-actions li { + display: inline-block; +} + +/* APR */ +.leaflet-draw-actions li a { + color: #ffffff; +} + +.leaflet-draw-actions li:first-child a { + border-left: none; +} + +.leaflet-draw-actions li:last-child a { + -webkit-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.leaflet-right .leaflet-draw-actions li:last-child a { + -webkit-border-radius: 0; + border-radius: 0; +} + +.leaflet-right .leaflet-draw-actions li:first-child a { + -webkit-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.leaflet-draw-actions a { + background-color: #919187; + border-left: 1px solid #AAA; + color: #FFF; + font: 11px/19px "Helvetica Neue", Arial, Helvetica, sans-serif; + line-height: 28px; + text-decoration: none; + padding-left: 10px; + padding-right: 10px; + height: 28px; +} + +.leaflet-draw-actions-bottom { + margin-top: 0; + white-space: nowrap; +} + +.leaflet-draw-actions-top { + margin-top: 1px; + white-space: nowrap; +} + +.leaflet-draw-actions-top a, +.leaflet-draw-actions-bottom a { + height: 27px; + line-height: 27px; +} + +.leaflet-draw-actions a:hover { + background-color: #A0A098; +} + +.leaflet-draw-actions-top.leaflet-draw-actions-bottom a { + height: 26px; + line-height: 26px; +} + +/* ================================================================== */ +/* Draw toolbar +/* ================================================================== */ + +.leaflet-draw-toolbar .leaflet-draw-draw-polyline { + background-position: -2px -2px; +} + +.leaflet-draw-toolbar .leaflet-draw-draw-polygon { + background-position: -31px -2px; +} + +.leaflet-draw-toolbar .leaflet-draw-draw-rectangle { + background-position: -62px -2px; +} + +.leaflet-draw-toolbar .leaflet-draw-draw-circle { + background-position: -92px -2px; +} + +.leaflet-draw-toolbar .leaflet-draw-draw-marker { + background-position: -122px -2px; +} + +/* ================================================================== */ +/* Edit toolbar +/* ================================================================== */ + +.leaflet-draw-toolbar .leaflet-draw-edit-edit { + background-position: -152px -2px; +} + +.leaflet-draw-toolbar .leaflet-draw-edit-remove { + background-position: -182px -2px; +} + +.leaflet-draw-toolbar .leaflet-draw-edit-edit.leaflet-disabled { + background-position: -212px -2px; +} + +.leaflet-draw-toolbar .leaflet-draw-edit-remove.leaflet-disabled { + background-position: -242px -2px; +} + +/* ================================================================== */ +/* Drawing styles +/* ================================================================== */ + +.leaflet-mouse-marker { + background-color: #fff; + cursor: crosshair; +} + +.leaflet-draw-tooltip { + background: rgb(54, 54, 54); + background: rgba(0, 0, 0, 0.5); + border: 1px solid transparent; + -webkit-border-radius: 4px; + border-radius: 4px; + color: #fff; + font: 12px/18px "Helvetica Neue", Arial, Helvetica, sans-serif; + margin-left: 20px; + margin-top: -21px; + padding: 4px 8px; + position: absolute; + white-space: nowrap; + z-index: 6; +} + +.leaflet-draw-tooltip:before { + border-right: 6px solid black; + border-right-color: rgba(0, 0, 0, 0.5); + border-top: 6px solid transparent; + border-bottom: 6px solid transparent; + content: ""; + position: absolute; + top: 7px; + left: -7px; +} + +.leaflet-error-draw-tooltip { + background-color: #F2DEDE; + border: 1px solid #E6B6BD; + color: #B94A48; +} + +.leaflet-error-draw-tooltip:before { + border-right-color: #E6B6BD; +} + +.leaflet-draw-tooltip-single { + margin-top: -12px +} + +.leaflet-draw-tooltip-subtext { + color: #f8d5e4; +} + +.leaflet-draw-guide-dash { + font-size: 1%; + opacity: 0.6; + position: absolute; + width: 5px; + height: 5px; +} + +/* ================================================================== */ +/* Edit styles +/* ================================================================== */ + +.leaflet-edit-marker-selected { + background: rgba(254, 87, 161, 0.1); + border: 4px dashed rgba(254, 87, 161, 0.6); + -webkit-border-radius: 4px; + border-radius: 4px; +} + +.leaflet-edit-move { + cursor: move; +} + +.leaflet-edit-resize { + cursor: pointer; +} diff --git a/gui-src/css/maps/leaflet.draw.ie.css b/gui-src/css/maps/leaflet.draw.ie.css new file mode 100644 index 0000000..8ebfba4 --- /dev/null +++ b/gui-src/css/maps/leaflet.draw.ie.css @@ -0,0 +1,49 @@ +/* Conditional stylesheet for IE. */ + +.leaflet-draw-toolbar { + border: 3px solid #999; +} + +.leaflet-draw-toolbar a { + background-color: #eee; +} + +.leaflet-draw-toolbar a:hover { + background-color: #fff; +} + +.leaflet-draw-actions { + left: 32px; + margin-top: 3px; +} + +.leaflet-draw-actions li { + display: inline; + zoom: 1; +} + +.leaflet-edit-marker-selected { + border: 4px dashed #fe93c2; +} + +.leaflet-draw-actions a { + background-color: #999; +} + +.leaflet-draw-actions a:hover { + background-color: #a5a5a5; +} + +.leaflet-draw-actions-top a { + margin-top: 1px; +} + +.leaflet-draw-actions-bottom a { + height: 28px; + line-height: 28px; +} + +.leaflet-draw-actions-top.leaflet-draw-actions-bottom a { + height: 27px; + line-height: 27px; +} \ No newline at end of file diff --git a/gui-src/css/maps/leaflet.ie.css b/gui-src/css/maps/leaflet.ie.css new file mode 100644 index 0000000..f3daf1f --- /dev/null +++ b/gui-src/css/maps/leaflet.ie.css @@ -0,0 +1,51 @@ +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + +.leaflet-control { + display: inline; + } + +.leaflet-popup-tip { + width: 21px; + _width: 27px; + margin: 0 auto; + _margin-top: -3px; + + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + } +.leaflet-popup-tip-container { + margin-top: -1px; + } +.leaflet-popup-content-wrapper, .leaflet-popup-tip { + border: 1px solid #999; + } +.leaflet-popup-content-wrapper { + zoom: 1; + } + +.leaflet-control-zoom, +.leaflet-control-layers { + border: 3px solid #999; + } +.leaflet-control-layers-toggle { + } +.leaflet-control-attribution, +.leaflet-control-layers, +.leaflet-control-scale-line { + background: white; + } +.leaflet-zoom-box { + filter: alpha(opacity=50); + } +.leaflet-control-attribution { + border-top: 1px solid #bbb; + border-left: 1px solid #bbb; + } diff --git a/gui-src/css/maps/leaflet.sidebar.css b/gui-src/css/maps/leaflet.sidebar.css new file mode 100644 index 0000000..fc6e72e --- /dev/null +++ b/gui-src/css/maps/leaflet.sidebar.css @@ -0,0 +1,159 @@ +.leaflet-sidebar { + position: absolute; + height: 100%; + + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 10px; + + z-index: 20000; +} + +.leaflet-sidebar.left { + left: -700px; + transition: left 0.5s, width 0.5s; + + padding-right: 0; +} + +.leaflet-sidebar.right { + right: -700px; + transition: right 0.5s, width 0.5s; + + padding-left: 0; +} + +.leaflet-sidebar.left.visible { + left: 0; +} + +.leaflet-sidebar.right.visible { + right: 0; +} + +.leaflet-left { + transition: left 0.5s; +} + +.leaflet-right { + transition: right 0.5s; +} + +.leaflet-sidebar > .leaflet-control { + height: 100%; + width: 100%; + + overflow: auto; + -webkit-overflow-scrolling: touch; + + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 8px 24px; + + font-size: 1.1em; + + background: white; + box-shadow: 0 1px 7px rgba(0,0,0,0.65); + -webkit-border-radius: 4px; + border-radius: 4px; +} + +@media(max-width:767px){ + .leaflet-sidebar { + width: 100%; + padding: 0; + } + + .leaflet-sidebar.left { + left: -100%; + } + + .leaflet-sidebar.right { + right: -100%; + } + + .leaflet-sidebar.left.visible { + left: 0; + } + + .leaflet-sidebar.right.visible { + right: 0; + } + + .leaflet-sidebar > .leaflet-control { + box-shadow: none; + -webkit-border-radius: 0; + border-radius: 0; + } + + .leaflet-sidebar.left.visible ~ .leaflet-left { + left: 100%; + } + + .leaflet-sidebar.right.visible ~ .leaflet-right { + right: 100%; + } +} + +@media(min-width:768px) and (max-width:991px){ + .leaflet-sidebar { + width: 505px; + } + + .leaflet-sidebar.left.visible ~ .leaflet-left { + left: 505px; + } + + .leaflet-sidebar.right.visible ~ .leaflet-right { + right: 505px; + } +} + +@media(min-width:992px) and (max-width:1199px){ + .leaflet-sidebar { + width: 590px; + } + + .leaflet-sidebar.left.visible ~ .leaflet-left { + left: 590px; + } + + .leaflet-sidebar.right.visible ~ .leaflet-right { + right: 590px; + } +} + +@media(min-width:1200px){ + .leaflet-sidebar { + width: 660px; + } + + .leaflet-sidebar.left.visible ~ .leaflet-left { + left: 660px; + } + + .leaflet-sidebar.right.visible ~ .leaflet-right { + right: 660px; + } +} + +.leaflet-sidebar .close { + position: absolute; + right: 20px; + top: 20px; + width: 31px; + height: 31px; + + color: #333; + font-size: 25pt; + line-height: 1em; + text-align: center; + background: white; + -webkit-border-radius: 16px; + border-radius: 16px; + cursor: pointer; + + z-index: 8; +} diff --git a/gui-src/css/maps/mapbox.standalone.css b/gui-src/css/maps/mapbox.standalone.css new file mode 100644 index 0000000..606a217 --- /dev/null +++ b/gui-src/css/maps/mapbox.standalone.css @@ -0,0 +1,757 @@ +/* general typography */ +.leaflet-container { + background:#fff; + font:15px/25px 'Helvetica Neue', Arial, Helvetica, sans-serif; + color:#404040; + color:rgba(0,0,0,0.75); + outline:0; + overflow:hidden; + -ms-touch-action:none; + } +.leaflet-container *, +.leaflet-container *:after, +.leaflet-container *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } + +.leaflet-container h1, +.leaflet-container h2, +.leaflet-container h3, +.leaflet-container h4, +.leaflet-container h5, +.leaflet-container h6, +.leaflet-container p { + font-size:15px; + line-height:25px; + margin:0 0 10px; + } +.mapbox-small, +.leaflet-control-attribution, +.leaflet-control-scale, +.leaflet-container input, +.leaflet-container textarea, +.leaflet-container label, +.leaflet-container small { + font-size:12px; + line-height:20px; + } + +.leaflet-container a { + color:#3887BE; + font-weight:normal; + text-decoration:none; + } +.leaflet-container a:hover { color:#63b6e5; } +.leaflet-container.dark a { color:#63b6e5; } +.leaflet-container.dark a:hover { color:#8fcaec; } + +.leaflet-container.dark .mapbox-button, +.leaflet-container .mapbox-button { + background-color:#3887be; + display:inline-block; + height:40px; + line-height:40px; + text-decoration:none; + color:#fff; + font-size:12px; + white-space:nowrap; + text-overflow:ellipsis; + } + .leaflet-container.dark .mapbox-button:hover, + .leaflet-container .mapbox-button:hover { + color:#fff; + background-color:#3bb2d0; + } + +/* Base Leaflet +------------------------------------------------------- */ +.leaflet-map-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-pane, +.leaflet-tile-container, +.leaflet-overlay-pane, +.leaflet-shadow-pane, +.leaflet-marker-pane, +.leaflet-popup-pane, +.leaflet-overlay-pane svg, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position:absolute; + left:0; + top:0; + } + +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-drag:none; + -webkit-user-select:none; + -moz-user-select:none; + user-select:none; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } + +.leaflet-tile { + filter:inherit; + visibility:hidden; + } +.leaflet-tile-loaded { + visibility:inherit; + } +.leaflet-zoom-box { + width:0; + height:0; + } + +.leaflet-tile-pane { z-index:2; } +.leaflet-objects-pane { z-index:3; } +.leaflet-overlay-pane { z-index:4; } +.leaflet-shadow-pane { z-index:5; } +.leaflet-marker-pane { z-index:6; } +.leaflet-popup-pane { z-index:7; } + +.leaflet-control { + position:relative; + z-index:7; + pointer-events:auto; + float:left; + clear:both; + } + .leaflet-right .leaflet-control { float:right; } + .leaflet-top .leaflet-control { margin-top:10px; } + .leaflet-bottom .leaflet-control { margin-bottom:10px; } + .leaflet-left .leaflet-control { margin-left:10px; } + .leaflet-right .leaflet-control { margin-right:10px; } + +.leaflet-top, +.leaflet-bottom { + position:absolute; + z-index:1000; + pointer-events:none; + } + .leaflet-top { top:0; } + .leaflet-right { right:0; } + .leaflet-bottom { bottom:0; } + .leaflet-left { left:0; } + +/* zoom and fade animations */ +.leaflet-fade-anim .leaflet-tile, +.leaflet-fade-anim .leaflet-popup { + opacity:0; + -webkit-transition:opacity 0.2s linear; + -moz-transition:opacity 0.2s linear; + -o-transition:opacity 0.2s linear; + transition:opacity 0.2s linear; + } + .leaflet-fade-anim .leaflet-tile-loaded, + .leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity:1; + } + +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition:-webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile, +.leaflet-touching .leaflet-zoom-animated { + -webkit-transition:none; + -moz-transition:none; + -o-transition:none; + transition:none; + } +.leaflet-zoom-anim .leaflet-zoom-hide { visibility: hidden; } + +/* cursors */ +.map-clickable, +.leaflet-clickable { + cursor: pointer; + } +.leaflet-popup-pane, +.leaflet-control { + cursor:auto; + } +.leaflet-container { + cursor:-webkit-grab; + cursor: -moz-grab; + } +.leaflet-dragging, +.leaflet-dragging .map-clickable, +.leaflet-dragging .leaflet-clickable, +.leaflet-dragging .leaflet-container { + cursor:move; + cursor:-webkit-grabbing; + cursor: -moz-grabbing; + } + +.leaflet-zoom-box { + background:#fff; + border:2px dotted #202020; + opacity:0.5; + } + +/* general toolbar styles */ +.leaflet-control-layers, +.leaflet-bar { + background-color:#fff; + border:1px solid #999; + border-color:rgba(0,0,0,0.4); + border-radius:3px; + box-shadow:none; + } +.leaflet-bar a, +.leaflet-bar a:hover { + color:#404040; + color:rgba(0,0,0,0.75); + border-bottom:1px solid #ddd; + border-bottom-color:rgba(0,0,0,0.10); + } + .leaflet-bar a:hover, + .leaflet-bar a:active { + background-color:#f8f8f8; + cursor:pointer; + } + .leaflet-bar a:first-child { + border-radius:3px 3px 0 0; + } + .leaflet-bar a:last-child { + border-bottom:none; + border-radius:0 0 3px 3px; + } + .leaflet-bar a:only-of-type { + border-radius:3px; + } + +.leaflet-bar .leaflet-disabled { + cursor:default; + opacity:0.75; + } +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + display:block; + content:''; + text-indent:-999em; + } + +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display:none; + } + .leaflet-control-layers-expanded .leaflet-control-layers-list { + display:block; + position:relative; + } + +.leaflet-control-layers-expanded { + background:#fff; + padding:6px 10px 6px 6px; + color:#404040; + color:rgba(0,0,0,0.75); + } +.leaflet-control-layers-selector { + margin-top:2px; + position:relative; + top:1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height:0; + border-top:1px solid #ddd; + border-top-color:rgba(0,0,0,0.10); + margin:5px -10px 5px -6px; + } + +.leaflet-container .leaflet-control-attribution { + background-color:rgba(255,255,255,0.25); + margin:0; + box-shadow:none; + } +.leaflet-control-attribution a:hover, +.map-info-container a:hover { + color:inherit; + text-decoration:underline; + } + +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding:0 5px; + } + .leaflet-left .leaflet-control-scale { margin-left:5px; } + .leaflet-bottom .leaflet-control-scale { margin-bottom:5px; } + +.leaflet-control-scale-line { + background-color:rgba(255,255,255,0.5); + border:1px solid #999; + border-color:rgba(0,0,0,0.4); + border-top:none; + padding:2px 5px 1px; + white-space:nowrap; + overflow:hidden; + } + .leaflet-control-scale-line:not(:first-child) { + border-top:2px solid #ddd; + border-top-color:rgba(0,0,0,0.10); + border-bottom:none; + margin-top:-2px; + } + .leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom:2px solid #777; + } + +/* popup */ +.leaflet-popup { + position:absolute; + text-align:center; + pointer-events:none; + } +.leaflet-popup-content-wrapper { + padding:1px; + text-align:left; + pointer-events:all; + } +.leaflet-popup-content { + padding:10px 10px 15px; + margin:0; + line-height:inherit; + } +.leaflet-popup-tip-container { + width:20px; + height:20px; + margin:0 auto; + position:relative; + } +.leaflet-popup-tip { + width:0; + height:0; + margin:0; + border-left:10px solid transparent; + border-right:10px solid transparent; + border-top:10px solid #fff; + box-shadow:none; + } +.leaflet-popup-close-button { + text-indent:-999em; + position:absolute; + top:0;right:0; + pointer-events:all; + } + .leaflet-popup-close-button:hover { + background-color:#f8f8f8; + } + +.leaflet-popup-scrolled { + overflow:auto; + border-bottom:1px solid #ddd; + border-top:1px solid #ddd; + } + +/* div icon */ +.leaflet-div-icon { + background:#fff; + border:1px solid #999; + border-color:rgba(0,0,0,0.4); + } +.leaflet-editing-icon { + border-radius:3px; + } + +/* Leaflet + Mapbox +------------------------------------------------------- */ +.leaflet-bar a, +.mapbox-icon, +.map-tooltip.closable .close, +.leaflet-control-layers-toggle, +.leaflet-popup-close-button, +.mapbox-button-icon:before { + content:''; + display:inline-block; + width:26px; + height:26px; + vertical-align:middle; + background-repeat:no-repeat; + } +.leaflet-bar a { + display:block; + } + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out, +.leaflet-popup-close-button, +.leaflet-control-layers-toggle, +.leaflet-container.dark .map-tooltip .close, +.map-tooltip .close, +.mapbox-icon { + background-image:url(./images/icons-404040.png); + background-repeat:no-repeat; + background-size:26px 260px; + } + .mapbox-button-icon:before, + .leaflet-container.dark .leaflet-control-zoom-in, + .leaflet-container.dark .leaflet-control-zoom-out, + .leaflet-container.dark .leaflet-control-layers-toggle, + .leaflet-container.dark .mapbox-icon { + background-image:url(./images/icons-ffffff.png); + background-size:26px 260px; + } + .leaflet-bar .leaflet-control-zoom-in { background-position:0 0; } + .leaflet-bar .leaflet-control-zoom-out { background-position:0 -26px; } + .map-tooltip .close, .leaflet-popup-close-button { background-position:0 -52px; } + .mapbox-icon-info { background-position:0 -78px; } + .leaflet-control-layers-toggle { background-position:0 -104px; } + .mapbox-icon-share:before, .mapbox-icon-share { background-position:0 -130px; } + .mapbox-icon-geocoder:before, .mapbox-icon-geocoder { background-position:0 -156px; } + .mapbox-icon-facebook:before, .mapbox-icon-facebook { background-position:0 -182px; } + .mapbox-icon-twitter:before, .mapbox-icon-twitter { background-position:0 -208px; } + .mapbox-icon-pinterest:before, .mapbox-icon-pinterest { background-position:0 -234px; } + +@media + (-webkit-min-device-pixel-ratio:2), + (min-resolution:192dpi) { + .leaflet-control-zoom-in, + .leaflet-control-zoom-out, + .leaflet-popup-close-button, + .leaflet-control-layers-toggle, + .mapbox-icon { + background-image:url(./images/icons-404040@2x.png); + } + .mapbox-button-icon:before, + .leaflet-container.dark .leaflet-control-zoom-in, + .leaflet-container.dark .leaflet-control-zoom-out, + .leaflet-container.dark .leaflet-control-layers-toggle, + .leaflet-container.dark .mapbox-icon { + background-image:url(./images/icons-ffffff@2x.png); + } +} + +.leaflet-popup-content-wrapper, +.map-legends, +.map-tooltip { + background:#fff; + border-radius:3px; + box-shadow:0 1px 2px rgba(0,0,0,0.10); + } +.map-legends, +.map-tooltip { + max-width:300px; + } +.map-legends .map-legend { + padding:10px; + } +.map-tooltip { + z-index:999999; + padding:10px; + min-width:180px; + max-height:400px; + overflow:auto; + opacity:1; + -webkit-transition:opacity 150ms; + -moz-transition:opacity 150ms; + -o-transition:opacity 150ms; + transition:opacity 150ms; + } + +.map-tooltip .close { + text-indent:-999em; + overflow:hidden; + display:none; + } + .map-tooltip.closable .close { + position:absolute; + top:0;right:0; + border-radius:3px; + } + .map-tooltip.closable .close:active { + background-color:#f8f8f8; + } + +.leaflet-control-interaction { + position:absolute; + top:10px; + right:10px; + width:300px; + } +.leaflet-popup-content .marker-title { + font-weight:bold; + } +.leaflet-control .mapbox-button { + background-color:#fff; + border:1px solid #ddd; + border-color:rgba(0,0,0,0.10); + padding:5px 10px; + border-radius:3px; + } + +/* Share modal +------------------------------------------------------- */ +.mapbox-modal > div { + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + z-index:-1; + overflow-y:auto; + } + .mapbox-modal.active > div { + z-index:99999; + transition:all .2s, z-index 0 0; + } + +.mapbox-modal .mapbox-modal-mask { + background:rgba(0,0,0,0.5); + opacity:0; + } + .mapbox-modal.active .mapbox-modal-mask { opacity:1; } + +.mapbox-modal .mapbox-modal-content { + -webkit-transform:translateY(-100%); + -moz-transform:translateY(-100%); + -ms-transform:translateY(-100%); + transform:translateY(-100%); + } + .mapbox-modal.active .mapbox-modal-content { + -webkit-transform:translateY(0); + -moz-transform:translateY(0); + -ms-transform:translateY(0); + transform:translateY(0); + } + +.mapbox-modal-body { + position:relative; + background:#fff; + padding:20px; + z-index:1000; + width:50%; + margin:20px 0 20px 25%; + } +.mapbox-share-buttons { + margin:0 0 20px; + } +.mapbox-share-buttons a { + width:33.3333%; + border-left:1px solid #fff; + text-align:center; + border-radius:0; + } + .mapbox-share-buttons a:last-child { border-radius:0 3px 3px 0; } + .mapbox-share-buttons a:first-child { border:none; border-radius:3px 0 0 3px; } + +.mapbox-modal input { + width:100%; + height:40px; + padding:10px; + border:1px solid #ddd; + border-color:rgba(0,0,0,0.10); + color:rgba(0,0,0,0.5); + } + +/* Info Control +------------------------------------------------------- */ +.leaflet-control.mapbox-control-info { + margin:5px 30px 10px 10px; + min-height:26px; + } + .leaflet-control.mapbox-control-info-right { + margin:5px 10px 10px 30px; + } + +.mapbox-info-toggle { + background-color:#fff; + background-color:rgba(255,255,255,0.25); + border-radius:50%; + position:absolute; + bottom:0;left:0; + z-index:1; + } + .mapbox-control-info-right .mapbox-info-toggle { left:auto; right:0; } + .mapbox-control-info.active .mapbox-info-toggle { background-color:#fff; } + .mapbox-info-toggle:hover { background-color:rgba(255,255,255,0.5); } + +.map-info-container { + background:#fff; + background:rgba(255,255,255,0.75); + padding:3px 5px 3px 15px; + display:none; + position:relative; + bottom:0; + left:13px; + border-radius:3px; + } +.mapbox-control-info.active .map-info-container { display:inline-block; } +.mapbox-control-info-right .map-info-container { + left:auto; + right:13px; + padding:3px 15px 3px 5px; + } + +/* Geocoder +------------------------------------------------------- */ +.leaflet-control-mapbox-geocoder { + position:relative; + } +.leaflet-control-mapbox-geocoder.searching { + opacity:0.75; + } +.leaflet-control-mapbox-geocoder .leaflet-control-mapbox-geocoder-wrap { + background:#fff; + position:absolute; + border:1px solid #999; + border-color:rgba(0,0,0,0.4); + border-bottom-width:0; + overflow:hidden; + left:26px; + height:27px; + width:0; + top:-1px; + border-radius:0 3px 3px 0; + opacity:0; + -webkit-transition:opacity 100ms; + -moz-transition:opacity 100ms; + -o-transition:opacity 100ms; + transition:opacity 100ms; + } +.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-wrap { + width:180px; + opacity:1; + } +.leaflet-bar .leaflet-control-mapbox-geocoder-toggle, +.leaflet-bar .leaflet-control-mapbox-geocoder-toggle:hover { + border-bottom:none; + } +.leaflet-control-mapbox-geocoder-toggle { + border-radius:3px; + } +.leaflet-control-mapbox-geocoder.active, +.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-toggle { + border-top-right-radius:0; + border-bottom-right-radius:0; + } +.leaflet-control-mapbox-geocoder .leaflet-control-mapbox-geocoder-form input { + background:transparent; + border:0; + width:180px; + padding:0 0 0 10px; + height:26px; + outline:none; + } +.leaflet-control-mapbox-geocoder-results { + width:180px; + position:absolute; + left:26px; + top:25px; + border-radius:0 0 3px 3px; + } + .leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-results { + background:#fff; + border:1px solid #999; + border-color:rgba(0,0,0,0.4); + } + +.leaflet-control-mapbox-geocoder-results a, +.leaflet-control-mapbox-geocoder-results span { + padding:0 10px; + text-overflow:ellipsis; + white-space:nowrap; + display:block; + width:100%; + font-size:12px; + line-height:26px; + text-align:left; + overflow:hidden; + } + .leaflet-control-mapbox-geocoder-results a:first-child { + border-top:1px solid #999; + border-top-color:rgba(0,0,0,0.4); + border-radius:0; + } + .leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results a:hover, + .leaflet-control-mapbox-geocoder-results a:hover { + background:#f8f8f8; + opacity:1; + } + +/* Dark Theme +------------------------------------------------------- */ +.leaflet-container.dark .leaflet-bar { + background-color:#404040; + border-color:#202020; + border-color:rgba(0,0,0,0.75); + } + .leaflet-container.dark .leaflet-bar a { + color:#404040; + border-color:rgba(0,0,0,0.5); + } + .leaflet-container.dark .leaflet-bar a:active, + .leaflet-container.dark .leaflet-bar a:hover { + background-color:#505050; + } + +.leaflet-container.dark .mapbox-info-toggle, +.leaflet-container.dark .map-info-container, +.leaflet-container.dark .leaflet-control-attribution { + background-color:rgba(0,0,0,0.25); + color:#f8f8f8; + } +.leaflet-container.dark .leaflet-bar a.leaflet-disabled, +.leaflet-container.dark .leaflet-control .mapbox-button.disabled { + background-color:#252525; + color:#404040; + } +.leaflet-container.dark .leaflet-control-mapbox-geocoder > div { + border-color:#202020; + border-color:rgba(0,0,0,0.75); + } + .leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results a { + border-color:#ddd #202020; + border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.75); + } + .leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results span { + border-color:#202020; + border-color:rgba(0,0,0,0.75); + } + +/* Larger Screens +------------------------------------------------------- */ +@media only screen and (max-width:800px) { +.mapbox-modal-body { + width:83.3333%; + margin-left:8.3333%; + } +} + +/* Smaller Screens +------------------------------------------------------- */ +@media only screen and (max-width:640px) { +.mapbox-modal-body { + width:100%; + height:100%; + margin:0; + } +} + +/* Browser Fixes +------------------------------------------------------- */ +/* Map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container img { max-width:none!important; } +/* Stupid Android 2 doesn't understand "max-width: none" properly */ +.leaflet-container img.leaflet-image-layer { max-width:15000px!important; } +/* Android chrome makes tiles disappear without this */ +.leaflet-tile-container img { -webkit-backface-visibility:hidden; } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { -moz-user-select:none; } +/* Older IEs don't support the translateY property for display animation */ +.leaflet-oldie .mapbox-modal .mapbox-modal-content { display:none; } +.leaflet-oldie .mapbox-modal.active .mapbox-modal-content { display:block; } +.map-tooltip { width:280px\8; /* < IE9 */ } diff --git a/gui-src/css/maps/mapbox.v3.2.0.css b/gui-src/css/maps/mapbox.v3.2.0.css new file mode 100644 index 0000000..2b01927 --- /dev/null +++ b/gui-src/css/maps/mapbox.v3.2.0.css @@ -0,0 +1 @@ +.leaflet-container{background:#fff;font:12px/20px 'Helvetica Neue',Arial,Helvetica,sans-serif;color:#404040;color:rgba(0,0,0,.75);outline:0;overflow:hidden;-ms-touch-action:none}.leaflet-container *,.leaflet-container :after,.leaflet-container :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.leaflet-container h1,.leaflet-container h2,.leaflet-container h3,.leaflet-container h4,.leaflet-container h5,.leaflet-container h6,.leaflet-container p{font-size:15px;line-height:20px;margin:0 0 10px}.leaflet-container .marker-description img{margin-bottom:10px}.leaflet-container a{color:#3887be;font-weight:400;text-decoration:none}.leaflet-container a:hover{color:#63b6e5}.leaflet-container.dark a{color:#63b6e5}.leaflet-container.dark a:hover{color:#8fcaec}.leaflet-container .mapbox-button,.leaflet-container.dark .mapbox-button{background-color:#3887be;display:inline-block;height:40px;line-height:40px;text-decoration:none;color:#fff;font-size:12px;white-space:nowrap;text-overflow:ellipsis}.leaflet-container .mapbox-button:hover,.leaflet-container.dark .mapbox-button:hover{color:#fff;background-color:#3bb2d0}.leaflet-image-layer,.leaflet-layer,.leaflet-map-pane canvas,.leaflet-map-pane svg,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-pane,.leaflet-tile,.leaflet-tile-container,.leaflet-zoom-box{position:absolute;left:0;top:0}.leaflet-container{overflow:hidden}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-safari .leaflet-tile{image-rendering:-webkit-optimize-contrast}.leaflet-safari .leaflet-tile-container{width:1600px;height:1600px;-webkit-transform-origin:0 0}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-overlay-pane svg,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer{max-width:none!important}.leaflet-container.leaflet-touch-zoom{-ms-touch-action:pan-x pan-y;touch-action:pan-x pan-y}.leaflet-container.leaflet-touch-drag{-ms-touch-action:pinch-zoom}.leaflet-container.leaflet-touch-drag.leaflet-touch-drag{-ms-touch-action:none;touch-action:none}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0;z-index:800}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-map-pane canvas{z-index:1}.leaflet-map-pane svg{z-index:2}.leaflet-tile-pane{z-index:2}.leaflet-overlay-pane{z-index:4}.leaflet-shadow-pane{z-index:5}.leaflet-marker-pane{z-index:6}.leaflet-tooltip-pane{z-index:7}.leaflet-popup-pane{z-index:8}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{position:relative;z-index:800;pointer-events:visiblePainted;pointer-events:auto}.leaflet-bottom,.leaflet-top{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-control{float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-fade-anim .leaflet-tile{will-change:opacity}.leaflet-fade-anim .leaflet-popup{opacity:0;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-animated{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0}.leaflet-zoom-anim .leaflet-zoom-animated{will-change:transform}.leaflet-zoom-anim .leaflet-zoom-animated{-webkit-transition:-webkit-transform .25s cubic-bezier(0,0,.25,1);-moz-transition:-moz-transform .25s cubic-bezier(0,0,.25,1);-o-transition:-o-transform .25s cubic-bezier(0,0,.25,1);transition:transform .25s cubic-bezier(0,0,.25,1)}.leaflet-pan-anim .leaflet-tile,.leaflet-zoom-anim .leaflet-tile{-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:-webkit-grab;cursor:-moz-grab}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive{cursor:crosshair}.leaflet-control,.leaflet-popup-pane{cursor:auto}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable{cursor:move;cursor:-webkit-grabbing;cursor:-moz-grabbing}.leaflet-image-layer,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-pane>svg path,.leaflet-tile-container{pointer-events:none}.leaflet-image-layer.leaflet-interactive,.leaflet-marker-icon.leaflet-interactive,.leaflet-pane>svg path.leaflet-interactive{pointer-events:visiblePainted;pointer-events:auto}.leaflet-container{outline:0}.leaflet-zoom-box{background:#fff;border:2px dotted #202020;opacity:.5}.leaflet-bar,.leaflet-control-layers{background-color:#fff;border:1px solid #999;border-color:rgba(0,0,0,.4);border-radius:3px;box-shadow:none}.leaflet-bar a,.leaflet-bar a:hover{color:#404040;color:rgba(0,0,0,.75);border-bottom:1px solid #ddd;border-bottom-color:rgba(0,0,0,.1)}.leaflet-bar a:last-child{border-bottom:none}.leaflet-bar a:active,.leaflet-bar a:hover{background-color:#f8f8f8;cursor:pointer}.leaflet-bar a:hover:first-child{border-radius:3px 3px 0 0}.leaflet-bar a:hover:last-child{border-radius:0 0 3px 3px}.leaflet-bar a:hover:only-of-type{border-radius:3px}.leaflet-bar .leaflet-disabled{cursor:default;opacity:.75}.leaflet-control-zoom-in,.leaflet-control-zoom-out{display:block;content:'';text-indent:-999em}.leaflet-control-layers .leaflet-control-layers-list,.leaflet-control-layers-expanded .leaflet-control-layers-toggle{display:none}.leaflet-control-layers-expanded .leaflet-control-layers-list{display:block;position:relative}.leaflet-control-layers-expanded{background:#fff;padding:6px 10px 6px 6px;color:#404040;color:rgba(0,0,0,.75)}.leaflet-control-layers-selector{margin-top:2px;position:relative;top:1px}.leaflet-control-layers label{display:block}.leaflet-control-layers-separator{height:0;border-top:1px solid #ddd;border-top-color:rgba(0,0,0,.1);margin:5px -10px 5px -6px}.leaflet-default-icon-path{background-image:url(images/marker-icon.png)}.leaflet-container .leaflet-control-attribution{background-color:rgba(255,255,255,.5);margin:0;box-shadow:none}.leaflet-container .leaflet-control-attribution a,.leaflet-container .map-info-container a{color:#404040}.leaflet-control-attribution a:hover,.map-info-container a:hover{color:inherit;text-decoration:underline}.leaflet-control-attribution,.leaflet-control-scale-line{padding:0 5px}.leaflet-left .leaflet-control-scale{margin-left:5px}.leaflet-bottom .leaflet-control-scale{margin-bottom:5px}.leaflet-container .mapbox-improve-map{font-weight:700}.leaflet-control-scale-line{background-color:rgba(255,255,255,.5);border:1px solid #999;border-color:rgba(0,0,0,.4);border-top:none;padding:2px 5px 1px;white-space:nowrap;overflow:hidden}.leaflet-control-scale-line:last-child{border-top:2px solid #ddd;border-top-color:rgba(0,0,0,.1);border-bottom:none;margin-top:-2px}.leaflet-container .leaflet-control-attribution.leaflet-compact-attribution{margin:10px}.leaflet-container .leaflet-control-attribution.leaflet-compact-attribution{background:#fff;border-radius:3px 13px 13px 3px;padding:3px 31px 3px 3px;visibility:hidden}.leaflet-control-attribution.leaflet-compact-attribution:hover{visibility:visible}.leaflet-control-attribution.leaflet-compact-attribution:after{content:'';background-color:#fff;background-color:rgba(255,255,255,.5);background-position:0 -78px;border-radius:50%;position:absolute;display:inline-block;width:26px;height:26px;vertical-align:middle;bottom:0;z-index:1;visibility:visible;cursor:pointer}.leaflet-control-attribution.leaflet-compact-attribution:hover:after{background-color:#fff}.leaflet-right .leaflet-control-attribution.leaflet-compact-attribution:after{right:0}.leaflet-left .leaflet-control-attribution.leaflet-compact-attribution:after{left:0}.leaflet-touch .leaflet-bar,.leaflet-touch .leaflet-control-layers{border:2px solid rgba(0,0,0,.2);background-clip:padding-box}.leaflet-popup{position:absolute;text-align:center;pointer-events:none}.leaflet-popup-content-wrapper{padding:1px;text-align:left;pointer-events:all}.leaflet-popup-content{padding:10px 10px 15px;margin:0;line-height:inherit}.leaflet-popup-close-button+.leaflet-popup-content-wrapper .leaflet-popup-content{padding-top:15px}.leaflet-popup-tip-container{width:20px;height:20px;margin:0 auto;position:relative}.leaflet-popup-tip{width:0;height:0;margin:0;border-left:10px solid transparent;border-right:10px solid transparent;border-top:10px solid #fff;box-shadow:none}.leaflet-popup-close-button{text-indent:-999em;position:absolute;top:0;right:0;pointer-events:all}.leaflet-popup-close-button:hover{background-color:#f8f8f8}.leaflet-popup-scrolled{overflow:auto;border-bottom:1px solid #ddd;border-top:1px solid #ddd}.leaflet-div-icon{background:#fff;border:1px solid #999;border-color:rgba(0,0,0,.4)}.leaflet-editing-icon{border-radius:3px}.leaflet-tooltip{position:absolute;padding:5px;background-color:#fff;border:1px solid #fff;border-radius:3px;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}.leaflet-tooltip.leaflet-clickable{cursor:pointer;pointer-events:auto}.leaflet-tooltip-bottom:before,.leaflet-tooltip-left:before,.leaflet-tooltip-right:before,.leaflet-tooltip-top:before{content:'';position:absolute;pointer-events:none;border:5px solid transparent;background:0 0}.leaflet-tooltip-bottom{margin-top:5px}.leaflet-tooltip-top{margin-top:-5px}.leaflet-tooltip-bottom:before,.leaflet-tooltip-top:before{left:50%;margin-left:-5px}.leaflet-tooltip-top:before{bottom:0;margin-bottom:-10px;border-top-color:#fff}.leaflet-tooltip-bottom:before{top:0;margin-top:-15px;margin-left:-5px;border-bottom-color:#fff}.leaflet-tooltip-left{margin-left:-5px}.leaflet-tooltip-right{margin-left:5px}.leaflet-tooltip-left:before,.leaflet-tooltip-right:before{top:50%;margin-top:-5px}.leaflet-tooltip-left:before{right:0;margin-right:-10px;border-left-color:#fff}.leaflet-tooltip-right:before{left:0;margin-left:-10px;border-right-color:#fff}.leaflet-bar a,.leaflet-control-layers-toggle,.leaflet-popup-close-button,.map-tooltip.closable .close,.mapbox-button-icon:before,.mapbox-icon{content:'';display:inline-block;width:26px;height:26px;vertical-align:middle;background-repeat:no-repeat}.leaflet-bar a{display:block}.leaflet-container.dark .map-tooltip .close,.leaflet-control-attribution:after,.leaflet-control-layers-toggle,.leaflet-control-zoom-in,.leaflet-control-zoom-out,.leaflet-popup-close-button,.map-tooltip .close,.mapbox-icon{opacity:.75;background-image:url(images/icons-000000@2x.png);background-image:linear-gradient(transparent,transparent),url(images/icons.svg);background-repeat:no-repeat;background-size:26px 260px}.leaflet-container.dark .leaflet-control-attribution:after,.leaflet-container.dark .leaflet-control-layers-toggle,.leaflet-container.dark .leaflet-control-zoom-in,.leaflet-container.dark .leaflet-control-zoom-out,.leaflet-container.dark .mapbox-icon,.mapbox-button-icon:before{opacity:1;background-image:url(images/icons-ffffff@2x.png);background-image:linear-gradient(transparent,transparent),url(images/icons-ffffff.svg);background-size:26px 260px}.leaflet-bar .leaflet-control-zoom-in{background-position:0 0}.leaflet-bar .leaflet-control-zoom-out{background-position:0 -26px}.leaflet-popup-close-button,.map-tooltip.closable .close{background-position:-3px -55px;width:20px;height:20px;border-radius:0 3px 0 0}.mapbox-icon-info{background-position:0 -78px}.leaflet-control-layers-toggle{background-position:0 -104px}.mapbox-icon.mapbox-icon-share,.mapbox-icon.mapbox-icon-share:before{background-position:0 -130px}.mapbox-icon.mapbox-icon-geocoder,.mapbox-icon.mapbox-icon-geocoder:before{background-position:0 -156px}.mapbox-icon-facebook,.mapbox-icon-facebook:before{background-position:0 -182px}.mapbox-icon-twitter,.mapbox-icon-twitter:before{background-position:0 -208px}.mapbox-icon-pinterest,.mapbox-icon-pinterest:before{background-position:0 -234px}.leaflet-popup-content-wrapper,.map-legends,.map-tooltip{background:#fff;border-radius:3px;box-shadow:0 1px 2px rgba(0,0,0,.1)}.map-legends,.map-tooltip{max-width:300px}.map-legends .map-legend{padding:10px}.map-tooltip{z-index:999999;padding:10px;min-width:180px;max-height:400px;overflow:auto;opacity:1;-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;-o-transition:opacity 150ms;transition:opacity 150ms}.map-tooltip .close{text-indent:-999em;overflow:hidden;display:none}.map-tooltip.closable .close{position:absolute;top:0;right:0;border-radius:3px}.map-tooltip.closable .close:active{background-color:#f8f8f8}.leaflet-control-interaction{position:absolute;top:10px;right:10px;width:300px}.leaflet-popup-content .marker-title{font-weight:700}.leaflet-control .mapbox-button{background-color:#fff;border:1px solid #ddd;border-color:rgba(0,0,0,.1);padding:5px 10px;border-radius:3px}.mapbox-modal>div{position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;overflow-y:auto}.mapbox-modal.active>div{z-index:99999;transition:all .2s,z-index 0 0}.mapbox-modal .mapbox-modal-mask{background:rgba(0,0,0,.5);opacity:0}.mapbox-modal.active .mapbox-modal-mask{opacity:1}.mapbox-modal .mapbox-modal-content{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.mapbox-modal.active .mapbox-modal-content{-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.mapbox-modal-body{position:relative;background:#fff;padding:20px;z-index:1000;width:50%;margin:20px 0 20px 25%}.mapbox-share-buttons{margin:0 0 20px}.mapbox-share-buttons a{width:33.3333%;border-left:1px solid #fff;text-align:center;border-radius:0}.mapbox-share-buttons a:last-child{border-radius:0 3px 3px 0}.mapbox-share-buttons a:first-child{border:none;border-radius:3px 0 0 3px}.mapbox-modal input{width:100%;height:40px;padding:10px;border:1px solid #ddd;border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.mapbox-modal label{display:block;margin-top:5px}.leaflet-control-mapbox-geocoder{position:relative}.leaflet-control-mapbox-geocoder.searching{opacity:.75}.leaflet-control-mapbox-geocoder .leaflet-control-mapbox-geocoder-wrap{background:#fff;position:absolute;border:1px solid #999;border-color:rgba(0,0,0,.4);overflow:hidden;left:26px;height:28px;width:0;top:-1px;border-radius:0 3px 3px 0;opacity:0;-webkit-transition:opacity .1s;-moz-transition:opacity .1s;-o-transition:opacity .1s;transition:opacity .1s}.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-wrap{width:180px;opacity:1}.leaflet-bar .leaflet-control-mapbox-geocoder-toggle,.leaflet-bar .leaflet-control-mapbox-geocoder-toggle:hover{border-bottom:none}.leaflet-control-mapbox-geocoder-toggle{border-radius:3px}.leaflet-control-mapbox-geocoder.active,.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.leaflet-control-mapbox-geocoder .leaflet-control-mapbox-geocoder-form input{background:0 0;border:0;width:180px;padding:0 0 0 10px;height:26px;outline:0}.leaflet-control-mapbox-geocoder-results{width:180px;position:absolute;left:26px;top:25px;border-radius:0 0 3px 3px}.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-results{background:#fff;border:1px solid #999;border-color:rgba(0,0,0,.4)}.leaflet-control-mapbox-geocoder-results a,.leaflet-control-mapbox-geocoder-results span{padding:0 10px;text-overflow:ellipsis;white-space:nowrap;display:block;width:100%;font-size:12px;line-height:26px;text-align:left;overflow:hidden}.leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results a:hover,.leaflet-control-mapbox-geocoder-results a:hover{background:#f8f8f8;opacity:1}.leaflet-right .leaflet-control-mapbox-geocoder-results,.leaflet-right .leaflet-control-mapbox-geocoder-wrap{left:auto;right:26px}.leaflet-right .leaflet-control-mapbox-geocoder-wrap{border-radius:3px 0 0 3px}.leaflet-right .leaflet-control-mapbox-geocoder.active,.leaflet-right .leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-toggle{border-radius:0 3px 3px 0}.leaflet-bottom .leaflet-control-mapbox-geocoder-results{top:auto;bottom:25px;border-radius:3px 3px 0 0}.mapbox-logo.mapbox-logo-true{margin:0 0 5px 5px}.mapbox-logo-true:before{content:'';display:inline-block;width:85px;height:21px;vertical-align:middle}.mapbox-logo.mapbox-logo-true{background-repeat:no-repeat;background-size:85px 21px;background-image:url("data:image/svg+xml;charset=utf-8,%3C?xml%20version='1.0'%20encoding='utf-8'?%3E%3Csvg%20version='1.1'%20id='Layer_1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%20x='0px'%20y='0px'%20viewBox='0%200%2084.49%2021'%20style='enable-background:new%200%200%2084.49%2021;'%20xml:space='preserve'%3E%3Cg%3E%20%3Cpath%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20d='M83.25,14.26c0,0.12-0.09,0.21-0.21,0.21h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39l-1.44,2.39%20c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68L76.2,6.84%20c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.4-2.35%20c0.06-0.11,0.18-0.17,0.3-0.17H83c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.37,3.63l2.43,3.67%20C83.24,14.18,83.25,14.22,83.25,14.26z'/%3E%20%3Cpath%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20d='M66.24,9.59c-0.39-1.88-1.96-3.28-3.84-3.28c-1.03,0-2.03,0.42-2.73,1.18V3.51c0-0.13-0.1-0.23-0.23-0.23h-1.4%20c-0.13,0-0.23,0.11-0.23,0.23v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.11,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.73,1.18%20c1.88,0,3.45-1.41,3.84-3.29C66.37,10.79,66.37,10.18,66.24,9.59L66.24,9.59z%20M62.08,13c-1.32,0-2.39-1.11-2.41-2.48v-0.06%20c0.02-1.38,1.09-2.48,2.41-2.48s2.42,1.12,2.42,2.51S63.41,13,62.08,13z'/%3E%20%3Cpath%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20d='M71.67,6.32c-1.98-0.01-3.72,1.35-4.16,3.29c-0.13,0.59-0.13,1.19,0,1.77c0.44,1.94,2.17,3.32,4.17,3.3%20c2.35,0,4.26-1.87,4.26-4.19S74.04,6.32,71.67,6.32z%20M71.65,13.01c-1.33,0-2.42-1.12-2.42-2.51s1.08-2.52,2.42-2.52%20c1.33,0,2.42,1.12,2.42,2.51S72.99,13,71.65,13.01L71.65,13.01z'/%3E%20%3Cpath%20class='st1'%20style='opacity:0.35;%20enable-background:new;'%20d='M62.08,7.98c-1.32,0-2.39,1.11-2.41,2.48v0.06C59.68,11.9,60.75,13,62.08,13s2.42-1.12,2.42-2.51%20S63.41,7.98,62.08,7.98z%20M62.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25%20c0.63,0,1.17,0.57,1.17,1.27C63.24,11.2,62.73,11.76,62.08,11.76z'/%3E%20%3Cpath%20class='st1'%20style='opacity:0.35;%20enable-background:new;'%20d='M71.65,7.98c-1.33,0-2.42,1.12-2.42,2.51S70.32,13,71.65,13s2.42-1.12,2.42-2.51S72.99,7.98,71.65,7.98z%20M71.65,11.76c-0.64,0-1.17-0.57-1.17-1.27c0-0.7,0.53-1.26,1.17-1.26s1.17,0.57,1.17,1.27C72.82,11.21,72.29,11.76,71.65,11.76z'/%3E%20%3Cpath%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20d='M45.74,6.53h-1.4c-0.13,0-0.23,0.11-0.23,0.23v0.73c-0.71-0.75-1.7-1.18-2.73-1.18%20c-2.17,0-3.94,1.87-3.94,4.19s1.77,4.19,3.94,4.19c1.04,0,2.03-0.43,2.73-1.19v0.73c0,0.13,0.1,0.23,0.23,0.23h1.4%20c0.13,0,0.23-0.11,0.23-0.23V6.74c0-0.12-0.09-0.22-0.22-0.22C45.75,6.53,45.75,6.53,45.74,6.53z%20M44.12,10.53%20C44.11,11.9,43.03,13,41.71,13s-2.42-1.12-2.42-2.51s1.08-2.52,2.4-2.52c1.33,0,2.39,1.11,2.41,2.48L44.12,10.53z'/%3E%20%3Cpath%20class='st1'%20style='opacity:0.35;%20enable-background:new;'%20d='M41.71,7.98c-1.33,0-2.42,1.12-2.42,2.51S40.37,13,41.71,13s2.39-1.11,2.41-2.48v-0.06%20C44.1,9.09,43.03,7.98,41.71,7.98z%20M40.55,10.49c0-0.7,0.52-1.27,1.17-1.27c0.64,0,1.14,0.56,1.17,1.25v0.04%20c-0.01,0.68-0.53,1.24-1.17,1.24C41.08,11.75,40.55,11.19,40.55,10.49z'/%3E%20%3Cpath%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20d='M52.41,6.32c-1.03,0-2.03,0.42-2.73,1.18V6.75c0-0.13-0.1-0.23-0.23-0.23h-1.4c-0.13,0-0.23,0.11-0.23,0.23%20v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.1,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.74,1.18c2.17,0,3.94-1.87,3.94-4.19%20S54.58,6.32,52.41,6.32z%20M52.08,13.01c-1.32,0-2.39-1.11-2.42-2.48v-0.07c0.02-1.38,1.09-2.49,2.4-2.49c1.32,0,2.41,1.12,2.41,2.51%20S53.4,13,52.08,13.01L52.08,13.01z'/%3E%20%3Cpath%20class='st1'%20style='opacity:0.35;%20enable-background:new;'%20d='M52.08,7.98c-1.32,0-2.39,1.11-2.42,2.48v0.06c0.03,1.38,1.1,2.48,2.42,2.48s2.41-1.12,2.41-2.51%20S53.4,7.98,52.08,7.98z%20M52.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25c0.63,0,1.17,0.58,1.17,1.27%20S52.72,11.76,52.08,11.76z'/%3E%20%3Cpath%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20d='M36.08,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68c0-0.98-0.74-1.71-1.62-1.71%20c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.11,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68%20c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V6.74%20c0.01-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03c1.09,0,2.09,0.6,2.6,1.55%20c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78L36.08,14.24z'/%3E%20%3Cpath%20class='st1'%20style='opacity:0.35;%20enable-background:new;'%20d='M84.34,13.59l-0.07-0.13l-1.96-2.99l1.94-2.95c0.44-0.67,0.26-1.56-0.41-2.02c-0.02,0-0.03,0-0.04-0.01%20c-0.23-0.15-0.5-0.22-0.78-0.22h-1.61c-0.56,0-1.08,0.29-1.37,0.78L79.72,6.6l-0.34-0.56C79.09,5.56,78.57,5.27,78,5.27h-1.6%20c-0.6,0-1.13,0.37-1.35,0.92c-2.19-1.66-5.28-1.47-7.26,0.45c-0.35,0.34-0.65,0.72-0.89,1.14c-0.9-1.62-2.58-2.72-4.5-2.72%20c-0.5,0-1.01,0.07-1.48,0.23V3.51c0-0.82-0.66-1.48-1.47-1.48h-1.4c-0.81,0-1.47,0.66-1.47,1.47v3.75%20c-0.95-1.36-2.5-2.18-4.17-2.19c-0.74,0-1.46,0.16-2.12,0.47c-0.24-0.17-0.54-0.26-0.84-0.26h-1.4c-0.45,0-0.87,0.21-1.15,0.56%20c-0.02-0.03-0.04-0.05-0.07-0.08c-0.28-0.3-0.68-0.47-1.09-0.47h-1.39c-0.3,0-0.6,0.09-0.84,0.26c-0.67-0.3-1.39-0.46-2.12-0.46%20c-1.83,0-3.43,1-4.37,2.5c-0.2-0.46-0.48-0.89-0.83-1.25c-0.8-0.81-1.89-1.25-3.02-1.25h-0.01c-0.89,0.01-1.75,0.33-2.46,0.88%20c-0.74-0.57-1.64-0.88-2.57-0.88H28.1c-0.29,0-0.58,0.03-0.86,0.11c-0.28,0.06-0.56,0.16-0.82,0.28c-0.21-0.12-0.45-0.18-0.7-0.18%20h-1.4c-0.82,0-1.47,0.66-1.47,1.47v7.5c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.48-0.66,1.48-1.48l0,0V9.79%20c0.03-0.36,0.23-0.59,0.36-0.59c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41c0.82,0,1.47-0.66,1.47-1.47%20l-0.01-4.57c0.06-0.32,0.25-0.47,0.35-0.47c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41%20c0.82,0,1.47-0.66,1.47-1.47v-0.38c0.96,1.29,2.46,2.06,4.06,2.06c0.74,0,1.46-0.16,2.12-0.47c0.24,0.17,0.54,0.26,0.84,0.26h1.39%20c0.3,0,0.6-0.09,0.84-0.26v2.01c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.47-0.66,1.47-1.47v-1.77c0.48,0.15,0.99,0.23,1.49,0.22%20c1.7,0,3.22-0.87,4.17-2.2v0.52c0,0.82,0.66,1.47,1.47,1.47h1.4c0.3,0,0.6-0.09,0.84-0.26c0.66,0.31,1.39,0.47,2.12,0.47%20c1.92,0,3.6-1.1,4.49-2.73c1.54,2.65,4.95,3.53,7.58,1.98c0.18-0.11,0.36-0.22,0.53-0.36c0.22,0.55,0.76,0.91,1.35,0.9H78%20c0.56,0,1.08-0.29,1.37-0.78l0.37-0.61l0.37,0.61c0.29,0.48,0.81,0.78,1.38,0.78h1.6c0.81,0,1.46-0.66,1.45-1.46%20C84.49,14.02,84.44,13.8,84.34,13.59L84.34,13.59z%20M35.86,14.47h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68%20c0-0.98-0.74-1.71-1.62-1.71c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23%20V9.68c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23%20V6.74c0.01-0.13,0.11-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03%20c1.09,0,2.09,0.6,2.6,1.55c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78l0.01,5.16C36.09,14.36,35.98,14.46,35.86,14.47%20L35.86,14.47z%20M45.97,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V13.5c-0.7,0.76-1.69,1.18-2.72,1.18%20c-2.17,0-3.94-1.87-3.94-4.19s1.77-4.19,3.94-4.19c1.03,0,2.02,0.43,2.73,1.18V6.74c0-0.13,0.1-0.23,0.23-0.23h1.4%20c0.12-0.01,0.22,0.08,0.23,0.21c0,0.01,0,0.01,0,0.02v7.51h-0.01V14.24z%20M52.41,14.67c-1.03,0-2.02-0.43-2.73-1.18v3.97%20c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.1-0.23-0.23V6.75c0-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.23,0.11,0.23,0.23v0.73%20c0.71-0.76,1.7-1.18,2.73-1.18c2.17,0,3.94,1.86,3.94,4.18S54.58,14.67,52.41,14.67z%20M66.24,11.39c-0.39,1.87-1.96,3.29-3.84,3.29%20c-1.03,0-2.02-0.43-2.73-1.18v0.73c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V3.51c0-0.13,0.1-0.23,0.23-0.23%20h1.4c0.13,0,0.23,0.11,0.23,0.23v3.97c0.71-0.75,1.7-1.18,2.73-1.17c1.88,0,3.45,1.4,3.84,3.28C66.37,10.19,66.37,10.8,66.24,11.39%20L66.24,11.39L66.24,11.39z%20M71.67,14.68c-2,0.01-3.73-1.35-4.17-3.3c-0.13-0.59-0.13-1.19,0-1.77c0.44-1.94,2.17-3.31,4.17-3.3%20c2.36,0,4.26,1.87,4.26,4.19S74.03,14.68,71.67,14.68L71.67,14.68z%20M83.04,14.47h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39%20l-1.44,2.39c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68%20L76.2,6.84c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.41-2.36%20c0.06-0.11,0.18-0.17,0.3-0.17h1.61c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.38,3.64l2.43,3.67%20c0.02,0.03,0.03,0.07,0.03,0.12C83.25,14.38,83.16,14.47,83.04,14.47L83.04,14.47L83.04,14.47z'/%3E%20%3Cpath%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20d='M10.5,1.24c-5.11,0-9.25,4.15-9.25,9.25s4.15,9.25,9.25,9.25s9.25-4.15,9.25-9.25%20C19.75,5.38,15.61,1.24,10.5,1.24z%20M14.89,12.77c-1.93,1.93-4.78,2.31-6.7,2.31c-0.7,0-1.41-0.05-2.1-0.16c0,0-1.02-5.64,2.14-8.81%20c0.83-0.83,1.95-1.28,3.13-1.28c1.27,0,2.49,0.51,3.39,1.42C16.59,8.09,16.64,11,14.89,12.77z'/%3E%20%3Cpath%20class='st1'%20style='opacity:0.35;%20enable-background:new;'%20d='M10.5-0.01C4.7-0.01,0,4.7,0,10.49s4.7,10.5,10.5,10.5S21,16.29,21,10.49C20.99,4.7,16.3-0.01,10.5-0.01z%20M10.5,19.74c-5.11,0-9.25-4.15-9.25-9.25s4.14-9.26,9.25-9.26s9.25,4.15,9.25,9.25C19.75,15.61,15.61,19.74,10.5,19.74z'/%3E%20%3Cpath%20class='st1'%20style='opacity:0.35;%20enable-background:new;'%20d='M14.74,6.25C12.9,4.41,9.98,4.35,8.23,6.1c-3.16,3.17-2.14,8.81-2.14,8.81s5.64,1.02,8.81-2.14%20C16.64,11,16.59,8.09,14.74,6.25z%20M12.47,10.34l-0.91,1.87l-0.9-1.87L8.8,9.43l1.86-0.9l0.9-1.87l0.91,1.87l1.86,0.9L12.47,10.34z'/%3E%20%3Cpolygon%20class='st0'%20style='opacity:0.9;%20fill:%20%23FFFFFF;%20enable-background:%20new;'%20points='14.33,9.43%2012.47,10.34%2011.56,12.21%2010.66,10.34%208.8,9.43%2010.66,8.53%2011.56,6.66%2012.47,8.53%20'/%3E%3C/g%3E%3C/svg%3E")}.leaflet-container.dark .leaflet-bar{background-color:#404040;border-color:#202020;border-color:rgba(0,0,0,.75)}.leaflet-container.dark .leaflet-bar a{color:#404040;border-color:rgba(0,0,0,.5)}.leaflet-container.dark .leaflet-bar a:active,.leaflet-container.dark .leaflet-bar a:hover{background-color:#505050}.leaflet-container.dark .leaflet-control-attribution,.leaflet-container.dark .leaflet-control-attribution:after,.leaflet-container.dark .map-info-container,.leaflet-container.dark .mapbox-info-toggle{background-color:rgba(0,0,0,.5);color:#f8f8f8}.leaflet-container.dark .leaflet-control-attribution a,.leaflet-container.dark .leaflet-control-attribution a:hover,.leaflet-container.dark .map-info-container a,.leaflet-container.dark .map-info-container a:hover{color:#fff}.leaflet-container.dark .leaflet-control-attribution:hover:after{background-color:#000}.leaflet-container.dark .leaflet-control-layers-list span{color:#f8f8f8}.leaflet-container.dark .leaflet-control-layers-separator{border-top-color:rgba(255,255,255,.1)}.leaflet-container.dark .leaflet-bar a.leaflet-disabled,.leaflet-container.dark .leaflet-control .mapbox-button.disabled{background-color:#252525;color:#404040}.leaflet-container.dark .leaflet-control-mapbox-geocoder>div{border-color:#202020;border-color:rgba(0,0,0,.75)}.leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results a{border-color:#ddd #202020;border-color:rgba(0,0,0,.1) rgba(0,0,0,.75)}.leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results span{border-color:#202020;border-color:rgba(0,0,0,.75)}@media only screen and (max-width:800px){.mapbox-modal-body{width:83.3333%;margin-left:8.3333%}}@media only screen and (max-width:640px){.mapbox-modal-body{width:100%;height:100%;margin:0}}@media print{.mapbox-improve-map{display:none}}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-container img.leaflet-tile{max-width:none!important}.leaflet-container img.leaflet-marker-icon{max-width:none}.leaflet-container img.leaflet-image-layer{max-width:15000px!important}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-oldie .mapbox-modal .mapbox-modal-content{display:none}.leaflet-oldie .mapbox-modal.active .mapbox-modal-content{display:block}.leaflet-oldie .leaflet-container.dark .map-tooltip .close,.leaflet-oldie .leaflet-control-layers-toggle,.leaflet-oldie .leaflet-control-zoom-in,.leaflet-oldie .leaflet-control-zoom-out,.leaflet-oldie .leaflet-popup-close-button,.leaflet-oldie .map-tooltip .close,.leaflet-oldie .mapbox-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAEECAYAAAA24SSRAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAXnSURBVHic7ZxfiFVFGMB/33pRUQsKto002DY3McJ6yBYkESQxpYTypaB66KEXYRWLYOlhr9RTRGWRUkk9RyEU+Y9ClECJVTKlPybWBilqkYuWrqBOD/NdPV7PmTPn3NPtat/AcO6ZP9/vfN/Mmfl2Zs6Kc452hK62UAxkIANdEURkVERGC9crOjKIiANwzkmRep1lOjWXa2ijaU7jaGWgKsL110a1EnV+LQMqbLqyobO6t4EMZCADGchABrqmQUlPNSWOVgaqIpi7ZSADGchABjKQga49kIjURaQem14apGE4KVR/D0fXds5FRaAOOL1e+h1dP7ZgE6wQxDnXvs7QWaZLE1wUVmRNdY1zrp6wRF0kfqHYnHwDGchABjJQIETNRyIyFVgBzAPmavIIsAt4xzn3d66QiNl1PnCYy05JczwMzG9pKlfIhQCkES/kwUKQqRma9GpM02xqGXdrBdCXZm2NzaFP66SGUGeYl5E+WqJO0HRHSG+PXtJN54AjVbhbjQcbBSjiakH4hR0p+hChOiHQrhKg7Drt6t7//Qtb9RAU5XtXMaiak28gAxnIQO0Gicg0EXlMRDaIyFGNGzRtWhQpMA/1A6uAL4BzZM9H57TMKqC/8HyUPFhZJLiMI4sh0/UDK4FtwHig3LiWWal1UkPsDDsFWAgsBZZo8hZgM7DdOXcmV0igjQ4Ba4HFwORAuclaZi1wqNU2OgNsVw22aNoS1XAhMCXx4OkubOBJZwKDwFbgLNm97qyWGQRmtuoFWRsV0ujabCPzVA1kIAMZqBNAIjIgImPNRxUzK+SsmtRJn4Pqmj8AjCXzsmTlaTSck/8zcDRX/QiNMp8S6Ab2a5nvG5plyioDaoLs1/sBYKwyUBokkTdQJeiVZgi6UR+UVQI0QWHdoXKFvKDYz7RiynXctk7LPlmeRmsKyAqWNQfSQAYykIGuS5CI1ERkSET2ishpvQ6JSLE93ByfoQbsRHeNgfe4vOO8E6iF6hdxToZU6OqGUIWv1vShqkB7VYNaU3pN0/fGgvLa6C5gk3PufJO5zwObgDuraqM8jbZWpdEnwG3AYKOX6XVQ07+sSqNQr3P4QxS9LXeGBGxIzTiGXwR8QSHRsCj7ZjxAbxFYaVAKbMe/BkrAduRpZJ6qgQxkoP8DKDRY1sk/s5W6YFhoUG3nFnZeOIJfxLgXWB7zBFmmyzPT44my9zXSC098OZCTwCQttzOZVzVoX1a5LHmdtYyWDM29yjknItKF3xSelFWvKo1mhCClQLo1sC95T8T/ebr+xrqOABVZT82tY56qgQxkIAN1CkhEulsGiUi3iCzKyJsjIpuBYyLyo4isFpHXReTuTFLAr1sOnAeeT8nbzNW+3rfAM2UcyAcSQj4FngR68Ot0F1NA24CuMqBu4PMUgYdS0hzwYqlFJ+AeNV3s30aLSoEUtjEScoHE3nkZ0Ay1fR7o3ZCcGNAEYHcO5A/g5pZACpsMPEf6UexTwCN5MvI6w2zgaeBt4HQK5BsC57ubY+jPll/wHzn1Ayc07QD+u6MR4GPn3LlA/SuCOZAGMpCBDFRhiF50EpFl+PP49wOzgIPAHmCLc+6zXAERE18P+b7DRqAnJCfvfF0P/mTgLZr0l97vB27CL3HO0rwTwBzn3PHCGiU0uQisA6bhzT0T/T4ZeAr4s6FZmal8WcI0LwETgdfwHzY1XKz3teyjibLLioLWa8UDeG/oZbxD+QHwdULwg1r+K71fXxQ0ohXfAgS/Mvyh5i1MgNZp2qt6P5ImL/QezdbrSeAG4EbVJJkH8LteJ+p1FikhBPpNr3Odc6fUNHdo2oJEucbX8Y2zDQeLgr7T62IReRb4AX9mGGC6Xo8Bu0VkOvCQpu1JlRZoo6Vc/WL2ad4C4A28CWvAR5TtdU0dwqH/ewHvHi8HbgUexh+euDRCFH6PVOh0/FKzw3um4M8zpA1DxwkMQzFjXR9+d/9N1WI8BZI71kU56Aq8HXgC+Ak/5o3gX+rUNmmO5nsbqP2gfwCyvJzPNoKXiAAAAABJRU5ErkJggg==)}.leaflet-oldie .leaflet-container.dark .leaflet-control-layers-toggle,.leaflet-oldie .leaflet-container.dark .leaflet-control-zoom-in,.leaflet-oldie .leaflet-container.dark .leaflet-control-zoom-out,.leaflet-oldie .leaflet-container.dark .mapbox-icon,.leaflet-oldie .mapbox-button-icon:before{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAEECAYAAAA24SSRAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAXYSURBVHic7ZxfiFVFHMc/a4uKWtDDtqJGZprYgwX5ByTdkkLbSgghCiKih14EBYtg6aEr9RRREKRUUs9hGEVtChKaYMkq2VqWmnUX2tKiNDNZY/Xbw/wue7x7zsw559626zY/GM6df7/P+c3MPfO7M3NumyTGQiaMCSWCIiiC6qVqoZC0lXgy1Cq0FanUck1XxVmSNL8WrzYT1LCMvz5qL1FnoAyoTNOVkpYb3hEUQREUQREUQRF0RYOqjHim9aHaTFDDEt2tCIqgCIqgCIqgCLoiQRULedNLgwCeq1NasbR8IilvqMhJpe5zrvpFQElYIYiksRsMLdd0aYoLwYqsqW5i9KjLLdHJj6AIiqAIiiCP5J2PpgLrgGXAYkvrA/YBrwF/BTXkmB2XSzqhbDlhZRqaypdLuuiB1ORiCOaDTM2wZLaFNMumZunzDYZ1wJy01ubyPfOazLE6qeIbDMsy0qsl6ngtWpyRfqOFInVKbWFXS9TxWtRXQl9mHR9oXwlQdp2xGt4t8YVt6iMor+/d8EM1OvkRFEERFEH/AWga8CCwFfjJwlZLm5ZHge/pPQ+4z8IKYGJGub+BT4GPLBwvCio7f6QeWfQ13TxgA7ATGPKUG7IyG6xOOj3nxDcFWAl0A/da2sdAL/AJcD6kwAc6bop6gT1kWzUZ6LKb6CbDqrx9dB535704S8BZ1o2zdEpSZ1HQ3MRddtmdp8kQzuKa9d8VBSUl9lEh0Pjro6ZKy00TERRBERRBLQZaCpxh9FHFUqBKiiJZ+n5gFfBHnrsKgUKb7t/j/PCwBNZwapKW1yGp3/KPSDrjKVsalIT0W3ypwZoGSoPU8pY2E/RCCqSiwJ55GdBVBusIlCu0Xpf3Na1guZbb1mnYJwtZtKmALm/Z6EBGUARFUASNV1A70AMcBP60aw9F93ADPkO7pD3mDwxKesOusvT2QP3czkmPKd2YUNpucVl+LlBo4jsITAduAIbrmnMAOAncnqflQn10M26JebgufdjSb8oDyQM6hlv3ru/4dkv/vFmgd4EZwPoErN3iM4BdeUGNjDpJqsrtmzc86mqwHkkH5X4t7JD0tEFyw3INzYwwuwisEVA9bPe/CarBdocsip5qBEVQBP3fQRWyX4jOCpUsZS2xhR2SQdwixq3A2lDhMkcTa7Ie2G6fwzfsmax8clrSJCu3py4vVV/ZphsALtjnFXkqtNwyWlLqR1Ub7obPA5OyKjXLolk+SFmQgEN18eD/PLXEI2j8gYqspwbrRE81giIogiKohUAdzQB1APdk5C3Ends6CXwLbAReBm7J1OZxINdKGpb0VEpeb4pT+aWkx8os0SxJKHlf0iOSOiXNkHQpBbRT0oQyoA5JH6YoPJ6SJknPeHR5+6gTWJ2SPjej/BceXV7QV8AHvsoJucTlvt5o8ZkraZa1fUheD+gJfo9+Bq4JlPkNt4Xgl9CdSJos6UlJF1IsOSvp/hw6vL8mFgCLgCXA44w+730IeIiM89314gP9ACzHHXD9xdIO49476gO2MfJjLCjRgYygCIqgCGqiFFl0WoM7j78ImA8cBQ7gzuaHp/wck1anpO2BqXy7lSu9I9YJ9APXWfycxfuBa4HbzDpwc9ZC4FQZi2qWXJK0WdI0ue3SuRp5P/lRSb8nLCvsQK5JNM2zkiZKeknSkKVdlPSmlX0gUXZNUdAWq3hY7tzj83K++FuS9icU32Hl91p8S1FQn1V8VVKb3Mrw25a3MgHabGkvWrwvTZ/ve7TArqeBq3H+3f66PIBf7VrzkuaTIj7Qj3ZdDJwF9jLy5wJdiXK1t+NrZxuOFgV9bddVwBPAN8ARS5tp15PAZxa/29IOpGrz9FG3Rsscy+uS9IqkBXLD/Z1GRl1yQEjuHANy7vFaSdMlrZa0K1Gm1PcISTMlDZiSbZa2I8VSSTolz2Mo9PQeBO7CvTE1iDtRc2dKuffwPX4CfVQfrpf0sKRjks5Zs27J6pP6EH3vCBp70D8db2VXFPfIagAAAABJRU5ErkJggg==)}.leaflet-oldie .mapbox-logo-true{background-image:none} \ No newline at end of file diff --git a/gui-src/css/styles.css b/gui-src/css/styles.css new file mode 100644 index 0000000..f951cb4 --- /dev/null +++ b/gui-src/css/styles.css @@ -0,0 +1,241 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + color: #0f0f0f; + background-color: #f6f6f6; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +p { + color: #ececec; +} + +.container { + margin: 0; + padding-top: 1vh; + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: 0.75s; +} + +.logo.arnis:hover { + filter: drop-shadow(0 0 2em #b3b3b3); +} + +.row { + display: flex; + justify-content: center; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} + +a:hover { + color: #535bf2; +} + +.flex-container { + display: flex; + gap: 20px; + justify-content: center; + align-items: stretch; /* Ensures both sections take full height */ + margin-top: 5px; +} + +.section { + background: #575757; + padding: 20px; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +.map-box, +.controls-box { + width: 45%; + background: #575757; + padding: 20px; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + /* No display: flex here, so buttons and content aren't stretched */ +} + +.controls-content { + display: flex; + flex-direction: column; + height: 100%; +} + +.controls-box .progress-section { + margin-top: auto; /* Keeps the progress section at the bottom */ +} + +.map-container { + border: 2px solid #e0e0e0; + border-radius: 8px; +} + +.section h2 { + margin-top: 0; + margin-bottom: 10px; +} + +p { + color: #d6d6d6; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + color: #0f0f0f; + background-color: #ffffff; + cursor: pointer; + transition: border-color 0.25s; + box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); + margin-top: 10px; + width: auto; /* Ensures buttons don’t stretch */ +} + +button:hover { + border-color: #396cd8; +} + +#selected-directory { + font-size: 1em; + margin-top: 6px; +} + +.progress-section { + margin-top: auto; +} + +.progress-section h2 { + margin-bottom: 8px; + text-align: center; +} + +.progress-bar-container { + width: 100%; + height: 20px; + background-color: #e0e0e0; + border-radius: 10px; + overflow: hidden; + margin-top: 8px; +} + +.progress-bar { + height: 100%; + width: 0%; + background-color: #4caf50; + transition: width 0.4s; +} + +/* Left and right alignment for "Saving world..." text */ +.progress-status { + display: flex; + justify-content: space-between; + font-size: 0.9em; + margin-top: 8px; + color: #fff; +} + +.footer { + margin-top: 20px; + text-align: center; + font-size: 0.9em; +} + +.footer-link { + color: #ffffff; + text-decoration: none; +} + +.footer-link:hover { + color: #b3b3b3; +} + +@media (prefers-color-scheme: dark) { + :root { + color: #f6f6f6; + background-color: #2f2f2f; + } + + p { + color: #ececec; + } + + input, + button { + color: #ffffff; + background-color: #0f0f0f98; + } + button:active { + background-color: #0f0f0f69; + } +} + +.tooltip { + position: relative; + display: block; + width: 100%; +} + +.tooltip button { + width: 100%; +} + +.tooltip .tooltiptext { + visibility: hidden; + width: 90%; + background-color: #808080; + color: #fff; + text-align: center; + padding: 5px 0; + border-radius: 6px; + + position: absolute; + z-index: 1; + bottom: -100%; + left: 5%; + opacity: 0; + transition: opacity 0.3s; +} + +.tooltip .tooltiptext::after { + content: ""; + position: absolute; + top: -10px; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent transparent #808080 transparent; +} + +.tooltip:hover .tooltiptext { + visibility: visible; + opacity: 1; +} + +.controls-box button { + width: 100%; +} \ No newline at end of file diff --git a/gui-src/images/crosshair.png b/gui-src/images/crosshair.png new file mode 100644 index 0000000..5d873d1 Binary files /dev/null and b/gui-src/images/crosshair.png differ diff --git a/gui-src/images/logo.png b/gui-src/images/logo.png new file mode 100644 index 0000000..2541290 Binary files /dev/null and b/gui-src/images/logo.png differ diff --git a/gui-src/images/tile.png b/gui-src/images/tile.png new file mode 100644 index 0000000..ff1bcb4 Binary files /dev/null and b/gui-src/images/tile.png differ diff --git a/gui-src/index.html b/gui-src/index.html new file mode 100644 index 0000000..018ac4d --- /dev/null +++ b/gui-src/index.html @@ -0,0 +1,80 @@ + + + + + + + + Arnis + + + + +
+
+ + + +
+ +
+ +
+

Select Location

+ + Zoom in and choose your area using the rectangle tool + + + + +
+ + +
+
+

Select World

+ + +
+ + + Please select a Minecraft world that can be overwritten, as the generation process will replace existing structures in the chosen world! + +
+ +
+ + +

+ +
+

Progress

+
+
+
+
+ + 0% +
+
+
+
+
+ + + +
+ + + \ No newline at end of file diff --git a/gui-src/js/bbox.js b/gui-src/js/bbox.js new file mode 100644 index 0000000..c749056 --- /dev/null +++ b/gui-src/js/bbox.js @@ -0,0 +1,657 @@ +var map, rsidebar, lsidebar, drawControl, drawnItems = null; + +// Where we keep the big list of proj defs from the server +var proj4defs = null; +// Where we keep the proj objects we are using in this session +var projdefs = { "4326": L.CRS.EPSG4326, "3857": L.CRS.EPSG3857 }; +var currentproj = "3857"; +var currentmouse = L.latLng(0, 0); + +/* +** +** override L.Rectangle +** to fire an event after setting +** +** the base parent object L.Path +** includes the L.Mixin.Events +** +** ensures bbox box is always +** the topmost SVG feature +** +*/ +L.Rectangle.prototype.setBounds = function (latLngBounds) { + + this.setLatLngs(this._boundsToLatLngs(latLngBounds)); + this.fire('bounds-set'); +} + + +var FormatSniffer = (function () { // execute immediately + + 'use strict'; + + /* + ** + ** constructor + ** + */ + var FormatSniffer = function (options) { + + options || (options = {}); + + if (!this || !(this instanceof FormatSniffer)) { + return new FormatSniffer(options); + } + + + this.regExes = { + ogrinfoExtent: /Extent\:\s\((.*)\)/, + bbox: /^\(([\s|\-|0-9]*\.[0-9]*,[\s|\-|0-9]*\.[0-9]*,[\s|\-|0-9]*\.[0-9]*,[\s|\-|0-9]*\.[0-9|\s]*)\)$/ + }; + this.data = options.data || ""; + this.parse_type = null; + }; + + /* + ** + ** functions + ** + */ + FormatSniffer.prototype.sniff = function () { + return this._sniffFormat(); + }; + + FormatSniffer.prototype._is_ogrinfo = function () { + var match = this.regExes.ogrinfoExtent.exec(this.data.trim()); + var extent = []; + if (match) { + var pairs = match[1].split(") - ("); + for (var indx = 0; indx < pairs.length; indx++) { + var coords = pairs[indx].trim().split(","); + extent = (extent.concat([parseFloat(coords[0].trim()), parseFloat(coords[1].trim())])); + } + } + this.parse_type = "ogrinfo"; + return extent; + }; + + FormatSniffer.prototype._is_normal_bbox = function () { + var match = this.regExes.bbox.exec(this.data.trim()); + var extent = []; + if (match) { + var bbox = match[1].split(","); + for (var indx = 0; indx < bbox.length; indx++) { + var coord = bbox[indx].trim(); + extent = (extent.concat([parseFloat(coord)])); + } + } + this.parse_type = "bbox"; + return extent; + }; + + FormatSniffer.prototype._is_geojson = function () { + try { + // try JSON + var json = JSON.parse(this.data); + + // try GeoJSON + var parsed_data = new L.geoJson(json) + + } catch (err) { + + return null; + + } + + this.parse_type = "geojson"; + return parsed_data; + }; + + FormatSniffer.prototype._is_wkt = function () { + if (this.data === "") { + throw new Error("empty -- nothing to parse"); + } + + try { + var parsed_data = new Wkt.Wkt(this.data); + } catch (err) { + return null; + } + + this.parse_type = "wkt"; + return parsed_data; + }; + + FormatSniffer.prototype._sniffFormat = function () { + + var parsed_data = null; + var fail = false; + try { + var next = true; + + // try ogrinfo + parsed_data = this._is_ogrinfo() + if (parsed_data.length > 0) { + next = false; + } + + // try normal bbox + if (next) { + parsed_data = this._is_normal_bbox(); + if (parsed_data.length > 0) next = false; + } + + // try GeoJSON + if (next) { + parsed_data = this._is_geojson(); + if (parsed_data) next = false; + } + + // try WKT + if (next) { + parsed_data = this._is_wkt(); + if (parsed_data) next = false; + } + + // no matches, throw error + if (next) { + fail = true; + /* + ** sorry, this block needs to be left aligned + ** to make the alert more readable + ** which means, we probably shouldn't use alerts ;-) + */ + throw { + "name": "NoTypeMatchError", + "message": "The data is not a recognized format:\n \ +1. ogrinfo extent output\n \ +2. bbox as (xMin,yMin,xMax,yMax )\n \ +3. GeoJSON\n \ +4. WKT\n\n " + } + } + + + } catch (err) { + + alert("Your paste is not parsable:\n" + err.message); + fail = true; + + } + + // delegate to format handler + if (!fail) { + + this._formatHandler[this.parse_type].call(this._formatHandler, parsed_data); + + } + + return (fail ? false : true); + }; + + + /* + ** an object with functions as property names. + ** if we need to add another format + ** we can do so here as a property name + ** to enforce reusability + ** + ** to add different formats as L.FeatureGroup layer + ** so they work with L.Draw edit and delete options + ** we fake passing event information + ** and triggering draw:created for L.Draw + */ + FormatSniffer.prototype._formatHandler = { + + + // coerce event objects to work with L.Draw types + coerce: function (lyr, type_obj) { + + var event_obj = { + layer: lyr, + layerType: null, + } + + // coerce to L.Draw types + if (/point/i.test(type_obj)) { + event_obj.layerType = "marker"; + } + else if (/linestring/i.test(type_obj)) { + event_obj.layerType = "polyline"; + } + else if (/polygon/i.test(type_obj)) { + event_obj.layerType = "polygon"; + } + + return event_obj; + + }, + + reduce_layers: function (lyr) { + var lyr_parts = []; + if (typeof lyr['getLayers'] === 'undefined') { + return [lyr]; + } + else { + var all_layers = lyr.getLayers(); + for (var i = 0; i < all_layers.length; i++) { + lyr_parts = lyr_parts.concat(this.reduce_layers(all_layers[i])); + } + } + return lyr_parts; + }, + + get_leaflet_bounds: function (data) { + /* + ** data comes in an extent ( xMin,yMin,xMax,yMax ) + ** we need to swap lat/lng positions + ** because leaflet likes it hard + */ + var sw = [data[1], data[0]]; + var ne = [data[3], data[2]]; + return new L.LatLngBounds(sw, ne); + }, + + wkt: function (data) { + var wkt_layer = data.construct[data.type].call(data); + var all_layers = this.reduce_layers(wkt_layer); + for (var indx = 0; indx < all_layers.length; indx++) { + var lyr = all_layers[indx]; + var evt = this.coerce(lyr, data.type); + + // call L.Draw.Feature.prototype._fireCreatedEvent + map.fire('draw:created', evt); + } + + }, + + geojson: function (geojson_layer) { + var all_layers = this.reduce_layers(geojson_layer); + for (var indx = 0; indx < all_layers.length; indx++) { + var lyr = all_layers[indx]; + + var geom_type = geojson_layer.getLayers()[0].feature.geometry.type; + var evt = this.coerce(lyr, geom_type); + + // call L.Draw.Feature.prototype._fireCreatedEvent + map.fire('draw:created', evt); + } + }, + + ogrinfo: function (data) { + var lBounds = this.get_leaflet_bounds(data); + // create a rectangle layer + var lyr = new L.Rectangle(lBounds); + var evt = this.coerce(lyr, 'polygon'); + + // call L.Draw.Feature.prototype._fireCreatedEvent + map.fire('draw:created', evt); + }, + + bbox: function (data) { + var lBounds = this.get_leaflet_bounds(data); + // create a rectangle layer + var lyr = new L.Rectangle(lBounds); + var evt = this.coerce(lyr, 'polygon'); + + // call L.Draw.Feature.prototype._fireCreatedEvent + map.fire('draw:created', evt); + } + }; + + return FormatSniffer; // return class def + +})(); // end FormatSniffer + + +function addLayer(layer, name, title, zIndex, on) { + if (on) { + layer.setZIndex(zIndex).addTo(map); + } else { + layer.setZIndex(zIndex); + } + // Create a simple layer switcher that toggles layers on and off. + var ui = document.getElementById('map-ui'); + var item = document.createElement('li'); + var link = document.createElement('a'); + link.href = '#'; + if (on) { + link.className = 'enabled'; + } else { + link.className = ''; + } + link.innerHTML = name; + link.title = title; + link.onclick = function(e) { + e.preventDefault(); + e.stopPropagation(); + + if (map.hasLayer(layer)) { + map.removeLayer(layer); + this.className = ''; + } else { + map.addLayer(layer); + this.className = 'enabled'; + } + }; + item.appendChild(link); + ui.appendChild(item); +}; + +function formatBounds(bounds, proj) { + var gdal = $("input[name='gdal-checkbox']").prop('checked'); + var lngLat = $("input[name='coord-order']").prop('checked'); + + var formattedBounds = ''; + var southwest = bounds.getSouthWest(); + var northeast = bounds.getNorthEast(); + var xmin = 0; + var ymin = 0; + var xmax = 0; + var ymax = 0; + if (proj == '4326') { + xmin = southwest.lng.toFixed(6); + ymin = southwest.lat.toFixed(6); + xmax = northeast.lng.toFixed(6); + ymax = northeast.lat.toFixed(6); + } else { + var proj_to_use = null; + if (typeof (projdefs[proj]) !== 'undefined') { + // we have it already, then grab it and use it... + proj_to_use = projdefs[proj]; + } else { + // We have not used this one yet... make it and store it... + projdefs[proj] = new L.Proj.CRS(proj, proj4defs[proj][1]); + proj_to_use = projdefs[proj]; + } + southwest = proj_to_use.project(southwest) + northeast = proj_to_use.project(northeast) + xmin = southwest.x.toFixed(4); + ymin = southwest.y.toFixed(4); + xmax = northeast.x.toFixed(4); + ymax = northeast.y.toFixed(4); + } + + if (gdal) { + if (lngLat) { + formattedBounds = xmin + ',' + ymin + ',' + xmax + ',' + ymax; + } else { + formattedBounds = ymin + ',' + xmin + ',' + ymax + ',' + xmax; + } + } else { + if (lngLat) { + formattedBounds = xmin + ' ' + ymin + ' ' + xmax + ' ' + ymax; + } else { + formattedBounds = ymin + ' ' + xmin + ' ' + ymax + ' ' + xmax; + } + } + return formattedBounds +} + +function formatTile(point, zoom) { + var xTile = Math.floor((point.lng + 180) / 360 * Math.pow(2, zoom)); + var yTile = Math.floor((1 - Math.log(Math.tan(point.lat * Math.PI / 180) + 1 / Math.cos(point.lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)); + return xTile.toString() + ',' + yTile.toString(); +} + +function formatPoint(point, proj) { + var gdal = $("input[name='gdal-checkbox']").prop('checked'); + var lngLat = $("input[name='coord-order']").prop('checked'); + + var formattedPoint = ''; + if (proj == '4326') { + x = point.lng.toFixed(6); + y = point.lat.toFixed(6); + } else { + var proj_to_use = null; + if (typeof (projdefs[proj]) !== 'undefined') { + // we have it already, then grab it and use it... + proj_to_use = projdefs[proj]; + } else { + // We have not used this one yet... make it and store it... + projdefs[proj] = new L.Proj.CRS(proj, proj4defs[proj][1]); + proj_to_use = projdefs[proj]; + } + point = proj_to_use.project(point) + x = point.x.toFixed(4); + y = point.y.toFixed(4); + } + if (gdal) { + if (lngLat) { + formattedBounds = x + ',' + y; + } else { + formattedBounds = y + ',' + x; + } + } else { + if (lngLat) { + formattedBounds = x + ' ' + y; + } else { + formattedBounds = y + ' ' + x; + } + } + return formattedBounds +} + +function validateStringAsBounds(bounds) { + var splitBounds = bounds ? bounds.split(',') : null; + return ((splitBounds !== null) && + (splitBounds.length == 4) && + ((-90.0 <= parseFloat(splitBounds[0]) <= 90.0) && + (-180.0 <= parseFloat(splitBounds[1]) <= 180.0) && + (-90.0 <= parseFloat(splitBounds[2]) <= 90.0) && + (-180.0 <= parseFloat(splitBounds[3]) <= 180.0)) && + (parseFloat(splitBounds[0]) < parseFloat(splitBounds[2]) && + parseFloat(splitBounds[1]) < parseFloat(splitBounds[3]))) +} + +$(document).ready(function () { + /* + ** + ** make sure all textarea inputs + ** are selected once they are clicked + ** because some people might not + ** have flash enabled or installed + ** and yes... + ** there's a fucking Flash movie floating + ** on top of your DOM + ** + */ + $('input[type="textarea"]').on('click', function (evt) { this.select() }); + + // Have to init the projection input box as it is used to format the initial values + $("#projection").val(currentproj); + + L.mapbox.accessToken = 'pk.eyJ1IjoiY3Vnb3MiLCJhIjoiY2p4Nm43MzA3MDFmZDQwcGxsMjB4Z3hnNiJ9.SQbnMASwdqZe6G4n6OMvVw'; + map = L.mapbox.map('map').setView([50.114768, 8.687322], 4).addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/streets-v11')); + + rsidebar = L.control.sidebar('rsidebar', { + position: 'right', + closeButton: true + }); + rsidebar.on("sidebar-show", function (e) { + $("#map .leaflet-tile-loaded").addClass("blurred"); + }); + rsidebar.on("sidebar-hide", function (e) { + $('#map .leaflet-tile-loaded').removeClass('blurred'); + $('#map .leaflet-tile-loaded').addClass('unblurred'); + setTimeout(function () { + $('#map .leaflet-tile-loaded').removeClass('unblurred'); + }, 7000); + }); + + map.addControl(rsidebar); + + lsidebar = L.control.sidebar('lsidebar', { + position: 'left' + }); + + map.addControl(lsidebar); + + // Add in a crosshair for the map + var crosshairIcon = L.icon({ + iconUrl: 'images/crosshair.png', + iconSize: [20, 20], // size of the icon + iconAnchor: [10, 10], // point of the icon which will correspond to marker's location + }); + crosshair = new L.marker(map.getCenter(), { icon: crosshairIcon, clickable: false }); + crosshair.addTo(map); + + // Initialize the FeatureGroup to store editable layers + drawnItems = new L.FeatureGroup(); + map.addLayer(drawnItems); + + // Initialize the draw control and pass it the FeatureGroup of editable layers + drawControl = new L.Control.Draw({ + edit: { + featureGroup: drawnItems + }, + draw: { + polyline: false, + polygon: false, + circle: false, + marker: false + } + }); + map.addControl(drawControl); + + /* + ** + ** create bounds layer + ** and default it at first + ** to draw on null island + ** so it's not seen onload + ** + */ + startBounds = new L.LatLngBounds([0.0, 0.0], [0.0, 0.0]); + var bounds = new L.Rectangle(startBounds, + { + fill: false, + opacity: 1.0, + color: '#000' + } + ); + bounds.on('bounds-set', function (e) { + // move it to the end of the parent + var parent = e.target._renderer._container.parentElement; + $(parent).append(e.target._renderer._container); + // Set the hash + var southwest = this.getBounds().getSouthWest(); + var northeast = this.getBounds().getNorthEast(); + var xmin = southwest.lng.toFixed(6); + var ymin = southwest.lat.toFixed(6); + var xmax = northeast.lng.toFixed(6); + var ymax = northeast.lat.toFixed(6); + location.hash = ymin + ',' + xmin + ',' + ymax + ',' + xmax; + }); + map.addLayer(bounds) + map.on('draw:created', function (e) { + drawnItems.addLayer(e.layer); + bounds.setBounds(drawnItems.getBounds()) + $('#boxbounds').text(formatBounds(bounds.getBounds(), '4326')); + $('#boxboundsmerc').text(formatBounds(bounds.getBounds(), currentproj)); + notifyBboxUpdate(); + if (!e.geojson && + !((drawnItems.getLayers().length == 1) && (drawnItems.getLayers()[0] instanceof L.Marker))) { + map.fitBounds(bounds.getBounds()); + } else { + if ((drawnItems.getLayers().length == 1) && (drawnItems.getLayers()[0] instanceof L.Marker)) { + map.panTo(drawnItems.getLayers()[0].getLatLng()); + } + } + }); + + map.on('draw:deleted', function (e) { + e.layers.eachLayer(function (l) { + drawnItems.removeLayer(l); + }); + if (drawnItems.getLayers().length > 0 && + !((drawnItems.getLayers().length == 1) && (drawnItems.getLayers()[0] instanceof L.Marker))) { + bounds.setBounds(drawnItems.getBounds()) + $('#boxbounds').text(formatBounds(bounds.getBounds(), '4326')); + $('#boxboundsmerc').text(formatBounds(bounds.getBounds(), currentproj)); + notifyBboxUpdate(); + map.fitBounds(bounds.getBounds()); + } else { + bounds.setBounds(new L.LatLngBounds([0.0, 0.0], [0.0, 0.0])); + $('#boxbounds').text(formatBounds(bounds.getBounds(), '4326')); + $('#boxboundsmerc').text(formatBounds(bounds.getBounds(), currentproj)); + notifyBboxUpdate(); + if (drawnItems.getLayers().length == 1) { + map.panTo(drawnItems.getLayers()[0].getLatLng()); + } + } + }); + + map.on('draw:edited', function (e) { + bounds.setBounds(drawnItems.getBounds()) + $('#boxbounds').text(formatBounds(bounds.getBounds(), '4326')); + $('#boxboundsmerc').text(formatBounds(bounds.getBounds(), currentproj)); + notifyBboxUpdate(); + map.fitBounds(bounds.getBounds()); + }); + + function display() { + $('#boxbounds').text(formatBounds(bounds.getBounds(), '4326')); + $('#boxboundsmerc').text(formatBounds(bounds.getBounds(), currentproj)); + notifyBboxUpdate(); + } + display(); + + map.on('move', function (e) { + crosshair.setLatLng(map.getCenter()); + }); + + // handle geolocation click events + $('#geolocation').click(function () { + map.locate({ setView: true, maxZoom: 8 }); + $('#geolocation a').toggleClass('active'); + $('#geolocation a').toggleClass('active', 350); + }); + + + + $('button#add').on('click', function (evt) { + var sniffer = FormatSniffer({ data: $('div#rsidebar textarea').val() }); + var is_valid = sniffer.sniff(); + if (is_valid) { + rsidebar.hide(); + $('#create-geojson a').toggleClass('enabled'); + map.fitBounds(bounds.getBounds()); + } + }); + $('button#clear').on('click', function (evt) { + $('div#rsidebar textarea').val(''); + }); + + var initialBBox = location.hash ? location.hash.replace(/^#/, '') : null; + if (initialBBox) { + if (validateStringAsBounds(initialBBox)) { + var splitBounds = initialBBox.split(','); + startBounds = new L.LatLngBounds([splitBounds[0], splitBounds[1]], + [splitBounds[2], splitBounds[3]]); + var lyr = new L.Rectangle(startBounds); + var evt = { + layer: lyr, + layerType: "polygon", + } + map.fire('draw:created', evt); + //map.fitBounds(bounds.getBounds()); + } else { + // This will reset the hash if the original hash was not valid + bounds.setBounds(bounds.getBounds()); + } + } else { + // Initially set the hash if there was not one set by the user + bounds.setBounds(bounds.getBounds()); + } + + $("input").click(function (e) { + display(); + }); + +}); + +function notifyBboxUpdate() { + const bboxText = document.getElementById('boxbounds').textContent; + window.parent.postMessage({ bboxText: bboxText }, '*'); +} diff --git a/gui-src/js/libs/jquery-1.9.1.js b/gui-src/js/libs/jquery-1.9.1.js new file mode 100644 index 0000000..e2c203f --- /dev/null +++ b/gui-src/js/libs/jquery-1.9.1.js @@ -0,0 +1,9597 @@ +/*! + * jQuery JavaScript Library v1.9.1 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-2-4 + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<9 + // For `typeof node.method` instead of `node.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + location = window.location, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.9.1", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( list && ( !fired || stack ) ) { + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function() { + + var support, all, a, + input, select, fragment, + opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
a"; + + // Support tests won't run in some limited or non-browser environments + all = div.getElementsByTagName("*"); + a = div.getElementsByTagName("a")[ 0 ]; + if ( !all || !a || !all.length ) { + return {}; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + support = { + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.5/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + checkOn: !!input.value, + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Tests for enctype support on a form (#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode + boxModel: document.compatMode === "CSS1Compat", + + // Will be defined later + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + boxSizingReliable: true, + pixelPosition: false + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
t
"; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + support.boxSizing = ( div.offsetWidth === 4 ); + support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})(); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var i, l, thisCache, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( !name.indexOf( "data-" ) ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + // Try to fetch any internally stored data first + return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + } + + this.each(function() { + jQuery.data( this, key, value ); + }); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + hooks.cur = fn; + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val, + self = jQuery(this); + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, notxml, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + // In IE9+, Flash objects don't have .getAttribute (#12945) + // Support: IE9+ + if ( typeof elem.getAttribute !== core_strundefined ) { + ret = elem.getAttribute( name ); + } + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( rboolean.test( name ) ) { + // Set corresponding property to false for boolean attributes + // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8 + if ( !getSetAttribute && ruseDefault.test( name ) ) { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } else { + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + var + // Use .prop to determine if this attribute is understood as boolean + prop = jQuery.prop( elem, name ), + + // Fetch it accordingly + attr = typeof prop === "boolean" && elem.getAttribute( name ), + detail = typeof prop === "boolean" ? + + getSetInput && getSetAttribute ? + attr != null : + // oldIE fabricates an empty string for missing boolean attributes + // and conflates checked/selected into attroperties + ruseDefault.test( name ) ? + elem[ jQuery.camelCase( "default-" + name ) ] : + !!attr : + + // fetch an attribute node for properties not recognized as boolean + elem.getAttributeNode( name ); + + return detail && detail.value !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; + +// fix oldIE value attroperty +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return jQuery.nodeName( elem, "input" ) ? + + // Ignore the value *property* by using defaultValue + elem.defaultValue : + + ret && ret.specified ? ret.value : undefined; + }, + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ? + ret.value : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret == null ? undefined : ret; + } + }); + }); + + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + event.isTrigger = true; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + for ( ; cur != this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + } + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== document.activeElement && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === document.activeElement && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +(function( window, undefined ) { + +var i, + cachedruns, + Expr, + getText, + isXML, + compile, + hasDuplicate, + outermostContext, + + // Local document vars + setDocument, + document, + docElem, + documentIsXML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + sortOrder, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + support = {}, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Array methods + arr = [], + pop = arr.pop, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rsibling = /[\x20\t\r\n\f]*[+~]/, + + rnative = /^[^{]+\{\s*\[native code/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g, + funescape = function( _, escaped ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + return high !== high ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Use a stripped-down slice if we can't use a native one +try { + slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, + results = []; + while ( (elem = this[i++]) ) { + results.push( elem ); + } + return results; + }; +} + +/** + * For feature detection + * @param {Function} fn The function to test for native support + */ +function isNative( fn ) { + return rnative.test( fn + "" ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var cache, + keys = []; + + return (cache = function( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + }); +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return fn( div ); + } catch (e) { + return false; + } finally { + // release memory in IE + div = null; + } +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( !documentIsXML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + + // QSA path + if ( support.qsa && !rbuggyQSA.test(selector) ) { + old = true; + nid = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, slice.call( newContext.querySelectorAll( + newSelector + ), 0 ) ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsXML = isXML( doc ); + + // Check if getElementsByTagName("*") returns only elements + support.tagNameNoComments = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if attributes should be retrieved by attribute nodes + support.attributes = assert(function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }); + + // Check if getElementsByClassName can be trusted + support.getByClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length === 2; + }); + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + support.getByName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = doc.getElementsByName && + // buggy browsers will return fewer than the correct 2 + doc.getElementsByName( expando ).length === 2 + + // buggy browsers will return more than the correct 0 + doc.getElementsByName( expando + 0 ).length; + support.getIdNotName = !doc.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }); + + // IE6/7 return modified attributes + Expr.attrHandle = assert(function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }) ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }; + + // ID find and filter + if ( support.getIdNotName ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.tagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Name + Expr.find["NAME"] = support.getByName && function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }; + + // Class + Expr.find["CLASS"] = support.getByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) { + return context.getElementsByClassName( className ); + } + }; + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21), + // no need to also add to buggyMatches since matches checks buggyQSA + // A support test would require too much code (would include document ready) + rbuggyQSA = [ ":focus" ]; + + if ( (support.qsa = isNative(doc.querySelectorAll)) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE8 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = ""; + if ( div.querySelectorAll("[i^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = new RegExp( rbuggyMatches.join("|") ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = isNative(docElem.contains) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + var compare; + + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) { + if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) { + if ( a === doc || contains( preferredDoc, a ) ) { + return -1; + } + if ( b === doc || contains( preferredDoc, b ) ) { + return 1; + } + return 0; + } + return compare & 4 ? -1 : 1; + } + + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + // Always assume the presence of duplicates if sort doesn't + // pass them to our comparison function (as in Google Chrome). + hasDuplicate = false; + [0, 0].sort( sortOrder ); + support.detectDuplicates = hasDuplicate; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyQSA always contains :focus, so no need for an existence check + if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + var val; + + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + if ( !documentIsXML ) { + name = name.toLowerCase(); + } + if ( (val = Expr.attrHandle[ name ]) ) { + return val( elem ); + } + if ( documentIsXML || support.attributes ) { + return elem.getAttribute( name ); + } + return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ? + name : + val && val.specified ? val.value : null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + i = 1, + j = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +// Returns a function to use in pseudos for input types +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +// Returns a function to use in pseudos for buttons +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +// Returns a function to use in pseudos for positionals +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[4] ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + + nodeName = nodeName.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifider + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsXML ? + elem.getAttribute("xml:lang") || elem.getAttribute("lang") : + elem.lang) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push( { + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && !documentIsXML && + Expr.relative[ tokens[1].type ] ) { + + context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, slice.call( seed, 0 ) ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + documentIsXML, + results, + rsibling.test( selector ) + ); + return results; +} + +// Deprecated +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Easy API for creating new setFilters +function setFilters() {} +Expr.filters = setFilters.prototype = Expr.pseudos; +Expr.setFilters = new setFilters(); + +// Initialize with the default document +setDocument(); + +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + isSimple = /^.[^:#\[\.,]*$/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, ret, self, + len = this.length; + + if ( typeof selector !== "string" ) { + self = this; + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + ret = []; + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, this[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = ( this.selector ? this.selector + " " : "" ) + selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true) ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + rneedsContext.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + cur = this[i]; + + while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + } + cur = cur.parentNode; + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +jQuery.fn.andSelf = jQuery.fn.addBack; + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( this.length > 1 && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function( value ) { + var isFunc = jQuery.isFunction( value ); + + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( !isFunc && typeof value !== "string" ) { + value = jQuery( value ).not( this ).detach(); + } + + return this.domManip( [ value ], true, function( elem ) { + var next = this.nextSibling, + parent = this.parentNode; + + if ( parent ) { + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + }); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, table ? self.html() : undefined ); + } + self.domManip( args, table, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( + table && jQuery.nodeName( this[i], "table" ) ? + findOrAppend( this[i], "tbody" ) : + this[i], + node, + i + ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery.ajax({ + url: node.src, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +function findOrAppend( elem, tag ) { + return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + var attr = elem.getAttributeNode("type"); + elem.type = ( attr && attr.specified ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + var bool = typeof state === "boolean"; + + return this.each(function() { + if ( bool ? state : isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("'.replace("{{embed}}",e.embed||window.location),u="Copy and paste this HTML code into documents to embed this map on web pages."; +L.DomUtil.addClass(this._modal,"active"),this._sharing=this._map._createPane("mapbox-modal-body",this._content),this._sharing.innerHTML=l;var h=L.DomUtil.create("input","mapbox-embed",this._sharing);h.type="text",h.value=c;var p=L.DomUtil.create("label","mapbox-embed-description",this._sharing);p.innerHTML=u;var f=L.DomUtil.create("a","leaflet-popup-close-button",this._sharing);f.href="#",L.DomEvent.disableClickPropagation(this._sharing),L.DomEvent.addListener(f,"click",this._clickOut,this),L.DomEvent.addListener(h,"click",function(t){t.target.focus(),t.target.select()})}});e.exports=function(t,e){return new i(t,e)}},{"./load_tilejson":16,"./url":23}],22:[function(t,e){"use strict";var n=t("./util"),i=(t("./url"),L.TileLayer.extend({includes:[t("./load_tilejson")],options:{format:"png"},formats:["png","png32","png64","png128","png256","jpg70","jpg80","jpg90"],scalePrefix:"@2x.",initialize:function(t,e){L.TileLayer.prototype.initialize.call(this,void 0,e),this._tilejson={},e&&e.detectRetina&&L.Browser.retina&&e.retinaVersion&&(t=e.retinaVersion),e&&e.format&&n.strict_oneof(e.format,this.formats),this._loadTileJSON(t)},setFormat:function(t){return n.strict(t,"string"),this.options.format=t,this.redraw(),this},_autoScale:function(){return this.options&&L.Browser.retina&&this.options.detectRetina&&!this.options.retinaVersion&&this.options.autoscale},setUrl:null,_setTileJSON:function(t){return n.strict(t,"object"),L.extend(this.options,{tiles:t.tiles,attribution:t.attribution,minZoom:t.minzoom,maxZoom:t.maxzoom,autoscale:t.autoscale||!1,tms:"tms"===t.scheme,bounds:t.bounds&&n.lbounds(t.bounds)}),this._tilejson=t,this.redraw(),this},getTileJSON:function(){return this._tilejson},getTileUrl:function(t){var e=this.options.tiles,n=Math.floor(Math.abs(t.x+t.y)%e.length),i=e[n],o=L.Util.template(i,t);return o?o.replace(".png",(this._autoScale()?this.scalePrefix:".")+this.options.format):o},_update:function(){this.options.tiles&&L.TileLayer.prototype._update.call(this)}}));e.exports=function(t,e){return new i(t,e)}},{"./load_tilejson":16,"./url":23,"./util":24}],23:[function(t,e){"use strict";var n=t("./config");e.exports={isSSL:function(){return"https:"===document.location.protocol||n.FORCE_HTTPS},base:function(t){var e=this.isSSL()?n.HTTPS_URLS:n.HTTP_URLS;return void 0===t||"number"!=typeof t?e[0]:e[t%e.length]},secureFlag:function(t){return this.isSSL()?t.match(/(\?|&)secure/)?t:-1!==t.indexOf("?")?t+"&secure":t+"?secure":t},jsonify:function(t){return t.replace(/\.(geo)?jsonp(?=$|\?)/,".$1json")}}},{"./config":8}],24:[function(t,e){"use strict";e.exports={idUrl:function(t,e){-1==t.indexOf("/")?e.loadID(t):e.loadURL(t)},log:function(t){console&&"function"==typeof console.error&&console.error(t)},strict:function(t,e){if(typeof t!==e)throw new Error("Invalid argument: "+e+" expected")},strict_instance:function(t,e,n){if(!(t instanceof e))throw new Error("Invalid argument: "+n+" expected")},strict_oneof:function(t,e){if(-1==e.indexOf(t))throw new Error("Invalid argument: "+t+" given, valid values are "+e.join(", "))},strip_tags:function(t){return t.replace(/<[^<]+>/g,"")},lbounds:function(t){return new L.LatLngBounds([[t[1],t[0]],[t[3],t[2]]])}}},{}]},{},[1]); \ No newline at end of file diff --git a/gui-src/js/maps/mapbox.v3.2.0.js b/gui-src/js/maps/mapbox.v3.2.0.js new file mode 100644 index 0000000..e9838a8 --- /dev/null +++ b/gui-src/js/maps/mapbox.v3.2.0.js @@ -0,0 +1,66 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i=200&&n<300||304===n}function e(){void 0===r.status||i(r.status)?t.call(r,null,r):t.call(r,r,null)}var l=!1;if(void 0===window.XMLHttpRequest)return t(Error("Browser not supported"));if(void 0===o){var u=n.match(/^\s*https?:\/\/[^\/]*/);o=u&&u[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var r=new window.XMLHttpRequest;if(o&&!("withCredentials"in r)){r=new window.XDomainRequest;var a=t;t=function(){if(l)a.apply(this,arguments);else{var n=this,t=arguments;setTimeout(function(){a.apply(n,t)},0)}}}return"onload"in r?r.onload=e:r.onreadystatechange=function(){4===r.readyState&&e()},r.onerror=function(n){t.call(this,n||!0,null),t=function(){}},r.onprogress=function(){},r.ontimeout=function(n){t.call(this,n,null),t=function(){}},r.onabort=function(n){t.call(this,n,null),t=function(){}},r.open("GET",n,!0),r.send(null),l=!0,r}"undefined"!=typeof module&&(module.exports=corslite); +},{}],2:[function(require,module,exports){ +!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i(t.L={})}(this,function(t){"use strict";function i(t){var i,e,n,o;for(e=1,n=arguments.length;e=0}function A(t,i,e,n){return"touchstart"===i?O(t,e,n):"touchmove"===i?W(t,e,n):"touchend"===i&&H(t,e,n),this}function I(t,i,e){var n=t["_leaflet_"+i+e];return"touchstart"===i?t.removeEventListener(de,n,!1):"touchmove"===i?t.removeEventListener(pe,n,!1):"touchend"===i&&(t.removeEventListener(me,n,!1),t.removeEventListener(fe,n,!1)),this}function O(t,i,n){var o=e(function(t){if("mouse"!==t.pointerType&&t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(ge.indexOf(t.target.tagName)<0))return;Pt(t)}j(t,i)});t["_leaflet_touchstart"+n]=o,t.addEventListener(de,o,!1),ye||(document.documentElement.addEventListener(de,R,!0),document.documentElement.addEventListener(pe,N,!0),document.documentElement.addEventListener(me,D,!0),document.documentElement.addEventListener(fe,D,!0),ye=!0)}function R(t){ve[t.pointerId]=t,xe++}function N(t){ve[t.pointerId]&&(ve[t.pointerId]=t)}function D(t){delete ve[t.pointerId],xe--}function j(t,i){t.touches=[];for(var e in ve)t.touches.push(ve[e]);t.changedTouches=[t],i(t)}function W(t,i,e){var n=function(t){(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons)&&j(t,i)};t["_leaflet_touchmove"+e]=n,t.addEventListener(pe,n,!1)}function H(t,i,e){var n=function(t){j(t,i)};t["_leaflet_touchend"+e]=n,t.addEventListener(me,n,!1),t.addEventListener(fe,n,!1)}function F(t,i,e){function n(t){var i;if(oe){if(!Ri||"mouse"===t.pointerType)return;i=xe}else i=t.touches.length;if(!(i>1)){var e=Date.now(),n=e-(s||e);r=t.touches?t.touches[0]:t,a=n>0&&n<=h,s=e}}function o(t){if(a&&!r.cancelBubble){if(oe){if(!Ri||"mouse"===t.pointerType)return;var e,n,o={};for(n in r)e=r[n],o[n]=e&&e.bind?e.bind(r):e;r=o}r.type="dblclick",i(r),s=null}}var s,r,a=!1,h=250;return t[Le+we+e]=n,t[Le+Pe+e]=o,t[Le+"dblclick"+e]=i,t.addEventListener(we,n,!1),t.addEventListener(Pe,o,!1),t.addEventListener("dblclick",i,!1),this}function U(t,i){var e=t[Le+we+i],n=t[Le+Pe+i],o=t[Le+"dblclick"+i];return t.removeEventListener(we,e,!1),t.removeEventListener(Pe,n,!1),Ri||t.removeEventListener("dblclick",o,!1),this}function V(t){return"string"==typeof t?document.getElementById(t):t}function q(t,i){var e=t.style[i]||t.currentStyle&&t.currentStyle[i];if((!e||"auto"===e)&&document.defaultView){var n=document.defaultView.getComputedStyle(t,null);e=n?n[i]:null}return"auto"===e?null:e}function G(t,i,e){var n=document.createElement(t);return n.className=i||"",e&&e.appendChild(n),n}function K(t){var i=t.parentNode;i&&i.removeChild(t)}function Y(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function X(t){var i=t.parentNode;i&&i.lastChild!==t&&i.appendChild(t)}function J(t){var i=t.parentNode;i&&i.firstChild!==t&&i.insertBefore(t,i.firstChild)}function $(t,i){if(void 0!==t.classList)return t.classList.contains(i);var e=et(t);return e.length>0&&new RegExp("(^|\\s)"+i+"(\\s|$)").test(e)}function Q(t,i){if(void 0!==t.classList)for(var e=u(i),n=0,o=e.length;n100&&n<500||t.target._simulatedClick&&!t._simulated)return void Lt(t);Ze=e,i(t)}function Zt(t,i){return new Re(t,i)}function Et(t,i){if(!i||!t.length)return t.slice();var e=i*i;return t=Ot(t,e),t=At(t,e)}function kt(t,i,e){return Math.sqrt(Wt(t,i,e,!0))}function Bt(t,i,e){return Wt(t,i,e)}function At(t,i){var e=t.length,n=typeof Uint8Array!=void 0+""?Uint8Array:Array,o=new n(e);o[0]=o[e-1]=1,It(t,o,i,0,e-1);var s,r=[];for(s=0;sh&&(s=r,h=a);h>e&&(i[s]=1,It(t,i,e,n,s),It(t,i,e,s,o))}function Ot(t,i){for(var e=[t[0]],n=1,o=0,s=t.length;ni&&(e.push(t[n]),o=n);return oi.max.x&&(e|=2),t.yi.max.y&&(e|=8),e}function jt(t,i){var e=i.x-t.x,n=i.y-t.y;return e*e+n*n}function Wt(t,i,e,n){var o,s=i.x,r=i.y,a=e.x-s,h=e.y-r,u=a*a+h*h;return u>0&&(o=((t.x-s)*a+(t.y-r)*h)/u,o>1?(s=e.x,r=e.y):o>0&&(s+=a*o,r+=h*o)),a=t.x-s,h=t.y-r,n?a*a+h*h:new x(s,r)}function Ht(t){return!gi(t[0])||"object"!=typeof t[0][0]&&void 0!==t[0][0]}function Ft(t){return console.warn("Deprecated use of _flat, please use L.LineUtil.isFlat instead."),Ht(t)}function Ut(t,i,e){var n,o,s,r,a,h,u,l,c,_=[1,4,2,8];for(o=0,u=t.length;o0?Math.floor(t):Math.ceil(t)};x.prototype={clone:function(){return new x(this.x,this.y)},add:function(t){return this.clone()._add(w(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(w(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},scaleBy:function(t){return new x(this.x*t.x,this.y*t.y)},unscaleBy:function(t){return new x(this.x/t.x,this.y/t.y)},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.clone()._ceil()},_ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},trunc:function(){return this.clone()._trunc()},_trunc:function(){return this.x=Ti(this.x),this.y=Ti(this.y),this},distanceTo:function(t){t=w(t);var i=t.x-this.x,e=t.y-this.y;return Math.sqrt(i*i+e*e)},equals:function(t){return t=w(t),t.x===this.x&&t.y===this.y},contains:function(t){return t=w(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+a(this.x)+", "+a(this.y)+")"}},P.prototype={extend:function(t){return t=w(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new x((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new x(this.min.x,this.max.y)},getTopRight:function(){return new x(this.max.x,this.min.y)},getTopLeft:function(){return this.min},getBottomRight:function(){return this.max},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var i,e;return t="number"==typeof t[0]||t instanceof x?w(t):b(t),t instanceof P?(i=t.min,e=t.max):i=e=t,i.x>=this.min.x&&e.x<=this.max.x&&i.y>=this.min.y&&e.y<=this.max.y},intersects:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>=i.x&&n.x<=e.x,r=o.y>=i.y&&n.y<=e.y;return s&&r},overlaps:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>i.x&&n.xi.y&&n.y=n.lat&&e.lat<=o.lat&&i.lng>=n.lng&&e.lng<=o.lng},intersects:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>=i.lat&&n.lat<=e.lat,r=o.lng>=i.lng&&n.lng<=e.lng;return s&&r},overlaps:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>i.lat&&n.lati.lng&&n.lng1,ue=function(){return!!document.createElement("canvas").getContext}(),le=!(!document.createElementNS||!E("svg").createSVGRect),ce=!le&&function(){try{var t=document.createElement("div");t.innerHTML='';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(t){return!1}}(),_e=(Object.freeze||Object)({ie:Ii,ielt9:Oi,edge:Ri,webkit:Ni,android:Di,android23:ji,androidStock:Hi,opera:Fi,chrome:Ui,gecko:Vi,safari:qi,phantom:Gi,opera12:Ki,win:Yi,ie3d:Xi,webkit3d:Ji,gecko3d:$i,any3d:Qi,mobile:te,mobileWebkit:ie,mobileWebkit3d:ee,msPointer:ne,pointer:oe,touch:se,mobileOpera:re,mobileGecko:ae,retina:he,canvas:ue,svg:le,vml:ce}),de=ne?"MSPointerDown":"pointerdown",pe=ne?"MSPointerMove":"pointermove",me=ne?"MSPointerUp":"pointerup",fe=ne?"MSPointerCancel":"pointercancel",ge=["INPUT","SELECT","OPTION"],ve={},ye=!1,xe=0,we=ne?"MSPointerDown":oe?"pointerdown":"touchstart",Pe=ne?"MSPointerUp":oe?"pointerup":"touchend",Le="_leaflet_",be=st(["transform","webkitTransform","OTransform","MozTransform","msTransform"]),Te=st(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),ze="webkitTransition"===Te||"OTransition"===Te?Te+"End":"transitionend";if("onselectstart"in document)Si=function(){mt(window,"selectstart",Pt)},Zi=function(){ft(window,"selectstart",Pt)};else{var Me=st(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);Si=function(){if(Me){var t=document.documentElement.style;Ei=t[Me],t[Me]="none"}},Zi=function(){Me&&(document.documentElement.style[Me]=Ei,Ei=void 0)}}var Ce,Se,Ze,Ee=(Object.freeze||Object)({TRANSFORM:be,TRANSITION:Te,TRANSITION_END:ze,get:V,getStyle:q,create:G,remove:K,empty:Y,toFront:X,toBack:J,hasClass:$,addClass:Q,removeClass:tt,setClass:it,getClass:et,setOpacity:nt,testProp:st,setTransform:rt,setPosition:at,getPosition:ht,disableTextSelection:Si,enableTextSelection:Zi,disableImageDrag:ut,enableImageDrag:lt,preventOutline:ct,restoreOutline:_t,getSizedParentNode:dt,getScale:pt}),ke="_leaflet_events",Be=Yi&&Ui?2*window.devicePixelRatio:Vi?window.devicePixelRatio:1,Ae={},Ie=(Object.freeze||Object)({on:mt,off:ft,stopPropagation:yt,disableScrollPropagation:xt,disableClickPropagation:wt,preventDefault:Pt,stop:Lt,getMousePosition:bt,getWheelDelta:Tt,fakeStop:zt,skipped:Mt,isExternalTarget:Ct,addListener:mt,removeListener:ft}),Oe=bi.extend({run:function(t,i,e,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=e||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=ht(t),this._offset=i.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(!0),this._complete())},_animate:function(){this._animId=f(this._animate,this),this._step()},_step:function(t){var i=+new Date-this._startTime,e=1e3*this._duration;ithis.options.maxZoom)?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,z(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},panInside:function(t,i){i=i||{};var e=w(i.paddingTopLeft||i.padding||[0,0]),n=w(i.paddingBottomRight||i.padding||[0,0]),o=this.getCenter(),s=this.project(o),r=this.project(t),a=this.getPixelBounds(),h=a.getSize().divideBy(2),u=b([a.min.add(e),a.max.subtract(n)]);if(!u.contains(r)){this._enforcingBounds=!0;var l=s.subtract(r),c=w(r.x+l.x,r.y+l.y);(r.xu.max.x)&&(c.x=s.x-l.x,l.x>0?c.x+=h.x-e.x:c.x-=h.x-n.x),(r.yu.max.y)&&(c.y=s.y-l.y,l.y>0?c.y+=h.y-e.y:c.y-=h.y-n.y),this.panTo(this.unproject(c),i),this._enforcingBounds=!1}return this},invalidateSize:function(t){if(!this._loaded)return this;t=i({animate:!1,pan:!0},!0===t?{animate:!0}:t);var n=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var o=this.getSize(),s=n.divideBy(2).round(),r=o.divideBy(2).round(),a=s.subtract(r);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(e(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:n,newSize:o})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){if(t=this._locateOptions=i({timeout:1e4,watch:!1},t),!("geolocation"in navigator))return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var n=e(this._handleGeolocationResponse,this),o=e(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(n,o,t):navigator.geolocation.getCurrentPosition(n,o,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var i=t.code,e=t.message||(1===i?"permission denied":2===i?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:i,message:"Geolocation error: "+e+"."})},_handleGeolocationResponse:function(t){var i=t.coords.latitude,e=t.coords.longitude,n=new M(i,e),o=n.toBounds(2*t.coords.accuracy),s=this._locateOptions;if(s.setView){var r=this.getBoundsZoom(o);this.setView(n,s.maxZoom?Math.min(r,s.maxZoom):r)}var a={latlng:n,bounds:o,timestamp:t.timestamp};for(var h in t.coords)"number"==typeof t.coords[h]&&(a[h]=t.coords[h]);this.fire("locationfound",a)},addHandler:function(t,i){if(!i)return this;var e=this[t]=new i(this);return this._handlers.push(e),this.options[t]&&e.enable(),this},remove:function(){if(this._initEvents(!0),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}void 0!==this._locationWatchId&&this.stopLocate(),this._stop(),K(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._resizeRequest&&(g(this._resizeRequest),this._resizeRequest=null),this._clearHandlers(),this._loaded&&this.fire("unload");var t;for(t in this._layers)this._layers[t].remove();for(t in this._panes)K(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,i){var e="leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),n=G("div",e,i||this._mapPane);return t&&(this._panes[t]=n),n},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new T(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,i,e){t=z(t),e=w(e||[0,0]);var n=this.getZoom()||0,o=this.getMinZoom(),s=this.getMaxZoom(),r=t.getNorthWest(),a=t.getSouthEast(),h=this.getSize().subtract(e),u=b(this.project(a,n),this.project(r,n)).getSize(),l=Qi?this.options.zoomSnap:1,c=h.x/u.x,_=h.y/u.y,d=i?Math.max(c,_):Math.min(c,_);return n=this.getScaleZoom(d,n),l&&(n=Math.round(n/(l/100))*(l/100),n=i?Math.ceil(n/l)*l:Math.floor(n/l)*l),Math.max(o,Math.min(s,n))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new x(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,i){var e=this._getTopLeftPoint(t,i);return new P(e,e.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,i){var e=this.options.crs;return i=void 0===i?this._zoom:i,e.scale(t)/e.scale(i)},getScaleZoom:function(t,i){var e=this.options.crs;i=void 0===i?this._zoom:i;var n=e.zoom(t*e.scale(i));return isNaN(n)?1/0:n},project:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.latLngToPoint(C(t),i)},unproject:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.pointToLatLng(w(t),i)},layerPointToLatLng:function(t){var i=w(t).add(this.getPixelOrigin());return this.unproject(i)},latLngToLayerPoint:function(t){return this.project(C(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(C(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(z(t))},distance:function(t,i){return this.options.crs.distance(C(t),C(i))},containerPointToLayerPoint:function(t){return w(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return w(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var i=this.containerPointToLayerPoint(w(t));return this.layerPointToLatLng(i)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(C(t)))},mouseEventToContainerPoint:function(t){return bt(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var i=this._container=V(t);if(!i)throw new Error("Map container not found.");if(i._leaflet_id)throw new Error("Map container is already initialized.");mt(i,"scroll",this._onScroll,this),this._containerId=n(i)},_initLayout:function(){var t=this._container;this._fadeAnimated=this.options.fadeAnimation&&Qi,Q(t,"leaflet-container"+(se?" leaflet-touch":"")+(he?" leaflet-retina":"")+(Oi?" leaflet-oldie":"")+(qi?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":""));var i=q(t,"position");"absolute"!==i&&"relative"!==i&&"fixed"!==i&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),at(this._mapPane,new x(0,0)),this.createPane("tilePane"),this.createPane("shadowPane"),this.createPane("overlayPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(Q(t.markerPane,"leaflet-zoom-hide"),Q(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,i){at(this._mapPane,new x(0,0));var e=!this._loaded;this._loaded=!0,i=this._limitZoom(i),this.fire("viewprereset");var n=this._zoom!==i;this._moveStart(n,!1)._move(t,i)._moveEnd(n),this.fire("viewreset"),e&&this.fire("load")},_moveStart:function(t,i){return t&&this.fire("zoomstart"),i||this.fire("movestart"),this},_move:function(t,i,e){void 0===i&&(i=this._zoom);var n=this._zoom!==i;return this._zoom=i,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),(n||e&&e.pinch)&&this.fire("zoom",e),this.fire("move",e)},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return g(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){at(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={},this._targets[n(this._container)]=this;var i=t?ft:mt;i(this._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress",this._handleDOMEvent,this),this.options.trackResize&&i(window,"resize",this._onResize,this),Qi&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){g(this._resizeRequest),this._resizeRequest=f(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,o=[],s="mouseout"===i||"mouseover"===i,r=t.target||t.srcElement,a=!1;r;){if((e=this._targets[n(r)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){a=!0;break}if(e&&e.listens(i,!0)){if(s&&!Ct(r,t))break;if(o.push(e),s)break}if(r===this._container)break;r=r.parentNode}return o.length||a||s||!Ct(r,t)||(o=[this]),o},_handleDOMEvent:function(t){if(this._loaded&&!Mt(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i||ct(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,n){if("click"===t.type){var o=i({},t);o.type="preclick",this._fireDOMEvent(o,o.type,n)}if(!t._stopped&&(n=(n||[]).concat(this._findEventTargets(t,e)),n.length)){var s=n[0];"contextmenu"===e&&s.listens(e,!0)&&Pt(t);var r={originalEvent:t};if("keypress"!==t.type){var a=s.getLatLng&&(!s._radius||s._radius<=10);r.containerPoint=a?this.latLngToContainerPoint(s.getLatLng()):this.mouseEventToContainerPoint(t),r.layerPoint=this.containerPointToLayerPoint(r.containerPoint),r.latlng=a?s.getLatLng():this.layerPointToLatLng(r.layerPoint)}for(var h=0;h0?Math.round(t-i)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(i))},_limitZoom:function(t){var i=this.getMinZoom(),e=this.getMaxZoom(),n=Qi?this.options.zoomSnap:1;return n&&(t=Math.round(t/n)*n),Math.max(i,Math.min(e,t))},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){tt(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,i){var e=this._getCenterOffset(t)._trunc();return!(!0!==(i&&i.animate)&&!this.getSize().contains(e))&&(this.panBy(e,i),!0)},_createAnimProxy:function(){var t=this._proxy=G("div","leaflet-proxy leaflet-zoom-animated");this._panes.mapPane.appendChild(t),this.on("zoomanim",function(t){var i=be,e=this._proxy.style[i];rt(this._proxy,this.project(t.center,t.zoom),this.getZoomScale(t.zoom,1)),e===this._proxy.style[i]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on("load moveend",function(){var t=this.getCenter(),i=this.getZoom();rt(this._proxy,this.project(t,i),this.getZoomScale(i,1))},this),this._on("unload",this._destroyAnimProxy,this)},_destroyAnimProxy:function(){K(this._proxy),delete this._proxy},_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,i,e){if(this._animatingZoom)return!0;if(e=e||{},!this._zoomAnimated||!1===e.animate||this._nothingToAnimate()||Math.abs(i-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o))&&(f(function(){this._moveStart(!0,!1)._animateZoom(t,i,!0)},this),!0)},_animateZoom:function(t,i,n,o){this._mapPane&&(n&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,Q(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:o}),setTimeout(e(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&tt(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),f(function(){this._moveEnd(!0)},this))}}),Ne=v.extend({options:{position:"topright"},initialize:function(t){l(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return Q(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this},remove:function(){return this._map?(K(this._container),this.onRemove&&this.onRemove(this._map),this._map=null,this):this},_refocusOnMap:function(t){this._map&&t&&t.screenX>0&&t.screenY>0&&this._map.getContainer().focus()}}),De=function(t){return new Ne(t)};Re.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){function t(t,o){var s=e+t+" "+e+o;i[t+o]=G("div",s,n)}var i=this._controlCorners={},e="leaflet-",n=this._controlContainer=G("div",e+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){for(var t in this._controlCorners)K(this._controlCorners[t]);K(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var je=Ne.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,i,e,n){return e1,this._baseLayersList.style.display=t?"":"none"),this._separator.style.display=i&&t?"":"none",this},_onLayerChange:function(t){this._handlingClick||this._update();var i=this._getLayer(n(t.target)),e=i.overlay?"add"===t.type?"overlayadd":"overlayremove":"add"===t.type?"baselayerchange":null;e&&this._map.fire(e,i)},_createRadioElement:function(t,i){var e='",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),o=this._map.hasLayer(t.layer);t.overlay?(i=document.createElement("input"),i.type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=o):i=this._createRadioElement("leaflet-base-layers",o),this._layerControlInputs.push(i),i.layerId=n(t.layer),mt(i,"click",this._onInputClick,this);var s=document.createElement("span");s.innerHTML=" "+t.name;var r=document.createElement("div");return e.appendChild(r),r.appendChild(i),r.appendChild(s),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e=this._layerControlInputs,n=[],o=[];this._handlingClick=!0;for(var s=e.length-1;s>=0;s--)t=e[s],i=this._getLayer(t.layerId).layer,t.checked?n.push(i):t.checked||o.push(i);for(s=0;s=0;o--)t=e[o],i=this._getLayer(t.layerId).layer,t.disabled=void 0!==i.options.minZoom&&ni.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),We=function(t,i,e){return new je(t,i,e)},He=Ne.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=G("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=G("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),wt(s),mt(s,"click",Lt),mt(s,"click",o,this),mt(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";tt(this._zoomInButton,i),tt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMinZoom())&&Q(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMaxZoom())&&Q(this._zoomInButton,i)}});Re.mergeOptions({zoomControl:!0}),Re.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new He,this.addControl(this.zoomControl))});var Fe=function(t){return new He(t)},Ue=Ne.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i=G("div","leaflet-control-scale"),e=this.options;return this._addScales(e,"leaflet-control-scale-line",i),t.on(e.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=G("div",i,e)),t.imperial&&(this._iScale=G("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;o>5280?(i=o/5280,e=this._getRoundNum(i),this._updateScale(this._iScale,e+" mi",e/i)):(n=this._getRoundNum(o),this._updateScale(this._iScale,n+" ft",n/o))},_updateScale:function(t,i,e){t.style.width=Math.round(this.options.maxWidth*e)+"px",t.innerHTML=i},_getRoundNum:function(t){var i=Math.pow(10,(Math.floor(t)+"").length-1),e=t/i;return e=e>=10?10:e>=5?5:e>=3?3:e>=2?2:1,i*e}}),Ve=function(t){return new Ue(t)},qe=Ne.extend({options:{position:"bottomright",prefix:'Leaflet'},initialize:function(t){l(this,t),this._attributions={}},onAdd:function(t){t.attributionControl=this,this._container=G("div","leaflet-control-attribution"),wt(this._container);for(var i in t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):this},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});Re.mergeOptions({attributionControl:!0}),Re.addInitHook(function(){this.options.attributionControl&&(new qe).addTo(this)});var Ge=function(t){return new qe(t)};Ne.Layers=je,Ne.Zoom=He,Ne.Scale=Ue,Ne.Attribution=qe,De.layers=We,De.zoom=Fe,De.scale=Ve,De.attribution=Ge;var Ke=v.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}});Ke.addTo=function(t,i){return t.addHandler(i,this),this};var Ye,Xe={Events:Li},Je=se?"touchstart mousedown":"mousedown",$e={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},Qe={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},tn=bi.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){l(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(mt(this._dragStartTarget,Je,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(tn._dragging===this&&this.finishDrag(),ft(this._dragStartTarget,Je,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!$(this._element,"leaflet-zoom-anim")&&!(tn._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(tn._dragging=this,this._preventOutline&&ct(this._element),ut(),Si(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t,e=dt(this._element);this._startPoint=new x(i.clientX,i.clientY),this._parentScale=pt(e),mt(document,Qe[t.type],this._onMove,this),mt(document,$e[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled){if(t.touches&&t.touches.length>1)return void(this._moved=!0);var i=t.touches&&1===t.touches.length?t.touches[0]:t,e=new x(i.clientX,i.clientY)._subtract(this._startPoint);(e.x||e.y)&&(Math.abs(e.x)+Math.abs(e.y)1e-7;h++)i=s*Math.sin(a),i=Math.pow((1-i)/(1+i),s/2),u=Math.PI/2-2*Math.atan(r*i)-a,a+=u;return new M(a*e,t.x*e/n)}},rn=(Object.freeze||Object)({LonLat:on,Mercator:sn,SphericalMercator:Ci}),an=i({},Mi,{code:"EPSG:3395",projection:sn,transformation:function(){var t=.5/(Math.PI*sn.R);return Z(t,.5,-t,.5)}()}),hn=i({},Mi,{code:"EPSG:4326",projection:on,transformation:Z(1/180,1,-1/180,.5)}),un=i({},zi,{projection:on,transformation:Z(1,0,-1,0),scale:function(t){return Math.pow(2,t)},zoom:function(t){return Math.log(t)/Math.LN2},distance:function(t,i){var e=i.lng-t.lng,n=i.lat-t.lat;return Math.sqrt(e*e+n*n)},infinite:!0});zi.Earth=Mi,zi.EPSG3395=an,zi.EPSG3857=ki,zi.EPSG900913=Bi,zi.EPSG4326=hn,zi.Simple=un;var ln=bi.extend({options:{pane:"overlayPane",attribution:null,bubblingMouseEvents:!0},addTo:function(t){return t.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(t){return t&&t.removeLayer(this),this},getPane:function(t){return this._map.getPane(t?this.options[t]||t:this.options.pane)},addInteractiveTarget:function(t){return this._map._targets[n(t)]=this,this},removeInteractiveTarget:function(t){return delete this._map._targets[n(t)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(t){var i=t.target;if(i.hasLayer(this)){if(this._map=i,this._zoomAnimated=i._zoomAnimated,this.getEvents){var e=this.getEvents();i.on(e,this),this.once("remove",function(){i.off(e,this)},this)}this.onAdd(i),this.getAttribution&&i.attributionControl&&i.attributionControl.addAttribution(this.getAttribution()),this.fire("add"),i.fire("layeradd",{layer:this})}}});Re.include({addLayer:function(t){if(!t._layerAdd)throw new Error("The provided object is not a Layer.");var i=n(t);return this._layers[i]?this:(this._layers[i]=t,t._mapToAdd=this,t.beforeAdd&&t.beforeAdd(this),this.whenReady(t._layerAdd,t),this)},removeLayer:function(t){var i=n(t);return this._layers[i]?(this._loaded&&t.onRemove(this),t.getAttribution&&this.attributionControl&&this.attributionControl.removeAttribution(t.getAttribution()),delete this._layers[i],this._loaded&&(this.fire("layerremove",{layer:t}),t.fire("remove")),t._map=t._mapToAdd=null,this):this},hasLayer:function(t){return!!t&&n(t)in this._layers},eachLayer:function(t,i){for(var e in this._layers)t.call(i,this._layers[e]);return this},_addLayers:function(t){t=t?gi(t)?t:[t]:[];for(var i=0,e=t.length;ithis._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()i)return r=(n-i)/e,this._map.layerPointToLatLng([s.x-r*(s.x-o.x),s.y-r*(s.y-o.y)])},getBounds:function(){return this._bounds},addLatLng:function(t,i){return i=i||this._defaultShape(),t=C(t),i.push(t),this._bounds.extend(t),this.redraw()},_setLatLngs:function(t){this._bounds=new T,this._latlngs=this._convertLatLngs(t)},_defaultShape:function(){return Ht(this._latlngs)?this._latlngs:this._latlngs[0]},_convertLatLngs:function(t){for(var i=[],e=Ht(t),n=0,o=t.length;n=2&&i[0]instanceof M&&i[0].equals(i[e-1])&&i.pop(),i},_setLatLngs:function(t){Pn.prototype._setLatLngs.call(this,t),Ht(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return Ht(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var t=this._renderer._bounds,i=this.options.weight,e=new x(i,i);if(t=new P(t.min.subtract(e),t.max.add(e)),this._parts=[],this._pxBounds&&this._pxBounds.intersects(t)){if(this.options.noClip)return void(this._parts=this._rings);for(var n,o=0,s=this._rings.length;ot.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||Pn.prototype._containsPoint.call(this,t,!0)}}),bn=dn.extend({initialize:function(t,i){l(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=gi(t)?t:t.features;if(o){for(i=0,e=o.length;i0?o:[i.src])}gi(this._url)||(this._url=[this._url]),i.autoplay=!!this.options.autoplay,i.loop=!!this.options.loop;for(var a=0;ao?(i.height=o+"px",Q(t,"leaflet-popup-scrolled")):tt(t,"leaflet-popup-scrolled"),this._containerWidth=this._container.offsetWidth},_animateZoom:function(t){var i=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center),e=this._getAnchor();at(this._container,i.add(e))},_adjustPan:function(){if(this.options.autoPan){this._map._panAnim&&this._map._panAnim.stop();var t=this._map,i=parseInt(q(this._container,"marginBottom"),10)||0,e=this._container.offsetHeight+i,n=this._containerWidth,o=new x(this._containerLeft,-e-this._containerBottom);o._add(ht(this._container));var s=t.layerPointToContainerPoint(o),r=w(this.options.autoPanPadding),a=w(this.options.autoPanPaddingTopLeft||r),h=w(this.options.autoPanPaddingBottomRight||r),u=t.getSize(),l=0,c=0;s.x+n+h.x>u.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Lt(t)},_getAnchor:function(){return w(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}}),kn=function(t,i){return new En(t,i)};Re.mergeOptions({closePopupOnClick:!0}),Re.include({openPopup:function(t,i,e){return t instanceof En||(t=new En(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),ln.include({bindPopup:function(t,i){return t instanceof En?(l(t,i),this._popup=t,t._source=this):(this._popup&&!i||(this._popup=new En(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){if(t instanceof ln||(i=t,t=this),t instanceof dn)for(var e in this._layers){t=this._layers[e];break}return i||(i=t.getCenter?t.getCenter():t.getLatLng()),this._popup&&this._map&&(this._popup._source=t,this._popup.update(),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){ +return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;if(this._popup&&this._map){if(Lt(t),i instanceof yn)return void this.openPopup(t.layer||t.target,t.latlng);this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng)}},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var Bn=Zn.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){Zn.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){Zn.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=Zn.prototype.getEvents.call(this);return se&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=G("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=w(this.options.offset),u=this._getAnchor();"top"===s?t=t.add(w(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t=t.subtract(w(r/2-h.x,-h.y,!0)):"center"===s?t=t.subtract(w(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||en&&this._retainParent(o,s,r,n))},_retainChildren:function(t,i,e,n){for(var o=2*t;o<2*t+2;o++)for(var s=2*i;s<2*i+2;s++){var r=new x(o,s);r.z=e+1;var a=this._tileCoordsToKey(r),h=this._tiles[a];h&&h.active?h.retain=!0:(h&&h.loaded&&(h.retain=!0),e+1this.options.maxZoom||void 0!==this.options.minZoom&&o1)return void this._setView(t,e);for(var c=o.min.y;c<=o.max.y;c++)for(var _=o.min.x;_<=o.max.x;_++){var d=new x(_,c);if(d.z=this._tileZoom,this._isValidTile(d)){var p=this._tiles[this._tileCoordsToKey(d)];p?p.current=!0:r.push(d)}}if(r.sort(function(t,i){return t.distanceTo(s)-i.distanceTo(s)}),0!==r.length){this._loading||(this._loading=!0,this.fire("loading"));var m=document.createDocumentFragment();for(_=0;_e.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return z(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToNwSe:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e);return[i.unproject(n,t.z),i.unproject(o,t.z)]},_tileCoordsToBounds:function(t){var i=this._tileCoordsToNwSe(t),e=new T(i[0],i[1]);return this.options.noWrap||(e=this._map.wrapLatLngBounds(e)),e},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new x(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(K(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){Q(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=r,t.onmousemove=r,Oi&&this.options.opacity<1&&nt(t,this.options.opacity),Di&&!ji&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var n=this._getTilePos(t),o=this._tileCoordsToKey(t),s=this.createTile(this._wrapCoords(t),e(this._tileReady,this,t));this._initTile(s),this.createTile.length<2&&f(e(this._tileReady,this,t,null,s)),at(s,n),this._tiles[o]={el:s,coords:t,current:!0},i.appendChild(s),this.fire("tileloadstart",{tile:s,coords:t})},_tileReady:function(t,i,n){i&&this.fire("tileerror",{error:i,tile:n,coords:t});var o=this._tileCoordsToKey(t);(n=this._tiles[o])&&(n.loaded=+new Date,this._map._fadeAnimated?(nt(n.el,0),g(this._fadeFrame),this._fadeFrame=f(this._updateOpacity,this)):(n.active=!0,this._pruneTiles()),i||(Q(n.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:n.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),Oi||!this._map._fadeAnimated?f(this._pruneTiles,this):setTimeout(e(this._pruneTiles,this),250)))},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new x(this._wrapX?s(t.x,this._wrapX):t.x,this._wrapY?s(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new P(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}}),Rn=On.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,i=l(this,i),i.detectRetina&&he&&i.maxZoom>0&&(i.tileSize=Math.floor(i.tileSize/2),i.zoomReverse?(i.zoomOffset--,i.minZoom++):(i.zoomOffset++,i.maxZoom--),i.minZoom=Math.max(0,i.minZoom)),"string"==typeof i.subdomains&&(i.subdomains=i.subdomains.split("")),Di||this.on("tileunload",this._onTileRemove)},setUrl:function(t,i){return this._url===t&&void 0===i&&(i=!0),this._url=t,i||this.redraw(),this},createTile:function(t,i){var n=document.createElement("img");return mt(n,"load",e(this._tileOnLoad,this,i,n)),mt(n,"error",e(this._tileOnError,this,i,n)),(this.options.crossOrigin||""===this.options.crossOrigin)&&(n.crossOrigin=!0===this.options.crossOrigin?"":this.options.crossOrigin),n.alt="",n.setAttribute("role","presentation"),n.src=this.getTileUrl(t),n},getTileUrl:function(t){var e={r:he?"@2x":"",s:this._getSubdomain(t),x:t.x,y:t.y,z:this._getZoomForUrl()};if(this._map&&!this._map.options.crs.infinite){var n=this._globalTileRange.max.y-t.y;this.options.tms&&(e.y=n),e["-y"]=n}return _(this._url,i(e,this.options))},_tileOnLoad:function(t,i){Oi?setTimeout(e(t,this,null,i),0):t(null,i)},_tileOnError:function(t,i,e){var n=this.options.errorTileUrl;n&&i.getAttribute("src")!==n&&(i.src=n),t(e,i)},_onTileRemove:function(t){t.tile.onload=null},_getZoomForUrl:function(){var t=this._tileZoom,i=this.options.maxZoom,e=this.options.zoomReverse,n=this.options.zoomOffset;return e&&(t=i-t),t+n},_getSubdomain:function(t){var i=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[i]},_abortLoading:function(){var t,i;for(t in this._tiles)this._tiles[t].coords.z!==this._tileZoom&&(i=this._tiles[t].el,i.onload=r,i.onerror=r,i.complete||(i.src=vi,K(i),delete this._tiles[t]))},_removeTile:function(t){var i=this._tiles[t];if(i)return Hi||i.el.setAttribute("src",vi),On.prototype._removeTile.call(this,t)},_tileReady:function(t,i,e){if(this._map&&(!e||e.getAttribute("src")!==vi))return On.prototype._tileReady.call(this,t,i,e)}}),Nn=Rn.extend({defaultWmsParams:{service:"WMS",request:"GetMap",layers:"",styles:"",format:"image/jpeg",transparent:!1,version:"1.1.1"},options:{crs:null,uppercase:!1},initialize:function(t,e){this._url=t;var n=i({},this.defaultWmsParams);for(var o in e)o in this.options||(n[o]=e[o]);e=l(this,e);var s=e.detectRetina&&he?2:1,r=this.getTileSize();n.width=r.x*s,n.height=r.y*s,this.wmsParams=n},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var i=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[i]=this._crs.code,Rn.prototype.onAdd.call(this,t)},getTileUrl:function(t){var i=this._tileCoordsToNwSe(t),e=this._crs,n=b(e.project(i[0]),e.project(i[1])),o=n.min,s=n.max,r=(this._wmsVersion>=1.3&&this._crs===hn?[o.y,o.x,s.y,s.x]:[o.x,o.y,s.x,s.y]).join(","),a=Rn.prototype.getTileUrl.call(this,t);return a+c(this.wmsParams,a,this.options.uppercase)+(this.options.uppercase?"&BBOX=":"&bbox=")+r},setParams:function(t,e){return i(this.wmsParams,t),e||this.redraw(),this}});Rn.WMS=Nn,hi.wms=ui;var Dn=ln.extend({options:{padding:.1,tolerance:0},initialize:function(t){l(this,t),n(this),this._layers=this._layers||{}},onAdd:function(){this._container||(this._initContainer(),this._zoomAnimated&&Q(this._container,"leaflet-zoom-animated")),this.getPane().appendChild(this._container),this._update(),this.on("update",this._updatePaths,this)},onRemove:function(){this.off("update",this._updatePaths,this),this._destroyContainer()},getEvents:function(){var t={viewreset:this._reset,zoom:this._onZoom,moveend:this._update,zoomend:this._onZoomEnd};return this._zoomAnimated&&(t.zoomanim=this._onAnimZoom),t},_onAnimZoom:function(t){this._updateTransform(t.center,t.zoom)},_onZoom:function(){this._updateTransform(this._map.getCenter(),this._map.getZoom())},_updateTransform:function(t,i){var e=this._map.getZoomScale(i,this._zoom),n=ht(this._container),o=this._map.getSize().multiplyBy(.5+this.options.padding),s=this._map.project(this._center,i),r=this._map.project(t,i),a=r.subtract(s),h=o.multiplyBy(-e).add(n).add(o).subtract(a);Qi?rt(this._container,h,e):at(this._container,h)},_reset:function(){this._update(),this._updateTransform(this._center,this._zoom);for(var t in this._layers)this._layers[t]._reset()},_onZoomEnd:function(){for(var t in this._layers)this._layers[t]._project()},_updatePaths:function(){for(var t in this._layers)this._layers[t]._update()},_update:function(){var t=this.options.padding,i=this._map.getSize(),e=this._map.containerPointToLayerPoint(i.multiplyBy(-t)).round();this._bounds=new P(e,e.add(i.multiplyBy(1+2*t)).round()),this._center=this._map.getCenter(),this._zoom=this._map.getZoom()}}),jn=Dn.extend({getEvents:function(){var t=Dn.prototype.getEvents.call(this);return t.viewprereset=this._onViewPreReset,t},_onViewPreReset:function(){this._postponeUpdatePaths=!0},onAdd:function(){Dn.prototype.onAdd.call(this),this._draw()},_initContainer:function(){var t=this._container=document.createElement("canvas");mt(t,"mousemove",o(this._onMouseMove,32,this),this),mt(t,"click dblclick mousedown mouseup contextmenu",this._onClick,this),mt(t,"mouseout",this._handleMouseOut,this),this._ctx=t.getContext("2d")},_destroyContainer:function(){g(this._redrawRequest),delete this._ctx,K(this._container),ft(this._container),delete this._container},_updatePaths:function(){if(!this._postponeUpdatePaths){var t;this._redrawBounds=null;for(var i in this._layers)t=this._layers[i],t._update();this._redraw()}},_update:function(){if(!this._map._animatingZoom||!this._bounds){Dn.prototype._update.call(this);var t=this._bounds,i=this._container,e=t.getSize(),n=he?2:1;at(i,t.min),i.width=n*e.x,i.height=n*e.y,i.style.width=e.x+"px",i.style.height=e.y+"px",he&&this._ctx.scale(2,2),this._ctx.translate(-t.min.x,-t.min.y),this.fire("update")}},_reset:function(){Dn.prototype._reset.call(this),this._postponeUpdatePaths&&(this._postponeUpdatePaths=!1,this._updatePaths())},_initPath:function(t){this._updateDashArray(t),this._layers[n(t)]=t;var i=t._order={layer:t,prev:this._drawLast,next:null};this._drawLast&&(this._drawLast.next=i),this._drawLast=i,this._drawFirst=this._drawFirst||this._drawLast},_addPath:function(t){this._requestRedraw(t)},_removePath:function(t){var i=t._order,e=i.next,o=i.prev;e?e.prev=o:this._drawLast=o,o?o.next=e:this._drawFirst=e,delete t._order,delete this._layers[n(t)],this._requestRedraw(t)},_updatePath:function(t){this._extendRedrawBounds(t),t._project(),t._update(),this._requestRedraw(t)},_updateStyle:function(t){this._updateDashArray(t),this._requestRedraw(t)},_updateDashArray:function(t){if("string"==typeof t.options.dashArray){var i,e,n=t.options.dashArray.split(/[, ]+/),o=[];for(e=0;e')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),Hn={_initContainer:function(){this._container=G("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(Dn.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=Wn("shape");Q(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=Wn("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;K(i),t.removeInteractiveTarget(i),delete this._layers[n(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=Wn("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=gi(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=Wn("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){X(t._container)},_bringToBack:function(t){J(t._container)}},Fn=ce?Wn:E,Un=Dn.extend({getEvents:function(){var t=Dn.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=Fn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=Fn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){K(this._container),ft(this._container),delete this._container,delete this._rootGroup,delete this._svgSize},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){Dn.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),at(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=Fn("path");t.options.className&&Q(i,t.options.className),t.options.interactive&&Q(i,"leaflet-interactive"),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){K(t._path),t.removeInteractiveTarget(t._path),delete this._layers[n(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,k(t._parts,i))},_updateCircle:function(t){var i=t._point,e=Math.max(Math.round(t._radius),1),n=Math.max(Math.round(t._radiusY),1)||e,o="a"+e+","+n+" 0 1,0 ",s=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+o+2*e+",0 "+o+2*-e+",0 ";this._setPath(t,s)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){X(t._path)},_bringToBack:function(t){J(t._path)}});ce&&Un.include(Hn),Re.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this._createRenderer()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=this._createRenderer({pane:t}),this._paneRenderers[t]=i),i},_createRenderer:function(t){return this.options.preferCanvas&&li(t)||ci(t)}});var Vn=Ln.extend({initialize:function(t,i){Ln.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=z(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});Un.create=Fn,Un.pointsToPath=k,bn.geometryToLayer=Jt,bn.coordsToLatLng=$t,bn.coordsToLatLngs=Qt,bn.latLngToCoords=ti,bn.latLngsToCoords=ii,bn.getFeature=ei,bn.asFeature=ni,Re.mergeOptions({boxZoom:!0});var qn=Ke.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){mt(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){ft(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){K(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){if(!t.shiftKey||1!==t.which&&1!==t.button)return!1;this._clearDeferredResetState(),this._resetState(),Si(),ut(),this._startPoint=this._map.mouseEventToContainerPoint(t), +mt(document,{contextmenu:Lt,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=G("div","leaflet-zoom-box",this._container),Q(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new P(this._point,this._startPoint),e=i.getSize();at(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(K(this._box),tt(this._container,"leaflet-crosshair")),Zi(),lt(),ft(document,{contextmenu:Lt,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(e(this._resetState,this),0);var i=new T(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});Re.addInitHook("addHandler","boxZoom",qn),Re.mergeOptions({doubleClickZoom:!0});var Gn=Ke.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});Re.addInitHook("addHandler","doubleClickZoom",Gn),Re.mergeOptions({dragging:!0,inertia:!ji,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var Kn=Ke.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new tn(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}Q(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){tt(this._map._container,"leaflet-grab"),tt(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=z(this._map.options.maxBounds);this._offsetLimit=b(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),this._prunePositions(i)}this._map.fire("move",t).fire("drag",t)},_prunePositions:function(t){for(;this._positions.length>1&&t-this._times[0]>50;)this._positions.shift(),this._times.shift()},_onZoomEnd:function(){var t=this._map.getSize().divideBy(2),i=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=i.subtract(t).x,this._worldWidth=this._map.getPixelWorldBounds().getSize().x},_viscousLimit:function(t,i){return t-(t-i)*this._viscosity},_onPreDragLimit:function(){if(this._viscosity&&this._offsetLimit){var t=this._draggable._newPos.subtract(this._draggable._startPos),i=this._offsetLimit;t.xi.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});Re.addInitHook("addHandler","scrollWheelZoom",Xn),Re.mergeOptions({tap:!0,tapTolerance:15});var Jn=Ke.extend({addHooks:function(){mt(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){ft(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(Pt(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&Q(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),mt(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),ft(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&tt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});se&&!oe&&Re.addInitHook("addHandler","tap",Jn),Re.mergeOptions({touchZoom:se&&!ji,bounceAtZoomLimits:!0});var $n=Ke.extend({addHooks:function(){Q(this._map._container,"leaflet-touch-zoom"),mt(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){tt(this._map._container,"leaflet-touch-zoom"),ft(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),mt(document,"touchmove",this._onTouchMove,this),mt(document,"touchend",this._onTouchEnd,this),Pt(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0,!1),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),Pt(t)}},_onTouchEnd:function(){if(!this._moved||!this._zooming)return void(this._zooming=!1);this._zooming=!1,g(this._animRequest),ft(document,"touchmove",this._onTouchMove),ft(document,"touchend",this._onTouchEnd),this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom))}});Re.addInitHook("addHandler","touchZoom",$n),Re.BoxZoom=qn,Re.DoubleClickZoom=Gn,Re.Drag=Kn,Re.Keyboard=Yn,Re.ScrollWheelZoom=Xn,Re.Tap=Jn,Re.TouchZoom=$n,Object.freeze=di,t.version="1.4.0",t.Control=Ne,t.control=De,t.Browser=_e,t.Evented=bi,t.Mixin=Xe,t.Util=Pi,t.Class=v,t.Handler=Ke,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=Ie,t.DomUtil=Ee,t.PosAnimation=Oe,t.Draggable=tn,t.LineUtil=en,t.PolyUtil=nn,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=S,t.transformation=Z,t.Projection=rn,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=zi,t.GeoJSON=bn,t.geoJSON=oi,t.geoJson=zn,t.Layer=ln,t.LayerGroup=cn,t.layerGroup=_n,t.FeatureGroup=dn,t.featureGroup=pn,t.ImageOverlay=Mn,t.imageOverlay=Cn,t.VideoOverlay=Sn,t.videoOverlay=si,t.DivOverlay=Zn,t.Popup=En,t.popup=kn,t.Tooltip=Bn,t.tooltip=An,t.Icon=mn,t.icon=Vt,t.DivIcon=In,t.divIcon=ri,t.Marker=vn,t.marker=qt,t.TileLayer=Rn,t.tileLayer=hi,t.GridLayer=On,t.gridLayer=ai,t.SVG=Un,t.svg=ci,t.Renderer=Dn,t.Canvas=jn,t.canvas=li,t.Path=yn,t.CircleMarker=xn,t.circleMarker=Gt,t.Circle=wn,t.circle=Kt,t.Polyline=Pn,t.polyline=Yt,t.Polygon=Ln,t.polygon=Xt,t.Rectangle=Vn,t.rectangle=_i,t.Map=Re,t.map=Zt;var Qn=window.L;t.noConflict=function(){return window.L=Qn,this},window.L=t}); +},{}],3:[function(require,module,exports){ +!function(e,t){"object"==typeof exports&&exports&&"string"!=typeof exports.nodeName?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):(e.Mustache={},t(e.Mustache))}(this,function(e){function t(e){return"function"==typeof e}function n(e){return v(e)?"array":typeof e}function r(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function i(e,t){return null!=e&&"object"==typeof e&&t in e}function o(e,t){return null!=e&&"object"!=typeof e&&e.hasOwnProperty&&e.hasOwnProperty(t)}function s(e,t){return w.call(e,t)}function a(e){return!s(y,e)}function u(e){return String(e).replace(/[&<>"'`=\/]/g,function(e){return x[e]})}function c(t,n){function i(e){if("string"==typeof e&&(e=e.split(k,2)),!v(e)||2!==e.length)throw new Error("Invalid tags: "+e);o=new RegExp(r(e[0])+"\\s*"),s=new RegExp("\\s*"+r(e[1])),u=new RegExp("\\s*"+r("}"+e[1]))}if(!t)return[];var o,s,u,c=[],f=[],d=[],g=!1,w=!1;i(n||e.tags);for(var y,x,T,j,S,V,C=new h(t);!C.eos();){if(y=C.pos,T=C.scanUntil(o))for(var O=0,P=T.length;O0?o[o.length-1][4]:r;break;default:i.push(t)}return r}function h(e){this.string=e,this.tail=e,this.pos=0}function f(e,t){this.view=e,this.cache={".":this.view},this.parent=t}function d(){this.cache={}}var g=Object.prototype.toString,v=Array.isArray||function(e){return"[object Array]"===g.call(e)},w=RegExp.prototype.test,y=/\S/,x={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="},b=/\s*/,k=/\s+/,m=/\s*=/,E=/\s*\}/,U=/#|\^|\/|>|\{|&|=|!/;h.prototype.eos=function(){return""===this.tail},h.prototype.scan=function(e){var t=this.tail.match(e);if(!t||0!==t.index)return"";var n=t[0];return this.tail=this.tail.substring(n.length),this.pos+=n.length,n},h.prototype.scanUntil=function(e){var t,n=this.tail.search(e);switch(n){case-1:t=this.tail,this.tail="";break;case 0:t="";break;default:t=this.tail.substring(0,n),this.tail=this.tail.substring(n)}return this.pos+=t.length,t},f.prototype.push=function(e){return new f(e,this)},f.prototype.lookup=function(e){var n,r=this.cache;if(r.hasOwnProperty(e))n=r[e];else{for(var s,a,u,c=this,p=!1;c;){if(e.indexOf(".")>0)for(s=c.view,a=e.split("."),u=0;null!=s&&u"===s?a=this.renderPartial(o,t,n,i):"&"===s?a=this.unescapedValue(o,t):"name"===s?a=this.escapedValue(o,t):"text"===s&&(a=this.rawValue(o)),void 0!==a&&(u+=a);return u},d.prototype.renderSection=function(e,n,r,i){function o(e){return s.render(e,n,r)}var s=this,a="",u=n.lookup(e[1]);if(u){if(v(u))for(var c=0,p=u.length;c0?i.toString():null,n(l,f),null,a(m));return c&&("string"==typeof c?u.setRawQuery(c.replace(/[^?&=0-9A-Za-z_\-~.%]/g,r)):u.setAllParameters(c)),u}function a(e){return"string"==typeof e?encodeURIComponent(e):null}function n(e,t){return"string"==typeof e?encodeURI(e).replace(t,r):null}function r(e){var t=e.charCodeAt(0);return"%"+"0123456789ABCDEF".charAt(t>>4&15)+"0123456789ABCDEF".charAt(15&t)}function o(e){return e.replace(/(^|\/)\.(?:\/|$)/g,"$1").replace(/\/{2,}/g,"/")}function i(e){if(null===e)return null;for(var t,a=o(e),n=u;(t=a.replace(n,"$1"))!=a;a=t);return a}function l(e,t){var a=e.clone(),n=t.hasScheme();n?a.setRawScheme(t.getRawScheme()):n=t.hasCredentials(),n?a.setRawCredentials(t.getRawCredentials()):n=t.hasDomain(),n?a.setRawDomain(t.getRawDomain()):n=t.hasPort();var r=t.getRawPath(),o=i(r);if(n)a.setPort(t.getPort()),o=o&&o.replace(h,"");else if(n=!!r){if(47!==o.charCodeAt(0)){var l=i(a.getRawPath()||"").replace(h,""),s=l.lastIndexOf("/")+1;o=i((s?l.substring(0,s):"")+i(r)).replace(h,"")}}else(o=o&&o.replace(h,""))!==r&&a.setRawPath(o);return n?a.setRawPath(o):n=t.hasQuery(),n?a.setRawQuery(t.getRawQuery()):n=t.hasFragment(),n&&a.setRawFragment(t.getRawFragment()),a}function s(e,t,a,n,r,o,i){this.scheme_=e,this.credentials_=t,this.domain_=a,this.port_=n,this.path_=r,this.query_=o,this.fragment_=i,this.paramCache_=null}function c(e){return"string"==typeof e&&e.length>0?e:null}var m=new RegExp("(/|^)(?:[^./][^/]*|\\.{2,}(?:[^./][^/]*)|\\.{3,}[^/]*)/\\.\\.(?:/|$)"),u=new RegExp(m),h=/^(?:\.\.\/)*(?:\.\.$)?/;s.prototype.toString=function(){var e=[];return null!==this.scheme_&&e.push(this.scheme_,":"),null!==this.domain_&&(e.push("//"),null!==this.credentials_&&e.push(this.credentials_,"@"),e.push(this.domain_),null!==this.port_&&e.push(":",this.port_.toString())),null!==this.path_&&e.push(this.path_),null!==this.query_&&e.push("?",this.query_),null!==this.fragment_&&e.push("#",this.fragment_),e.join("")},s.prototype.clone=function(){return new s(this.scheme_,this.credentials_,this.domain_,this.port_,this.path_,this.query_,this.fragment_)},s.prototype.getScheme=function(){return this.scheme_&&decodeURIComponent(this.scheme_).toLowerCase()},s.prototype.getRawScheme=function(){return this.scheme_},s.prototype.setScheme=function(e){return this.scheme_=n(e,d),this},s.prototype.setRawScheme=function(e){return this.scheme_=e||null,this},s.prototype.hasScheme=function(){return null!==this.scheme_},s.prototype.getCredentials=function(){return this.credentials_&&decodeURIComponent(this.credentials_)},s.prototype.getRawCredentials=function(){return this.credentials_},s.prototype.setCredentials=function(e){return this.credentials_=n(e,d),this},s.prototype.setRawCredentials=function(e){return this.credentials_=e||null,this},s.prototype.hasCredentials=function(){return null!==this.credentials_},s.prototype.getDomain=function(){return this.domain_&&decodeURIComponent(this.domain_)},s.prototype.getRawDomain=function(){return this.domain_},s.prototype.setDomain=function(e){return this.setRawDomain(e&&encodeURIComponent(e))},s.prototype.setRawDomain=function(e){return this.domain_=e||null,this.setRawPath(this.path_)},s.prototype.hasDomain=function(){return null!==this.domain_},s.prototype.getPort=function(){return this.port_&&decodeURIComponent(this.port_)},s.prototype.setPort=function(e){if(e){if((e=Number(e))!==(65535&e))throw new Error("Bad port number "+e);this.port_=""+e}else this.port_=null;return this},s.prototype.hasPort=function(){return null!==this.port_},s.prototype.getPath=function(){return this.path_&&decodeURIComponent(this.path_)},s.prototype.getRawPath=function(){return this.path_},s.prototype.setPath=function(e){return this.setRawPath(n(e,f))},s.prototype.setRawPath=function(e){return e?(e=String(e),this.path_=!this.domain_||/^\//.test(e)?e:"/"+e):this.path_=null,this},s.prototype.hasPath=function(){return null!==this.path_},s.prototype.getQuery=function(){return this.query_&&decodeURIComponent(this.query_).replace(/\+/g," ")},s.prototype.getRawQuery=function(){return this.query_},s.prototype.setQuery=function(e){return this.paramCache_=null,this.query_=a(e),this},s.prototype.setRawQuery=function(e){return this.paramCache_=null,this.query_=e||null,this},s.prototype.hasQuery=function(){return null!==this.query_},s.prototype.setAllParameters=function(e){if("object"==typeof e&&!(e instanceof Array)&&(e instanceof Object||"[object Array]"!==Object.prototype.toString.call(e))){var t=[],a=-1;for(var n in e){var r=e[n];"string"==typeof r&&(t[++a]=n,t[++a]=r)}e=t}this.paramCache_=null;for(var o=[],i="",l=0;l"===a[m+1]?(m+=2,s=i[1].toLowerCase(),t.endTag&&t.endTag(s,o,Y,c(t,a,m,r,o))):m=h(a,m,t,o,Y,r):t.pcdata&&t.pcdata("</",o,Y,c(t,a,m,r,o));break;case"<":if(i=/^([-\w:]+)\s*\/?/.exec(g))if(i[0].length===g.length&&">"===a[m+1]){m+=2,s=i[1].toLowerCase(),t.startTag&&t.startTag(s,[],o,Y,c(t,a,m,r,o));var E=e.ELEMENTS[s];if(E&j){var T={name:s,next:m,eflags:E};m=d(a,T,t,o,Y,r)}}else m=p(a,m,t,o,Y,r);else t.pcdata&&t.pcdata("<",o,Y,c(t,a,m,r,o));break;case"\x3c!--":if(!r.noMoreEndComments){for(l=m+1;l"!==a[l]||!/--$/.test(a[l-1]));l++);if(l"!==a[l];l++);l"!==a[l];l++);l":t.pcdata&&t.pcdata(">",o,Y,c(t,a,m,r,o));break;case"":break;default:t.pcdata&&t.pcdata(f,o,Y,c(t,a,m,r,o))}}t.endDoc&&t.endDoc(o)}catch(e){if(e!==Y)throw e}}function u(e){var t=/(<\/|<\!--|<[!?]|[&<>])/g;if(e+="",$)return e.split(t);for(var a,n=[],r=0;null!==(a=t.exec(e));)n.push(e.substring(r,a.index)),n.push(a[0]),r=a.index+a[0].length;return n.push(e.substring(r)),n}function h(e,t,a,n,r,o){var i=f(e,t);return i?(a.endTag&&a.endTag(i.name,n,r,c(a,e,t,o,n)),i.next):e.length}function p(e,t,a,n,r,o){var i=f(e,t);return i?(a.startTag&&a.startTag(i.name,i.attrs,n,r,c(a,e,i.next,o,n)),i.eflags&j?d(e,i,a,n,r,o):i.next):e.length}function d(t,a,n,r,o,l){var s=t.length;Q.hasOwnProperty(a.name)||(Q[a.name]=new RegExp("^"+a.name+"(?:[\\s\\/]|$)","i"));for(var m=Q[a.name],u=a.next,h=a.next+1;h"!==t[i];i++)o+=t[i];if(!(l<=i)){for(var s=[];""!==o;)if(n=G.exec(o)){if(n[4]&&!n[5]||n[6]&&!n[7]){for(var c=n[4]||n[6],m=!1,u=[o,t[i++]];i"===t[i])break}else 0<=t[i].indexOf(c)&&(m=!0);u.push(t[i])}if(l<=i)break;o=u.join("");continue}var h=n[1].toLowerCase(),p=n[2]?g(n[3]):"";s.push(h,p),o=o.substr(n[0].length)}else o=o.replace(/^[\s\S][^a-z\s]*/,"");return r.attrs=s,r.next=i+1,r}}function g(e){var t=e.charCodeAt(0);return 34!==t&&39!==t||(e=e.substr(1,e.length-2)),r(n(e))}function E(t){var a,n,r=function(e,t){n||t.push(e)};return l({startDoc:function(e){a=[],n=!1},startTag:function(r,i,l){if(!n&&e.ELEMENTS.hasOwnProperty(r)){var s=e.ELEMENTS[r];if(!(s&e.eflags.FOLDABLE)){var c=t(r,i);if(!c)return void(n=!(s&e.eflags.EMPTY));if("object"!=typeof c)throw new Error("tagPolicy did not return object (old API?)");if(!("attribs"in c))throw new Error("tagPolicy gave no attribs");i=c.attribs;var m,u;if("tagName"in c?(u=c.tagName,m=e.ELEMENTS[u]):(u=r,m=s),s&e.eflags.OPTIONAL_ENDTAG){var h=a[a.length-1];!h||h.orig!==r||h.rep===u&&r===u||l.push("")}s&e.eflags.EMPTY||a.push({orig:r,rep:u}),l.push("<",u);for(var p=0,d=i.length;p"),s&e.eflags.EMPTY&&!(m&e.eflags.EMPTY)&&l.push("")}}},endTag:function(t,r){if(n)return void(n=!1);if(e.ELEMENTS.hasOwnProperty(t)){var o=e.ELEMENTS[t];if(!(o&(e.eflags.EMPTY|e.eflags.FOLDABLE))){var i;if(o&e.eflags.OPTIONAL_ENDTAG)for(i=a.length;--i>=0;){var l=a[i].orig;if(l===t)break;if(!(e.ELEMENTS[l]&e.eflags.OPTIONAL_ENDTAG))return}else for(i=a.length;--i>=0&&a[i].orig!==t;);if(i<0)return;for(var s=a.length;--s>i;){var c=a[s].rep;e.ELEMENTS[c]&e.eflags.OPTIONAL_ENDTAG||r.push("")}i")}}},pcdata:r,rcdata:r,cdata:r,endDoc:function(e){for(;a.length;a.length--)e.push("")}})}function T(e,t,a,n,r){if(!r)return null;try{var o=URI.parse(""+e);if(o&&(!o.hasScheme()||V.test(o.getScheme()))){var i=r(o,t,a,n);return i?i.toString():null}}catch(e){return null}return null}function L(e,t,a,n,r){if(a||e(t+" removed",{change:"removed",tagName:t}),n!==r){var o="changed";n&&!r?o="removed":!n&&r&&(o="added"),e(t+"."+a+" "+o,{change:o,tagName:t,attribName:a,oldValue:n,newValue:r})}}function M(e,t,a){var n;return n=t+"::"+a,e.hasOwnProperty(n)?e[n]:(n="*::"+a,e.hasOwnProperty(n)?e[n]:void 0)}function b(t,a){return M(e.LOADERTYPES,t,a)}function y(t,a){return M(e.URIEFFECTS,t,a)}function v(t,a,n,r,o){for(var i=0;i0?h.join(" ; "):null,o&&L(o,t,s,m,c);break;case e.atype.ID:case e.atype.IDREF:case e.atype.IDREFS:case e.atype.GLOBAL_NAME:case e.atype.LOCAL_NAME:case e.atype.CLASSES:c=r?r(c):c,o&&L(o,t,s,m,c);break;case e.atype.URI:c=T(c,y(t,s),b(t,s),{TYPE:"MARKUP",XML_ATTR:s,XML_TAG:t},n),o&&L(o,t,s,m,c);break;case e.atype.URI_FRAGMENT:c&&"#"===c.charAt(0)?(c=c.substring(1),null!==(c=r?r(c):c)&&void 0!==c&&(c="#"+c)):c=null,o&&L(o,t,s,m,c);break;default:c=null,o&&L(o,t,s,m,c)}else c=null,o&&L(o,t,s,m,c);a[i+1]=c}return a}function H(t,a,n){return function(r,o){if(!(e.ELEMENTS[r]&e.eflags.UNSAFE))return{attribs:v(r,o,t,a,n)};n&&L(n,r,void 0,void 0,void 0)}}function _(e,t){var a=[];return E(t)(e,a),a.join("")}function w(e,t,a,n){return _(e,H(t,a,n))}var A,R,C;"undefined"!=typeof window&&(A=window.parseCssDeclarations,R=window.sanitizeCssProperty,C=window.cssSchema);var S={lt:"<",LT:"<",gt:">",GT:">",amp:"&",AMP:"&",quot:'"',apos:"'",nbsp:" "},P=/^#(\d+)$/,D=/^#x([0-9A-Fa-f]+)$/,k=/^[A-Za-z][A-za-z0-9]+$/,I="undefined"!=typeof window&&window.document?window.document.createElement("textarea"):null,x=/\0/g,N=/&(#[0-9]+|#[xX][0-9A-Fa-f]+|\w+);/g,O=/^(#[0-9]+|#[xX][0-9A-Fa-f]+|\w+);/,F=/&/g,U=/&([^a-z#]|#(?:[^0-9x]|x(?:[^0-9a-f]|$)|$)|$)/gi,B=/[<]/g,q=/>/g,z=/\"/g,G=new RegExp("^\\s*([-.:\\w]+)(?:\\s*(=)\\s*((\")[^\"]*(\"|$)|(')[^']*('|$)|(?=[a-z][-\\w]*\\s*=)|[^\"'\\s]*))?","i"),$=3==="a,b".split(/(,)/).length,j=e.eflags.CDATA|e.eflags.RCDATA,Y={},Q={},V=/^(?:https?|mailto|data)$/i,X={};return X.escapeAttrib=X.escapeAttrib=o,X.makeHtmlSanitizer=X.makeHtmlSanitizer=E,X.makeSaxParser=X.makeSaxParser=l,X.makeTagPolicy=X.makeTagPolicy=H,X.normalizeRCData=X.normalizeRCData=i,X.sanitize=X.sanitize=w,X.sanitizeAttribs=X.sanitizeAttribs=v,X.sanitizeWithPolicy=X.sanitizeWithPolicy=_,X.unescapeEntities=X.unescapeEntities=r,X}(html4),html_sanitize=html.sanitize;html4.ATTRIBS["*::style"]=0,html4.ELEMENTS.style=0,html4.ATTRIBS["a::target"]=0,html4.ELEMENTS.video=0,html4.ATTRIBS["video::src"]=0,html4.ATTRIBS["video::poster"]=0,html4.ATTRIBS["video::controls"]=0,html4.ELEMENTS.audio=0,html4.ATTRIBS["audio::src"]=0,html4.ATTRIBS["video::autoplay"]=0,html4.ATTRIBS["video::controls"]=0,"undefined"!=typeof module&&(module.exports=html_sanitize); +},{}],6:[function(require,module,exports){ +module.exports={"author":"Mapbox","name":"mapbox.js","description":"Mapbox plugin for Leaflet","version":"3.2.0","homepage":"http://mapbox.com/","repository":{"type":"git","url":"git://github.com/mapbox/mapbox.js.git"},"main":"src/index.js","files":["dist","src","*.md"],"dependencies":{"corslite":"0.0.7","leaflet":"1.4.0","mustache":"3.0.1","sanitize-caja":"0.1.4"},"scripts":{"test":"eslint src && phantomjs node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html","prepublishOnly":"npm run build","build":"make"},"license":"BSD-3-Clause","devDependencies":{"browserify":"^16.2.3","clean-css-cli":"^4.2.1","eslint":"^5.14.1","expect.js":"0.3.1","happen":"0.3.2","marked":"~0.6.1","minifyify":"^7.3.5","minimist":"1.2.0","mocha":"6.0.1","mocha-phantomjs-core":"2.1.2","phantomjs-prebuilt":"2.1.16","sinon":"7.2.4"},"optionalDependencies":{}} +},{}],7:[function(require,module,exports){ +"use strict";module.exports={HTTP_URL:"http://a.tiles.mapbox.com/v4",HTTPS_URL:"https://a.tiles.mapbox.com/v4",FORCE_HTTPS:!0,REQUIRE_ACCESS_TOKEN:!0}; +},{}],8:[function(require,module,exports){ +"use strict";var util=require("./util"),format_url=require("./format_url"),request=require("./request"),marker=require("./marker"),simplestyle=require("./simplestyle"),FeatureLayer=L.FeatureGroup.extend({options:{filter:function(){return!0},sanitizer:require("sanitize-caja"),style:simplestyle.style,popupOptions:{closeButton:!1}},initialize:function(e,t){L.setOptions(this,t),this._layers={},"string"==typeof e?util.idUrl(e,this):e&&"object"==typeof e&&this.setGeoJSON(e)},setGeoJSON:function(e){return this._geojson=e,this.clearLayers(),this._initialize(e),this},getGeoJSON:function(){return this._geojson},loadURL:function(e){return this._request&&"abort"in this._request&&this._request.abort(),this._request=request(e,L.bind(function(t,i){this._request=null,t&&"abort"!==t.type?(util.log("could not load features at "+e),this.fire("error",{error:t})):i&&(this.setGeoJSON(i),this.fire("ready"))},this)),this},loadID:function(e){return this.loadURL(format_url("/v4/"+e+"/features.json",this.options.accessToken))},setFilter:function(e){return this.options.filter=e,this._geojson&&(this.clearLayers(),this._initialize(this._geojson)),this},getFilter:function(){return this.options.filter},_initialize:function(e){var t,i,r=L.Util.isArray(e)?e:e.features;if(r)for(t=0,i=r.length;t1?(this.fire("found",{results:e.results}),this._displayResults(i)):(this.fire("notfound"),this._displayResults(i))}},_updateAutocomplete:function(t,e){if(this._results.innerHTML="",t||!e)this.fire("error",{error:t});else{var i=[];e.results&&e.results.features&&(i=e.results.features),i.length?this.fire("found",{results:e.results}):this.fire("notfound"),this._displayResults(i)}},_displayResults:function(t){for(var e=0,i=Math.min(t.length,5);e5){L.DomUtil.create("span","",this._results).innerHTML="Top 5 of "+t.length+" results"}},_chooseResult:function(t){t.bbox?this._map.fitBounds(util.lbounds(t.bbox)):t.center&&this._map.setView([t.center[1],t.center[0]],void 0===this._map.getZoom()?this.options.pointZoom:Math.max(this._map.getZoom(),this.options.pointZoom))},_geocode:function(t){if(L.DomEvent.preventDefault(t),""===this._input.value)return this._updateSubmit();L.DomUtil.addClass(this._container,"searching"),this.geocoder.query(L.Util.extend({query:this._input.value,proximity:!!this.options.proximity&&this._map.getCenter()},this.options.queryOptions),this._updateSubmit)},_autocomplete:function(){if(this.options.autocomplete)return""===this._input.value?this._updateAutocomplete():void this.geocoder.query(L.Util.extend({query:this._input.value,proximity:!!this.options.proximity&&this._map.getCenter()},this.options.queryOptions),this._updateAutocomplete)}});module.exports.GeocoderControl=GeocoderControl,module.exports.geocoderControl=function(t,e){return new GeocoderControl(t,e)}; +},{"./geocoder":11,"./util":29}],13:[function(require,module,exports){ +"use strict";function utfDecode(t){return t>=93&&t--,t>=35&&t--,t-32}module.exports=function(t){return function(e,r){if(t){var u=utfDecode(t.grid[r].charCodeAt(e)),n=t.keys[u];return t.data[n]}}}; +},{}],14:[function(require,module,exports){ +"use strict";var util=require("./util"),Mustache=require("mustache"),GridControl=L.Control.extend({options:{pinnable:!0,follow:!1,sanitizer:require("sanitize-caja"),touchTeaser:!0,location:!0},_currentContent:"",_pinned:!1,initialize:function(t,o){L.Util.setOptions(this,o),util.strict_instance(t,L.Class,"L.mapbox.gridLayer"),this._layer=t},setTemplate:function(t){return util.strict(t,"string"),this.options.template=t,this},_template:function(t,o){if(o){var i=this.options.template||this._layer.getTileJSON().template;if(i){var e={};return e["__"+t+"__"]=!0,this.options.sanitizer(Mustache.to_html(i,L.extend(e,o)))}}},_show:function(t,o){t!==this._currentContent&&(this._currentContent=t,this.options.follow?(this._popup.setContent(t).setLatLng(o.latLng),this._map._popup!==this._popup&&this._popup.openOn(this._map)):(this._container.style.display="block",this._contentWrapper.innerHTML=t))},hide:function(){return this._pinned=!1,this._currentContent="",this._map.closePopup(),this._container.style.display="none",this._contentWrapper.innerHTML="",L.DomUtil.removeClass(this._container,"closable"),this},_mouseover:function(t){if(t.data?L.DomUtil.addClass(this._map._container,"map-clickable"):L.DomUtil.removeClass(this._map._container,"map-clickable"),!this._pinned){var o=this._template("teaser",t.data);o?this._show(o,t):this.hide()}},_mousemove:function(t){this._pinned||this.options.follow&&this._popup.setLatLng(t.latLng)},_navigateTo:function(t){window.top.location.href=t},_click:function(t){var o=this._template("location",t.data);if(this.options.location&&o&&0===o.search(/^https?:/))return this._navigateTo(this._template("location",t.data));if(this.options.pinnable){var i=this._template("full",t.data);!i&&this.options.touchTeaser&&L.Browser.touch&&(i=this._template("teaser",t.data)),i?(L.DomUtil.addClass(this._container,"closable"),this._pinned=!0,this._show(i,t)):this._pinned&&(L.DomUtil.removeClass(this._container,"closable"),this._pinned=!1,this.hide())}},_onPopupClose:function(){this._currentContent=null,this._pinned=!1},_createClosebutton:function(t,o){var i=L.DomUtil.create("a","close",t);return i.innerHTML="close",i.href="#",i.title="close",L.DomEvent.on(i,"click",L.DomEvent.stopPropagation).on(i,"mousedown",L.DomEvent.stopPropagation).on(i,"dblclick",L.DomEvent.stopPropagation).on(i,"click",L.DomEvent.preventDefault).on(i,"click",o,this),i},onAdd:function(t){this._map=t;var o=L.DomUtil.create("div","leaflet-control-grid map-tooltip"),i=L.DomUtil.create("div","map-tooltip-content");return o.style.display="none",this._createClosebutton(o,this.hide),o.appendChild(i),this._contentWrapper=i,this._popup=new L.Popup({autoPan:!1,closeOnClick:!1}),t.on("popupclose",this._onPopupClose,this),L.DomEvent.disableClickPropagation(o).addListener(o,"mousewheel",L.DomEvent.stopPropagation),this._layer.on("mouseover",this._mouseover,this).on("mousemove",this._mousemove,this).on("click",this._click,this),o},onRemove:function(t){t.off("popupclose",this._onPopupClose,this),this._layer.off("mouseover",this._mouseover,this).off("mousemove",this._mousemove,this).off("click",this._click,this)}});module.exports.GridControl=GridControl,module.exports.gridControl=function(t,o){return new GridControl(t,o)}; +},{"./util":29,"mustache":3,"sanitize-caja":4}],15:[function(require,module,exports){ +"use strict";var util=require("./util"),request=require("./request"),grid=require("./grid"),GridLayer=L.Layer.extend({includes:[require("./load_tilejson")],options:{template:function(){return""}},_mouseOn:null,_tilejson:{},_cache:{},initialize:function(t,i){L.Util.setOptions(this,i),this._loadTileJSON(t)},_setTileJSON:function(t){return util.strict(t,"object"),L.extend(this.options,{grids:t.grids,minZoom:t.minzoom,maxZoom:t.maxzoom,bounds:t.bounds&&util.lbounds(t.bounds)}),this._tilejson=t,this._cache={},this._update(),this},getTileJSON:function(){return this._tilejson},active:function(){return!!(this._map&&this.options.grids&&this.options.grids.length)},onAdd:function(t){this._map=t,this._update(),this._map.on("click",this._click,this).on("mousemove",this._move,this).on("moveend",this._update,this)},onRemove:function(){this._map.off("click",this._click,this).off("mousemove",this._move,this).off("moveend",this._update,this)},getData:function(t,i){if(this.active()){var e=this._map,o=e.project(t.wrap()),s=Math.floor(o.x/256),n=Math.floor(o.y/256),a=e.options.crs.scale(e.getZoom())/256;return s=(s+a)%a,n=(n+a)%a,this._getTile(e.getZoom(),s,n,function(t){var e=Math.floor((o.x-256*s)/4),a=Math.floor((o.y-256*n)/4);i(t(e,a))}),this}},_click:function(t){this.getData(t.latlng,L.bind(function(i){this.fire("click",{latLng:t.latlng,data:i})},this))},_move:function(t){this.getData(t.latlng,L.bind(function(i){i!==this._mouseOn?(this._mouseOn&&this.fire("mouseout",{latLng:t.latlng,data:this._mouseOn}),this.fire("mouseover",{latLng:t.latlng,data:i}),this._mouseOn=i):this.fire("mousemove",{latLng:t.latlng,data:i})},this))},_getTileURL:function(t){var i=this.options.grids,e=(t.x+t.y)%i.length,o=i[e];return L.Util.template(o,t)},_update:function(){if(this.active()){var t=this._map.getPixelBounds(),i=this._map.getZoom();if(!(i>this.options.maxZoom||ithis.options.maxZoom||t.z640?L.DomUtil.removeClass(this.attributionControl._container,"leaflet-compact-attribution"):L.DomUtil.addClass(this.attributionControl._container,"leaflet-compact-attribution")})}this.options.tileLayer&&(this.tileLayer=tileLayer(void 0,withAccessToken(this.options.tileLayer,this.options.accessToken)),this.addLayer(this.tileLayer)),this.options.featureLayer&&(this.featureLayer=featureLayer(void 0,withAccessToken(this.options.featureLayer,this.options.accessToken)),this.addLayer(this.featureLayer)),this.options.gridLayer&&(this.gridLayer=gridLayer(void 0,withAccessToken(this.options.gridLayer,this.options.accessToken)),this.addLayer(this.gridLayer)),this.options.gridLayer&&this.options.gridControl&&(this.gridControl=gridControl(this.gridLayer,this.options.gridControl),this.addControl(this.gridControl)),this.options.legendControl&&(this.legendControl=legendControl(this.options.legendControl),this.addControl(this.legendControl)),this.options.shareControl&&(this.shareControl=shareControl(void 0,withAccessToken(this.options.shareControl,this.options.accessToken)),this.addControl(this.shareControl)),this._mapboxLogoControl=mapboxLogoControl(this.options.mapboxLogoControl),this.addControl(this._mapboxLogoControl),this._loadTileJSON(e),this.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this).on("moveend",this._updateMapFeedbackLink,this),this.whenReady(function(){feedback.on("change",this._updateMapFeedbackLink,this)}),this.on("unload",function(){feedback.off("change",this._updateMapFeedbackLink,this)})},_setTileJSON:function(t){return this._tilejson=t,this._initialize(t),this},getTileJSON:function(){return this._tilejson},_initialize:function(t){if(this.tileLayer&&(this.tileLayer._setTileJSON(t),this._updateLayer(this.tileLayer)),this.featureLayer&&!this.featureLayer.getGeoJSON()&&t.data&&t.data[0]&&this.featureLayer.loadURL(t.data[0]),this.gridLayer&&(this.gridLayer._setTileJSON(t),this._updateLayer(this.gridLayer)),this.legendControl&&t.legend&&this.legendControl.addLegend(t.legend),this.shareControl&&this.shareControl._setTileJSON(t),this._mapboxLogoControl._setTileJSON(t),!this._loaded&&t.center){var e=void 0!==this.getZoom()?this.getZoom():t.center[2],o=L.latLng(t.center[1],t.center[0]);this.setView(o,e)}},_updateMapFeedbackLink:function(){if(this._controlContainer.getElementsByClassName){var t=this._controlContainer.getElementsByClassName("mapbox-improve-map");if(t.length&&this._loaded){var e=this.getCenter().wrap(),o=this._tilejson||{},i=o.id||"",r="#"+i+"/"+e.lng.toFixed(3)+"/"+e.lat.toFixed(3)+"/"+this.getZoom();for(var a in feedback.data)r+="/"+a+"="+feedback.data[a];for(var n=0;n"),r.properties.description&&(i+='
'+r.properties.description+"
"),(e||sanitize)(i)}var format_url=require("./format_url"),util=require("./util"),sanitize=require("sanitize-caja");module.exports={icon:icon,style:style,createPopup:createPopup}; +},{"./format_url":10,"./util":29,"sanitize-caja":4}],24:[function(require,module,exports){ +"use strict";var corslite=require("corslite"),strict=require("./util").strict,config=require("./config"),protocol=/^(https?:)?(?=\/\/(.|api)\.tiles\.mapbox\.com\/)/;module.exports=function(t,o){function r(t,r){!t&&r&&(r=JSON.parse(r.responseText)),o(t,r)}return strict(t,"string"),strict(o,"function"),t=t.replace(protocol,function(t,o){return"withCredentials"in new window.XMLHttpRequest?"https:"===o||"https:"===document.location.protocol||config.FORCE_HTTPS?"https:":"http:":document.location.protocol}),corslite(t,r)}; +},{"./config":7,"./util":29,"corslite":1}],25:[function(require,module,exports){ +"use strict";var format_url=require("./format_url"),ShareControl=L.Control.extend({includes:[require("./load_tilejson")],options:{position:"topleft",url:""},initialize:function(t,e){L.setOptions(this,e),this._loadTileJSON(t)},_setTileJSON:function(t){this._tilejson=t},onAdd:function(t){this._map=t;var e=L.DomUtil.create("div","leaflet-control-mapbox-share leaflet-bar"),o=L.DomUtil.create("a","mapbox-share mapbox-icon mapbox-icon-share",e);return o.href="#",this._modal=L.DomUtil.create("div","mapbox-modal",this._map._container),this._mask=L.DomUtil.create("div","mapbox-modal-mask",this._modal),this._content=L.DomUtil.create("div","mapbox-modal-content",this._modal),L.DomEvent.addListener(o,"click",this._shareClick,this),L.DomEvent.disableClickPropagation(e),this._map.on("mousedown",this._clickOut,this),e},_clickOut:function(t){if(this._sharing)return L.DomEvent.preventDefault(t),L.DomUtil.removeClass(this._modal,"active"),this._content.innerHTML="",void(this._sharing=null)},_shareClick:function(t){function e(t,e,o){var i=document.createElement("a");return i.setAttribute("class",t),i.setAttribute("href",e),i.setAttribute("target","_blank"),o=document.createTextNode(o),i.appendChild(o),i}if(L.DomEvent.stop(t),this._sharing)return this._clickOut(t);var o=this._tilejson||this._map._tilejson||{},i=encodeURIComponent(this.options.url||o.webpage||window.location),a=encodeURIComponent(o.name),n=format_url("/v4/"+o.id+"/"+this._map.getCenter().lng+","+this._map.getCenter().lat+","+this._map.getZoom()+"/600x600.png",this.options.accessToken),r=format_url("/v4/"+o.id+".html",this.options.accessToken),s="//twitter.com/intent/tweet?status="+a+" "+i,l="//www.facebook.com/sharer.php?u="+i+"&t="+a,m="//www.pinterest.com/pin/create/button/?url="+i+"&media="+n+"&description="+a,c='';L.DomUtil.addClass(this._modal,"active"),this._sharing=L.DomUtil.create("div","mapbox-modal-body",this._content);var h=e("mapbox-button mapbox-button-icon mapbox-icon-twitter",s,"Twitter"),p=e("mapbox-button mapbox-button-icon mapbox-icon-facebook",l,"Facebook"),d=e("mapbox-button mapbox-button-icon mapbox-icon-pinterest",m,"Pinterest"),u=document.createElement("h3"),b=document.createTextNode("Share this map");u.appendChild(b);var _=document.createElement("div");_.setAttribute("class","mapbox-share-buttons"),_.appendChild(p),_.appendChild(h),_.appendChild(d),this._sharing.appendChild(u),this._sharing.appendChild(_);var v=L.DomUtil.create("input","mapbox-embed",this._sharing);v.type="text",v.value=c,L.DomUtil.create("label","mapbox-embed-description",this._sharing).innerHTML="Copy and paste this HTML code into documents to embed this map on web pages.";var f=L.DomUtil.create("a","leaflet-popup-close-button",this._sharing);f.href="#",L.DomEvent.disableClickPropagation(this._sharing),L.DomEvent.addListener(f,"click",this._clickOut,this),L.DomEvent.addListener(v,"click",function(t){t.target.focus(),t.target.select()})}});module.exports.ShareControl=ShareControl,module.exports.shareControl=function(t,e){return new ShareControl(t,e)}; +},{"./format_url":10,"./load_tilejson":19}],26:[function(require,module,exports){ +"use strict";function fallback(t,l){var i={};for(var r in l)void 0===t[r]?i[r]=l[r]:i[r]=t[r];return i}function remap(t){for(var l={},i=0;i/g,"")},lbounds:function(n){return new L.LatLngBounds([[n[1],n[0]],[n[3],n[2]]])}}; +},{}]},{},[16]) + + +//# sourceMappingURL=mapbox.js.map \ No newline at end of file diff --git a/gui-src/js/maps/proj4-src.js b/gui-src/js/maps/proj4-src.js new file mode 100644 index 0000000..06bfdc5 --- /dev/null +++ b/gui-src/js/maps/proj4-src.js @@ -0,0 +1,5733 @@ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.proj4=e():"undefined"!=typeof global?global.proj4=e():"undefined"!=typeof self&&(self.proj4=e())}(function(){var define,module,exports; +return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0) || (srsCode.indexOf('GEOCCS') >= 0) || (srsCode.indexOf('PROJCS') >= 0) || (srsCode.indexOf('LOCAL_CS') >= 0)) { + obj = wkt(srsCode); + this.deriveConstants(obj); + extend(this, obj); + //this.loadProjCode(this.projName); + } + else if (srsCode[0] === '+') { + obj = projStr(srsCode); + this.deriveConstants(obj); + extend(this, obj); + } + } + else { + this.deriveConstants(srsCode); + extend(this, srsCode); + } + + this.initTransforms(this.projName); +} +Projection.projections = projections; +Projection.projections.start(); +Projection.prototype = { + /** + * Function: initTransforms + * Finalize the initialization of the Proj object + * + */ + initTransforms: function(projName) { + var ourProj = Projection.projections.get(projName); + if (ourProj) { + extend(this, ourProj); + this.init(); + } + else { + throw ("unknown projection " + projName); + } + }, + + deriveConstants: function(self) { + // DGR 2011-03-20 : nagrids -> nadgrids + if (self.nadgrids && self.nadgrids.length === 0) { + self.nadgrids = null; + } + if (self.nadgrids) { + self.grids = self.nadgrids.split(","); + var g = null, + l = self.grids.length; + if (l > 0) { + for (var i = 0; i < l; i++) { + g = self.grids[i]; + var fg = g.split("@"); + if (fg[fg.length - 1] === "") { + //..reportError("nadgrids syntax error '" + self.nadgrids + "' : empty grid found"); + continue; + } + self.grids[i] = { + mandatory: fg.length === 1, //@=> optional grid (no error if not found) + name: fg[fg.length - 1], + grid: constants.grids[fg[fg.length - 1]] //FIXME: grids loading ... + }; + if (self.grids[i].mandatory && !self.grids[i].grid) { + //..reportError("Missing '" + self.grids[i].name + "'"); + } + } + } + // DGR, 2011-03-20: grids is an array of objects that hold + // the loaded grids, its name and the mandatory informations of it. + } + if (self.datumCode && self.datumCode !== 'none') { + var datumDef = constants.Datum[self.datumCode]; + if (datumDef) { + self.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null; + self.ellps = datumDef.ellipse; + self.datumName = datumDef.datumName ? datumDef.datumName : self.datumCode; + } + } + if (!self.a) { // do we have an ellipsoid? + var ellipse = constants.Ellipsoid[self.ellps] ? constants.Ellipsoid[self.ellps] : constants.Ellipsoid.WGS84; + extend(self, ellipse); + } + if (self.rf && !self.b) { + self.b = (1.0 - 1.0 / self.rf) * self.a; + } + if (self.rf === 0 || Math.abs(self.a - self.b) < common.EPSLN) { + self.sphere = true; + self.b = self.a; + } + self.a2 = self.a * self.a; // used in geocentric + self.b2 = self.b * self.b; // used in geocentric + self.es = (self.a2 - self.b2) / self.a2; // e ^ 2 + self.e = Math.sqrt(self.es); // eccentricity + if (self.R_A) { + self.a *= 1 - self.es * (common.SIXTH + self.es * (common.RA4 + self.es * common.RA6)); + self.a2 = self.a * self.a; + self.b2 = self.b * self.b; + self.es = 0; + } + self.ep2 = (self.a2 - self.b2) / self.b2; // used in geocentric + if (!self.k0) { + self.k0 = 1.0; //default value + } + //DGR 2010-11-12: axis + if (!self.axis) { + self.axis = "enu"; + } + + self.datum = datum(self); + } +}; +module.exports = Projection; + +},{"./common":4,"./constants/index":9,"./datum":11,"./defs":13,"./extend":14,"./projString":18,"./projections/index":27,"./wkt":47}],3:[function(require,module,exports){ +module.exports = function(crs, denorm, point) { + var xin = point.x, + yin = point.y, + zin = point.z || 0.0; + var v, t, i; + for (i = 0; i < 3; i++) { + if (denorm && i === 2 && point.z === undefined) { + continue; + } + if (i === 0) { + v = xin; + t = 'x'; + } + else if (i === 1) { + v = yin; + t = 'y'; + } + else { + v = zin; + t = 'z'; + } + switch (crs.axis[i]) { + case 'e': + point[t] = v; + break; + case 'w': + point[t] = -v; + break; + case 'n': + point[t] = v; + break; + case 's': + point[t] = -v; + break; + case 'u': + if (point[t] !== undefined) { + point.z = v; + } + break; + case 'd': + if (point[t] !== undefined) { + point.z = -v; + } + break; + default: + //console.log("ERROR: unknow axis ("+crs.axis[i]+") - check definition of "+crs.projName); + return null; + } + } + return point; +}; + +},{}],4:[function(require,module,exports){ +exports.PI = 3.141592653589793238; //Math.PI; +exports.HALF_PI = 1.570796326794896619; //Math.PI*0.5; +exports.TWO_PI = 6.283185307179586477; //Math.PI*2; +exports.FORTPI = 0.78539816339744833; +exports.R2D = 57.29577951308232088; +exports.D2R = 0.01745329251994329577; +exports.SEC_TO_RAD = 4.84813681109535993589914102357e-6; +/* SEC_TO_RAD = Pi/180/3600 */ +exports.EPSLN = 1.0e-10; +exports.MAX_ITER = 20; +// following constants from geocent.c +exports.COS_67P5 = 0.38268343236508977; +/* cosine of 67.5 degrees */ +exports.AD_C = 1.0026000; +/* Toms region 1 constant */ + +/* datum_type values */ +exports.PJD_UNKNOWN = 0; +exports.PJD_3PARAM = 1; +exports.PJD_7PARAM = 2; +exports.PJD_GRIDSHIFT = 3; +exports.PJD_WGS84 = 4; // WGS84 or equivalent +exports.PJD_NODATUM = 5; // WGS84 or equivalent +exports.SRS_WGS84_SEMIMAJOR = 6378137; // only used in grid shift transforms +exports.SRS_WGS84_ESQUARED = 0.006694379990141316; //DGR: 2012-07-29 + +// ellipoid pj_set_ell.c +exports.SIXTH = 0.1666666666666666667; +/* 1/6 */ +exports.RA4 = 0.04722222222222222222; +/* 17/360 */ +exports.RA6 = 0.02215608465608465608; +/* 67/3024 */ +exports.RV4 = 0.06944444444444444444; +/* 5/72 */ +exports.RV6 = 0.04243827160493827160; +/* 55/1296 */ + +// Function to compute the constant small m which is the radius of +// a parallel of latitude; phi; divided by the semimajor axis. +// ----------------------------------------------------------------- +exports.msfnz = function(eccent, sinphi, cosphi) { + var con = eccent * sinphi; + return cosphi / (Math.sqrt(1 - con * con)); +}; + +// Function to compute the constant small t for use in the forward +// computations in the Lambert Conformal Conic and the Polar +// Stereographic projections. +// ----------------------------------------------------------------- +exports.tsfnz = function(eccent, phi, sinphi) { + var con = eccent * sinphi; + var com = 0.5 * eccent; + con = Math.pow(((1 - con) / (1 + con)), com); + return (Math.tan(0.5 * (this.HALF_PI - phi)) / con); +}; + +// Function to compute the latitude angle; phi2; for the inverse of the +// Lambert Conformal Conic and Polar Stereographic projections. +// ---------------------------------------------------------------- +exports.phi2z = function(eccent, ts) { + var eccnth = 0.5 * eccent; + var con, dphi; + var phi = this.HALF_PI - 2 * Math.atan(ts); + for (var i = 0; i <= 15; i++) { + con = eccent * Math.sin(phi); + dphi = this.HALF_PI - 2 * Math.atan(ts * (Math.pow(((1 - con) / (1 + con)), eccnth))) - phi; + phi += dphi; + if (Math.abs(dphi) <= 0.0000000001) { + return phi; + } + } + //console.log("phi2z has NoConvergence"); + return -9999; +}; + +/* Function to compute constant small q which is the radius of a + parallel of latitude, phi, divided by the semimajor axis. +------------------------------------------------------------*/ +exports.qsfnz = function(eccent, sinphi) { + var con; + if (eccent > 1.0e-7) { + con = eccent * sinphi; + return ((1 - eccent * eccent) * (sinphi / (1 - con * con) - (0.5 / eccent) * Math.log((1 - con) / (1 + con)))); + } + else { + return (2 * sinphi); + } +}; + +/* Function to compute the inverse of qsfnz +------------------------------------------------------------*/ +exports.iqsfnz = function(eccent, q) { + var temp = 1 - (1 - eccent * eccent) / (2 * eccent) * Math.log((1 - eccent) / (1 + eccent)); + if (Math.abs(Math.abs(q) - temp) < 1.0E-6) { + if (q < 0) { + return (-1 * exports.HALF_PI); + } + else { + return exports.HALF_PI; + } + } + //var phi = 0.5* q/(1-eccent*eccent); + var phi = Math.asin(0.5 * q); + var dphi; + var sin_phi; + var cos_phi; + var con; + for (var i = 0; i < 30; i++) { + sin_phi = Math.sin(phi); + cos_phi = Math.cos(phi); + con = eccent * sin_phi; + dphi = Math.pow(1 - con * con, 2) / (2 * cos_phi) * (q / (1 - eccent * eccent) - sin_phi / (1 - con * con) + 0.5 / eccent * Math.log((1 - con) / (1 + con))); + phi += dphi; + if (Math.abs(dphi) <= 0.0000000001) { + return phi; + } + } + + //console.log("IQSFN-CONV:Latitude failed to converge after 30 iterations"); + return NaN; +}; + +/* Function to eliminate roundoff errors in asin +----------------------------------------------*/ +exports.asinz = function(x) { + if (Math.abs(x) > 1) { + x = (x > 1) ? 1 : -1; + } + return Math.asin(x); +}; + +// following functions from gctpc cproj.c for transverse mercator projections +exports.e0fn = function(x) { + return (1 - 0.25 * x * (1 + x / 16 * (3 + 1.25 * x))); +}; +exports.e1fn = function(x) { + return (0.375 * x * (1 + 0.25 * x * (1 + 0.46875 * x))); +}; +exports.e2fn = function(x) { + return (0.05859375 * x * x * (1 + 0.75 * x)); +}; +exports.e3fn = function(x) { + return (x * x * x * (35 / 3072)); +}; +exports.mlfn = function(e0, e1, e2, e3, phi) { + return (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi)); +}; +exports.imlfn = function(ml, e0, e1, e2, e3) { + var phi; + var dphi; + + phi = ml / e0; + for (var i = 0; i < 15; i++) { + dphi = (ml - (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi))) / (e0 - 2 * e1 * Math.cos(2 * phi) + 4 * e2 * Math.cos(4 * phi) - 6 * e3 * Math.cos(6 * phi)); + phi += dphi; + if (Math.abs(dphi) <= 0.0000000001) { + return phi; + } + } + + //..reportError("IMLFN-CONV:Latitude failed to converge after 15 iterations"); + return NaN; +}; + +exports.srat = function(esinp, exp) { + return (Math.pow((1 - esinp) / (1 + esinp), exp)); +}; + +// Function to return the sign of an argument +exports.sign = function(x) { + if (x < 0) { + return (-1); + } + else { + return (1); + } +}; + +// Function to adjust longitude to -180 to 180; input in radians +exports.adjust_lon = function(x) { + x = (Math.abs(x) < this.PI) ? x : (x - (this.sign(x) * this.TWO_PI)); + return x; +}; + +// IGNF - DGR : algorithms used by IGN France + +// Function to adjust latitude to -90 to 90; input in radians +exports.adjust_lat = function(x) { + x = (Math.abs(x) < this.HALF_PI) ? x : (x - (this.sign(x) * this.PI)); + return x; +}; + +// Latitude Isometrique - close to tsfnz ... +exports.latiso = function(eccent, phi, sinphi) { + if (Math.abs(phi) > this.HALF_PI) { + return Number.NaN; + } + if (phi === this.HALF_PI) { + return Number.POSITIVE_INFINITY; + } + if (phi === -1 * this.HALF_PI) { + return Number.NEGATIVE_INFINITY; + } + + var con = eccent * sinphi; + return Math.log(Math.tan((this.HALF_PI + phi) / 2)) + eccent * Math.log((1 - con) / (1 + con)) / 2; +}; + +exports.fL = function(x, L) { + return 2 * Math.atan(x * Math.exp(L)) - this.HALF_PI; +}; + +// Inverse Latitude Isometrique - close to ph2z +exports.invlatiso = function(eccent, ts) { + var phi = this.fL(1, ts); + var Iphi = 0; + var con = 0; + do { + Iphi = phi; + con = eccent * Math.sin(Iphi); + phi = this.fL(Math.exp(eccent * Math.log((1 + con) / (1 - con)) / 2), ts); + } while (Math.abs(phi - Iphi) > 1.0e-12); + return phi; +}; + +// Needed for Gauss Schreiber +// Original: Denis Makarov (info@binarythings.com) +// Web Site: http://www.binarythings.com +exports.sinh = function(x) { + var r = Math.exp(x); + r = (r - 1 / r) / 2; + return r; +}; + +exports.cosh = function(x) { + var r = Math.exp(x); + r = (r + 1 / r) / 2; + return r; +}; + +exports.tanh = function(x) { + var r = Math.exp(x); + r = (r - 1 / r) / (r + 1 / r); + return r; +}; + +exports.asinh = function(x) { + var s = (x >= 0 ? 1 : -1); + return s * (Math.log(Math.abs(x) + Math.sqrt(x * x + 1))); +}; + +exports.acosh = function(x) { + return 2 * Math.log(Math.sqrt((x + 1) / 2) + Math.sqrt((x - 1) / 2)); +}; + +exports.atanh = function(x) { + return Math.log((x - 1) / (x + 1)) / 2; +}; + +// Grande Normale +exports.gN = function(a, e, sinphi) { + var temp = e * sinphi; + return a / Math.sqrt(1 - temp * temp); +}; + +//code from the PROJ.4 pj_mlfn.c file; this may be useful for other projections +exports.pj_enfn = function(es) { + var en = []; + en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08))); + en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08))); + var t = es * es; + en[2] = t * (this.C44 - es * (this.C46 + es * this.C48)); + t *= es; + en[3] = t * (this.C66 - es * this.C68); + en[4] = t * es * this.C88; + return en; +}; + +exports.pj_mlfn = function(phi, sphi, cphi, en) { + cphi *= sphi; + sphi *= sphi; + return (en[0] * phi - cphi * (en[1] + sphi * (en[2] + sphi * (en[3] + sphi * en[4])))); +}; + +exports.pj_inv_mlfn = function(arg, es, en) { + var k = 1 / (1 - es); + var phi = arg; + for (var i = exports.MAX_ITER; i; --i) { /* rarely goes over 2 iterations */ + var s = Math.sin(phi); + var t = 1 - es * s * s; + //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg; + //phi -= t * (t * Math.sqrt(t)) * k; + t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k; + phi -= t; + if (Math.abs(t) < exports.EPSLN) { + return phi; + } + } + //..reportError("cass:pj_inv_mlfn: Convergence error"); + return phi; +}; +exports.nadInterBreakout = function(indx, frct, letter, number, ct) { + var inx; + if (indx[letter] < 0) { + if (!(indx[letter] === -1 && frct[letter] > 0.99999999999)) { + return false; + } + indx[letter]++; + frct[letter] = 0; + } + else { + inx = indx[letter] + 1; + if (inx >= ct.lim[number]) { + if (!(inx === ct.lim[number] && frct[letter] < 1e-11)) { + return false; + } + if (letter === 'x') { + indx[letter]--; + } + else { + indx[letter]++; + } + frct[letter] = 1; + } + } + return [indx, frct]; +}; +/** + * Determine correction values + * source: nad_intr.c (DGR: 2012-07-29) + */ +exports.nad_intr = function(pin, ct) { + // force computation by decreasing by 1e-7 to be as closed as possible + // from computation under C:C++ by leveraging rounding problems ... + var t = { + x: (pin.x - 1e-7) / ct.del[0], + y: (pin.y - 1e-7) / ct.del[1] + }; + var indx = { + x: Math.floor(t.x), + y: Math.floor(t.y) + }; + var frct = { + x: t.x - 1 * indx.x, + y: t.y - 1 * indx.y + }; + var val = { + x: Number.NaN, + y: Number.NaN + }; + + + var temp = exports.nadInterBreakout(indx, frct, 'x', 0, ct); + if (temp) { + indx = temp[0]; + frct = temp[1]; + } + else { + return val; + } + temp = exports.nadInterBreakout(indx, frct, 'y', 1, ct); + if (temp) { + indx = temp[0]; + frct = temp[1]; + } + else { + return val; + } + var inx = (indx.y * ct.lim[0]) + indx.x; + var f00 = { + x: ct.cvs[inx][0], + y: ct.cvs[inx][1] + }; + inx++; + var f10 = { + x: ct.cvs[inx][0], + y: ct.cvs[inx][1] + }; + inx += ct.lim[0]; + var f11 = { + x: ct.cvs[inx][0], + y: ct.cvs[inx][1] + }; + inx--; + var f01 = { + x: ct.cvs[inx][0], + y: ct.cvs[inx][1] + }; + var m11 = frct.x * frct.y, + m10 = frct.x * (1 - frct.y), + m00 = (1 - frct.x) * (1 - frct.y), + m01 = (1 - frct.x) * frct.y; + val.x = (m00 * f00.x + m10 * f10.x + m01 * f01.x + m11 * f11.x); + val.y = (m00 * f00.y + m10 * f10.y + m01 * f01.y + m11 * f11.y); + return val; +}; + +/** + * Correct value + * source: nad_cvt.c (DGR: 2012-07-29) + */ +exports.inverseNadCvt = function(t, val, tb, ct) { + if (isNaN(t.x)) { + return val; + } + t.x = tb.x + t.x; + t.y = tb.y - t.y; + var i = 9, + tol = 1e-12; + var dif, del; + do { + del = exports.nad_intr(t, ct); + if (isNaN(del.x)) { + this.reportError("Inverse grid shift iteration failed, presumably at grid edge. Using first approximation."); + break; + } + dif = { + "x": t.x - del.x - tb.x, + "y": t.y + del.y - tb.y + }; + t.x -= dif.x; + t.y -= dif.y; + } while (i-- && Math.abs(dif.x) > tol && Math.abs(dif.y) > tol); + if (i < 0) { + this.reportError("Inverse grid shift iterator failed to converge."); + return val; + } + val.x = exports.adjust_lon(t.x + ct.ll[0]); + val.y = t.y + ct.ll[1]; + return val; +}; +exports.nad_cvt = function(pin, inverse, ct) { + var val = { + "x": Number.NaN, + "y": Number.NaN + }; + if (isNaN(pin.x)) { + return val; + } + var tb = { + "x": pin.x, + "y": pin.y + }; + tb.x -= ct.ll[0]; + tb.y -= ct.ll[1]; + tb.x = exports.adjust_lon(tb.x - exports.PI) + exports.PI; + var t = exports.nad_intr(tb, ct); + if (inverse) { + return exports.inverseNadCvt(t, val, tb, ct); + } + else { + if (!isNaN(t.x)) { + val.x = pin.x - t.x; + val.y = pin.y + t.y; + } + } + return val; +}; + +/* meridinal distance for ellipsoid and inverse + ** 8th degree - accurate to < 1e-5 meters when used in conjuction + ** with typical major axis values. + ** Inverse determines phi to EPS (1e-11) radians, about 1e-6 seconds. + */ +exports.C00 = 1; +exports.C02 = 0.25; +exports.C04 = 0.046875; +exports.C06 = 0.01953125; +exports.C08 = 0.01068115234375; +exports.C22 = 0.75; +exports.C44 = 0.46875; +exports.C46 = 0.01302083333333333333; +exports.C48 = 0.00712076822916666666; +exports.C66 = 0.36458333333333333333; +exports.C68 = 0.00569661458333333333; +exports.C88 = 0.3076171875; + +},{}],5:[function(require,module,exports){ +exports.wgs84 = { + towgs84: "0,0,0", + ellipse: "WGS84", + datumName: "WGS84" +}; +exports.ch1903 = { + towgs84: "674.374,15.056,405.346", + ellipse: "bessel", + datumName: "swiss" +}; +exports.ggrs87 = { + towgs84: "-199.87,74.79,246.62", + ellipse: "GRS80", + datumName: "Greek_Geodetic_Reference_System_1987" +}; +exports.nad83 = { + towgs84: "0,0,0", + ellipse: "GRS80", + datumName: "North_American_Datum_1983" +}; +exports.nad27 = { + nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", + ellipse: "clrk66", + datumName: "North_American_Datum_1927" +}; +exports.potsdam = { + towgs84: "606.0,23.0,413.0", + ellipse: "bessel", + datumName: "Potsdam Rauenberg 1950 DHDN" +}; +exports.carthage = { + towgs84: "-263.0,6.0,431.0", + ellipse: "clark80", + datumName: "Carthage 1934 Tunisia" +}; +exports.hermannskogel = { + towgs84: "653.0,-212.0,449.0", + ellipse: "bessel", + datumName: "Hermannskogel" +}; +exports.ire65 = { + towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", + ellipse: "mod_airy", + datumName: "Ireland 1965" +}; +exports.rassadiran = { + towgs84: "-133.63,-157.5,-158.62", + ellipse: "intl", + datumName: "Rassadiran" +}; +exports.nzgd49 = { + towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", + ellipse: "intl", + datumName: "New Zealand Geodetic Datum 1949" +}; +exports.osgb36 = { + towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", + ellipse: "airy", + datumName: "Airy 1830" +}; +exports.s_jtsk = { + towgs84: "589,76,480", + ellipse: 'bessel', + datumName: 'S-JTSK (Ferro)' +}; +exports.beduaram = { + towgs84: '-106,-87,188', + ellipse: 'clrk80', + datumName: 'Beduaram' +}; +exports.gunung_segara = { + towgs84: '-403,684,41', + ellipse: 'bessel', + datumName: 'Gunung Segara Jakarta' +}; +},{}],6:[function(require,module,exports){ +exports.MERIT = { + a: 6378137.0, + rf: 298.257, + ellipseName: "MERIT 1983" +}; +exports.SGS85 = { + a: 6378136.0, + rf: 298.257, + ellipseName: "Soviet Geodetic System 85" +}; +exports.GRS80 = { + a: 6378137.0, + rf: 298.257222101, + ellipseName: "GRS 1980(IUGG, 1980)" +}; +exports.IAU76 = { + a: 6378140.0, + rf: 298.257, + ellipseName: "IAU 1976" +}; +exports.airy = { + a: 6377563.396, + b: 6356256.910, + ellipseName: "Airy 1830" +}; +exports.APL4 = { + a: 6378137, + rf: 298.25, + ellipseName: "Appl. Physics. 1965" +}; +exports.NWL9D = { + a: 6378145.0, + rf: 298.25, + ellipseName: "Naval Weapons Lab., 1965" +}; +exports.mod_airy = { + a: 6377340.189, + b: 6356034.446, + ellipseName: "Modified Airy" +}; +exports.andrae = { + a: 6377104.43, + rf: 300.0, + ellipseName: "Andrae 1876 (Den., Iclnd.)" +}; +exports.aust_SA = { + a: 6378160.0, + rf: 298.25, + ellipseName: "Australian Natl & S. Amer. 1969" +}; +exports.GRS67 = { + a: 6378160.0, + rf: 298.2471674270, + ellipseName: "GRS 67(IUGG 1967)" +}; +exports.bessel = { + a: 6377397.155, + rf: 299.1528128, + ellipseName: "Bessel 1841" +}; +exports.bess_nam = { + a: 6377483.865, + rf: 299.1528128, + ellipseName: "Bessel 1841 (Namibia)" +}; +exports.clrk66 = { + a: 6378206.4, + b: 6356583.8, + ellipseName: "Clarke 1866" +}; +exports.clrk80 = { + a: 6378249.145, + rf: 293.4663, + ellipseName: "Clarke 1880 mod." +}; +exports.clrk58 = { + a: 6378293.645208759, + rf: 294.2606763692654, + ellipseName: "Clarke 1858" +}; +exports.CPM = { + a: 6375738.7, + rf: 334.29, + ellipseName: "Comm. des Poids et Mesures 1799" +}; +exports.delmbr = { + a: 6376428.0, + rf: 311.5, + ellipseName: "Delambre 1810 (Belgium)" +}; +exports.engelis = { + a: 6378136.05, + rf: 298.2566, + ellipseName: "Engelis 1985" +}; +exports.evrst30 = { + a: 6377276.345, + rf: 300.8017, + ellipseName: "Everest 1830" +}; +exports.evrst48 = { + a: 6377304.063, + rf: 300.8017, + ellipseName: "Everest 1948" +}; +exports.evrst56 = { + a: 6377301.243, + rf: 300.8017, + ellipseName: "Everest 1956" +}; +exports.evrst69 = { + a: 6377295.664, + rf: 300.8017, + ellipseName: "Everest 1969" +}; +exports.evrstSS = { + a: 6377298.556, + rf: 300.8017, + ellipseName: "Everest (Sabah & Sarawak)" +}; +exports.fschr60 = { + a: 6378166.0, + rf: 298.3, + ellipseName: "Fischer (Mercury Datum) 1960" +}; +exports.fschr60m = { + a: 6378155.0, + rf: 298.3, + ellipseName: "Fischer 1960" +}; +exports.fschr68 = { + a: 6378150.0, + rf: 298.3, + ellipseName: "Fischer 1968" +}; +exports.helmert = { + a: 6378200.0, + rf: 298.3, + ellipseName: "Helmert 1906" +}; +exports.hough = { + a: 6378270.0, + rf: 297.0, + ellipseName: "Hough" +}; +exports.intl = { + a: 6378388.0, + rf: 297.0, + ellipseName: "International 1909 (Hayford)" +}; +exports.kaula = { + a: 6378163.0, + rf: 298.24, + ellipseName: "Kaula 1961" +}; +exports.lerch = { + a: 6378139.0, + rf: 298.257, + ellipseName: "Lerch 1979" +}; +exports.mprts = { + a: 6397300.0, + rf: 191.0, + ellipseName: "Maupertius 1738" +}; +exports.new_intl = { + a: 6378157.5, + b: 6356772.2, + ellipseName: "New International 1967" +}; +exports.plessis = { + a: 6376523.0, + rf: 6355863.0, + ellipseName: "Plessis 1817 (France)" +}; +exports.krass = { + a: 6378245.0, + rf: 298.3, + ellipseName: "Krassovsky, 1942" +}; +exports.SEasia = { + a: 6378155.0, + b: 6356773.3205, + ellipseName: "Southeast Asia" +}; +exports.walbeck = { + a: 6376896.0, + b: 6355834.8467, + ellipseName: "Walbeck" +}; +exports.WGS60 = { + a: 6378165.0, + rf: 298.3, + ellipseName: "WGS 60" +}; +exports.WGS66 = { + a: 6378145.0, + rf: 298.25, + ellipseName: "WGS 66" +}; +exports.WGS7 = { + a: 6378135.0, + rf: 298.26, + ellipseName: "WGS 72" +}; +exports.WGS84 = { + a: 6378137.0, + rf: 298.257223563, + ellipseName: "WGS 84" +}; +exports.sphere = { + a: 6370997.0, + b: 6370997.0, + ellipseName: "Normal Sphere (r=6370997)" +}; +},{}],7:[function(require,module,exports){ +exports.greenwich = 0.0; //"0dE", +exports.lisbon = -9.131906111111; //"9d07'54.862\"W", +exports.paris = 2.337229166667; //"2d20'14.025\"E", +exports.bogota = -74.080916666667; //"74d04'51.3\"W", +exports.madrid = -3.687938888889; //"3d41'16.58\"W", +exports.rome = 12.452333333333; //"12d27'8.4\"E", +exports.bern = 7.439583333333; //"7d26'22.5\"E", +exports.jakarta = 106.807719444444; //"106d48'27.79\"E", +exports.ferro = -17.666666666667; //"17d40'W", +exports.brussels = 4.367975; //"4d22'4.71\"E", +exports.stockholm = 18.058277777778; //"18d3'29.8\"E", +exports.athens = 23.7163375; //"23d42'58.815\"E", +exports.oslo = 10.722916666667; //"10d43'22.5\"E" +},{}],8:[function(require,module,exports){ +// Based on . CTABLE structure : + // FIXME: better to have array instead of object holding longitudes, latitudes members + // In the former case, one has to document index 0 is longitude and + // 1 is latitude ... + // In the later case, grid object gets bigger !!!! + // Solution 1 is chosen based on pj_gridinfo.c +exports.null = { // name of grid's file + "ll": [-3.14159265, - 1.57079633], // lower-left coordinates in radians (longitude, latitude): + "del": [3.14159265, 1.57079633], // cell's size in radians (longitude, latitude): + "lim": [3, 3], // number of nodes in longitude, latitude (including edges): + "count": 9, // total number of nodes + "cvs": [ // shifts : in ntv2 reverse order : lon, lat in radians ... + [0.0, 0.0], + [0.0, 0.0], + [0.0, 0.0], // for (lon= 0; lon 3) { + if (proj.datum_params[3] !== 0 || proj.datum_params[4] !== 0 || proj.datum_params[5] !== 0 || proj.datum_params[6] !== 0) { + this.datum_type = common.PJD_7PARAM; + proj.datum_params[3] *= common.SEC_TO_RAD; + proj.datum_params[4] *= common.SEC_TO_RAD; + proj.datum_params[5] *= common.SEC_TO_RAD; + proj.datum_params[6] = (proj.datum_params[6] / 1000000.0) + 1.0; + } + } + } + // DGR 2011-03-21 : nadgrids support + this.datum_type = proj.grids ? common.PJD_GRIDSHIFT : this.datum_type; + + this.a = proj.a; //datum object also uses these values + this.b = proj.b; + this.es = proj.es; + this.ep2 = proj.ep2; + this.datum_params = proj.datum_params; + if (this.datum_type === common.PJD_GRIDSHIFT) { + this.grids = proj.grids; + } +}; +datum.prototype = { + + + /****************************************************************/ + // cs_compare_datums() + // Returns TRUE if the two datums match, otherwise FALSE. + compare_datums: function(dest) { + if (this.datum_type !== dest.datum_type) { + return false; // false, datums are not equal + } + else if (this.a !== dest.a || Math.abs(this.es - dest.es) > 0.000000000050) { + // the tolerence for es is to ensure that GRS80 and WGS84 + // are considered identical + return false; + } + else if (this.datum_type === common.PJD_3PARAM) { + return (this.datum_params[0] === dest.datum_params[0] && this.datum_params[1] === dest.datum_params[1] && this.datum_params[2] === dest.datum_params[2]); + } + else if (this.datum_type === common.PJD_7PARAM) { + return (this.datum_params[0] === dest.datum_params[0] && this.datum_params[1] === dest.datum_params[1] && this.datum_params[2] === dest.datum_params[2] && this.datum_params[3] === dest.datum_params[3] && this.datum_params[4] === dest.datum_params[4] && this.datum_params[5] === dest.datum_params[5] && this.datum_params[6] === dest.datum_params[6]); + } + else if (this.datum_type === common.PJD_GRIDSHIFT || dest.datum_type === common.PJD_GRIDSHIFT) { + //alert("ERROR: Grid shift transformations are not implemented."); + //return false + //DGR 2012-07-29 lazy ... + return this.nadgrids === dest.nadgrids; + } + else { + return true; // datums are equal + } + }, // cs_compare_datums() + + /* + * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates + * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z), + * according to the current ellipsoid parameters. + * + * Latitude : Geodetic latitude in radians (input) + * Longitude : Geodetic longitude in radians (input) + * Height : Geodetic height, in meters (input) + * X : Calculated Geocentric X coordinate, in meters (output) + * Y : Calculated Geocentric Y coordinate, in meters (output) + * Z : Calculated Geocentric Z coordinate, in meters (output) + * + */ + geodetic_to_geocentric: function(p) { + var Longitude = p.x; + var Latitude = p.y; + var Height = p.z ? p.z : 0; //Z value not always supplied + var X; // output + var Y; + var Z; + + var Error_Code = 0; // GEOCENT_NO_ERROR; + var Rn; /* Earth radius at location */ + var Sin_Lat; /* Math.sin(Latitude) */ + var Sin2_Lat; /* Square of Math.sin(Latitude) */ + var Cos_Lat; /* Math.cos(Latitude) */ + + /* + ** Don't blow up if Latitude is just a little out of the value + ** range as it may just be a rounding issue. Also removed longitude + ** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001. + */ + if (Latitude < -common.HALF_PI && Latitude > -1.001 * common.HALF_PI) { + Latitude = -common.HALF_PI; + } + else if (Latitude > common.HALF_PI && Latitude < 1.001 * common.HALF_PI) { + Latitude = common.HALF_PI; + } + else if ((Latitude < -common.HALF_PI) || (Latitude > common.HALF_PI)) { + /* Latitude out of range */ + //..reportError('geocent:lat out of range:' + Latitude); + return null; + } + + if (Longitude > common.PI) { + Longitude -= (2 * common.PI); + } + Sin_Lat = Math.sin(Latitude); + Cos_Lat = Math.cos(Latitude); + Sin2_Lat = Sin_Lat * Sin_Lat; + Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat)); + X = (Rn + Height) * Cos_Lat * Math.cos(Longitude); + Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude); + Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat; + + p.x = X; + p.y = Y; + p.z = Z; + return Error_Code; + }, // cs_geodetic_to_geocentric() + + + geocentric_to_geodetic: function(p) { + /* local defintions and variables */ + /* end-criterium of loop, accuracy of sin(Latitude) */ + var genau = 1e-12; + var genau2 = (genau * genau); + var maxiter = 30; + + var P; /* distance between semi-minor axis and location */ + var RR; /* distance between center and location */ + var CT; /* sin of geocentric latitude */ + var ST; /* cos of geocentric latitude */ + var RX; + var RK; + var RN; /* Earth radius at location */ + var CPHI0; /* cos of start or old geodetic latitude in iterations */ + var SPHI0; /* sin of start or old geodetic latitude in iterations */ + var CPHI; /* cos of searched geodetic latitude */ + var SPHI; /* sin of searched geodetic latitude */ + var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */ + var At_Pole; /* indicates location is in polar region */ + var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */ + + var X = p.x; + var Y = p.y; + var Z = p.z ? p.z : 0.0; //Z value not always supplied + var Longitude; + var Latitude; + var Height; + + At_Pole = false; + P = Math.sqrt(X * X + Y * Y); + RR = Math.sqrt(X * X + Y * Y + Z * Z); + + /* special cases for latitude and longitude */ + if (P / this.a < genau) { + + /* special case, if P=0. (X=0., Y=0.) */ + At_Pole = true; + Longitude = 0.0; + + /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis + * of ellipsoid (=center of mass), Latitude becomes PI/2 */ + if (RR / this.a < genau) { + Latitude = common.HALF_PI; + Height = -this.b; + return; + } + } + else { + /* ellipsoidal (geodetic) longitude + * interval: -PI < Longitude <= +PI */ + Longitude = Math.atan2(Y, X); + } + + /* -------------------------------------------------------------- + * Following iterative algorithm was developped by + * "Institut for Erdmessung", University of Hannover, July 1988. + * Internet: www.ife.uni-hannover.de + * Iterative computation of CPHI,SPHI and Height. + * Iteration of CPHI and SPHI to 10**-12 radian resp. + * 2*10**-7 arcsec. + * -------------------------------------------------------------- + */ + CT = Z / RR; + ST = P / RR; + RX = 1.0 / Math.sqrt(1.0 - this.es * (2.0 - this.es) * ST * ST); + CPHI0 = ST * (1.0 - this.es) * RX; + SPHI0 = CT * RX; + iter = 0; + + /* loop to find sin(Latitude) resp. Latitude + * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */ + do { + iter++; + RN = this.a / Math.sqrt(1.0 - this.es * SPHI0 * SPHI0); + + /* ellipsoidal (geodetic) height */ + Height = P * CPHI0 + Z * SPHI0 - RN * (1.0 - this.es * SPHI0 * SPHI0); + + RK = this.es * RN / (RN + Height); + RX = 1.0 / Math.sqrt(1.0 - RK * (2.0 - RK) * ST * ST); + CPHI = ST * (1.0 - RK) * RX; + SPHI = CT * RX; + SDPHI = SPHI * CPHI0 - CPHI * SPHI0; + CPHI0 = CPHI; + SPHI0 = SPHI; + } + while (SDPHI * SDPHI > genau2 && iter < maxiter); + + /* ellipsoidal (geodetic) latitude */ + Latitude = Math.atan(SPHI / Math.abs(CPHI)); + + p.x = Longitude; + p.y = Latitude; + p.z = Height; + return p; + }, // cs_geocentric_to_geodetic() + + /** Convert_Geocentric_To_Geodetic + * The method used here is derived from 'An Improved Algorithm for + * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996 + */ + geocentric_to_geodetic_noniter: function(p) { + var X = p.x; + var Y = p.y; + var Z = p.z ? p.z : 0; //Z value not always supplied + var Longitude; + var Latitude; + var Height; + + var W; /* distance from Z axis */ + var W2; /* square of distance from Z axis */ + var T0; /* initial estimate of vertical component */ + var T1; /* corrected estimate of vertical component */ + var S0; /* initial estimate of horizontal component */ + var S1; /* corrected estimate of horizontal component */ + var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */ + var Sin3_B0; /* cube of Math.sin(B0) */ + var Cos_B0; /* Math.cos(B0) */ + var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */ + var Cos_p1; /* Math.cos(phi1) */ + var Rn; /* Earth radius at location */ + var Sum; /* numerator of Math.cos(phi1) */ + var At_Pole; /* indicates location is in polar region */ + + X = parseFloat(X); // cast from string to float + Y = parseFloat(Y); + Z = parseFloat(Z); + + At_Pole = false; + if (X !== 0.0) { + Longitude = Math.atan2(Y, X); + } + else { + if (Y > 0) { + Longitude = common.HALF_PI; + } + else if (Y < 0) { + Longitude = -common.HALF_PI; + } + else { + At_Pole = true; + Longitude = 0.0; + if (Z > 0.0) { /* north pole */ + Latitude = common.HALF_PI; + } + else if (Z < 0.0) { /* south pole */ + Latitude = -common.HALF_PI; + } + else { /* center of earth */ + Latitude = common.HALF_PI; + Height = -this.b; + return; + } + } + } + W2 = X * X + Y * Y; + W = Math.sqrt(W2); + T0 = Z * common.AD_C; + S0 = Math.sqrt(T0 * T0 + W2); + Sin_B0 = T0 / S0; + Cos_B0 = W / S0; + Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0; + T1 = Z + this.b * this.ep2 * Sin3_B0; + Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0; + S1 = Math.sqrt(T1 * T1 + Sum * Sum); + Sin_p1 = T1 / S1; + Cos_p1 = Sum / S1; + Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1); + if (Cos_p1 >= common.COS_67P5) { + Height = W / Cos_p1 - Rn; + } + else if (Cos_p1 <= -common.COS_67P5) { + Height = W / -Cos_p1 - Rn; + } + else { + Height = Z / Sin_p1 + Rn * (this.es - 1.0); + } + if (At_Pole === false) { + Latitude = Math.atan(Sin_p1 / Cos_p1); + } + + p.x = Longitude; + p.y = Latitude; + p.z = Height; + return p; + }, // geocentric_to_geodetic_noniter() + + /****************************************************************/ + // pj_geocentic_to_wgs84( p ) + // p = point to transform in geocentric coordinates (x,y,z) + geocentric_to_wgs84: function(p) { + + if (this.datum_type === common.PJD_3PARAM) { + // if( x[io] === HUGE_VAL ) + // continue; + p.x += this.datum_params[0]; + p.y += this.datum_params[1]; + p.z += this.datum_params[2]; + + } + else if (this.datum_type === common.PJD_7PARAM) { + var Dx_BF = this.datum_params[0]; + var Dy_BF = this.datum_params[1]; + var Dz_BF = this.datum_params[2]; + var Rx_BF = this.datum_params[3]; + var Ry_BF = this.datum_params[4]; + var Rz_BF = this.datum_params[5]; + var M_BF = this.datum_params[6]; + // if( x[io] === HUGE_VAL ) + // continue; + var x_out = M_BF * (p.x - Rz_BF * p.y + Ry_BF * p.z) + Dx_BF; + var y_out = M_BF * (Rz_BF * p.x + p.y - Rx_BF * p.z) + Dy_BF; + var z_out = M_BF * (-Ry_BF * p.x + Rx_BF * p.y + p.z) + Dz_BF; + p.x = x_out; + p.y = y_out; + p.z = z_out; + } + }, // cs_geocentric_to_wgs84 + + /****************************************************************/ + // pj_geocentic_from_wgs84() + // coordinate system definition, + // point to transform in geocentric coordinates (x,y,z) + geocentric_from_wgs84: function(p) { + + if (this.datum_type === common.PJD_3PARAM) { + //if( x[io] === HUGE_VAL ) + // continue; + p.x -= this.datum_params[0]; + p.y -= this.datum_params[1]; + p.z -= this.datum_params[2]; + + } + else if (this.datum_type === common.PJD_7PARAM) { + var Dx_BF = this.datum_params[0]; + var Dy_BF = this.datum_params[1]; + var Dz_BF = this.datum_params[2]; + var Rx_BF = this.datum_params[3]; + var Ry_BF = this.datum_params[4]; + var Rz_BF = this.datum_params[5]; + var M_BF = this.datum_params[6]; + var x_tmp = (p.x - Dx_BF) / M_BF; + var y_tmp = (p.y - Dy_BF) / M_BF; + var z_tmp = (p.z - Dz_BF) / M_BF; + //if( x[io] === HUGE_VAL ) + // continue; + + p.x = x_tmp + Rz_BF * y_tmp - Ry_BF * z_tmp; + p.y = -Rz_BF * x_tmp + y_tmp + Rx_BF * z_tmp; + p.z = Ry_BF * x_tmp - Rx_BF * y_tmp + z_tmp; + } //cs_geocentric_from_wgs84() + } +}; + +/** point object, nothing fancy, just allows values to be + passed back and forth by reference rather than by value. + Other point classes may be used as long as they have + x and y properties, which will get modified in the transform method. +*/ +module.exports = datum; + +},{"./common":4}],12:[function(require,module,exports){ +var common = require('./common'); +module.exports = function(source, dest, point) { + var wp, i, l; + + function checkParams(fallback) { + return (fallback === common.PJD_3PARAM || fallback === common.PJD_7PARAM); + } + // Short cut if the datums are identical. + if (source.compare_datums(dest)) { + return point; // in this case, zero is sucess, + // whereas cs_compare_datums returns 1 to indicate TRUE + // confusing, should fix this + } + + // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest + if (source.datum_type === common.PJD_NODATUM || dest.datum_type === common.PJD_NODATUM) { + return point; + } + + //DGR: 2012-07-29 : add nadgrids support (begin) + var src_a = source.a; + var src_es = source.es; + + var dst_a = dest.a; + var dst_es = dest.es; + + var fallback = source.datum_type; + // If this datum requires grid shifts, then apply it to geodetic coordinates. + if (fallback === common.PJD_GRIDSHIFT) { + if (this.apply_gridshift(source, 0, point) === 0) { + source.a = common.SRS_WGS84_SEMIMAJOR; + source.es = common.SRS_WGS84_ESQUARED; + } + else { + // try 3 or 7 params transformation or nothing ? + if (!source.datum_params) { + source.a = src_a; + source.es = source.es; + return point; + } + wp = 1; + for (i = 0, l = source.datum_params.length; i < l; i++) { + wp *= source.datum_params[i]; + } + if (wp === 0) { + source.a = src_a; + source.es = source.es; + return point; + } + if (source.datum_params.length > 3) { + fallback = common.PJD_7PARAM; + } + else { + fallback = common.PJD_3PARAM; + } + } + } + if (dest.datum_type === common.PJD_GRIDSHIFT) { + dest.a = common.SRS_WGS84_SEMIMAJOR; + dest.es = common.SRS_WGS84_ESQUARED; + } + // Do we need to go through geocentric coordinates? + if (source.es !== dest.es || source.a !== dest.a || checkParams(fallback) || checkParams(dest.datum_type)) { + //DGR: 2012-07-29 : add nadgrids support (end) + // Convert to geocentric coordinates. + source.geodetic_to_geocentric(point); + // CHECK_RETURN; + // Convert between datums + if (checkParams(source.datum_type)) { + source.geocentric_to_wgs84(point); + // CHECK_RETURN; + } + if (checkParams(dest.datum_type)) { + dest.geocentric_from_wgs84(point); + // CHECK_RETURN; + } + // Convert back to geodetic coordinates + dest.geocentric_to_geodetic(point); + // CHECK_RETURN; + } + // Apply grid shift to destination if required + if (dest.datum_type === common.PJD_GRIDSHIFT) { + this.apply_gridshift(dest, 1, point); + // CHECK_RETURN; + } + + source.a = src_a; + source.es = src_es; + dest.a = dst_a; + dest.es = dst_es; + + return point; +}; + + +},{"./common":4}],13:[function(require,module,exports){ +var globals = require('./global'); +var parseProj = require('./projString'); +var wkt = require('./wkt'); + +function defs(name) { + /*global console*/ + var that = this; + if (arguments.length === 2) { + if (arguments[1][0] === '+') { + defs[name] = parseProj(arguments[1]); + } + else { + defs[name] = wkt(arguments[1]); + } + } + else if (arguments.length === 1) { + if (Array.isArray(name)) { + return name.map(function(v) { + if (Array.isArray(v)) { + defs.apply(that, v); + } + else { + defs(v); + } + }); + } + else if (typeof name === 'string') { + + } + else if ('EPSG' in name) { + defs['EPSG:' + name.EPSG] = name; + } + else if ('ESRI' in name) { + defs['ESRI:' + name.ESRI] = name; + } + else if ('IAU2000' in name) { + defs['IAU2000:' + name.IAU2000] = name; + } + else { + console.log(name); + } + return; + } + + +} +globals(defs); +module.exports = defs; + +},{"./global":15,"./projString":18,"./wkt":47}],14:[function(require,module,exports){ +module.exports = function(destination, source) { + destination = destination || {}; + var value, property; + if (!source) { + return destination; + } + for (property in source) { + value = source[property]; + if (value !== undefined) { + destination[property] = value; + } + } + return destination; +}; + +},{}],15:[function(require,module,exports){ +module.exports = function(defs) { + defs('WGS84', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees"); + defs('EPSG:4326', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees"); + defs('EPSG:4269', "+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees"); + defs('EPSG:3857', "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"); + + defs['EPSG:3785'] = defs['EPSG:3857']; // maintain backward compat, official code is 3857 + defs.GOOGLE = defs['EPSG:3857']; + defs['EPSG:900913'] = defs['EPSG:3857']; + defs['EPSG:102113'] = defs['EPSG:3857']; +}; + +},{}],16:[function(require,module,exports){ +var proj4 = require('./core'); +proj4.defaultDatum = 'WGS84'; //default datum +proj4.Proj = require('./Proj'); +proj4.WGS84 = new proj4.Proj('WGS84'); +proj4.Point = require('./Point'); +proj4.defs = require('./defs'); +proj4.transform = require('./transform'); +proj4.mgrs = require('./mgrs'); +proj4.version = require('./version'); +module.exports = proj4; +},{"./Point":1,"./Proj":2,"./core":10,"./defs":13,"./mgrs":17,"./transform":45,"./version":46}],17:[function(require,module,exports){ +/* +Portions of this software are based on a port of components from the OpenMap +com.bbn.openmap.proj.coords Java package. An initial port was initially created +by Patrice G. Cappelaere and included in Community Mapbuilder +(http://svn.codehaus.org/mapbuilder/), which is licensed under the LGPL license +as per http://www.gnu.org/copyleft/lesser.html. OpenMap is licensed under the +following license agreement: + + + OpenMap Software License Agreement + ---------------------------------- + +This Agreement sets forth the terms and conditions under which +the software known as OpenMap(tm) will be licensed by BBN +Technologies ("BBN") to you ("Licensee"), and by which Derivative +Works (as hereafter defined) of OpenMap will be licensed by you to BBN. + +Definitions: + + "Derivative Work(s)" shall mean any revision, enhancement, + modification, translation, abridgement, condensation or + expansion created by Licensee or BBN that is based upon the + Software or a portion thereof that would be a copyright + infringement if prepared without the authorization of the + copyright owners of the Software or portion thereof. + + "OpenMap" shall mean a programmer's toolkit for building map + based applications as originally created by BBN, and any + Derivative Works thereof as created by either BBN or Licensee, + but shall include only those Derivative Works BBN has approved + for inclusion into, and BBN has integrated into OpenMap. + + "Standard Version" shall mean OpenMap, as originally created by + BBN. + + "Software" shall mean OpenMap and the Derivative Works created + by Licensee and the collection of files distributed by the + Licensee with OpenMap, and the collection of files created + through textual modifications. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the Derivative Works. + + "Licensee" is you, only if you agree to be bound by the terms + and conditions set forth in this Agreement. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people + involved. + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions that they received it. + +1. BBN maintains all rights, title and interest in and to +OpenMap, including all applicable copyrights, trade secrets, +patents and other intellectual rights therein. Licensee hereby +grants to BBN all right, title and interest into the compilation +of OpenMap. Licensee shall own all rights, title and interest +into the Derivative Works created by Licensee (subject to the +compilation ownership by BBN). + +2. BBN hereby grants to Licensee a royalty free, worldwide right +and license to use, copy, distribute and make Derivative Works of +OpenMap, and sublicensing rights of any of the foregoing in +accordance with the terms and conditions of this Agreement, +provided that you duplicate all of the original copyright notices +and associated disclaimers. + +3. Licensee hereby grants to BBN a royalty free, worldwide right +and license to use, copy, distribute and make Derivative Works of +Derivative Works created by Licensee and sublicensing rights of +any of the foregoing. + +4. Licensee's right to create Derivative Works in the Software is +subject to Licensee agreement to insert a prominent notice in +each changed file stating how and when you changed that file, and +provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise + make them Freely Available, such as by posting said + modifications to Usenet or an equivalent medium, or + placing the modifications on a major archive site and by + providing your modifications to the Copyright Holder. + + b) use the modified Package only within your corporation or + organization. + + c) rename any non-standard executables so the names do not + conflict with standard executables, which must also be + provided, and provide a separate manual page for each + non-standard executable that clearly documents how it + differs from OpenMap. + + d) make other distribution arrangements with the Copyright + Holder. + +5. Licensee may distribute the programs of this Software in +object code or executable form, provided that you do at least ONE +of the following: + + a) distribute an OpenMap version of the executables and + library files, together with instructions (in the manual + page or equivalent) on where to get OpenMap. + + b) accompany the distribution with the machine-readable + source code with your modifications. + + c) accompany any non-standard executables with their + corresponding OpenMap executables, giving the non-standard + executables non-standard names, and clearly documenting + the differences in manual pages (or equivalent), together + with instructions on where to get OpenMap. + + d) make other distribution arrangements with the Copyright + Holder. + +6. You may charge a reasonable copying fee for any distribution +of this Software. You may charge any fee you choose for support +of this Software. You may not charge a fee for this Software +itself. However, you may distribute this Software in aggregate +with other (possibly commercial) programs as part of a larger +(possibly commercial) software distribution provided that you do +not advertise this Software as a product of your own. + +7. The data and images supplied as input to or produced as output +from the Software do not automatically fall under the copyright +of this Software, but belong to whomever generated them, and may +be sold commercially, and may be aggregated with this Software. + +8. BBN makes no representation about the suitability of OpenMap +for any purposes. BBN shall have no duty or requirement to +include any Derivative Works into OpenMap. + +9. Each party hereto represents and warrants that they have the +full unrestricted right to grant all rights and licenses granted +to the other party herein. + +10. THIS PACKAGE IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY +KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND +WITHOUT ANY WARRANTIES AS TO NONINFRINGEMENT. + +11. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE OF DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS CONDUCT, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PACKAGE. + +12. Without limitation of the foregoing, You agree to commit no +act which, directly or indirectly, would violate any U.S. law, +regulation, or treaty, or any other international treaty or +agreement to which the United States adheres or with which the +United States complies, relating to the export or re-export of +any commodities, software, or technical data. +*/ + + + +/** + * UTM zones are grouped, and assigned to one of a group of 6 + * sets. + * + * {int} @private + */ +var NUM_100K_SETS = 6; + +/** + * The column letters (for easting) of the lower left value, per + * set. + * + * {string} @private + */ +var SET_ORIGIN_COLUMN_LETTERS = 'AJSAJS'; + +/** + * The row letters (for northing) of the lower left value, per + * set. + * + * {string} @private + */ +var SET_ORIGIN_ROW_LETTERS = 'AFAFAF'; + +var A = 65; // A +var I = 73; // I +var O = 79; // O +var V = 86; // V +var Z = 90; // Z + +/** + * Conversion of lat/lon to MGRS. + * + * @param {object} ll Object literal with lat and lon properties on a + * WGS84 ellipsoid. + * @param {int} accuracy Accuracy in digits (5 for 1 m, 4 for 10 m, 3 for + * 100 m, 4 for 1000 m or 5 for 10000 m). Optional, default is 5. + * @return {string} the MGRS string for the given location and accuracy. + */ +exports.forward = function(ll, accuracy) { + accuracy = accuracy || 5; // default accuracy 1m + return encode(LLtoUTM({ + lat: ll.lat, + lon: ll.lon + }), accuracy); +}; + +/** + * Conversion of MGRS to lat/lon. + * + * @param {string} mgrs MGRS string. + * @return {array} An array with left (longitude), bottom (latitude), right + * (longitude) and top (latitude) values in WGS84, representing the + * bounding box for the provided MGRS reference. + */ +exports.inverse = function(mgrs) { + var bbox = UTMtoLL(decode(mgrs.toUpperCase())); + return [bbox.left, bbox.bottom, bbox.right, bbox.top]; +}; + +/** + * Conversion from degrees to radians. + * + * @private + * @param {number} deg the angle in degrees. + * @return {number} the angle in radians. + */ +function degToRad(deg) { + return (deg * (Math.PI / 180.0)); +} + +/** + * Conversion from radians to degrees. + * + * @private + * @param {number} rad the angle in radians. + * @return {number} the angle in degrees. + */ +function radToDeg(rad) { + return (180.0 * (rad / Math.PI)); +} + +/** + * Converts a set of Longitude and Latitude co-ordinates to UTM + * using the WGS84 ellipsoid. + * + * @private + * @param {object} ll Object literal with lat and lon properties + * representing the WGS84 coordinate to be converted. + * @return {object} Object literal containing the UTM value with easting, + * northing, zoneNumber and zoneLetter properties, and an optional + * accuracy property in digits. Returns null if the conversion failed. + */ +function LLtoUTM(ll) { + var Lat = ll.lat; + var Long = ll.lon; + var a = 6378137.0; //ellip.radius; + var eccSquared = 0.00669438; //ellip.eccsq; + var k0 = 0.9996; + var LongOrigin; + var eccPrimeSquared; + var N, T, C, A, M; + var LatRad = degToRad(Lat); + var LongRad = degToRad(Long); + var LongOriginRad; + var ZoneNumber; + // (int) + ZoneNumber = Math.floor((Long + 180) / 6) + 1; + + //Make sure the longitude 180.00 is in Zone 60 + if (Long === 180) { + ZoneNumber = 60; + } + + // Special zone for Norway + if (Lat >= 56.0 && Lat < 64.0 && Long >= 3.0 && Long < 12.0) { + ZoneNumber = 32; + } + + // Special zones for Svalbard + if (Lat >= 72.0 && Lat < 84.0) { + if (Long >= 0.0 && Long < 9.0) { + ZoneNumber = 31; + } + else if (Long >= 9.0 && Long < 21.0) { + ZoneNumber = 33; + } + else if (Long >= 21.0 && Long < 33.0) { + ZoneNumber = 35; + } + else if (Long >= 33.0 && Long < 42.0) { + ZoneNumber = 37; + } + } + + LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin + // in middle of + // zone + LongOriginRad = degToRad(LongOrigin); + + eccPrimeSquared = (eccSquared) / (1 - eccSquared); + + N = a / Math.sqrt(1 - eccSquared * Math.sin(LatRad) * Math.sin(LatRad)); + T = Math.tan(LatRad) * Math.tan(LatRad); + C = eccPrimeSquared * Math.cos(LatRad) * Math.cos(LatRad); + A = Math.cos(LatRad) * (LongRad - LongOriginRad); + + M = a * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * LatRad - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.sin(2 * LatRad) + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.sin(4 * LatRad) - (35 * eccSquared * eccSquared * eccSquared / 3072) * Math.sin(6 * LatRad)); + + var UTMEasting = (k0 * N * (A + (1 - T + C) * A * A * A / 6.0 + (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120.0) + 500000.0); + + var UTMNorthing = (k0 * (M + N * Math.tan(LatRad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24.0 + (61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A * A * A * A * A * A / 720.0))); + if (Lat < 0.0) { + UTMNorthing += 10000000.0; //10000000 meter offset for + // southern hemisphere + } + + return { + northing: Math.round(UTMNorthing), + easting: Math.round(UTMEasting), + zoneNumber: ZoneNumber, + zoneLetter: getLetterDesignator(Lat) + }; +} + +/** + * Converts UTM coords to lat/long, using the WGS84 ellipsoid. This is a convenience + * class where the Zone can be specified as a single string eg."60N" which + * is then broken down into the ZoneNumber and ZoneLetter. + * + * @private + * @param {object} utm An object literal with northing, easting, zoneNumber + * and zoneLetter properties. If an optional accuracy property is + * provided (in meters), a bounding box will be returned instead of + * latitude and longitude. + * @return {object} An object literal containing either lat and lon values + * (if no accuracy was provided), or top, right, bottom and left values + * for the bounding box calculated according to the provided accuracy. + * Returns null if the conversion failed. + */ +function UTMtoLL(utm) { + + var UTMNorthing = utm.northing; + var UTMEasting = utm.easting; + var zoneLetter = utm.zoneLetter; + var zoneNumber = utm.zoneNumber; + // check the ZoneNummber is valid + if (zoneNumber < 0 || zoneNumber > 60) { + return null; + } + + var k0 = 0.9996; + var a = 6378137.0; //ellip.radius; + var eccSquared = 0.00669438; //ellip.eccsq; + var eccPrimeSquared; + var e1 = (1 - Math.sqrt(1 - eccSquared)) / (1 + Math.sqrt(1 - eccSquared)); + var N1, T1, C1, R1, D, M; + var LongOrigin; + var mu, phi1Rad; + + // remove 500,000 meter offset for longitude + var x = UTMEasting - 500000.0; + var y = UTMNorthing; + + // We must know somehow if we are in the Northern or Southern + // hemisphere, this is the only time we use the letter So even + // if the Zone letter isn't exactly correct it should indicate + // the hemisphere correctly + if (zoneLetter < 'N') { + y -= 10000000.0; // remove 10,000,000 meter offset used + // for southern hemisphere + } + + // There are 60 zones with zone 1 being at West -180 to -174 + LongOrigin = (zoneNumber - 1) * 6 - 180 + 3; // +3 puts origin + // in middle of + // zone + + eccPrimeSquared = (eccSquared) / (1 - eccSquared); + + M = y / k0; + mu = M / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256)); + + phi1Rad = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * Math.sin(6 * mu); + // double phi1 = ProjMath.radToDeg(phi1Rad); + + N1 = a / Math.sqrt(1 - eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad)); + T1 = Math.tan(phi1Rad) * Math.tan(phi1Rad); + C1 = eccPrimeSquared * Math.cos(phi1Rad) * Math.cos(phi1Rad); + R1 = a * (1 - eccSquared) / Math.pow(1 - eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad), 1.5); + D = x / (N1 * k0); + + var lat = phi1Rad - (N1 * Math.tan(phi1Rad) / R1) * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24 + (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) * D * D * D * D * D * D / 720); + lat = radToDeg(lat); + + var lon = (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1) * D * D * D * D * D / 120) / Math.cos(phi1Rad); + lon = LongOrigin + radToDeg(lon); + + var result; + if (utm.accuracy) { + var topRight = UTMtoLL({ + northing: utm.northing + utm.accuracy, + easting: utm.easting + utm.accuracy, + zoneLetter: utm.zoneLetter, + zoneNumber: utm.zoneNumber + }); + result = { + top: topRight.lat, + right: topRight.lon, + bottom: lat, + left: lon + }; + } + else { + result = { + lat: lat, + lon: lon + }; + } + return result; +} + +/** + * Calculates the MGRS letter designator for the given latitude. + * + * @private + * @param {number} lat The latitude in WGS84 to get the letter designator + * for. + * @return {char} The letter designator. + */ +function getLetterDesignator(lat) { + //This is here as an error flag to show that the Latitude is + //outside MGRS limits + var LetterDesignator = 'Z'; + + if ((84 >= lat) && (lat >= 72)) { + LetterDesignator = 'X'; + } + else if ((72 > lat) && (lat >= 64)) { + LetterDesignator = 'W'; + } + else if ((64 > lat) && (lat >= 56)) { + LetterDesignator = 'V'; + } + else if ((56 > lat) && (lat >= 48)) { + LetterDesignator = 'U'; + } + else if ((48 > lat) && (lat >= 40)) { + LetterDesignator = 'T'; + } + else if ((40 > lat) && (lat >= 32)) { + LetterDesignator = 'S'; + } + else if ((32 > lat) && (lat >= 24)) { + LetterDesignator = 'R'; + } + else if ((24 > lat) && (lat >= 16)) { + LetterDesignator = 'Q'; + } + else if ((16 > lat) && (lat >= 8)) { + LetterDesignator = 'P'; + } + else if ((8 > lat) && (lat >= 0)) { + LetterDesignator = 'N'; + } + else if ((0 > lat) && (lat >= -8)) { + LetterDesignator = 'M'; + } + else if ((-8 > lat) && (lat >= -16)) { + LetterDesignator = 'L'; + } + else if ((-16 > lat) && (lat >= -24)) { + LetterDesignator = 'K'; + } + else if ((-24 > lat) && (lat >= -32)) { + LetterDesignator = 'J'; + } + else if ((-32 > lat) && (lat >= -40)) { + LetterDesignator = 'H'; + } + else if ((-40 > lat) && (lat >= -48)) { + LetterDesignator = 'G'; + } + else if ((-48 > lat) && (lat >= -56)) { + LetterDesignator = 'F'; + } + else if ((-56 > lat) && (lat >= -64)) { + LetterDesignator = 'E'; + } + else if ((-64 > lat) && (lat >= -72)) { + LetterDesignator = 'D'; + } + else if ((-72 > lat) && (lat >= -80)) { + LetterDesignator = 'C'; + } + return LetterDesignator; +} + +/** + * Encodes a UTM location as MGRS string. + * + * @private + * @param {object} utm An object literal with easting, northing, + * zoneLetter, zoneNumber + * @param {number} accuracy Accuracy in digits (1-5). + * @return {string} MGRS string for the given UTM location. + */ +function encode(utm, accuracy) { + var seasting = "" + utm.easting, + snorthing = "" + utm.northing; + + return utm.zoneNumber + utm.zoneLetter + get100kID(utm.easting, utm.northing, utm.zoneNumber) + seasting.substr(seasting.length - 5, accuracy) + snorthing.substr(snorthing.length - 5, accuracy); +} + +/** + * Get the two letter 100k designator for a given UTM easting, + * northing and zone number value. + * + * @private + * @param {number} easting + * @param {number} northing + * @param {number} zoneNumber + * @return the two letter 100k designator for the given UTM location. + */ +function get100kID(easting, northing, zoneNumber) { + var setParm = get100kSetForZone(zoneNumber); + var setColumn = Math.floor(easting / 100000); + var setRow = Math.floor(northing / 100000) % 20; + return getLetter100kID(setColumn, setRow, setParm); +} + +/** + * Given a UTM zone number, figure out the MGRS 100K set it is in. + * + * @private + * @param {number} i An UTM zone number. + * @return {number} the 100k set the UTM zone is in. + */ +function get100kSetForZone(i) { + var setParm = i % NUM_100K_SETS; + if (setParm === 0) { + setParm = NUM_100K_SETS; + } + + return setParm; +} + +/** + * Get the two-letter MGRS 100k designator given information + * translated from the UTM northing, easting and zone number. + * + * @private + * @param {number} column the column index as it relates to the MGRS + * 100k set spreadsheet, created from the UTM easting. + * Values are 1-8. + * @param {number} row the row index as it relates to the MGRS 100k set + * spreadsheet, created from the UTM northing value. Values + * are from 0-19. + * @param {number} parm the set block, as it relates to the MGRS 100k set + * spreadsheet, created from the UTM zone. Values are from + * 1-60. + * @return two letter MGRS 100k code. + */ +function getLetter100kID(column, row, parm) { + // colOrigin and rowOrigin are the letters at the origin of the set + var index = parm - 1; + var colOrigin = SET_ORIGIN_COLUMN_LETTERS.charCodeAt(index); + var rowOrigin = SET_ORIGIN_ROW_LETTERS.charCodeAt(index); + + // colInt and rowInt are the letters to build to return + var colInt = colOrigin + column - 1; + var rowInt = rowOrigin + row; + var rollover = false; + + if (colInt > Z) { + colInt = colInt - Z + A - 1; + rollover = true; + } + + if (colInt === I || (colOrigin < I && colInt > I) || ((colInt > I || colOrigin < I) && rollover)) { + colInt++; + } + + if (colInt === O || (colOrigin < O && colInt > O) || ((colInt > O || colOrigin < O) && rollover)) { + colInt++; + + if (colInt === I) { + colInt++; + } + } + + if (colInt > Z) { + colInt = colInt - Z + A - 1; + } + + if (rowInt > V) { + rowInt = rowInt - V + A - 1; + rollover = true; + } + else { + rollover = false; + } + + if (((rowInt === I) || ((rowOrigin < I) && (rowInt > I))) || (((rowInt > I) || (rowOrigin < I)) && rollover)) { + rowInt++; + } + + if (((rowInt === O) || ((rowOrigin < O) && (rowInt > O))) || (((rowInt > O) || (rowOrigin < O)) && rollover)) { + rowInt++; + + if (rowInt === I) { + rowInt++; + } + } + + if (rowInt > V) { + rowInt = rowInt - V + A - 1; + } + + var twoLetter = String.fromCharCode(colInt) + String.fromCharCode(rowInt); + return twoLetter; +} + +/** + * Decode the UTM parameters from a MGRS string. + * + * @private + * @param {string} mgrsString an UPPERCASE coordinate string is expected. + * @return {object} An object literal with easting, northing, zoneLetter, + * zoneNumber and accuracy (in meters) properties. + */ +function decode(mgrsString) { + + if (mgrsString && mgrsString.length === 0) { + throw ("MGRSPoint coverting from nothing"); + } + + var length = mgrsString.length; + + var hunK = null; + var sb = ""; + var testChar; + var i = 0; + + // get Zone number + while (!(/[A-Z]/).test(testChar = mgrsString.charAt(i))) { + if (i >= 2) { + throw ("MGRSPoint bad conversion from: " + mgrsString); + } + sb += testChar; + i++; + } + + var zoneNumber = parseInt(sb, 10); + + if (i === 0 || i + 3 > length) { + // A good MGRS string has to be 4-5 digits long, + // ##AAA/#AAA at least. + throw ("MGRSPoint bad conversion from: " + mgrsString); + } + + var zoneLetter = mgrsString.charAt(i++); + + // Should we check the zone letter here? Why not. + if (zoneLetter <= 'A' || zoneLetter === 'B' || zoneLetter === 'Y' || zoneLetter >= 'Z' || zoneLetter === 'I' || zoneLetter === 'O') { + throw ("MGRSPoint zone letter " + zoneLetter + " not handled: " + mgrsString); + } + + hunK = mgrsString.substring(i, i += 2); + + var set = get100kSetForZone(zoneNumber); + + var east100k = getEastingFromChar(hunK.charAt(0), set); + var north100k = getNorthingFromChar(hunK.charAt(1), set); + + // We have a bug where the northing may be 2000000 too low. + // How + // do we know when to roll over? + + while (north100k < getMinNorthing(zoneLetter)) { + north100k += 2000000; + } + + // calculate the char index for easting/northing separator + var remainder = length - i; + + if (remainder % 2 !== 0) { + throw ("MGRSPoint has to have an even number \nof digits after the zone letter and two 100km letters - front \nhalf for easting meters, second half for \nnorthing meters" + mgrsString); + } + + var sep = remainder / 2; + + var sepEasting = 0.0; + var sepNorthing = 0.0; + var accuracyBonus, sepEastingString, sepNorthingString, easting, northing; + if (sep > 0) { + accuracyBonus = 100000.0 / Math.pow(10, sep); + sepEastingString = mgrsString.substring(i, i + sep); + sepEasting = parseFloat(sepEastingString) * accuracyBonus; + sepNorthingString = mgrsString.substring(i + sep); + sepNorthing = parseFloat(sepNorthingString) * accuracyBonus; + } + + easting = sepEasting + east100k; + northing = sepNorthing + north100k; + + return { + easting: easting, + northing: northing, + zoneLetter: zoneLetter, + zoneNumber: zoneNumber, + accuracy: accuracyBonus + }; +} + +/** + * Given the first letter from a two-letter MGRS 100k zone, and given the + * MGRS table set for the zone number, figure out the easting value that + * should be added to the other, secondary easting value. + * + * @private + * @param {char} e The first letter from a two-letter MGRS 100´k zone. + * @param {number} set The MGRS table set for the zone number. + * @return {number} The easting value for the given letter and set. + */ +function getEastingFromChar(e, set) { + // colOrigin is the letter at the origin of the set for the + // column + var curCol = SET_ORIGIN_COLUMN_LETTERS.charCodeAt(set - 1); + var eastingValue = 100000.0; + var rewindMarker = false; + + while (curCol !== e.charCodeAt(0)) { + curCol++; + if (curCol === I) { + curCol++; + } + if (curCol === O) { + curCol++; + } + if (curCol > Z) { + if (rewindMarker) { + throw ("Bad character: " + e); + } + curCol = A; + rewindMarker = true; + } + eastingValue += 100000.0; + } + + return eastingValue; +} + +/** + * Given the second letter from a two-letter MGRS 100k zone, and given the + * MGRS table set for the zone number, figure out the northing value that + * should be added to the other, secondary northing value. You have to + * remember that Northings are determined from the equator, and the vertical + * cycle of letters mean a 2000000 additional northing meters. This happens + * approx. every 18 degrees of latitude. This method does *NOT* count any + * additional northings. You have to figure out how many 2000000 meters need + * to be added for the zone letter of the MGRS coordinate. + * + * @private + * @param {char} n Second letter of the MGRS 100k zone + * @param {number} set The MGRS table set number, which is dependent on the + * UTM zone number. + * @return {number} The northing value for the given letter and set. + */ +function getNorthingFromChar(n, set) { + + if (n > 'V') { + throw ("MGRSPoint given invalid Northing " + n); + } + + // rowOrigin is the letter at the origin of the set for the + // column + var curRow = SET_ORIGIN_ROW_LETTERS.charCodeAt(set - 1); + var northingValue = 0.0; + var rewindMarker = false; + + while (curRow !== n.charCodeAt(0)) { + curRow++; + if (curRow === I) { + curRow++; + } + if (curRow === O) { + curRow++; + } + // fixing a bug making whole application hang in this loop + // when 'n' is a wrong character + if (curRow > V) { + if (rewindMarker) { // making sure that this loop ends + throw ("Bad character: " + n); + } + curRow = A; + rewindMarker = true; + } + northingValue += 100000.0; + } + + return northingValue; +} + +/** + * The function getMinNorthing returns the minimum northing value of a MGRS + * zone. + * + * Ported from Geotrans' c Lattitude_Band_Value structure table. + * + * @private + * @param {char} zoneLetter The MGRS zone to get the min northing for. + * @return {number} + */ +function getMinNorthing(zoneLetter) { + var northing; + switch (zoneLetter) { + case 'C': + northing = 1100000.0; + break; + case 'D': + northing = 2000000.0; + break; + case 'E': + northing = 2800000.0; + break; + case 'F': + northing = 3700000.0; + break; + case 'G': + northing = 4600000.0; + break; + case 'H': + northing = 5500000.0; + break; + case 'J': + northing = 6400000.0; + break; + case 'K': + northing = 7300000.0; + break; + case 'L': + northing = 8200000.0; + break; + case 'M': + northing = 9100000.0; + break; + case 'N': + northing = 0.0; + break; + case 'P': + northing = 800000.0; + break; + case 'Q': + northing = 1700000.0; + break; + case 'R': + northing = 2600000.0; + break; + case 'S': + northing = 3500000.0; + break; + case 'T': + northing = 4400000.0; + break; + case 'U': + northing = 5300000.0; + break; + case 'V': + northing = 6200000.0; + break; + case 'W': + northing = 7000000.0; + break; + case 'X': + northing = 7900000.0; + break; + default: + northing = -1.0; + } + if (northing >= 0.0) { + return northing; + } + else { + throw ("Invalid zone letter: " + zoneLetter); + } + +} + +},{}],18:[function(require,module,exports){ +var common = require('./common'); +var constants = require('./constants/index'); +module.exports = function(defData) { + var self = {}; + + var paramObj = {}; + defData.split("+").map(function(v) { + return v.trim(); + }).filter(function(a) { + return a; + }).forEach(function(a) { + var split = a.split("="); + split.push(true); + paramObj[split[0].toLowerCase()] = split[1]; + }); + var paramName, paramVal, paramOutname; + var params = { + proj: 'projName', + datum: 'datumCode', + rf: function(v) { + self.rf = parseFloat(v, 10); + }, + lat_0: function(v) { + self.lat0 = v * common.D2R; + }, + lat_1: function(v) { + self.lat1 = v * common.D2R; + }, + lat_2: function(v) { + self.lat2 = v * common.D2R; + }, + lat_ts: function(v) { + self.lat_ts = v * common.D2R; + }, + lon_0: function(v) { + self.long0 = v * common.D2R; + }, + lon_1: function(v) { + self.long1 = v * common.D2R; + }, + lon_2: function(v) { + self.long2 = v * common.D2R; + }, + alpha: function(v) { + self.alpha = parseFloat(v) * common.D2R; + }, + lonc: function(v) { + self.longc = v * common.D2R; + }, + x_0: function(v) { + self.x0 = parseFloat(v, 10); + }, + y_0: function(v) { + self.y0 = parseFloat(v, 10); + }, + k_0: function(v) { + self.k0 = parseFloat(v, 10); + }, + k: function(v) { + self.k0 = parseFloat(v, 10); + }, + r_a: function() { + self.R_A = true; + }, + zone: function(v) { + self.zone = parseInt(v, 10); + }, + south: function() { + self.utmSouth = true; + }, + towgs84: function(v) { + self.datum_params = v.split(",").map(function(a) { + return parseFloat(a, 10); + }); + }, + to_meter: function(v) { + self.to_meter = parseFloat(v, 10); + }, + from_greenwich: function(v) { + self.from_greenwich = v * common.D2R; + }, + pm: function(v) { + self.from_greenwich = (constants.PrimeMeridian[v] ? constants.PrimeMeridian[v] : parseFloat(v, 10)) * common.D2R; + }, + nadgrids: function(v) { + if (v === '@null') { + self.datumCode = 'none'; + } + else { + self.nadgrids = v; + } + }, + axis: function(v) { + var legalAxis = "ewnsud"; + if (v.length === 3 && legalAxis.indexOf(v.substr(0, 1)) !== -1 && legalAxis.indexOf(v.substr(1, 1)) !== -1 && legalAxis.indexOf(v.substr(2, 1)) !== -1) { + self.axis = v; + } + } + }; + for (paramName in paramObj) { + paramVal = paramObj[paramName]; + if (paramName in params) { + paramOutname = params[paramName]; + if (typeof paramOutname === 'function') { + paramOutname(paramVal); + } + else { + self[paramOutname] = paramVal; + } + } + else { + self[paramName] = paramVal; + } + } + return self; +}; + +},{"./common":4,"./constants/index":9}],19:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + + if (Math.abs(this.lat1 + this.lat2) < common.EPSLN) { + return; + } + this.temp = this.b / this.a; + this.es = 1 - Math.pow(this.temp, 2); + this.e3 = Math.sqrt(this.es); + + this.sin_po = Math.sin(this.lat1); + this.cos_po = Math.cos(this.lat1); + this.t1 = this.sin_po; + this.con = this.sin_po; + this.ms1 = common.msfnz(this.e3, this.sin_po, this.cos_po); + this.qs1 = common.qsfnz(this.e3, this.sin_po, this.cos_po); + + this.sin_po = Math.sin(this.lat2); + this.cos_po = Math.cos(this.lat2); + this.t2 = this.sin_po; + this.ms2 = common.msfnz(this.e3, this.sin_po, this.cos_po); + this.qs2 = common.qsfnz(this.e3, this.sin_po, this.cos_po); + + this.sin_po = Math.sin(this.lat0); + this.cos_po = Math.cos(this.lat0); + this.t3 = this.sin_po; + this.qs0 = common.qsfnz(this.e3, this.sin_po, this.cos_po); + + if (Math.abs(this.lat1 - this.lat2) > common.EPSLN) { + this.ns0 = (this.ms1 * this.ms1 - this.ms2 * this.ms2) / (this.qs2 - this.qs1); + } + else { + this.ns0 = this.con; + } + this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1; + this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0) / this.ns0; +}; + +/* Albers Conical Equal Area forward equations--mapping lat,long to x,y + -------------------------------------------------------------------*/ +exports.forward = function(p) { + + var lon = p.x; + var lat = p.y; + + this.sin_phi = Math.sin(lat); + this.cos_phi = Math.cos(lat); + + var qs = common.qsfnz(this.e3, this.sin_phi, this.cos_phi); + var rh1 = this.a * Math.sqrt(this.c - this.ns0 * qs) / this.ns0; + var theta = this.ns0 * common.adjust_lon(lon - this.long0); + var x = rh1 * Math.sin(theta) + this.x0; + var y = this.rh - rh1 * Math.cos(theta) + this.y0; + + p.x = x; + p.y = y; + return p; +}; + + +exports.inverse = function(p) { + var rh1, qs, con, theta, lon, lat; + + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + if (this.ns0 >= 0) { + rh1 = Math.sqrt(p.x * p.x + p.y * p.y); + con = 1; + } + else { + rh1 = -Math.sqrt(p.x * p.x + p.y * p.y); + con = -1; + } + theta = 0; + if (rh1 !== 0) { + theta = Math.atan2(con * p.x, con * p.y); + } + con = rh1 * this.ns0 / this.a; + if (this.sphere) { + lat = Math.asin((this.c - con * con) / (2 * this.ns0)); + } + else { + qs = (this.c - con * con) / this.ns0; + lat = this.phi1z(this.e3, qs); + } + + lon = common.adjust_lon(theta / this.ns0 + this.long0); + p.x = lon; + p.y = lat; + return p; +}; + +/* Function to compute phi1, the latitude for the inverse of the + Albers Conical Equal-Area projection. +-------------------------------------------*/ +exports.phi1z = function(eccent, qs) { + var sinphi, cosphi, con, com, dphi; + var phi = common.asinz(0.5 * qs); + if (eccent < common.EPSLN) { + return phi; + } + + var eccnts = eccent * eccent; + for (var i = 1; i <= 25; i++) { + sinphi = Math.sin(phi); + cosphi = Math.cos(phi); + con = eccent * sinphi; + com = 1 - con * con; + dphi = 0.5 * com * com / cosphi * (qs / (1 - eccnts) - sinphi / com + 0.5 / eccent * Math.log((1 - con) / (1 + con))); + phi = phi + dphi; + if (Math.abs(dphi) <= 1e-7) { + return phi; + } + } + return null; +}; +exports.names = ["Albers_Conic_Equal_Area", "Albers", "aea"]; + +},{"../common":4}],20:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + this.sin_p12 = Math.sin(this.lat0); + this.cos_p12 = Math.cos(this.lat0); +}; + +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + var sinphi = Math.sin(p.y); + var cosphi = Math.cos(p.y); + var dlon = common.adjust_lon(lon - this.long0); + var e0, e1, e2, e3, Mlp, Ml, tanphi, Nl1, Nl, psi, Az, G, H, GH, Hs, c, kp, cos_c, s, s2, s3, s4, s5; + if (this.sphere) { + if (Math.abs(this.sin_p12 - 1) <= common.EPSLN) { + //North Pole case + p.x = this.x0 + this.a * (common.HALF_PI - lat) * Math.sin(dlon); + p.y = this.y0 - this.a * (common.HALF_PI - lat) * Math.cos(dlon); + return p; + } + else if (Math.abs(this.sin_p12 + 1) <= common.EPSLN) { + //South Pole case + p.x = this.x0 + this.a * (common.HALF_PI + lat) * Math.sin(dlon); + p.y = this.y0 + this.a * (common.HALF_PI + lat) * Math.cos(dlon); + return p; + } + else { + //default case + cos_c = this.sin_p12 * sinphi + this.cos_p12 * cosphi * Math.cos(dlon); + c = Math.acos(cos_c); + kp = c / Math.sin(c); + p.x = this.x0 + this.a * kp * cosphi * Math.sin(dlon); + p.y = this.y0 + this.a * kp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * Math.cos(dlon)); + return p; + } + } + else { + e0 = common.e0fn(this.es); + e1 = common.e1fn(this.es); + e2 = common.e2fn(this.es); + e3 = common.e3fn(this.es); + if (Math.abs(this.sin_p12 - 1) <= common.EPSLN) { + //North Pole case + Mlp = this.a * common.mlfn(e0, e1, e2, e3, common.HALF_PI); + Ml = this.a * common.mlfn(e0, e1, e2, e3, lat); + p.x = this.x0 + (Mlp - Ml) * Math.sin(dlon); + p.y = this.y0 - (Mlp - Ml) * Math.cos(dlon); + return p; + } + else if (Math.abs(this.sin_p12 + 1) <= common.EPSLN) { + //South Pole case + Mlp = this.a * common.mlfn(e0, e1, e2, e3, common.HALF_PI); + Ml = this.a * common.mlfn(e0, e1, e2, e3, lat); + p.x = this.x0 + (Mlp + Ml) * Math.sin(dlon); + p.y = this.y0 + (Mlp + Ml) * Math.cos(dlon); + return p; + } + else { + //Default case + tanphi = sinphi / cosphi; + Nl1 = common.gN(this.a, this.e, this.sin_p12); + Nl = common.gN(this.a, this.e, sinphi); + psi = Math.atan((1 - this.es) * tanphi + this.es * Nl1 * this.sin_p12 / (Nl * cosphi)); + Az = Math.atan2(Math.sin(dlon), this.cos_p12 * Math.tan(psi) - this.sin_p12 * Math.cos(dlon)); + if (Az === 0) { + s = Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi)); + } + else if (Math.abs(Math.abs(Az) - common.PI) <= common.EPSLN) { + s = -Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi)); + } + else { + s = Math.asin(Math.sin(dlon) * Math.cos(psi) / Math.sin(Az)); + } + G = this.e * this.sin_p12 / Math.sqrt(1 - this.es); + H = this.e * this.cos_p12 * Math.cos(Az) / Math.sqrt(1 - this.es); + GH = G * H; + Hs = H * H; + s2 = s * s; + s3 = s2 * s; + s4 = s3 * s; + s5 = s4 * s; + c = Nl1 * s * (1 - s2 * Hs * (1 - Hs) / 6 + s3 / 8 * GH * (1 - 2 * Hs) + s4 / 120 * (Hs * (4 - 7 * Hs) - 3 * G * G * (1 - 7 * Hs)) - s5 / 48 * GH); + p.x = this.x0 + c * Math.sin(Az); + p.y = this.y0 + c * Math.cos(Az); + return p; + } + } + + +}; + +exports.inverse = function(p) { + p.x -= this.x0; + p.y -= this.y0; + var rh, z, sinz, cosz, lon, lat, con, e0, e1, e2, e3, Mlp, M, N1, psi, Az, cosAz, tmp, A, B, D, Ee, F; + if (this.sphere) { + rh = Math.sqrt(p.x * p.x + p.y * p.y); + if (rh > (2 * common.HALF_PI * this.a)) { + return; + } + z = rh / this.a; + + sinz = Math.sin(z); + cosz = Math.cos(z); + + lon = this.long0; + if (Math.abs(rh) <= common.EPSLN) { + lat = this.lat0; + } + else { + lat = common.asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh); + con = Math.abs(this.lat0) - common.HALF_PI; + if (Math.abs(con) <= common.EPSLN) { + if (this.lat0 >= 0) { + lon = common.adjust_lon(this.long0 + Math.atan2(p.x, - p.y)); + } + else { + lon = common.adjust_lon(this.long0 - Math.atan2(-p.x, p.y)); + } + } + else { + /*con = cosz - this.sin_p12 * Math.sin(lat); + if ((Math.abs(con) < common.EPSLN) && (Math.abs(p.x) < common.EPSLN)) { + //no-op, just keep the lon value as is + } else { + var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh)); + lon = common.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh))); + }*/ + lon = common.adjust_lon(this.long0 + Math.atan2(p.x * sinz, rh * this.cos_p12 * cosz - p.y * this.sin_p12 * sinz)); + } + } + + p.x = lon; + p.y = lat; + return p; + } + else { + e0 = common.e0fn(this.es); + e1 = common.e1fn(this.es); + e2 = common.e2fn(this.es); + e3 = common.e3fn(this.es); + if (Math.abs(this.sin_p12 - 1) <= common.EPSLN) { + //North pole case + Mlp = this.a * common.mlfn(e0, e1, e2, e3, common.HALF_PI); + rh = Math.sqrt(p.x * p.x + p.y * p.y); + M = Mlp - rh; + lat = common.imlfn(M / this.a, e0, e1, e2, e3); + lon = common.adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y)); + p.x = lon; + p.y = lat; + return p; + } + else if (Math.abs(this.sin_p12 + 1) <= common.EPSLN) { + //South pole case + Mlp = this.a * common.mlfn(e0, e1, e2, e3, common.HALF_PI); + rh = Math.sqrt(p.x * p.x + p.y * p.y); + M = rh - Mlp; + + lat = common.imlfn(M / this.a, e0, e1, e2, e3); + lon = common.adjust_lon(this.long0 + Math.atan2(p.x, p.y)); + p.x = lon; + p.y = lat; + return p; + } + else { + //default case + rh = Math.sqrt(p.x * p.x + p.y * p.y); + Az = Math.atan2(p.x, p.y); + N1 = common.gN(this.a, this.e, this.sin_p12); + cosAz = Math.cos(Az); + tmp = this.e * this.cos_p12 * cosAz; + A = -tmp * tmp / (1 - this.es); + B = 3 * this.es * (1 - A) * this.sin_p12 * this.cos_p12 * cosAz / (1 - this.es); + D = rh / N1; + Ee = D - A * (1 + A) * Math.pow(D, 3) / 6 - B * (1 + 3 * A) * Math.pow(D, 4) / 24; + F = 1 - A * Ee * Ee / 2 - D * Ee * Ee * Ee / 6; + psi = Math.asin(this.sin_p12 * Math.cos(Ee) + this.cos_p12 * Math.sin(Ee) * cosAz); + lon = common.adjust_lon(this.long0 + Math.asin(Math.sin(Az) * Math.sin(Ee) / Math.cos(psi))); + lat = Math.atan((1 - this.es * F * this.sin_p12 / Math.sin(psi)) * Math.tan(psi) / (1 - this.es)); + p.x = lon; + p.y = lat; + return p; + } + } + +}; +exports.names = ["Azimuthal_Equidistant", "aeqd"]; + +},{"../common":4}],21:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + if (!this.sphere) { + this.e0 = common.e0fn(this.es); + this.e1 = common.e1fn(this.es); + this.e2 = common.e2fn(this.es); + this.e3 = common.e3fn(this.es); + this.ml0 = this.a * common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); + } +}; + + + +/* Cassini forward equations--mapping lat,long to x,y + -----------------------------------------------------------------------*/ +exports.forward = function(p) { + + /* Forward equations + -----------------*/ + var x, y; + var lam = p.x; + var phi = p.y; + lam = common.adjust_lon(lam - this.long0); + + if (this.sphere) { + x = this.a * Math.asin(Math.cos(phi) * Math.sin(lam)); + y = this.a * (Math.atan2(Math.tan(phi), Math.cos(lam)) - this.lat0); + } + else { + //ellipsoid + var sinphi = Math.sin(phi); + var cosphi = Math.cos(phi); + var nl = common.gN(this.a, this.e, sinphi); + var tl = Math.tan(phi) * Math.tan(phi); + var al = lam * Math.cos(phi); + var asq = al * al; + var cl = this.es * cosphi * cosphi / (1 - this.es); + var ml = this.a * common.mlfn(this.e0, this.e1, this.e2, this.e3, phi); + + x = nl * al * (1 - asq * tl * (1 / 6 - (8 - tl + 8 * cl) * asq / 120)); + y = ml - this.ml0 + nl * sinphi / cosphi * asq * (0.5 + (5 - tl + 6 * cl) * asq / 24); + + + } + + p.x = x + this.x0; + p.y = y + this.y0; + return p; +}; + +/* Inverse equations + -----------------*/ +exports.inverse = function(p) { + p.x -= this.x0; + p.y -= this.y0; + var x = p.x / this.a; + var y = p.y / this.a; + var phi, lam; + + if (this.sphere) { + var dd = y + this.lat0; + phi = Math.asin(Math.sin(dd) * Math.cos(x)); + lam = Math.atan2(Math.tan(x), Math.cos(dd)); + } + else { + /* ellipsoid */ + var ml1 = this.ml0 / this.a + y; + var phi1 = common.imlfn(ml1, this.e0, this.e1, this.e2, this.e3); + if (Math.abs(Math.abs(phi1) - common.HALF_PI) <= common.EPSLN) { + p.x = this.long0; + p.y = common.HALF_PI; + if (y < 0) { + p.y *= -1; + } + return p; + } + var nl1 = common.gN(this.a, this.e, Math.sin(phi1)); + + var rl1 = nl1 * nl1 * nl1 / this.a / this.a * (1 - this.es); + var tl1 = Math.pow(Math.tan(phi1), 2); + var dl = x * this.a / nl1; + var dsq = dl * dl; + phi = phi1 - nl1 * Math.tan(phi1) / rl1 * dl * dl * (0.5 - (1 + 3 * tl1) * dl * dl / 24); + lam = dl * (1 - dsq * (tl1 / 3 + (1 + 3 * tl1) * tl1 * dsq / 15)) / Math.cos(phi1); + + } + + p.x = common.adjust_lon(lam + this.long0); + p.y = common.adjust_lat(phi); + return p; + +}; +exports.names = ["Cassini", "Cassini_Soldner", "cass"]; +},{"../common":4}],22:[function(require,module,exports){ +var common = require('../common'); +/* + reference: + "Cartographic Projection Procedures for the UNIX Environment- + A User's Manual" by Gerald I. Evenden, + USGS Open File Report 90-284and Release 4 Interim Reports (2003) +*/ +exports.init = function() { + //no-op + if (!this.sphere) { + this.k0 = common.msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts)); + } +}; + + +/* Cylindrical Equal Area forward equations--mapping lat,long to x,y + ------------------------------------------------------------*/ +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + var x, y; + /* Forward equations + -----------------*/ + var dlon = common.adjust_lon(lon - this.long0); + if (this.sphere) { + x = this.x0 + this.a * dlon * Math.cos(this.lat_ts); + y = this.y0 + this.a * Math.sin(lat) / Math.cos(this.lat_ts); + } + else { + var qs = common.qsfnz(this.e, Math.sin(lat)); + x = this.x0 + this.a * this.k0 * dlon; + y = this.y0 + this.a * qs * 0.5 / this.k0; + } + + p.x = x; + p.y = y; + return p; +}; + +/* Cylindrical Equal Area inverse equations--mapping x,y to lat/long + ------------------------------------------------------------*/ +exports.inverse = function(p) { + p.x -= this.x0; + p.y -= this.y0; + var lon, lat; + + if (this.sphere) { + lon = common.adjust_lon(this.long0 + (p.x / this.a) / Math.cos(this.lat_ts)); + lat = Math.asin((p.y / this.a) * Math.cos(this.lat_ts)); + } + else { + lat = common.iqsfnz(this.e, 2 * p.y * this.k0 / this.a); + lon = common.adjust_lon(this.long0 + p.x / (this.a * this.k0)); + } + + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["cea"]; + +},{"../common":4}],23:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + + this.x0 = this.x0 || 0; + this.y0 = this.y0 || 0; + this.lat0 = this.lat0 || 0; + this.long0 = this.long0 || 0; + this.lat_ts = this.lat_t || 0; + this.title = this.title || "Equidistant Cylindrical (Plate Carre)"; + + this.rc = Math.cos(this.lat_ts); +}; + + +// forward equations--mapping lat,long to x,y +// ----------------------------------------------------------------- +exports.forward = function(p) { + + var lon = p.x; + var lat = p.y; + + var dlon = common.adjust_lon(lon - this.long0); + var dlat = common.adjust_lat(lat - this.lat0); + p.x = this.x0 + (this.a * dlon * this.rc); + p.y = this.y0 + (this.a * dlat); + return p; +}; + +// inverse equations--mapping x,y to lat/long +// ----------------------------------------------------------------- +exports.inverse = function(p) { + + var x = p.x; + var y = p.y; + + p.x = common.adjust_lon(this.long0 + ((x - this.x0) / (this.a * this.rc))); + p.y = common.adjust_lat(this.lat0 + ((y - this.y0) / (this.a))); + return p; +}; +exports.names = ["Equirectangular", "Equidistant_Cylindrical", "eqc"]; + +},{"../common":4}],24:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + // Standard Parallels cannot be equal and on opposite sides of the equator + if (Math.abs(this.lat1 + this.lat2) < common.EPSLN) { + common.reportError("eqdc:init: Equal Latitudes"); + return; + } + this.lat2 = this.lat2 || this.lat1; + this.temp = this.b / this.a; + this.es = 1 - Math.pow(this.temp, 2); + this.e = Math.sqrt(this.es); + this.e0 = common.e0fn(this.es); + this.e1 = common.e1fn(this.es); + this.e2 = common.e2fn(this.es); + this.e3 = common.e3fn(this.es); + + this.sinphi = Math.sin(this.lat1); + this.cosphi = Math.cos(this.lat1); + + this.ms1 = common.msfnz(this.e, this.sinphi, this.cosphi); + this.ml1 = common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat1); + + if (Math.abs(this.lat1 - this.lat2) < common.EPSLN) { + this.ns = this.sinphi; + } + else { + this.sinphi = Math.sin(this.lat2); + this.cosphi = Math.cos(this.lat2); + this.ms2 = common.msfnz(this.e, this.sinphi, this.cosphi); + this.ml2 = common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2); + this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1); + } + this.g = this.ml1 + this.ms1 / this.ns; + this.ml0 = common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); + this.rh = this.a * (this.g - this.ml0); +}; + + +/* Equidistant Conic forward equations--mapping lat,long to x,y + -----------------------------------------------------------*/ +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + var rh1; + + /* Forward equations + -----------------*/ + if (this.sphere) { + rh1 = this.a * (this.g - lat); + } + else { + var ml = common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + rh1 = this.a * (this.g - ml); + } + var theta = this.ns * common.adjust_lon(lon - this.long0); + var x = this.x0 + rh1 * Math.sin(theta); + var y = this.y0 + this.rh - rh1 * Math.cos(theta); + p.x = x; + p.y = y; + return p; +}; + +/* Inverse equations + -----------------*/ +exports.inverse = function(p) { + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + var con, rh1, lat, lon; + if (this.ns >= 0) { + rh1 = Math.sqrt(p.x * p.x + p.y * p.y); + con = 1; + } + else { + rh1 = -Math.sqrt(p.x * p.x + p.y * p.y); + con = -1; + } + var theta = 0; + if (rh1 !== 0) { + theta = Math.atan2(con * p.x, con * p.y); + } + + if (this.sphere) { + lon = common.adjust_lon(this.long0 + theta / this.ns); + lat = common.adjust_lat(this.g - rh1 / this.a); + p.x = lon; + p.y = lat; + return p; + } + else { + var ml = this.g - rh1 / this.a; + lat = common.imlfn(ml, this.e0, this.e1, this.e2, this.e3); + lon = common.adjust_lon(this.long0 + theta / this.ns); + p.x = lon; + p.y = lat; + return p; + } + +}; +exports.names = ["Equidistant_Conic", "eqdc"]; + +},{"../common":4}],25:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + var sphi = Math.sin(this.lat0); + var cphi = Math.cos(this.lat0); + cphi *= cphi; + this.rc = Math.sqrt(1 - this.es) / (1 - this.es * sphi * sphi); + this.C = Math.sqrt(1 + this.es * cphi * cphi / (1 - this.es)); + this.phic0 = Math.asin(sphi / this.C); + this.ratexp = 0.5 * this.C * this.e; + this.K = Math.tan(0.5 * this.phic0 + common.FORTPI) / (Math.pow(Math.tan(0.5 * this.lat0 + common.FORTPI), this.C) * common.srat(this.e * sphi, this.ratexp)); +}; + +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + + p.y = 2 * Math.atan(this.K * Math.pow(Math.tan(0.5 * lat + common.FORTPI), this.C) * common.srat(this.e * Math.sin(lat), this.ratexp)) - common.HALF_PI; + p.x = this.C * lon; + return p; +}; + +exports.inverse = function(p) { + var DEL_TOL = 1e-14; + var lon = p.x / this.C; + var lat = p.y; + var num = Math.pow(Math.tan(0.5 * lat + common.FORTPI) / this.K, 1 / this.C); + for (var i = common.MAX_ITER; i > 0; --i) { + lat = 2 * Math.atan(num * common.srat(this.e * Math.sin(p.y), - 0.5 * this.e)) - common.HALF_PI; + if (Math.abs(lat - p.y) < DEL_TOL) { + break; + } + p.y = lat; + } + /* convergence failed */ + if (!i) { + return null; + } + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["gauss"]; + +},{"../common":4}],26:[function(require,module,exports){ +var common = require('../common'); +/* + reference: + Wolfram Mathworld "Gnomonic Projection" + http://mathworld.wolfram.com/GnomonicProjection.html + Accessed: 12th November 2009 + */ +exports.init = function() { + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + this.sin_p14 = Math.sin(this.lat0); + this.cos_p14 = Math.cos(this.lat0); + // Approximation for projecting points to the horizon (infinity) + this.infinity_dist = 1000 * this.a; + this.rc = 1; +}; + + +/* Gnomonic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ +exports.forward = function(p) { + var sinphi, cosphi; /* sin and cos value */ + var dlon; /* delta longitude value */ + var coslon; /* cos of longitude */ + var ksp; /* scale factor */ + var g; + var x, y; + var lon = p.x; + var lat = p.y; + /* Forward equations + -----------------*/ + dlon = common.adjust_lon(lon - this.long0); + + sinphi = Math.sin(lat); + cosphi = Math.cos(lat); + + coslon = Math.cos(dlon); + g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; + ksp = 1; + if ((g > 0) || (Math.abs(g) <= common.EPSLN)) { + x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon) / g; + y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon) / g; + } + else { + + // Point is in the opposing hemisphere and is unprojectable + // We still need to return a reasonable point, so we project + // to infinity, on a bearing + // equivalent to the northern hemisphere equivalent + // This is a reasonable approximation for short shapes and lines that + // straddle the horizon. + + x = this.x0 + this.infinity_dist * cosphi * Math.sin(dlon); + y = this.y0 + this.infinity_dist * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); + + } + p.x = x; + p.y = y; + return p; +}; + + +exports.inverse = function(p) { + var rh; /* Rho */ + var sinc, cosc; + var c; + var lon, lat; + + /* Inverse equations + -----------------*/ + p.x = (p.x - this.x0) / this.a; + p.y = (p.y - this.y0) / this.a; + + p.x /= this.k0; + p.y /= this.k0; + + if ((rh = Math.sqrt(p.x * p.x + p.y * p.y))) { + c = Math.atan2(rh, this.rc); + sinc = Math.sin(c); + cosc = Math.cos(c); + + lat = common.asinz(cosc * this.sin_p14 + (p.y * sinc * this.cos_p14) / rh); + lon = Math.atan2(p.x * sinc, rh * this.cos_p14 * cosc - p.y * this.sin_p14 * sinc); + lon = common.adjust_lon(this.long0 + lon); + } + else { + lat = this.phic0; + lon = 0; + } + + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["gnom"]; + +},{"../common":4}],27:[function(require,module,exports){ +var projs = [ + require('./tmerc'), + require('./utm'), + require('./sterea'), + require('./stere'), + require('./somerc'), + require('./omerc'), + require('./lcc'), + require('./krovak'), + require('./cass'), + require('./laea'), + require('./merc'), + require('./aea'), + require('./gnom'), + require('./cea'), + require('./eqc'), + require('./poly'), + require('./nzmg'), + require('./mill'), + require('./sinu'), + require('./moll'), + require('./eqdc'), + require('./vandg'), + require('./aeqd'), + require('./longlat') +]; +var names = {}; +var projStore = []; + +function add(proj, i) { + var len = projStore.length; + if (!proj.names) { + console.log(i); + return true; + } + projStore[len] = proj; + proj.names.forEach(function(n) { + names[n.toLowerCase()] = len; + }); + return this; +} + +exports.add = add; + +exports.get = function(name) { + if (!name) { + return false; + } + var n = name.toLowerCase(); + if (typeof names[n] !== 'undefined' && projStore[names[n]]) { + return projStore[names[n]]; + } +}; +exports.start = function() { + projs.forEach(add); +}; + +},{"./aea":19,"./aeqd":20,"./cass":21,"./cea":22,"./eqc":23,"./eqdc":24,"./gnom":26,"./krovak":28,"./laea":29,"./lcc":30,"./longlat":31,"./merc":32,"./mill":33,"./moll":34,"./nzmg":35,"./omerc":36,"./poly":37,"./sinu":38,"./somerc":39,"./stere":40,"./sterea":41,"./tmerc":42,"./utm":43,"./vandg":44}],28:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + this.a = 6377397.155; + this.es = 0.006674372230614; + this.e = Math.sqrt(this.es); + if (!this.lat0) { + this.lat0 = 0.863937979737193; + } + if (!this.long0) { + this.long0 = 0.7417649320975901 - 0.308341501185665; + } + /* if scale not set default to 0.9999 */ + if (!this.k0) { + this.k0 = 0.9999; + } + this.s45 = 0.785398163397448; /* 45 */ + this.s90 = 2 * this.s45; + this.fi0 = this.lat0; + this.e2 = this.es; + this.e = Math.sqrt(this.e2); + this.alfa = Math.sqrt(1 + (this.e2 * Math.pow(Math.cos(this.fi0), 4)) / (1 - this.e2)); + this.uq = 1.04216856380474; + this.u0 = Math.asin(Math.sin(this.fi0) / this.alfa); + this.g = Math.pow((1 + this.e * Math.sin(this.fi0)) / (1 - this.e * Math.sin(this.fi0)), this.alfa * this.e / 2); + this.k = Math.tan(this.u0 / 2 + this.s45) / Math.pow(Math.tan(this.fi0 / 2 + this.s45), this.alfa) * this.g; + this.k1 = this.k0; + this.n0 = this.a * Math.sqrt(1 - this.e2) / (1 - this.e2 * Math.pow(Math.sin(this.fi0), 2)); + this.s0 = 1.37008346281555; + this.n = Math.sin(this.s0); + this.ro0 = this.k1 * this.n0 / Math.tan(this.s0); + this.ad = this.s90 - this.uq; +}; + +/* ellipsoid */ +/* calculate xy from lat/lon */ +/* Constants, identical to inverse transform function */ +exports.forward = function(p) { + var gfi, u, deltav, s, d, eps, ro; + var lon = p.x; + var lat = p.y; + var delta_lon = common.adjust_lon(lon - this.long0); + /* Transformation */ + gfi = Math.pow(((1 + this.e * Math.sin(lat)) / (1 - this.e * Math.sin(lat))), (this.alfa * this.e / 2)); + u = 2 * (Math.atan(this.k * Math.pow(Math.tan(lat / 2 + this.s45), this.alfa) / gfi) - this.s45); + deltav = -delta_lon * this.alfa; + s = Math.asin(Math.cos(this.ad) * Math.sin(u) + Math.sin(this.ad) * Math.cos(u) * Math.cos(deltav)); + d = Math.asin(Math.cos(u) * Math.sin(deltav) / Math.cos(s)); + eps = this.n * d; + ro = this.ro0 * Math.pow(Math.tan(this.s0 / 2 + this.s45), this.n) / Math.pow(Math.tan(s / 2 + this.s45), this.n); + p.y = ro * Math.cos(eps) / 1; + p.x = ro * Math.sin(eps) / 1; + + if (!this.czech) { + p.y *= -1; + p.x *= -1; + } + return (p); +}; + +/* calculate lat/lon from xy */ +exports.inverse = function(p) { + var u, deltav, s, d, eps, ro, fi1; + var ok; + + /* Transformation */ + /* revert y, x*/ + var tmp = p.x; + p.x = p.y; + p.y = tmp; + if (!this.czech) { + p.y *= -1; + p.x *= -1; + } + ro = Math.sqrt(p.x * p.x + p.y * p.y); + eps = Math.atan2(p.y, p.x); + d = eps / Math.sin(this.s0); + s = 2 * (Math.atan(Math.pow(this.ro0 / ro, 1 / this.n) * Math.tan(this.s0 / 2 + this.s45)) - this.s45); + u = Math.asin(Math.cos(this.ad) * Math.sin(s) - Math.sin(this.ad) * Math.cos(s) * Math.cos(d)); + deltav = Math.asin(Math.cos(s) * Math.sin(d) / Math.cos(u)); + p.x = this.long0 - deltav / this.alfa; + fi1 = u; + ok = 0; + var iter = 0; + do { + p.y = 2 * (Math.atan(Math.pow(this.k, - 1 / this.alfa) * Math.pow(Math.tan(u / 2 + this.s45), 1 / this.alfa) * Math.pow((1 + this.e * Math.sin(fi1)) / (1 - this.e * Math.sin(fi1)), this.e / 2)) - this.s45); + if (Math.abs(fi1 - p.y) < 0.0000000001) { + ok = 1; + } + fi1 = p.y; + iter += 1; + } while (ok === 0 && iter < 15); + if (iter >= 15) { + return null; + } + + return (p); +}; +exports.names = ["Krovak", "krovak"]; + +},{"../common":4}],29:[function(require,module,exports){ +var common = require('../common'); +/* + reference + "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + */ + +exports.S_POLE = 1; +exports.N_POLE = 2; +exports.EQUIT = 3; +exports.OBLIQ = 4; + + +/* Initialize the Lambert Azimuthal Equal Area projection + ------------------------------------------------------*/ +exports.init = function() { + var t = Math.abs(this.lat0); + if (Math.abs(t - common.HALF_PI) < common.EPSLN) { + this.mode = this.lat0 < 0 ? this.S_POLE : this.N_POLE; + } + else if (Math.abs(t) < common.EPSLN) { + this.mode = this.EQUIT; + } + else { + this.mode = this.OBLIQ; + } + if (this.es > 0) { + var sinphi; + + this.qp = common.qsfnz(this.e, 1); + this.mmf = 0.5 / (1 - this.es); + this.apa = this.authset(this.es); + switch (this.mode) { + case this.N_POLE: + this.dd = 1; + break; + case this.S_POLE: + this.dd = 1; + break; + case this.EQUIT: + this.rq = Math.sqrt(0.5 * this.qp); + this.dd = 1 / this.rq; + this.xmf = 1; + this.ymf = 0.5 * this.qp; + break; + case this.OBLIQ: + this.rq = Math.sqrt(0.5 * this.qp); + sinphi = Math.sin(this.lat0); + this.sinb1 = common.qsfnz(this.e, sinphi) / this.qp; + this.cosb1 = Math.sqrt(1 - this.sinb1 * this.sinb1); + this.dd = Math.cos(this.lat0) / (Math.sqrt(1 - this.es * sinphi * sinphi) * this.rq * this.cosb1); + this.ymf = (this.xmf = this.rq) / this.dd; + this.xmf *= this.dd; + break; + } + } + else { + if (this.mode === this.OBLIQ) { + this.sinph0 = Math.sin(this.lat0); + this.cosph0 = Math.cos(this.lat0); + } + } +}; + +/* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y + -----------------------------------------------------------------------*/ +exports.forward = function(p) { + + /* Forward equations + -----------------*/ + var x, y, coslam, sinlam, sinphi, q, sinb, cosb, b, cosphi; + var lam = p.x; + var phi = p.y; + + lam = common.adjust_lon(lam - this.long0); + + if (this.sphere) { + sinphi = Math.sin(phi); + cosphi = Math.cos(phi); + coslam = Math.cos(lam); + if (this.mode === this.OBLIQ || this.mode === this.EQUIT) { + y = (this.mode === this.EQUIT) ? 1 + cosphi * coslam : 1 + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam; + if (y <= common.EPSLN) { + return null; + } + y = Math.sqrt(2 / y); + x = y * cosphi * Math.sin(lam); + y *= (this.mode === this.EQUIT) ? sinphi : this.cosph0 * sinphi - this.sinph0 * cosphi * coslam; + } + else if (this.mode === this.N_POLE || this.mode === this.S_POLE) { + if (this.mode === this.N_POLE) { + coslam = -coslam; + } + if (Math.abs(phi + this.phi0) < common.EPSLN) { + return null; + } + y = common.FORTPI - phi * 0.5; + y = 2 * ((this.mode === this.S_POLE) ? Math.cos(y) : Math.sin(y)); + x = y * Math.sin(lam); + y *= coslam; + } + } + else { + sinb = 0; + cosb = 0; + b = 0; + coslam = Math.cos(lam); + sinlam = Math.sin(lam); + sinphi = Math.sin(phi); + q = common.qsfnz(this.e, sinphi); + if (this.mode === this.OBLIQ || this.mode === this.EQUIT) { + sinb = q / this.qp; + cosb = Math.sqrt(1 - sinb * sinb); + } + switch (this.mode) { + case this.OBLIQ: + b = 1 + this.sinb1 * sinb + this.cosb1 * cosb * coslam; + break; + case this.EQUIT: + b = 1 + cosb * coslam; + break; + case this.N_POLE: + b = common.HALF_PI + phi; + q = this.qp - q; + break; + case this.S_POLE: + b = phi - common.HALF_PI; + q = this.qp + q; + break; + } + if (Math.abs(b) < common.EPSLN) { + return null; + } + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + b = Math.sqrt(2 / b); + if (this.mode === this.OBLIQ) { + y = this.ymf * b * (this.cosb1 * sinb - this.sinb1 * cosb * coslam); + } + else { + y = (b = Math.sqrt(2 / (1 + cosb * coslam))) * sinb * this.ymf; + } + x = this.xmf * b * cosb * sinlam; + break; + case this.N_POLE: + case this.S_POLE: + if (q >= 0) { + x = (b = Math.sqrt(q)) * sinlam; + y = coslam * ((this.mode === this.S_POLE) ? b : -b); + } + else { + x = y = 0; + } + break; + } + } + + p.x = this.a * x + this.x0; + p.y = this.a * y + this.y0; + return p; +}; + +/* Inverse equations + -----------------*/ +exports.inverse = function(p) { + p.x -= this.x0; + p.y -= this.y0; + var x = p.x / this.a; + var y = p.y / this.a; + var lam, phi, cCe, sCe, q, rho, ab; + + if (this.sphere) { + var cosz = 0, + rh, sinz = 0; + + rh = Math.sqrt(x * x + y * y); + phi = rh * 0.5; + if (phi > 1) { + return null; + } + phi = 2 * Math.asin(phi); + if (this.mode === this.OBLIQ || this.mode === this.EQUIT) { + sinz = Math.sin(phi); + cosz = Math.cos(phi); + } + switch (this.mode) { + case this.EQUIT: + phi = (Math.abs(rh) <= common.EPSLN) ? 0 : Math.asin(y * sinz / rh); + x *= sinz; + y = cosz * rh; + break; + case this.OBLIQ: + phi = (Math.abs(rh) <= common.EPSLN) ? this.phi0 : Math.asin(cosz * this.sinph0 + y * sinz * this.cosph0 / rh); + x *= sinz * this.cosph0; + y = (cosz - Math.sin(phi) * this.sinph0) * rh; + break; + case this.N_POLE: + y = -y; + phi = common.HALF_PI - phi; + break; + case this.S_POLE: + phi -= common.HALF_PI; + break; + } + lam = (y === 0 && (this.mode === this.EQUIT || this.mode === this.OBLIQ)) ? 0 : Math.atan2(x, y); + } + else { + ab = 0; + if (this.mode === this.OBLIQ || this.mode === this.EQUIT) { + x /= this.dd; + y *= this.dd; + rho = Math.sqrt(x * x + y * y); + if (rho < common.EPSLN) { + p.x = 0; + p.y = this.phi0; + return p; + } + sCe = 2 * Math.asin(0.5 * rho / this.rq); + cCe = Math.cos(sCe); + x *= (sCe = Math.sin(sCe)); + if (this.mode === this.OBLIQ) { + ab = cCe * this.sinb1 + y * sCe * this.cosb1 / rho; + q = this.qp * ab; + y = rho * this.cosb1 * cCe - y * this.sinb1 * sCe; + } + else { + ab = y * sCe / rho; + q = this.qp * ab; + y = rho * cCe; + } + } + else if (this.mode === this.N_POLE || this.mode === this.S_POLE) { + if (this.mode === this.N_POLE) { + y = -y; + } + q = (x * x + y * y); + if (!q) { + p.x = 0; + p.y = this.phi0; + return p; + } + ab = 1 - q / this.qp; + if (this.mode === this.S_POLE) { + ab = -ab; + } + } + lam = Math.atan2(x, y); + phi = this.authlat(Math.asin(ab), this.apa); + } + + + p.x = common.adjust_lon(this.long0 + lam); + p.y = phi; + return p; +}; + +/* determine latitude from authalic latitude */ +exports.P00 = 0.33333333333333333333; +exports.P01 = 0.17222222222222222222; +exports.P02 = 0.10257936507936507936; +exports.P10 = 0.06388888888888888888; +exports.P11 = 0.06640211640211640211; +exports.P20 = 0.01641501294219154443; + +exports.authset = function(es) { + var t; + var APA = []; + APA[0] = es * this.P00; + t = es * es; + APA[0] += t * this.P01; + APA[1] = t * this.P10; + t *= es; + APA[0] += t * this.P02; + APA[1] += t * this.P11; + APA[2] = t * this.P20; + return APA; +}; + +exports.authlat = function(beta, APA) { + var t = beta + beta; + return (beta + APA[0] * Math.sin(t) + APA[1] * Math.sin(t + t) + APA[2] * Math.sin(t + t + t)); +}; +exports.names = ["Lambert Azimuthal Equal Area", "Lambert_Azimuthal_Equal_Area", "laea"]; + +},{"../common":4}],30:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + + // array of: r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north + //double c_lat; /* center latitude */ + //double c_lon; /* center longitude */ + //double lat1; /* first standard parallel */ + //double lat2; /* second standard parallel */ + //double r_maj; /* major axis */ + //double r_min; /* minor axis */ + //double false_east; /* x offset in meters */ + //double false_north; /* y offset in meters */ + + if (!this.lat2) { + this.lat2 = this.lat1; + } //if lat2 is not defined + if (!this.k0) { + this.k0 = 1; + } + + // Standard Parallels cannot be equal and on opposite sides of the equator + if (Math.abs(this.lat1 + this.lat2) < common.EPSLN) { + return; + } + + var temp = this.b / this.a; + this.e = Math.sqrt(1 - temp * temp); + + var sin1 = Math.sin(this.lat1); + var cos1 = Math.cos(this.lat1); + var ms1 = common.msfnz(this.e, sin1, cos1); + var ts1 = common.tsfnz(this.e, this.lat1, sin1); + + var sin2 = Math.sin(this.lat2); + var cos2 = Math.cos(this.lat2); + var ms2 = common.msfnz(this.e, sin2, cos2); + var ts2 = common.tsfnz(this.e, this.lat2, sin2); + + var ts0 = common.tsfnz(this.e, this.lat0, Math.sin(this.lat0)); + + if (Math.abs(this.lat1 - this.lat2) > common.EPSLN) { + this.ns = Math.log(ms1 / ms2) / Math.log(ts1 / ts2); + } + else { + this.ns = sin1; + } + if (isNaN(this.ns)) { + this.ns = sin1; + } + this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns)); + this.rh = this.a * this.f0 * Math.pow(ts0, this.ns); + if (!this.title) { + this.title = "Lambert Conformal Conic"; + } +}; + + +// Lambert Conformal conic forward equations--mapping lat,long to x,y +// ----------------------------------------------------------------- +exports.forward = function(p) { + + var lon = p.x; + var lat = p.y; + + // singular cases : + if (Math.abs(2 * Math.abs(lat) - common.PI) <= common.EPSLN) { + lat = common.sign(lat) * (common.HALF_PI - 2 * common.EPSLN); + } + + var con = Math.abs(Math.abs(lat) - common.HALF_PI); + var ts, rh1; + if (con > common.EPSLN) { + ts = common.tsfnz(this.e, lat, Math.sin(lat)); + rh1 = this.a * this.f0 * Math.pow(ts, this.ns); + } + else { + con = lat * this.ns; + if (con <= 0) { + return null; + } + rh1 = 0; + } + var theta = this.ns * common.adjust_lon(lon - this.long0); + p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0; + p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0; + + return p; +}; + +// Lambert Conformal Conic inverse equations--mapping x,y to lat/long +// ----------------------------------------------------------------- +exports.inverse = function(p) { + + var rh1, con, ts; + var lat, lon; + var x = (p.x - this.x0) / this.k0; + var y = (this.rh - (p.y - this.y0) / this.k0); + if (this.ns > 0) { + rh1 = Math.sqrt(x * x + y * y); + con = 1; + } + else { + rh1 = -Math.sqrt(x * x + y * y); + con = -1; + } + var theta = 0; + if (rh1 !== 0) { + theta = Math.atan2((con * x), (con * y)); + } + if ((rh1 !== 0) || (this.ns > 0)) { + con = 1 / this.ns; + ts = Math.pow((rh1 / (this.a * this.f0)), con); + lat = common.phi2z(this.e, ts); + if (lat === -9999) { + return null; + } + } + else { + lat = -common.HALF_PI; + } + lon = common.adjust_lon(theta / this.ns + this.long0); + + p.x = lon; + p.y = lat; + return p; +}; + +exports.names = ["Lambert Tangential Conformal Conic Projection", "Lambert_Conformal_Conic", "Lambert_Conformal_Conic_2SP", "lcc"]; + +},{"../common":4}],31:[function(require,module,exports){ +exports.init = function() { + //no-op for longlat +}; + +function identity(pt) { + return pt; +} +exports.forward = identity; +exports.inverse = identity; +exports.names = ["longlat", "identity"]; + +},{}],32:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + var con = this.b / this.a; + this.es = 1 - con * con; + this.e = Math.sqrt(this.es); + if (this.lat_ts) { + if (this.sphere) { + this.k0 = Math.cos(this.lat_ts); + } + else { + this.k0 = common.msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts)); + } + } + else { + if (!this.k0) { + if (this.k) { + this.k0 = this.k; + } + else { + this.k0 = 1; + } + } + } +}; + +/* Mercator forward equations--mapping lat,long to x,y + --------------------------------------------------*/ + +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + // convert to radians + if (lat * common.R2D > 90 && lat * common.R2D < -90 && lon * common.R2D > 180 && lon * common.R2D < -180) { + return null; + } + + var x, y; + if (Math.abs(Math.abs(lat) - common.HALF_PI) <= common.EPSLN) { + return null; + } + else { + if (this.sphere) { + x = this.x0 + this.a * this.k0 * common.adjust_lon(lon - this.long0); + y = this.y0 + this.a * this.k0 * Math.log(Math.tan(common.FORTPI + 0.5 * lat)); + } + else { + var sinphi = Math.sin(lat); + var ts = common.tsfnz(this.e, lat, sinphi); + x = this.x0 + this.a * this.k0 * common.adjust_lon(lon - this.long0); + y = this.y0 - this.a * this.k0 * Math.log(ts); + } + p.x = x; + p.y = y; + return p; + } +}; + + +/* Mercator inverse equations--mapping x,y to lat/long + --------------------------------------------------*/ +exports.inverse = function(p) { + + var x = p.x - this.x0; + var y = p.y - this.y0; + var lon, lat; + + if (this.sphere) { + lat = common.HALF_PI - 2 * Math.atan(Math.exp(-y / (this.a * this.k0))); + } + else { + var ts = Math.exp(-y / (this.a * this.k0)); + lat = common.phi2z(this.e, ts); + if (lat === -9999) { + return null; + } + } + lon = common.adjust_lon(this.long0 + x / (this.a * this.k0)); + + p.x = lon; + p.y = lat; + return p; +}; + +exports.names = ["Mercator", "Popular Visualisation Pseudo Mercator", "Mercator_1SP", "Mercator_Auxiliary_Sphere", "merc"]; + +},{"../common":4}],33:[function(require,module,exports){ +var common = require('../common'); +/* + reference + "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + */ + + +/* Initialize the Miller Cylindrical projection + -------------------------------------------*/ +exports.init = function() { + //no-op +}; + + +/* Miller Cylindrical forward equations--mapping lat,long to x,y + ------------------------------------------------------------*/ +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + /* Forward equations + -----------------*/ + var dlon = common.adjust_lon(lon - this.long0); + var x = this.x0 + this.a * dlon; + var y = this.y0 + this.a * Math.log(Math.tan((common.PI / 4) + (lat / 2.5))) * 1.25; + + p.x = x; + p.y = y; + return p; +}; + +/* Miller Cylindrical inverse equations--mapping x,y to lat/long + ------------------------------------------------------------*/ +exports.inverse = function(p) { + p.x -= this.x0; + p.y -= this.y0; + + var lon = common.adjust_lon(this.long0 + p.x / this.a); + var lat = 2.5 * (Math.atan(Math.exp(0.8 * p.y / this.a)) - common.PI / 4); + + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["Miller_Cylindrical", "mill"]; + +},{"../common":4}],34:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() {}; + +/* Mollweide forward equations--mapping lat,long to x,y + ----------------------------------------------------*/ +exports.forward = function(p) { + + /* Forward equations + -----------------*/ + var lon = p.x; + var lat = p.y; + + var delta_lon = common.adjust_lon(lon - this.long0); + var theta = lat; + var con = common.PI * Math.sin(lat); + + /* Iterate using the Newton-Raphson method to find theta + -----------------------------------------------------*/ + for (var i = 0; true; i++) { + var delta_theta = -(theta + Math.sin(theta) - con) / (1 + Math.cos(theta)); + theta += delta_theta; + if (Math.abs(delta_theta) < common.EPSLN) { + break; + } + } + theta /= 2; + + /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting" + this is done here because of precision problems with "cos(theta)" + --------------------------------------------------------------------------*/ + if (common.PI / 2 - Math.abs(lat) < common.EPSLN) { + delta_lon = 0; + } + var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0; + var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0; + + p.x = x; + p.y = y; + return p; +}; + +exports.inverse = function(p) { + var theta; + var arg; + + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + arg = p.y / (1.4142135623731 * this.a); + + /* Because of division by zero problems, 'arg' can not be 1. Therefore + a number very close to one is used instead. + -------------------------------------------------------------------*/ + if (Math.abs(arg) > 0.999999999999) { + arg = 0.999999999999; + } + theta = Math.asin(arg); + var lon = common.adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta)))); + if (lon < (-common.PI)) { + lon = -common.PI; + } + if (lon > common.PI) { + lon = common.PI; + } + arg = (2 * theta + Math.sin(2 * theta)) / common.PI; + if (Math.abs(arg) > 1) { + arg = 1; + } + var lat = Math.asin(arg); + + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["Mollweide", "moll"]; + +},{"../common":4}],35:[function(require,module,exports){ +var common = require('../common'); +/* + reference + Department of Land and Survey Technical Circular 1973/32 + http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf + OSG Technical Report 4.1 + http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf + */ + +/** + * iterations: Number of iterations to refine inverse transform. + * 0 -> km accuracy + * 1 -> m accuracy -- suitable for most mapping applications + * 2 -> mm accuracy + */ +exports.iterations = 1; + +exports.init = function() { + this.A = []; + this.A[1] = 0.6399175073; + this.A[2] = -0.1358797613; + this.A[3] = 0.063294409; + this.A[4] = -0.02526853; + this.A[5] = 0.0117879; + this.A[6] = -0.0055161; + this.A[7] = 0.0026906; + this.A[8] = -0.001333; + this.A[9] = 0.00067; + this.A[10] = -0.00034; + + this.B_re = []; + this.B_im = []; + this.B_re[1] = 0.7557853228; + this.B_im[1] = 0; + this.B_re[2] = 0.249204646; + this.B_im[2] = 0.003371507; + this.B_re[3] = -0.001541739; + this.B_im[3] = 0.041058560; + this.B_re[4] = -0.10162907; + this.B_im[4] = 0.01727609; + this.B_re[5] = -0.26623489; + this.B_im[5] = -0.36249218; + this.B_re[6] = -0.6870983; + this.B_im[6] = -1.1651967; + + this.C_re = []; + this.C_im = []; + this.C_re[1] = 1.3231270439; + this.C_im[1] = 0; + this.C_re[2] = -0.577245789; + this.C_im[2] = -0.007809598; + this.C_re[3] = 0.508307513; + this.C_im[3] = -0.112208952; + this.C_re[4] = -0.15094762; + this.C_im[4] = 0.18200602; + this.C_re[5] = 1.01418179; + this.C_im[5] = 1.64497696; + this.C_re[6] = 1.9660549; + this.C_im[6] = 2.5127645; + + this.D = []; + this.D[1] = 1.5627014243; + this.D[2] = 0.5185406398; + this.D[3] = -0.03333098; + this.D[4] = -0.1052906; + this.D[5] = -0.0368594; + this.D[6] = 0.007317; + this.D[7] = 0.01220; + this.D[8] = 0.00394; + this.D[9] = -0.0013; +}; + +/** + New Zealand Map Grid Forward - long/lat to x/y + long/lat in radians + */ +exports.forward = function(p) { + var n; + var lon = p.x; + var lat = p.y; + + var delta_lat = lat - this.lat0; + var delta_lon = lon - this.long0; + + // 1. Calculate d_phi and d_psi ... // and d_lambda + // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians. + var d_phi = delta_lat / common.SEC_TO_RAD * 1E-5; + var d_lambda = delta_lon; + var d_phi_n = 1; // d_phi^0 + + var d_psi = 0; + for (n = 1; n <= 10; n++) { + d_phi_n = d_phi_n * d_phi; + d_psi = d_psi + this.A[n] * d_phi_n; + } + + // 2. Calculate theta + var th_re = d_psi; + var th_im = d_lambda; + + // 3. Calculate z + var th_n_re = 1; + var th_n_im = 0; // theta^0 + var th_n_re1; + var th_n_im1; + + var z_re = 0; + var z_im = 0; + for (n = 1; n <= 6; n++) { + th_n_re1 = th_n_re * th_re - th_n_im * th_im; + th_n_im1 = th_n_im * th_re + th_n_re * th_im; + th_n_re = th_n_re1; + th_n_im = th_n_im1; + z_re = z_re + this.B_re[n] * th_n_re - this.B_im[n] * th_n_im; + z_im = z_im + this.B_im[n] * th_n_re + this.B_re[n] * th_n_im; + } + + // 4. Calculate easting and northing + p.x = (z_im * this.a) + this.x0; + p.y = (z_re * this.a) + this.y0; + + return p; +}; + + +/** + New Zealand Map Grid Inverse - x/y to long/lat + */ +exports.inverse = function(p) { + var n; + var x = p.x; + var y = p.y; + + var delta_x = x - this.x0; + var delta_y = y - this.y0; + + // 1. Calculate z + var z_re = delta_y / this.a; + var z_im = delta_x / this.a; + + // 2a. Calculate theta - first approximation gives km accuracy + var z_n_re = 1; + var z_n_im = 0; // z^0 + var z_n_re1; + var z_n_im1; + + var th_re = 0; + var th_im = 0; + for (n = 1; n <= 6; n++) { + z_n_re1 = z_n_re * z_re - z_n_im * z_im; + z_n_im1 = z_n_im * z_re + z_n_re * z_im; + z_n_re = z_n_re1; + z_n_im = z_n_im1; + th_re = th_re + this.C_re[n] * z_n_re - this.C_im[n] * z_n_im; + th_im = th_im + this.C_im[n] * z_n_re + this.C_re[n] * z_n_im; + } + + // 2b. Iterate to refine the accuracy of the calculation + // 0 iterations gives km accuracy + // 1 iteration gives m accuracy -- good enough for most mapping applications + // 2 iterations bives mm accuracy + for (var i = 0; i < this.iterations; i++) { + var th_n_re = th_re; + var th_n_im = th_im; + var th_n_re1; + var th_n_im1; + + var num_re = z_re; + var num_im = z_im; + for (n = 2; n <= 6; n++) { + th_n_re1 = th_n_re * th_re - th_n_im * th_im; + th_n_im1 = th_n_im * th_re + th_n_re * th_im; + th_n_re = th_n_re1; + th_n_im = th_n_im1; + num_re = num_re + (n - 1) * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im); + num_im = num_im + (n - 1) * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im); + } + + th_n_re = 1; + th_n_im = 0; + var den_re = this.B_re[1]; + var den_im = this.B_im[1]; + for (n = 2; n <= 6; n++) { + th_n_re1 = th_n_re * th_re - th_n_im * th_im; + th_n_im1 = th_n_im * th_re + th_n_re * th_im; + th_n_re = th_n_re1; + th_n_im = th_n_im1; + den_re = den_re + n * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im); + den_im = den_im + n * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im); + } + + // Complex division + var den2 = den_re * den_re + den_im * den_im; + th_re = (num_re * den_re + num_im * den_im) / den2; + th_im = (num_im * den_re - num_re * den_im) / den2; + } + + // 3. Calculate d_phi ... // and d_lambda + var d_psi = th_re; + var d_lambda = th_im; + var d_psi_n = 1; // d_psi^0 + + var d_phi = 0; + for (n = 1; n <= 9; n++) { + d_psi_n = d_psi_n * d_psi; + d_phi = d_phi + this.D[n] * d_psi_n; + } + + // 4. Calculate latitude and longitude + // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians. + var lat = this.lat0 + (d_phi * common.SEC_TO_RAD * 1E5); + var lon = this.long0 + d_lambda; + + p.x = lon; + p.y = lat; + + return p; +}; +exports.names = ["New_Zealand_Map_Grid", "nzmg"]; +},{"../common":4}],36:[function(require,module,exports){ +var common = require('../common'); + + +/* Initialize the Oblique Mercator projection + ------------------------------------------*/ +exports.init = function() { + this.no_off = this.no_off || false; + this.no_rot = this.no_rot || false; + + if (isNaN(this.k0)) { + this.k0 = 1; + } + var sinlat = Math.sin(this.lat0); + var coslat = Math.cos(this.lat0); + var con = this.e * sinlat; + + this.bl = Math.sqrt(1 + this.es / (1 - this.es) * Math.pow(coslat, 4)); + this.al = this.a * this.bl * this.k0 * Math.sqrt(1 - this.es) / (1 - con * con); + var t0 = common.tsfnz(this.e, this.lat0, sinlat); + var dl = this.bl / coslat * Math.sqrt((1 - this.es) / (1 - con * con)); + if (dl * dl < 1) { + dl = 1; + } + var fl; + var gl; + if (!isNaN(this.longc)) { + //Central point and azimuth method + + if (this.lat0 >= 0) { + fl = dl + Math.sqrt(dl * dl - 1); + } + else { + fl = dl - Math.sqrt(dl * dl - 1); + } + this.el = fl * Math.pow(t0, this.bl); + gl = 0.5 * (fl - 1 / fl); + this.gamma0 = Math.asin(Math.sin(this.alpha) / dl); + this.long0 = this.longc - Math.asin(gl * Math.tan(this.gamma0)) / this.bl; + + } + else { + //2 points method + var t1 = common.tsfnz(this.e, this.lat1, Math.sin(this.lat1)); + var t2 = common.tsfnz(this.e, this.lat2, Math.sin(this.lat2)); + if (this.lat0 >= 0) { + this.el = (dl + Math.sqrt(dl * dl - 1)) * Math.pow(t0, this.bl); + } + else { + this.el = (dl - Math.sqrt(dl * dl - 1)) * Math.pow(t0, this.bl); + } + var hl = Math.pow(t1, this.bl); + var ll = Math.pow(t2, this.bl); + fl = this.el / hl; + gl = 0.5 * (fl - 1 / fl); + var jl = (this.el * this.el - ll * hl) / (this.el * this.el + ll * hl); + var pl = (ll - hl) / (ll + hl); + var dlon12 = common.adjust_lon(this.long1 - this.long2); + this.long0 = 0.5 * (this.long1 + this.long2) - Math.atan(jl * Math.tan(0.5 * this.bl * (dlon12)) / pl) / this.bl; + this.long0 = common.adjust_lon(this.long0); + var dlon10 = common.adjust_lon(this.long1 - this.long0); + this.gamma0 = Math.atan(Math.sin(this.bl * (dlon10)) / gl); + this.alpha = Math.asin(dl * Math.sin(this.gamma0)); + } + + if (this.no_off) { + this.uc = 0; + } + else { + if (this.lat0 >= 0) { + this.uc = this.al / this.bl * Math.atan2(Math.sqrt(dl * dl - 1), Math.cos(this.alpha)); + } + else { + this.uc = -1 * this.al / this.bl * Math.atan2(Math.sqrt(dl * dl - 1), Math.cos(this.alpha)); + } + } + +}; + + +/* Oblique Mercator forward equations--mapping lat,long to x,y + ----------------------------------------------------------*/ +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + var dlon = common.adjust_lon(lon - this.long0); + var us, vs; + var con; + if (Math.abs(Math.abs(lat) - common.HALF_PI) <= common.EPSLN) { + if (lat > 0) { + con = -1; + } + else { + con = 1; + } + vs = this.al / this.bl * Math.log(Math.tan(common.FORTPI + con * this.gamma0 * 0.5)); + us = -1 * con * common.HALF_PI * this.al / this.bl; + } + else { + var t = common.tsfnz(this.e, lat, Math.sin(lat)); + var ql = this.el / Math.pow(t, this.bl); + var sl = 0.5 * (ql - 1 / ql); + var tl = 0.5 * (ql + 1 / ql); + var vl = Math.sin(this.bl * (dlon)); + var ul = (sl * Math.sin(this.gamma0) - vl * Math.cos(this.gamma0)) / tl; + if (Math.abs(Math.abs(ul) - 1) <= common.EPSLN) { + vs = Number.POSITIVE_INFINITY; + } + else { + vs = 0.5 * this.al * Math.log((1 - ul) / (1 + ul)) / this.bl; + } + if (Math.abs(Math.cos(this.bl * (dlon))) <= common.EPSLN) { + us = this.al * this.bl * (dlon); + } + else { + us = this.al * Math.atan2(sl * Math.cos(this.gamma0) + vl * Math.sin(this.gamma0), Math.cos(this.bl * dlon)) / this.bl; + } + } + + if (this.no_rot) { + p.x = this.x0 + us; + p.y = this.y0 + vs; + } + else { + + us -= this.uc; + p.x = this.x0 + vs * Math.cos(this.alpha) + us * Math.sin(this.alpha); + p.y = this.y0 + us * Math.cos(this.alpha) - vs * Math.sin(this.alpha); + } + return p; +}; + +exports.inverse = function(p) { + var us, vs; + if (this.no_rot) { + vs = p.y - this.y0; + us = p.x - this.x0; + } + else { + vs = (p.x - this.x0) * Math.cos(this.alpha) - (p.y - this.y0) * Math.sin(this.alpha); + us = (p.y - this.y0) * Math.cos(this.alpha) + (p.x - this.x0) * Math.sin(this.alpha); + us += this.uc; + } + var qp = Math.exp(-1 * this.bl * vs / this.al); + var sp = 0.5 * (qp - 1 / qp); + var tp = 0.5 * (qp + 1 / qp); + var vp = Math.sin(this.bl * us / this.al); + var up = (vp * Math.cos(this.gamma0) + sp * Math.sin(this.gamma0)) / tp; + var ts = Math.pow(this.el / Math.sqrt((1 + up) / (1 - up)), 1 / this.bl); + if (Math.abs(up - 1) < common.EPSLN) { + p.x = this.long0; + p.y = common.HALF_PI; + } + else if (Math.abs(up + 1) < common.EPSLN) { + p.x = this.long0; + p.y = -1 * common.HALF_PI; + } + else { + p.y = common.phi2z(this.e, ts); + p.x = common.adjust_lon(this.long0 - Math.atan2(sp * Math.cos(this.gamma0) - vp * Math.sin(this.gamma0), Math.cos(this.bl * us / this.al)) / this.bl); + } + return p; +}; + +exports.names = ["Hotine_Oblique_Mercator", "Hotine Oblique Mercator", "Hotine_Oblique_Mercator_Azimuth_Natural_Origin", "Hotine_Oblique_Mercator_Azimuth_Center", "omerc"]; +},{"../common":4}],37:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + /* Place parameters in static storage for common use + -------------------------------------------------*/ + this.temp = this.b / this.a; + this.es = 1 - Math.pow(this.temp, 2); // devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles + this.e = Math.sqrt(this.es); + this.e0 = common.e0fn(this.es); + this.e1 = common.e1fn(this.es); + this.e2 = common.e2fn(this.es); + this.e3 = common.e3fn(this.es); + this.ml0 = this.a * common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); //si que des zeros le calcul ne se fait pas +}; + + +/* Polyconic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + var x, y, el; + var dlon = common.adjust_lon(lon - this.long0); + el = dlon * Math.sin(lat); + if (this.sphere) { + if (Math.abs(lat) <= common.EPSLN) { + x = this.a * dlon; + y = -1 * this.a * this.lat0; + } + else { + x = this.a * Math.sin(el) / Math.tan(lat); + y = this.a * (common.adjust_lat(lat - this.lat0) + (1 - Math.cos(el)) / Math.tan(lat)); + } + } + else { + if (Math.abs(lat) <= common.EPSLN) { + x = this.a * dlon; + y = -1 * this.ml0; + } + else { + var nl = common.gN(this.a, this.e, Math.sin(lat)) / Math.tan(lat); + x = nl * Math.sin(el); + y = this.a * common.mlfn(this.e0, this.e1, this.e2, this.e3, lat) - this.ml0 + nl * (1 - Math.cos(el)); + } + + } + p.x = x + this.x0; + p.y = y + this.y0; + return p; +}; + + +/* Inverse equations + -----------------*/ +exports.inverse = function(p) { + var lon, lat, x, y, i; + var al, bl; + var phi, dphi; + x = p.x - this.x0; + y = p.y - this.y0; + + if (this.sphere) { + if (Math.abs(y + this.a * this.lat0) <= common.EPSLN) { + lon = common.adjust_lon(x / this.a + this.long0); + lat = 0; + } + else { + al = this.lat0 + y / this.a; + bl = x * x / this.a / this.a + al * al; + phi = al; + var tanphi; + for (i = common.MAX_ITER; i; --i) { + tanphi = Math.tan(phi); + dphi = -1 * (al * (phi * tanphi + 1) - phi - 0.5 * (phi * phi + bl) * tanphi) / ((phi - al) / tanphi - 1); + phi += dphi; + if (Math.abs(dphi) <= common.EPSLN) { + lat = phi; + break; + } + } + lon = common.adjust_lon(this.long0 + (Math.asin(x * Math.tan(phi) / this.a)) / Math.sin(lat)); + } + } + else { + if (Math.abs(y + this.ml0) <= common.EPSLN) { + lat = 0; + lon = common.adjust_lon(this.long0 + x / this.a); + } + else { + + al = (this.ml0 + y) / this.a; + bl = x * x / this.a / this.a + al * al; + phi = al; + var cl, mln, mlnp, ma; + var con; + for (i = common.MAX_ITER; i; --i) { + con = this.e * Math.sin(phi); + cl = Math.sqrt(1 - con * con) * Math.tan(phi); + mln = this.a * common.mlfn(this.e0, this.e1, this.e2, this.e3, phi); + mlnp = this.e0 - 2 * this.e1 * Math.cos(2 * phi) + 4 * this.e2 * Math.cos(4 * phi) - 6 * this.e3 * Math.cos(6 * phi); + ma = mln / this.a; + dphi = (al * (cl * ma + 1) - ma - 0.5 * cl * (ma * ma + bl)) / (this.es * Math.sin(2 * phi) * (ma * ma + bl - 2 * al * ma) / (4 * cl) + (al - ma) * (cl * mlnp - 2 / Math.sin(2 * phi)) - mlnp); + phi -= dphi; + if (Math.abs(dphi) <= common.EPSLN) { + lat = phi; + break; + } + } + + //lat=phi4z(this.e,this.e0,this.e1,this.e2,this.e3,al,bl,0,0); + cl = Math.sqrt(1 - this.es * Math.pow(Math.sin(lat), 2)) * Math.tan(lat); + lon = common.adjust_lon(this.long0 + Math.asin(x * cl / this.a) / Math.sin(lat)); + } + } + + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["Polyconic", "poly"]; +},{"../common":4}],38:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + /* Place parameters in static storage for common use + -------------------------------------------------*/ + + + if (!this.sphere) { + this.en = common.pj_enfn(this.es); + } + else { + this.n = 1; + this.m = 0; + this.es = 0; + this.C_y = Math.sqrt((this.m + 1) / this.n); + this.C_x = this.C_y / (this.m + 1); + } + +}; + +/* Sinusoidal forward equations--mapping lat,long to x,y + -----------------------------------------------------*/ +exports.forward = function(p) { + var x, y; + var lon = p.x; + var lat = p.y; + /* Forward equations + -----------------*/ + lon = common.adjust_lon(lon - this.long0); + + if (this.sphere) { + if (!this.m) { + lat = this.n !== 1 ? Math.asin(this.n * Math.sin(lat)) : lat; + } + else { + var k = this.n * Math.sin(lat); + for (var i = common.MAX_ITER; i; --i) { + var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat)); + lat -= V; + if (Math.abs(V) < common.EPSLN) { + break; + } + } + } + x = this.a * this.C_x * lon * (this.m + Math.cos(lat)); + y = this.a * this.C_y * lat; + + } + else { + + var s = Math.sin(lat); + var c = Math.cos(lat); + y = this.a * common.pj_mlfn(lat, s, c, this.en); + x = this.a * lon * c / Math.sqrt(1 - this.es * s * s); + } + + p.x = x; + p.y = y; + return p; +}; + +exports.inverse = function(p) { + var lat, temp, lon, s; + + p.x -= this.x0; + lon = p.x / this.a; + p.y -= this.y0; + lat = p.y / this.a; + + if (this.sphere) { + lat /= this.C_y; + lon = lon / (this.C_x * (this.m + Math.cos(lat))); + if (this.m) { + lat = common.asinz((this.m * lat + Math.sin(lat)) / this.n); + } + else if (this.n !== 1) { + lat = common.asinz(Math.sin(lat) / this.n); + } + lon = common.adjust_lon(lon + this.long0); + lat = common.adjust_lat(lat); + } + else { + lat = common.pj_inv_mlfn(p.y / this.a, this.es, this.en); + s = Math.abs(lat); + if (s < common.HALF_PI) { + s = Math.sin(lat); + temp = this.long0 + p.x * Math.sqrt(1 - this.es * s * s) / (this.a * Math.cos(lat)); + //temp = this.long0 + p.x / (this.a * Math.cos(lat)); + lon = common.adjust_lon(temp); + } + else if ((s - common.EPSLN) < common.HALF_PI) { + lon = this.long0; + } + } + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["Sinusoidal", "sinu"]; +},{"../common":4}],39:[function(require,module,exports){ +/* + references: + Formules et constantes pour le Calcul pour la + projection cylindrique conforme à axe oblique et pour la transformation entre + des systèmes de référence. + http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf + */ +exports.init = function() { + var phy0 = this.lat0; + this.lambda0 = this.long0; + var sinPhy0 = Math.sin(phy0); + var semiMajorAxis = this.a; + var invF = this.rf; + var flattening = 1 / invF; + var e2 = 2 * flattening - Math.pow(flattening, 2); + var e = this.e = Math.sqrt(e2); + this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2)); + this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4)); + this.b0 = Math.asin(sinPhy0 / this.alpha); + var k1 = Math.log(Math.tan(Math.PI / 4 + this.b0 / 2)); + var k2 = Math.log(Math.tan(Math.PI / 4 + phy0 / 2)); + var k3 = Math.log((1 + e * sinPhy0) / (1 - e * sinPhy0)); + this.K = k1 - this.alpha * k2 + this.alpha * e / 2 * k3; +}; + + +exports.forward = function(p) { + var Sa1 = Math.log(Math.tan(Math.PI / 4 - p.y / 2)); + var Sa2 = this.e / 2 * Math.log((1 + this.e * Math.sin(p.y)) / (1 - this.e * Math.sin(p.y))); + var S = -this.alpha * (Sa1 + Sa2) + this.K; + + // spheric latitude + var b = 2 * (Math.atan(Math.exp(S)) - Math.PI / 4); + + // spheric longitude + var I = this.alpha * (p.x - this.lambda0); + + // psoeudo equatorial rotation + var rotI = Math.atan(Math.sin(I) / (Math.sin(this.b0) * Math.tan(b) + Math.cos(this.b0) * Math.cos(I))); + + var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) - Math.sin(this.b0) * Math.cos(b) * Math.cos(I)); + + p.y = this.R / 2 * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB))) + this.y0; + p.x = this.R * rotI + this.x0; + return p; +}; + +exports.inverse = function(p) { + var Y = p.x - this.x0; + var X = p.y - this.y0; + + var rotI = Y / this.R; + var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4); + + var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB) + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI)); + var I = Math.atan(Math.sin(rotI) / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0) * Math.tan(rotB))); + + var lambda = this.lambda0 + I / this.alpha; + + var S = 0; + var phy = b; + var prevPhy = -1000; + var iteration = 0; + while (Math.abs(phy - prevPhy) > 0.0000001) { + if (++iteration > 20) { + //...reportError("omercFwdInfinity"); + return; + } + //S = Math.log(Math.tan(Math.PI / 4 + phy / 2)); + S = 1 / this.alpha * (Math.log(Math.tan(Math.PI / 4 + b / 2)) - this.K) + this.e * Math.log(Math.tan(Math.PI / 4 + Math.asin(this.e * Math.sin(phy)) / 2)); + prevPhy = phy; + phy = 2 * Math.atan(Math.exp(S)) - Math.PI / 2; + } + + p.x = lambda; + p.y = phy; + return p; +}; + +exports.names = ["somerc"]; + +},{}],40:[function(require,module,exports){ +var common = require('../common'); +exports.ssfn_ = function(phit, sinphi, eccen) { + sinphi *= eccen; + return (Math.tan(0.5 * (common.HALF_PI + phit)) * Math.pow((1 - sinphi) / (1 + sinphi), 0.5 * eccen)); +}; + +exports.init = function() { + this.coslat0 = Math.cos(this.lat0); + this.sinlat0 = Math.sin(this.lat0); + if (this.sphere) { + if (this.k0 === 1 && !isNaN(this.lat_ts) && Math.abs(this.coslat0) <= common.EPSLN) { + this.k0 = 0.5 * (1 + common.sign(this.lat0) * Math.sin(this.lat_ts)); + } + } + else { + if (Math.abs(this.coslat0) <= common.EPSLN) { + if (this.lat0 > 0) { + //North pole + //trace('stere:north pole'); + this.con = 1; + } + else { + //South pole + //trace('stere:south pole'); + this.con = -1; + } + } + this.cons = Math.sqrt(Math.pow(1 + this.e, 1 + this.e) * Math.pow(1 - this.e, 1 - this.e)); + if (this.k0 === 1 && !isNaN(this.lat_ts) && Math.abs(this.coslat0) <= common.EPSLN) { + this.k0 = 0.5 * this.cons * common.msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts)) / common.tsfnz(this.e, this.con * this.lat_ts, this.con * Math.sin(this.lat_ts)); + } + this.ms1 = common.msfnz(this.e, this.sinlat0, this.coslat0); + this.X0 = 2 * Math.atan(this.ssfn_(this.lat0, this.sinlat0, this.e)) - common.HALF_PI; + this.cosX0 = Math.cos(this.X0); + this.sinX0 = Math.sin(this.X0); + } +}; + +// Stereographic forward equations--mapping lat,long to x,y +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + var sinlat = Math.sin(lat); + var coslat = Math.cos(lat); + var A, X, sinX, cosX, ts, rh; + var dlon = common.adjust_lon(lon - this.long0); + + if (Math.abs(Math.abs(lon - this.long0) - common.PI) <= common.EPSLN && Math.abs(lat + this.lat0) <= common.EPSLN) { + //case of the origine point + //trace('stere:this is the origin point'); + p.x = NaN; + p.y = NaN; + return p; + } + if (this.sphere) { + //trace('stere:sphere case'); + A = 2 * this.k0 / (1 + this.sinlat0 * sinlat + this.coslat0 * coslat * Math.cos(dlon)); + p.x = this.a * A * coslat * Math.sin(dlon) + this.x0; + p.y = this.a * A * (this.coslat0 * sinlat - this.sinlat0 * coslat * Math.cos(dlon)) + this.y0; + return p; + } + else { + X = 2 * Math.atan(this.ssfn_(lat, sinlat, this.e)) - common.HALF_PI; + cosX = Math.cos(X); + sinX = Math.sin(X); + if (Math.abs(this.coslat0) <= common.EPSLN) { + ts = common.tsfnz(this.e, lat * this.con, this.con * sinlat); + rh = 2 * this.a * this.k0 * ts / this.cons; + p.x = this.x0 + rh * Math.sin(lon - this.long0); + p.y = this.y0 - this.con * rh * Math.cos(lon - this.long0); + //trace(p.toString()); + return p; + } + else if (Math.abs(this.sinlat0) < common.EPSLN) { + //Eq + //trace('stere:equateur'); + A = 2 * this.a * this.k0 / (1 + cosX * Math.cos(dlon)); + p.y = A * sinX; + } + else { + //other case + //trace('stere:normal case'); + A = 2 * this.a * this.k0 * this.ms1 / (this.cosX0 * (1 + this.sinX0 * sinX + this.cosX0 * cosX * Math.cos(dlon))); + p.y = A * (this.cosX0 * sinX - this.sinX0 * cosX * Math.cos(dlon)) + this.y0; + } + p.x = A * cosX * Math.sin(dlon) + this.x0; + } + //trace(p.toString()); + return p; +}; + + +//* Stereographic inverse equations--mapping x,y to lat/long +exports.inverse = function(p) { + p.x -= this.x0; + p.y -= this.y0; + var lon, lat, ts, ce, Chi; + var rh = Math.sqrt(p.x * p.x + p.y * p.y); + if (this.sphere) { + var c = 2 * Math.atan(rh / (0.5 * this.a * this.k0)); + lon = this.long0; + lat = this.lat0; + if (rh <= common.EPSLN) { + p.x = lon; + p.y = lat; + return p; + } + lat = Math.asin(Math.cos(c) * this.sinlat0 + p.y * Math.sin(c) * this.coslat0 / rh); + if (Math.abs(this.coslat0) < common.EPSLN) { + if (this.lat0 > 0) { + lon = common.adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y)); + } + else { + lon = common.adjust_lon(this.long0 + Math.atan2(p.x, p.y)); + } + } + else { + lon = common.adjust_lon(this.long0 + Math.atan2(p.x * Math.sin(c), rh * this.coslat0 * Math.cos(c) - p.y * this.sinlat0 * Math.sin(c))); + } + p.x = lon; + p.y = lat; + return p; + } + else { + if (Math.abs(this.coslat0) <= common.EPSLN) { + if (rh <= common.EPSLN) { + lat = this.lat0; + lon = this.long0; + p.x = lon; + p.y = lat; + //trace(p.toString()); + return p; + } + p.x *= this.con; + p.y *= this.con; + ts = rh * this.cons / (2 * this.a * this.k0); + lat = this.con * common.phi2z(this.e, ts); + lon = this.con * common.adjust_lon(this.con * this.long0 + Math.atan2(p.x, - 1 * p.y)); + } + else { + ce = 2 * Math.atan(rh * this.cosX0 / (2 * this.a * this.k0 * this.ms1)); + lon = this.long0; + if (rh <= common.EPSLN) { + Chi = this.X0; + } + else { + Chi = Math.asin(Math.cos(ce) * this.sinX0 + p.y * Math.sin(ce) * this.cosX0 / rh); + lon = common.adjust_lon(this.long0 + Math.atan2(p.x * Math.sin(ce), rh * this.cosX0 * Math.cos(ce) - p.y * this.sinX0 * Math.sin(ce))); + } + lat = -1 * common.phi2z(this.e, Math.tan(0.5 * (common.HALF_PI + Chi))); + } + } + p.x = lon; + p.y = lat; + + //trace(p.toString()); + return p; + +}; +exports.names = ["stere"]; +},{"../common":4}],41:[function(require,module,exports){ +var common = require('../common'); +var gauss = require('./gauss'); +exports.init = function() { + gauss.init.apply(this); + if (!this.rc) { + return; + } + this.sinc0 = Math.sin(this.phic0); + this.cosc0 = Math.cos(this.phic0); + this.R2 = 2 * this.rc; + if (!this.title) { + this.title = "Oblique Stereographic Alternative"; + } +}; + +exports.forward = function(p) { + var sinc, cosc, cosl, k; + p.x = common.adjust_lon(p.x - this.long0); + gauss.forward.apply(this, [p]); + sinc = Math.sin(p.y); + cosc = Math.cos(p.y); + cosl = Math.cos(p.x); + k = this.k0 * this.R2 / (1 + this.sinc0 * sinc + this.cosc0 * cosc * cosl); + p.x = k * cosc * Math.sin(p.x); + p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl); + p.x = this.a * p.x + this.x0; + p.y = this.a * p.y + this.y0; + return p; +}; + +exports.inverse = function(p) { + var sinc, cosc, lon, lat, rho; + p.x = (p.x - this.x0) / this.a; + p.y = (p.y - this.y0) / this.a; + + p.x /= this.k0; + p.y /= this.k0; + if ((rho = Math.sqrt(p.x * p.x + p.y * p.y))) { + var c = 2 * Math.atan2(rho, this.R2); + sinc = Math.sin(c); + cosc = Math.cos(c); + lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho); + lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc); + } + else { + lat = this.phic0; + lon = 0; + } + + p.x = lon; + p.y = lat; + gauss.inverse.apply(this, [p]); + p.x = common.adjust_lon(p.x + this.long0); + return p; +}; + +exports.names = ["Stereographic_North_Pole", "Oblique_Stereographic", "Polar_Stereographic", "sterea","Oblique Stereographic Alternative"]; + +},{"../common":4,"./gauss":25}],42:[function(require,module,exports){ +var common = require('../common'); +exports.init = function() { + this.e0 = common.e0fn(this.es); + this.e1 = common.e1fn(this.es); + this.e2 = common.e2fn(this.es); + this.e3 = common.e3fn(this.es); + this.ml0 = this.a * common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); +}; + +/** + Transverse Mercator Forward - long/lat to x/y + long/lat in radians + */ +exports.forward = function(p) { + var lon = p.x; + var lat = p.y; + + var delta_lon = common.adjust_lon(lon - this.long0); + var con; + var x, y; + var sin_phi = Math.sin(lat); + var cos_phi = Math.cos(lat); + + if (this.sphere) { + var b = cos_phi * Math.sin(delta_lon); + if ((Math.abs(Math.abs(b) - 1)) < 0.0000000001) { + return (93); + } + else { + x = 0.5 * this.a * this.k0 * Math.log((1 + b) / (1 - b)); + con = Math.acos(cos_phi * Math.cos(delta_lon) / Math.sqrt(1 - b * b)); + if (lat < 0) { + con = -con; + } + y = this.a * this.k0 * (con - this.lat0); + } + } + else { + var al = cos_phi * delta_lon; + var als = Math.pow(al, 2); + var c = this.ep2 * Math.pow(cos_phi, 2); + var tq = Math.tan(lat); + var t = Math.pow(tq, 2); + con = 1 - this.es * Math.pow(sin_phi, 2); + var n = this.a / Math.sqrt(con); + var ml = this.a * common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + + x = this.k0 * n * al * (1 + als / 6 * (1 - t + c + als / 20 * (5 - 18 * t + Math.pow(t, 2) + 72 * c - 58 * this.ep2))) + this.x0; + y = this.k0 * (ml - this.ml0 + n * tq * (als * (0.5 + als / 24 * (5 - t + 9 * c + 4 * Math.pow(c, 2) + als / 30 * (61 - 58 * t + Math.pow(t, 2) + 600 * c - 330 * this.ep2))))) + this.y0; + + } + p.x = x; + p.y = y; + return p; +}; + +/** + Transverse Mercator Inverse - x/y to long/lat + */ +exports.inverse = function(p) { + var con, phi; + var delta_phi; + var i; + var max_iter = 6; + var lat, lon; + + if (this.sphere) { + var f = Math.exp(p.x / (this.a * this.k0)); + var g = 0.5 * (f - 1 / f); + var temp = this.lat0 + p.y / (this.a * this.k0); + var h = Math.cos(temp); + con = Math.sqrt((1 - h * h) / (1 + g * g)); + lat = common.asinz(con); + if (temp < 0) { + lat = -lat; + } + if ((g === 0) && (h === 0)) { + lon = this.long0; + } + else { + lon = common.adjust_lon(Math.atan2(g, h) + this.long0); + } + } + else { // ellipsoidal form + var x = p.x - this.x0; + var y = p.y - this.y0; + + con = (this.ml0 + y / this.k0) / this.a; + phi = con; + for (i = 0; true; i++) { + delta_phi = ((con + this.e1 * Math.sin(2 * phi) - this.e2 * Math.sin(4 * phi) + this.e3 * Math.sin(6 * phi)) / this.e0) - phi; + phi += delta_phi; + if (Math.abs(delta_phi) <= common.EPSLN) { + break; + } + if (i >= max_iter) { + return (95); + } + } // for() + if (Math.abs(phi) < common.HALF_PI) { + var sin_phi = Math.sin(phi); + var cos_phi = Math.cos(phi); + var tan_phi = Math.tan(phi); + var c = this.ep2 * Math.pow(cos_phi, 2); + var cs = Math.pow(c, 2); + var t = Math.pow(tan_phi, 2); + var ts = Math.pow(t, 2); + con = 1 - this.es * Math.pow(sin_phi, 2); + var n = this.a / Math.sqrt(con); + var r = n * (1 - this.es) / con; + var d = x / (n * this.k0); + var ds = Math.pow(d, 2); + lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24 * (5 + 3 * t + 10 * c - 4 * cs - 9 * this.ep2 - ds / 30 * (61 + 90 * t + 298 * c + 45 * ts - 252 * this.ep2 - 3 * cs))); + lon = common.adjust_lon(this.long0 + (d * (1 - ds / 6 * (1 + 2 * t + c - ds / 20 * (5 - 2 * c + 28 * t - 3 * cs + 8 * this.ep2 + 24 * ts))) / cos_phi)); + } + else { + lat = common.HALF_PI * common.sign(y); + lon = this.long0; + } + } + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["Transverse_Mercator", "Transverse Mercator", "tmerc"]; + +},{"../common":4}],43:[function(require,module,exports){ +var common = require('../common'); +var tmerc = require('./tmerc'); +exports.dependsOn = 'tmerc'; +exports.init = function() { + if (!this.zone) { + return; + } + this.lat0 = 0; + this.long0 = ((6 * Math.abs(this.zone)) - 183) * common.D2R; + this.x0 = 500000; + this.y0 = this.utmSouth ? 10000000 : 0; + this.k0 = 0.9996; + + tmerc.init.apply(this); + this.forward = tmerc.forward; + this.inverse = tmerc.inverse; +}; +exports.names = ["Universal Transverse Mercator System", "utm"]; + +},{"../common":4,"./tmerc":42}],44:[function(require,module,exports){ +var common = require('../common'); + +/* Initialize the Van Der Grinten projection + ----------------------------------------*/ +exports.init = function() { + //this.R = 6370997; //Radius of earth + this.R = this.a; +}; + +exports.forward = function(p) { + + var lon = p.x; + var lat = p.y; + + /* Forward equations + -----------------*/ + var dlon = common.adjust_lon(lon - this.long0); + var x, y; + + if (Math.abs(lat) <= common.EPSLN) { + x = this.x0 + this.R * dlon; + y = this.y0; + } + var theta = common.asinz(2 * Math.abs(lat / common.PI)); + if ((Math.abs(dlon) <= common.EPSLN) || (Math.abs(Math.abs(lat) - common.HALF_PI) <= common.EPSLN)) { + x = this.x0; + if (lat >= 0) { + y = this.y0 + common.PI * this.R * Math.tan(0.5 * theta); + } + else { + y = this.y0 + common.PI * this.R * -Math.tan(0.5 * theta); + } + // return(OK); + } + var al = 0.5 * Math.abs((common.PI / dlon) - (dlon / common.PI)); + var asq = al * al; + var sinth = Math.sin(theta); + var costh = Math.cos(theta); + + var g = costh / (sinth + costh - 1); + var gsq = g * g; + var m = g * (2 / sinth - 1); + var msq = m * m; + var con = common.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq); + if (dlon < 0) { + con = -con; + } + x = this.x0 + con; + //con = Math.abs(con / (common.PI * this.R)); + var q = asq + g; + con = common.PI * this.R * (m * q - al * Math.sqrt((msq + asq) * (asq + 1) - q * q)) / (msq + asq); + if (lat >= 0) { + //y = this.y0 + common.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con); + y = this.y0 + con; + } + else { + //y = this.y0 - common.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con); + y = this.y0 - con; + } + p.x = x; + p.y = y; + return p; +}; + +/* Van Der Grinten inverse equations--mapping x,y to lat/long + ---------------------------------------------------------*/ +exports.inverse = function(p) { + var lon, lat; + var xx, yy, xys, c1, c2, c3; + var a1; + var m1; + var con; + var th1; + var d; + + /* inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + con = common.PI * this.R; + xx = p.x / con; + yy = p.y / con; + xys = xx * xx + yy * yy; + c1 = -Math.abs(yy) * (1 + xys); + c2 = c1 - 2 * yy * yy + xx * xx; + c3 = -2 * c1 + 1 + 2 * yy * yy + xys * xys; + d = yy * yy / c3 + (2 * c2 * c2 * c2 / c3 / c3 / c3 - 9 * c1 * c2 / c3 / c3) / 27; + a1 = (c1 - c2 * c2 / 3 / c3) / c3; + m1 = 2 * Math.sqrt(-a1 / 3); + con = ((3 * d) / a1) / m1; + if (Math.abs(con) > 1) { + if (con >= 0) { + con = 1; + } + else { + con = -1; + } + } + th1 = Math.acos(con) / 3; + if (p.y >= 0) { + lat = (-m1 * Math.cos(th1 + common.PI / 3) - c2 / 3 / c3) * common.PI; + } + else { + lat = -(-m1 * Math.cos(th1 + common.PI / 3) - c2 / 3 / c3) * common.PI; + } + + if (Math.abs(xx) < common.EPSLN) { + lon = this.long0; + } + else { + lon = common.adjust_lon(this.long0 + common.PI * (xys - 1 + Math.sqrt(1 + 2 * (xx * xx - yy * yy) + xys * xys)) / 2 / xx); + } + + p.x = lon; + p.y = lat; + return p; +}; +exports.names = ["Van_der_Grinten_I", "VanDerGrinten", "vandg"]; +},{"../common":4}],45:[function(require,module,exports){ +var common = require('./common'); +var datum_transform = require('./datum_transform'); +var adjust_axis = require('./adjust_axis'); +var proj = require('./Proj'); +module.exports = function transform(source, dest, point) { + var wgs84; + + function checkNotWGS(source, dest) { + return ((source.datum.datum_type === common.PJD_3PARAM || source.datum.datum_type === common.PJD_7PARAM) && dest.datumCode !== "WGS84"); + } + + // Workaround for datum shifts towgs84, if either source or destination projection is not wgs84 + if (source.datum && dest.datum && (checkNotWGS(source, dest) || checkNotWGS(dest, source))) { + wgs84 = new proj('WGS84'); + transform(source, wgs84, point); + source = wgs84; + } + // DGR, 2010/11/12 + if (source.axis !== "enu") { + adjust_axis(source, false, point); + } + // Transform source points to long/lat, if they aren't already. + if (source.projName === "longlat") { + point.x *= common.D2R; // convert degrees to radians + point.y *= common.D2R; + } + else { + if (source.to_meter) { + point.x *= source.to_meter; + point.y *= source.to_meter; + } + source.inverse(point); // Convert Cartesian to longlat + } + // Adjust for the prime meridian if necessary + if (source.from_greenwich) { + point.x += source.from_greenwich; + } + + // Convert datums if needed, and if possible. + point = datum_transform(source.datum, dest.datum, point); + + // Adjust for the prime meridian if necessary + if (dest.from_greenwich) { + point.x -= dest.from_greenwich; + } + + if (dest.projName === "longlat") { + // convert radians to decimal degrees + point.x *= common.R2D; + point.y *= common.R2D; + } + else { // else project + dest.forward(point); + if (dest.to_meter) { + point.x /= dest.to_meter; + point.y /= dest.to_meter; + } + } + + // DGR, 2010/11/12 + if (dest.axis !== "enu") { + adjust_axis(dest, true, point); + } + + return point; +}; +},{"./Proj":2,"./adjust_axis":3,"./common":4,"./datum_transform":12}],46:[function(require,module,exports){ +module.exports = '2.0.0'; +},{}],47:[function(require,module,exports){ +var common = require('./common'); +var extend = require('./extend'); + +function mapit(obj, key, v) { + obj[key] = v.map(function(aa) { + var o = {}; + sExpr(aa, o); + return o; + }).reduce(function(a, b) { + return extend(a, b); + }, {}); +} + +function sExpr(v, obj) { + var key; + if (!Array.isArray(v)) { + obj[v] = true; + return; + } + else { + key = v.shift(); + if (key === 'PARAMETER') { + key = v.shift(); + } + if (v.length === 1) { + if (Array.isArray(v[0])) { + obj[key] = {}; + sExpr(v[0], obj[key]); + } + else { + obj[key] = v[0]; + } + } + else if (!v.length) { + obj[key] = true; + } + else if (key === 'TOWGS84') { + obj[key] = v; + } + else { + obj[key] = {}; + if (['UNIT', 'PRIMEM', 'VERT_DATUM'].indexOf(key) > -1) { + obj[key] = { + name: v[0].toLowerCase(), + convert: v[1] + }; + if (v.length === 3) { + obj[key].auth = v[2]; + } + } + else if (key === 'SPHEROID') { + obj[key] = { + name: v[0], + a: v[1], + rf: v[2] + }; + if (v.length === 4) { + obj[key].auth = v[3]; + } + } + else if (['GEOGCS', 'GEOCCS', 'DATUM', 'VERT_CS', 'COMPD_CS', 'LOCAL_CS', 'FITTED_CS', 'LOCAL_DATUM'].indexOf(key) > -1) { + v[0] = ['name', v[0]]; + mapit(obj, key, v); + } + else if (v.every(function(aa) { + return Array.isArray(aa); + })) { + mapit(obj, key, v); + } + else { + sExpr(v, obj[key]); + } + } + } +} + +function rename(obj, params) { + var outName = params[0]; + var inName = params[1]; + if (!(outName in obj) && (inName in obj)) { + obj[outName] = obj[inName]; + if (params.length === 3) { + obj[outName] = params[2](obj[outName]); + } + } +} + +function d2r(input) { + return input * common.D2R; +} + +function cleanWKT(wkt) { + if (wkt.type === 'GEOGCS') { + wkt.projName = 'longlat'; + } + else if (wkt.type === 'LOCAL_CS') { + wkt.projName = 'identity'; + wkt.local = true; + } + else { + if (typeof wkt.PROJECTION === "object") { + wkt.projName = Object.keys(wkt.PROJECTION)[0]; + } + else { + wkt.projName = wkt.PROJECTION; + } + } + if (wkt.UNIT) { + wkt.units = wkt.UNIT.name.toLowerCase(); + if (wkt.units === 'metre') { + wkt.units = 'meter'; + } + if (wkt.UNIT.convert) { + wkt.to_meter = parseFloat(wkt.UNIT.convert, 10); + } + } + + if (wkt.GEOGCS) { + //if(wkt.GEOGCS.PRIMEM&&wkt.GEOGCS.PRIMEM.convert){ + // wkt.from_greenwich=wkt.GEOGCS.PRIMEM.convert*common.D2R; + //} + if (wkt.GEOGCS.DATUM) { + wkt.datumCode = wkt.GEOGCS.DATUM.name.toLowerCase(); + } + else { + wkt.datumCode = wkt.GEOGCS.name.toLowerCase(); + } + if (wkt.datumCode.slice(0, 2) === 'd_') { + wkt.datumCode = wkt.datumCode.slice(2); + } + if (wkt.datumCode === 'new_zealand_geodetic_datum_1949' || wkt.datumCode === 'new_zealand_1949') { + wkt.datumCode = 'nzgd49'; + } + if (wkt.datumCode === "wgs_1984") { + if (wkt.PROJECTION === 'Mercator_Auxiliary_Sphere') { + wkt.sphere = true; + } + wkt.datumCode = 'wgs84'; + } + if (wkt.datumCode.slice(-6) === '_ferro') { + wkt.datumCode = wkt.datumCode.slice(0, - 6); + } + if (wkt.datumCode.slice(-8) === '_jakarta') { + wkt.datumCode = wkt.datumCode.slice(0, - 8); + } + if (wkt.GEOGCS.DATUM && wkt.GEOGCS.DATUM.SPHEROID) { + wkt.ellps = wkt.GEOGCS.DATUM.SPHEROID.name.replace('_19', '').replace(/[Cc]larke\_18/, 'clrk'); + if (wkt.ellps.toLowerCase().slice(0, 13) === "international") { + wkt.ellps = 'intl'; + } + + wkt.a = wkt.GEOGCS.DATUM.SPHEROID.a; + wkt.rf = parseFloat(wkt.GEOGCS.DATUM.SPHEROID.rf, 10); + } + } + if (wkt.b && !isFinite(wkt.b)) { + wkt.b = wkt.a; + } + + function toMeter(input) { + var ratio = wkt.to_meter || 1; + return parseFloat(input, 10) * ratio; + } + var renamer = function(a) { + return rename(wkt, a); + }; + var list = [ + ['standard_parallel_1', 'Standard_Parallel_1'], + ['standard_parallel_2', 'Standard_Parallel_2'], + ['false_easting', 'False_Easting'], + ['false_northing', 'False_Northing'], + ['central_meridian', 'Central_Meridian'], + ['latitude_of_origin', 'Latitude_Of_Origin'], + ['scale_factor', 'Scale_Factor'], + ['k0', 'scale_factor'], + ['latitude_of_center', 'Latitude_of_center'], + ['lat0', 'latitude_of_center', d2r], + ['longitude_of_center', 'Longitude_Of_Center'], + ['longc', 'longitude_of_center', d2r], + ['x0', 'false_easting', toMeter], + ['y0', 'false_northing', toMeter], + ['long0', 'central_meridian', d2r], + ['lat0', 'latitude_of_origin', d2r], + ['lat0', 'standard_parallel_1', d2r], + ['lat1', 'standard_parallel_1', d2r], + ['lat2', 'standard_parallel_2', d2r], + ['alpha', 'azimuth', d2r], + ['srsCode', 'name'] + ]; + list.forEach(renamer); + if (!wkt.long0 && wkt.longc && (wkt.PROJECTION === 'Albers_Conic_Equal_Area' || wkt.PROJECTION === "Lambert_Azimuthal_Equal_Area")) { + wkt.long0 = wkt.longc; + } +} +module.exports = function(wkt, self) { + var lisp = JSON.parse(("," + wkt).replace(/\s*\,\s*([A-Z_0-9]+?)(\[)/g, ',["$1",').slice(1).replace(/\s*\,\s*([A-Z_0-9]+?)\]/g, ',"$1"]')); + var type = lisp.shift(); + var name = lisp.shift(); + lisp.unshift(['name', name]); + lisp.unshift(['type', type]); + lisp.unshift('output'); + var obj = {}; + sExpr(lisp, obj); + cleanWKT(obj.output); + return extend(self, obj.output); +}; + +},{"./common":4,"./extend":14}]},{},[16]) +(16) +}); +; \ No newline at end of file diff --git a/gui-src/js/maps/proj4.js b/gui-src/js/maps/proj4.js new file mode 100644 index 0000000..c956b57 --- /dev/null +++ b/gui-src/js/maps/proj4.js @@ -0,0 +1,3 @@ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.proj4=a():"undefined"!=typeof global?global.proj4=a():"undefined"!=typeof self&&(self.proj4=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=0||a.indexOf("GEOCCS")>=0||a.indexOf("PROJCS")>=0||a.indexOf("LOCAL_CS")>=0?(b=i(a),this.deriveConstants(b),c(this,b)):"+"===a[0]&&(b=j(a),this.deriveConstants(b),c(this,b)):(this.deriveConstants(a),c(this,a)),this.initTransforms(this.projName)}var c=a("./extend"),d=a("./common"),e=a("./defs"),f=a("./constants/index"),g=a("./datum"),h=a("./projections/index"),i=a("./wkt"),j=a("./projString");Projection.projections=h,Projection.projections.start(),Projection.prototype={initTransforms:function(a){var b=Projection.projections.get(a);if(!b)throw"unknown projection "+a;c(this,b),this.init()},deriveConstants:function(a){if(a.nadgrids&&0===a.nadgrids.length&&(a.nadgrids=null),a.nadgrids){a.grids=a.nadgrids.split(",");var b=null,e=a.grids.length;if(e>0)for(var h=0;e>h;h++){b=a.grids[h];var i=b.split("@");""!==i[i.length-1]&&(a.grids[h]={mandatory:1===i.length,name:i[i.length-1],grid:f.grids[i[i.length-1]]},a.grids[h].mandatory&&!a.grids[h].grid)}}if(a.datumCode&&"none"!==a.datumCode){var j=f.Datum[a.datumCode];j&&(a.datum_params=j.towgs84?j.towgs84.split(","):null,a.ellps=j.ellipse,a.datumName=j.datumName?j.datumName:a.datumCode)}if(!a.a){var k=f.Ellipsoid[a.ellps]?f.Ellipsoid[a.ellps]:f.Ellipsoid.WGS84;c(a,k)}a.rf&&!a.b&&(a.b=(1-1/a.rf)*a.a),(0===a.rf||Math.abs(a.a-a.b)f;f++)if(!b||2!==f||void 0!==c.z)switch(0===f?(d=g,e="x"):1===f?(d=h,e="y"):(d=i,e="z"),a.axis[f]){case"e":c[e]=d;break;case"w":c[e]=-d;break;case"n":c[e]=d;break;case"s":c[e]=-d;break;case"u":void 0!==c[e]&&(c.z=d);break;case"d":void 0!==c[e]&&(c.z=-d);break;default:return null}return c}},{}],4:[function(a,b,c){c.PI=3.141592653589793,c.HALF_PI=1.5707963267948966,c.TWO_PI=6.283185307179586,c.FORTPI=.7853981633974483,c.R2D=57.29577951308232,c.D2R=.017453292519943295,c.SEC_TO_RAD=484813681109536e-20,c.EPSLN=1e-10,c.MAX_ITER=20,c.COS_67P5=.3826834323650898,c.AD_C=1.0026,c.PJD_UNKNOWN=0,c.PJD_3PARAM=1,c.PJD_7PARAM=2,c.PJD_GRIDSHIFT=3,c.PJD_WGS84=4,c.PJD_NODATUM=5,c.SRS_WGS84_SEMIMAJOR=6378137,c.SRS_WGS84_ESQUARED=.006694379990141316,c.SIXTH=.16666666666666666,c.RA4=.04722222222222222,c.RA6=.022156084656084655,c.RV4=.06944444444444445,c.RV6=.04243827160493827,c.msfnz=function(a,b,c){var d=a*b;return c/Math.sqrt(1-d*d)},c.tsfnz=function(a,b,c){var d=a*c,e=.5*a;return d=Math.pow((1-d)/(1+d),e),Math.tan(.5*(this.HALF_PI-b))/d},c.phi2z=function(a,b){for(var c,d,e=.5*a,f=this.HALF_PI-2*Math.atan(b),g=0;15>=g;g++)if(c=a*Math.sin(f),d=this.HALF_PI-2*Math.atan(b*Math.pow((1-c)/(1+c),e))-f,f+=d,Math.abs(d)<=1e-10)return f;return-9999},c.qsfnz=function(a,b){var c;return a>1e-7?(c=a*b,(1-a*a)*(b/(1-c*c)-.5/a*Math.log((1-c)/(1+c)))):2*b},c.iqsfnz=function(a,b){var d=1-(1-a*a)/(2*a)*Math.log((1-a)/(1+a));if(Math.abs(Math.abs(b)-d)<1e-6)return 0>b?-1*c.HALF_PI:c.HALF_PI;for(var e,f,g,h,i=Math.asin(.5*b),j=0;30>j;j++)if(f=Math.sin(i),g=Math.cos(i),h=a*f,e=Math.pow(1-h*h,2)/(2*g)*(b/(1-a*a)-f/(1-h*h)+.5/a*Math.log((1-h)/(1+h))),i+=e,Math.abs(e)<=1e-10)return i;return 0/0},c.asinz=function(a){return Math.abs(a)>1&&(a=a>1?1:-1),Math.asin(a)},c.e0fn=function(a){return 1-.25*a*(1+a/16*(3+1.25*a))},c.e1fn=function(a){return.375*a*(1+.25*a*(1+.46875*a))},c.e2fn=function(a){return.05859375*a*a*(1+.75*a)},c.e3fn=function(a){return a*a*a*(35/3072)},c.mlfn=function(a,b,c,d,e){return a*e-b*Math.sin(2*e)+c*Math.sin(4*e)-d*Math.sin(6*e)},c.imlfn=function(a,b,c,d,e){var f,g;f=a/b;for(var h=0;15>h;h++)if(g=(a-(b*f-c*Math.sin(2*f)+d*Math.sin(4*f)-e*Math.sin(6*f)))/(b-2*c*Math.cos(2*f)+4*d*Math.cos(4*f)-6*e*Math.cos(6*f)),f+=g,Math.abs(g)<=1e-10)return f;return 0/0},c.srat=function(a,b){return Math.pow((1-a)/(1+a),b)},c.sign=function(a){return 0>a?-1:1},c.adjust_lon=function(a){return a=Math.abs(a)this.HALF_PI)return Number.NaN;if(b===this.HALF_PI)return Number.POSITIVE_INFINITY;if(b===-1*this.HALF_PI)return Number.NEGATIVE_INFINITY;var d=a*c;return Math.log(Math.tan((this.HALF_PI+b)/2))+a*Math.log((1-d)/(1+d))/2},c.fL=function(a,b){return 2*Math.atan(a*Math.exp(b))-this.HALF_PI},c.invlatiso=function(a,b){var c=this.fL(1,b),d=0,e=0;do d=c,e=a*Math.sin(d),c=this.fL(Math.exp(a*Math.log((1+e)/(1-e))/2),b);while(Math.abs(c-d)>1e-12);return c},c.sinh=function(a){var b=Math.exp(a);return b=(b-1/b)/2},c.cosh=function(a){var b=Math.exp(a);return b=(b+1/b)/2},c.tanh=function(a){var b=Math.exp(a);return b=(b-1/b)/(b+1/b)},c.asinh=function(a){var b=a>=0?1:-1;return b*Math.log(Math.abs(a)+Math.sqrt(a*a+1))},c.acosh=function(a){return 2*Math.log(Math.sqrt((a+1)/2)+Math.sqrt((a-1)/2))},c.atanh=function(a){return Math.log((a-1)/(a+1))/2},c.gN=function(a,b,c){var d=b*c;return a/Math.sqrt(1-d*d)},c.pj_enfn=function(a){var b=[];b[0]=this.C00-a*(this.C02+a*(this.C04+a*(this.C06+a*this.C08))),b[1]=a*(this.C22-a*(this.C04+a*(this.C06+a*this.C08)));var c=a*a;return b[2]=c*(this.C44-a*(this.C46+a*this.C48)),c*=a,b[3]=c*(this.C66-a*this.C68),b[4]=c*a*this.C88,b},c.pj_mlfn=function(a,b,c,d){return c*=b,b*=b,d[0]*a-c*(d[1]+b*(d[2]+b*(d[3]+b*d[4])))},c.pj_inv_mlfn=function(a,b,d){for(var e=1/(1-b),f=a,g=c.MAX_ITER;g;--g){var h=Math.sin(f),i=1-b*h*h;if(i=(this.pj_mlfn(f,h,Math.cos(f),d)-a)*i*Math.sqrt(i)*e,f-=i,Math.abs(i).99999999999))return!1;a[c]++,b[c]=0}else if(f=a[c]+1,f>=e.lim[d]){if(!(f===e.lim[d]&&b[c]<1e-11))return!1;"x"===c?a[c]--:a[c]++,b[c]=1}return[a,b]},c.nad_intr=function(a,b){var d={x:(a.x-1e-7)/b.del[0],y:(a.y-1e-7)/b.del[1]},e={x:Math.floor(d.x),y:Math.floor(d.y)},f={x:d.x-1*e.x,y:d.y-1*e.y},g={x:Number.NaN,y:Number.NaN},h=c.nadInterBreakout(e,f,"x",0,b);if(!h)return g;if(e=h[0],f=h[1],h=c.nadInterBreakout(e,f,"y",1,b),!h)return g;e=h[0],f=h[1];var i=e.y*b.lim[0]+e.x,j={x:b.cvs[i][0],y:b.cvs[i][1]};i++;var k={x:b.cvs[i][0],y:b.cvs[i][1]};i+=b.lim[0];var l={x:b.cvs[i][0],y:b.cvs[i][1]};i--;var m={x:b.cvs[i][0],y:b.cvs[i][1]},n=f.x*f.y,o=f.x*(1-f.y),p=(1-f.x)*(1-f.y),q=(1-f.x)*f.y;return g.x=p*j.x+o*k.x+q*m.x+n*l.x,g.y=p*j.y+o*k.y+q*m.y+n*l.y,g},c.inverseNadCvt=function(a,b,d,e){if(isNaN(a.x))return b;a.x=d.x+a.x,a.y=d.y-a.y;var f,g,h=9,i=1e-12;do{if(g=c.nad_intr(a,e),isNaN(g.x)){this.reportError("Inverse grid shift iteration failed, presumably at grid edge. Using first approximation.");break}f={x:a.x-g.x-d.x,y:a.y+g.y-d.y},a.x-=f.x,a.y-=f.y}while(h--&&Math.abs(f.x)>i&&Math.abs(f.y)>i);return 0>h?(this.reportError("Inverse grid shift iterator failed to converge."),b):(b.x=c.adjust_lon(a.x+e.ll[0]),b.y=a.y+e.ll[1],b)},c.nad_cvt=function(a,b,d){var e={x:Number.NaN,y:Number.NaN};if(isNaN(a.x))return e;var f={x:a.x,y:a.y};f.x-=d.ll[0],f.y-=d.ll[1],f.x=c.adjust_lon(f.x-c.PI)+c.PI;var g=c.nad_intr(f,d);return b?c.inverseNadCvt(g,e,f,d):(isNaN(g.x)||(e.x=a.x-g.x,e.y=a.y+g.y),e)},c.C00=1,c.C02=.25,c.C04=.046875,c.C06=.01953125,c.C08=.01068115234375,c.C22=.75,c.C44=.46875,c.C46=.013020833333333334,c.C48=.007120768229166667,c.C66=.3645833333333333,c.C68=.005696614583333333,c.C88=.3076171875},{}],5:[function(a,b,c){c.wgs84={towgs84:"0,0,0",ellipse:"WGS84",datumName:"WGS84"},c.ch1903={towgs84:"674.374,15.056,405.346",ellipse:"bessel",datumName:"swiss"},c.ggrs87={towgs84:"-199.87,74.79,246.62",ellipse:"GRS80",datumName:"Greek_Geodetic_Reference_System_1987"},c.nad83={towgs84:"0,0,0",ellipse:"GRS80",datumName:"North_American_Datum_1983"},c.nad27={nadgrids:"@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat",ellipse:"clrk66",datumName:"North_American_Datum_1927"},c.potsdam={towgs84:"606.0,23.0,413.0",ellipse:"bessel",datumName:"Potsdam Rauenberg 1950 DHDN"},c.carthage={towgs84:"-263.0,6.0,431.0",ellipse:"clark80",datumName:"Carthage 1934 Tunisia"},c.hermannskogel={towgs84:"653.0,-212.0,449.0",ellipse:"bessel",datumName:"Hermannskogel"},c.ire65={towgs84:"482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",ellipse:"mod_airy",datumName:"Ireland 1965"},c.rassadiran={towgs84:"-133.63,-157.5,-158.62",ellipse:"intl",datumName:"Rassadiran"},c.nzgd49={towgs84:"59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993",ellipse:"intl",datumName:"New Zealand Geodetic Datum 1949"},c.osgb36={towgs84:"446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894",ellipse:"airy",datumName:"Airy 1830"},c.s_jtsk={towgs84:"589,76,480",ellipse:"bessel",datumName:"S-JTSK (Ferro)"},c.beduaram={towgs84:"-106,-87,188",ellipse:"clrk80",datumName:"Beduaram"},c.gunung_segara={towgs84:"-403,684,41",ellipse:"bessel",datumName:"Gunung Segara Jakarta"}},{}],6:[function(a,b,c){c.MERIT={a:6378137,rf:298.257,ellipseName:"MERIT 1983"},c.SGS85={a:6378136,rf:298.257,ellipseName:"Soviet Geodetic System 85"},c.GRS80={a:6378137,rf:298.257222101,ellipseName:"GRS 1980(IUGG, 1980)"},c.IAU76={a:6378140,rf:298.257,ellipseName:"IAU 1976"},c.airy={a:6377563.396,b:6356256.91,ellipseName:"Airy 1830"},c.APL4={a:6378137,rf:298.25,ellipseName:"Appl. Physics. 1965"},c.NWL9D={a:6378145,rf:298.25,ellipseName:"Naval Weapons Lab., 1965"},c.mod_airy={a:6377340.189,b:6356034.446,ellipseName:"Modified Airy"},c.andrae={a:6377104.43,rf:300,ellipseName:"Andrae 1876 (Den., Iclnd.)"},c.aust_SA={a:6378160,rf:298.25,ellipseName:"Australian Natl & S. Amer. 1969"},c.GRS67={a:6378160,rf:298.247167427,ellipseName:"GRS 67(IUGG 1967)"},c.bessel={a:6377397.155,rf:299.1528128,ellipseName:"Bessel 1841"},c.bess_nam={a:6377483.865,rf:299.1528128,ellipseName:"Bessel 1841 (Namibia)"},c.clrk66={a:6378206.4,b:6356583.8,ellipseName:"Clarke 1866"},c.clrk80={a:6378249.145,rf:293.4663,ellipseName:"Clarke 1880 mod."},c.clrk58={a:6378293.645208759,rf:294.2606763692654,ellipseName:"Clarke 1858"},c.CPM={a:6375738.7,rf:334.29,ellipseName:"Comm. des Poids et Mesures 1799"},c.delmbr={a:6376428,rf:311.5,ellipseName:"Delambre 1810 (Belgium)"},c.engelis={a:6378136.05,rf:298.2566,ellipseName:"Engelis 1985"},c.evrst30={a:6377276.345,rf:300.8017,ellipseName:"Everest 1830"},c.evrst48={a:6377304.063,rf:300.8017,ellipseName:"Everest 1948"},c.evrst56={a:6377301.243,rf:300.8017,ellipseName:"Everest 1956"},c.evrst69={a:6377295.664,rf:300.8017,ellipseName:"Everest 1969"},c.evrstSS={a:6377298.556,rf:300.8017,ellipseName:"Everest (Sabah & Sarawak)"},c.fschr60={a:6378166,rf:298.3,ellipseName:"Fischer (Mercury Datum) 1960"},c.fschr60m={a:6378155,rf:298.3,ellipseName:"Fischer 1960"},c.fschr68={a:6378150,rf:298.3,ellipseName:"Fischer 1968"},c.helmert={a:6378200,rf:298.3,ellipseName:"Helmert 1906"},c.hough={a:6378270,rf:297,ellipseName:"Hough"},c.intl={a:6378388,rf:297,ellipseName:"International 1909 (Hayford)"},c.kaula={a:6378163,rf:298.24,ellipseName:"Kaula 1961"},c.lerch={a:6378139,rf:298.257,ellipseName:"Lerch 1979"},c.mprts={a:6397300,rf:191,ellipseName:"Maupertius 1738"},c.new_intl={a:6378157.5,b:6356772.2,ellipseName:"New International 1967"},c.plessis={a:6376523,rf:6355863,ellipseName:"Plessis 1817 (France)"},c.krass={a:6378245,rf:298.3,ellipseName:"Krassovsky, 1942"},c.SEasia={a:6378155,b:6356773.3205,ellipseName:"Southeast Asia"},c.walbeck={a:6376896,b:6355834.8467,ellipseName:"Walbeck"},c.WGS60={a:6378165,rf:298.3,ellipseName:"WGS 60"},c.WGS66={a:6378145,rf:298.25,ellipseName:"WGS 66"},c.WGS7={a:6378135,rf:298.26,ellipseName:"WGS 72"},c.WGS84={a:6378137,rf:298.257223563,ellipseName:"WGS 84"},c.sphere={a:6370997,b:6370997,ellipseName:"Normal Sphere (r=6370997)"}},{}],7:[function(a,b,c){c.greenwich=0,c.lisbon=-9.131906111111,c.paris=2.337229166667,c.bogota=-74.080916666667,c.madrid=-3.687938888889,c.rome=12.452333333333,c.bern=7.439583333333,c.jakarta=106.807719444444,c.ferro=-17.666666666667,c.brussels=4.367975,c.stockholm=18.058277777778,c.athens=23.7163375,c.oslo=10.722916666667},{}],8:[function(a,b,c){c.null={ll:[-3.14159265,-1.57079633],del:[3.14159265,1.57079633],lim:[3,3],count:9,cvs:[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]]}},{}],9:[function(a,b,c){c.PrimeMeridian=a("./PrimeMeridian"),c.Ellipsoid=a("./Ellipsoid"),c.Datum=a("./Datum"),c.Datum.OSB36=c.Datum.OSGB36,c.grids=a("./grids")},{"./Datum":5,"./Ellipsoid":6,"./PrimeMeridian":7,"./grids":8}],10:[function(a,b){function c(a,b,c){var d;return Array.isArray(c)?(d=g(a,b,e(c)),3===c.length?[d.x,d.y,d.z]:[d.x,d.y]):g(a,b,c)}function d(a){return a instanceof f?a:a.oProj?a.oProj:f(a)}function proj4(a,b,e){a=d(a);var f,g=!1;return"undefined"==typeof b?(b=a,a=h,g=!0):("undefined"!=typeof b.x||Array.isArray(b))&&(e=b,b=a,a=h,g=!0),b=d(b),e?c(a,b,e):(f={forward:function(d){return c(a,b,d)},inverse:function(d){return c(b,a,d)}},g&&(f.oProj=b),f)}var e=a("./Point"),f=a("./Proj"),g=a("./transform"),h=f("WGS84");b.exports=proj4},{"./Point":1,"./Proj":2,"./transform":45}],11:[function(a,b){var c=a("./common"),d=function(a){if(!(this instanceof d))return new d(a);if(this.datum_type=c.PJD_WGS84,a){if(a.datumCode&&"none"===a.datumCode&&(this.datum_type=c.PJD_NODATUM),a.datum_params){for(var b=0;b3&&(0!==a.datum_params[3]||0!==a.datum_params[4]||0!==a.datum_params[5]||0!==a.datum_params[6])&&(this.datum_type=c.PJD_7PARAM,a.datum_params[3]*=c.SEC_TO_RAD,a.datum_params[4]*=c.SEC_TO_RAD,a.datum_params[5]*=c.SEC_TO_RAD,a.datum_params[6]=a.datum_params[6]/1e6+1)}this.datum_type=a.grids?c.PJD_GRIDSHIFT:this.datum_type,this.a=a.a,this.b=a.b,this.es=a.es,this.ep2=a.ep2,this.datum_params=a.datum_params,this.datum_type===c.PJD_GRIDSHIFT&&(this.grids=a.grids)}};d.prototype={compare_datums:function(a){return this.datum_type!==a.datum_type?!1:this.a!==a.a||Math.abs(this.es-a.es)>5e-11?!1:this.datum_type===c.PJD_3PARAM?this.datum_params[0]===a.datum_params[0]&&this.datum_params[1]===a.datum_params[1]&&this.datum_params[2]===a.datum_params[2]:this.datum_type===c.PJD_7PARAM?this.datum_params[0]===a.datum_params[0]&&this.datum_params[1]===a.datum_params[1]&&this.datum_params[2]===a.datum_params[2]&&this.datum_params[3]===a.datum_params[3]&&this.datum_params[4]===a.datum_params[4]&&this.datum_params[5]===a.datum_params[5]&&this.datum_params[6]===a.datum_params[6]:this.datum_type===c.PJD_GRIDSHIFT||a.datum_type===c.PJD_GRIDSHIFT?this.nadgrids===a.nadgrids:!0},geodetic_to_geocentric:function(a){var b,d,e,f,g,h,i,j=a.x,k=a.y,l=a.z?a.z:0,m=0;if(k<-c.HALF_PI&&k>-1.001*c.HALF_PI)k=-c.HALF_PI;else if(k>c.HALF_PI&&k<1.001*c.HALF_PI)k=c.HALF_PI;else if(k<-c.HALF_PI||k>c.HALF_PI)return null;return j>c.PI&&(j-=2*c.PI),g=Math.sin(k),i=Math.cos(k),h=g*g,f=this.a/Math.sqrt(1-this.es*h),b=(f+l)*i*Math.cos(j),d=(f+l)*i*Math.sin(j),e=(f*(1-this.es)+l)*g,a.x=b,a.y=d,a.z=e,m},geocentric_to_geodetic:function(a){var b,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t=1e-12,u=t*t,v=30,w=a.x,x=a.y,y=a.z?a.z:0;if(o=!1,b=Math.sqrt(w*w+x*x),d=Math.sqrt(w*w+x*x+y*y),b/this.au&&v>p);return r=Math.atan(m/Math.abs(l)),a.x=q,a.y=r,a.z=s,a},geocentric_to_geodetic_noniter:function(a){var b,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t=a.x,u=a.y,v=a.z?a.z:0;if(t=parseFloat(t),u=parseFloat(u),v=parseFloat(v),s=!1,0!==t)b=Math.atan2(u,t);else if(u>0)b=c.HALF_PI;else if(0>u)b=-c.HALF_PI;else if(s=!0,b=0,v>0)d=c.HALF_PI;else{if(!(0>v))return d=c.HALF_PI,e=-this.b,void 0;d=-c.HALF_PI}return g=t*t+u*u,f=Math.sqrt(g),h=v*c.AD_C,j=Math.sqrt(h*h+g),l=h/j,n=f/j,m=l*l*l,i=v+this.b*this.ep2*m,r=f-this.a*this.es*n*n*n,k=Math.sqrt(i*i+r*r),o=i/k,p=r/k,q=this.a/Math.sqrt(1-this.es*o*o),e=p>=c.COS_67P5?f/p-q:p<=-c.COS_67P5?f/-p-q:v/o+q*(this.es-1),s===!1&&(d=Math.atan(o/p)),a.x=b,a.y=d,a.z=e,a},geocentric_to_wgs84:function(a){if(this.datum_type===c.PJD_3PARAM)a.x+=this.datum_params[0],a.y+=this.datum_params[1],a.z+=this.datum_params[2];else if(this.datum_type===c.PJD_7PARAM){var b=this.datum_params[0],d=this.datum_params[1],e=this.datum_params[2],f=this.datum_params[3],g=this.datum_params[4],h=this.datum_params[5],i=this.datum_params[6],j=i*(a.x-h*a.y+g*a.z)+b,k=i*(h*a.x+a.y-f*a.z)+d,l=i*(-g*a.x+f*a.y+a.z)+e;a.x=j,a.y=k,a.z=l}},geocentric_from_wgs84:function(a){if(this.datum_type===c.PJD_3PARAM)a.x-=this.datum_params[0],a.y-=this.datum_params[1],a.z-=this.datum_params[2];else if(this.datum_type===c.PJD_7PARAM){var b=this.datum_params[0],d=this.datum_params[1],e=this.datum_params[2],f=this.datum_params[3],g=this.datum_params[4],h=this.datum_params[5],i=this.datum_params[6],j=(a.x-b)/i,k=(a.y-d)/i,l=(a.z-e)/i;a.x=j+h*k-g*l,a.y=-h*j+k+f*l,a.z=g*j-f*k+l}}},b.exports=d},{"./common":4}],12:[function(a,b){var c=a("./common");b.exports=function(a,b,d){function e(a){return a===c.PJD_3PARAM||a===c.PJD_7PARAM}var f,g,h;if(a.compare_datums(b))return d;if(a.datum_type===c.PJD_NODATUM||b.datum_type===c.PJD_NODATUM)return d;var i=a.a,j=a.es,k=b.a,l=b.es,m=a.datum_type;if(m===c.PJD_GRIDSHIFT)if(0===this.apply_gridshift(a,0,d))a.a=c.SRS_WGS84_SEMIMAJOR,a.es=c.SRS_WGS84_ESQUARED;else{if(!a.datum_params)return a.a=i,a.es=a.es,d;for(f=1,g=0,h=a.datum_params.length;h>g;g++)f*=a.datum_params[g];if(0===f)return a.a=i,a.es=a.es,d;m=a.datum_params.length>3?c.PJD_7PARAM:c.PJD_3PARAM}return b.datum_type===c.PJD_GRIDSHIFT&&(b.a=c.SRS_WGS84_SEMIMAJOR,b.es=c.SRS_WGS84_ESQUARED),(a.es!==b.es||a.a!==b.a||e(m)||e(b.datum_type))&&(a.geodetic_to_geocentric(d),e(a.datum_type)&&a.geocentric_to_wgs84(d),e(b.datum_type)&&b.geocentric_from_wgs84(d),b.geocentric_to_geodetic(d)),b.datum_type===c.PJD_GRIDSHIFT&&this.apply_gridshift(b,1,d),a.a=i,a.es=j,b.a=k,b.es=l,d}},{"./common":4}],13:[function(a,b){function c(a){var b=this;if(2===arguments.length)c[a]="+"===arguments[1][0]?e(arguments[1]):f(arguments[1]);else if(1===arguments.length)return Array.isArray(a)?a.map(function(a){Array.isArray(a)?c.apply(b,a):c(a)}):("string"==typeof a||("EPSG"in a?c["EPSG:"+a.EPSG]=a:"ESRI"in a?c["ESRI:"+a.ESRI]=a:"IAU2000"in a?c["IAU2000:"+a.IAU2000]=a:console.log(a)),void 0)}var d=a("./global"),e=a("./projString"),f=a("./wkt");d(c),b.exports=c},{"./global":15,"./projString":18,"./wkt":47}],14:[function(a,b){b.exports=function(a,b){a=a||{};var c,d;if(!b)return a;for(d in b)c=b[d],void 0!==c&&(a[d]=c);return a}},{}],15:[function(a,b){b.exports=function(a){a("WGS84","+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees"),a("EPSG:4326","+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees"),a("EPSG:4269","+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees"),a("EPSG:3857","+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"),a["EPSG:3785"]=a["EPSG:3857"],a.GOOGLE=a["EPSG:3857"],a["EPSG:900913"]=a["EPSG:3857"],a["EPSG:102113"]=a["EPSG:3857"]}},{}],16:[function(a,b){var proj4=a("./core");proj4.defaultDatum="WGS84",proj4.Proj=a("./Proj"),proj4.WGS84=new proj4.Proj("WGS84"),proj4.Point=a("./Point"),proj4.defs=a("./defs"),proj4.transform=a("./transform"),proj4.mgrs=a("./mgrs"),proj4.version=a("./version"),b.exports=proj4},{"./Point":1,"./Proj":2,"./core":10,"./defs":13,"./mgrs":17,"./transform":45,"./version":46}],17:[function(a,b,c){function d(a){return a*(Math.PI/180)}function e(a){return 180*(a/Math.PI)}function f(a){var b,c,e,f,g,i,j,k,l,m=a.lat,n=a.lon,o=6378137,p=.00669438,q=.9996,r=d(m),s=d(n);l=Math.floor((n+180)/6)+1,180===n&&(l=60),m>=56&&64>m&&n>=3&&12>n&&(l=32),m>=72&&84>m&&(n>=0&&9>n?l=31:n>=9&&21>n?l=33:n>=21&&33>n?l=35:n>=33&&42>n&&(l=37)),b=6*(l-1)-180+3,k=d(b),c=p/(1-p),e=o/Math.sqrt(1-p*Math.sin(r)*Math.sin(r)),f=Math.tan(r)*Math.tan(r),g=c*Math.cos(r)*Math.cos(r),i=Math.cos(r)*(s-k),j=o*((1-p/4-3*p*p/64-5*p*p*p/256)*r-(3*p/8+3*p*p/32+45*p*p*p/1024)*Math.sin(2*r)+(15*p*p/256+45*p*p*p/1024)*Math.sin(4*r)-35*p*p*p/3072*Math.sin(6*r));var t=q*e*(i+(1-f+g)*i*i*i/6+(5-18*f+f*f+72*g-58*c)*i*i*i*i*i/120)+5e5,u=q*(j+e*Math.tan(r)*(i*i/2+(5-f+9*g+4*g*g)*i*i*i*i/24+(61-58*f+f*f+600*g-330*c)*i*i*i*i*i*i/720));return 0>m&&(u+=1e7),{northing:Math.round(u),easting:Math.round(t),zoneNumber:l,zoneLetter:h(m)}}function g(a){var b=a.northing,c=a.easting,d=a.zoneLetter,f=a.zoneNumber;if(0>f||f>60)return null;var h,i,j,k,l,m,n,o,p,q,r=.9996,s=6378137,t=.00669438,u=(1-Math.sqrt(1-t))/(1+Math.sqrt(1-t)),v=c-5e5,w=b;"N">d&&(w-=1e7),o=6*(f-1)-180+3,h=t/(1-t),n=w/r,p=n/(s*(1-t/4-3*t*t/64-5*t*t*t/256)),q=p+(3*u/2-27*u*u*u/32)*Math.sin(2*p)+(21*u*u/16-55*u*u*u*u/32)*Math.sin(4*p)+151*u*u*u/96*Math.sin(6*p),i=s/Math.sqrt(1-t*Math.sin(q)*Math.sin(q)),j=Math.tan(q)*Math.tan(q),k=h*Math.cos(q)*Math.cos(q),l=s*(1-t)/Math.pow(1-t*Math.sin(q)*Math.sin(q),1.5),m=v/(i*r);var x=q-i*Math.tan(q)/l*(m*m/2-(5+3*j+10*k-4*k*k-9*h)*m*m*m*m/24+(61+90*j+298*k+45*j*j-252*h-3*k*k)*m*m*m*m*m*m/720);x=e(x);var y=(m-(1+2*j+k)*m*m*m/6+(5-2*k+28*j-3*k*k+8*h+24*j*j)*m*m*m*m*m/120)/Math.cos(q);y=o+e(y);var z;if(a.accuracy){var A=g({northing:a.northing+a.accuracy,easting:a.easting+a.accuracy,zoneLetter:a.zoneLetter,zoneNumber:a.zoneNumber});z={top:A.lat,right:A.lon,bottom:x,left:y}}else z={lat:x,lon:y};return z}function h(a){var b="Z";return 84>=a&&a>=72?b="X":72>a&&a>=64?b="W":64>a&&a>=56?b="V":56>a&&a>=48?b="U":48>a&&a>=40?b="T":40>a&&a>=32?b="S":32>a&&a>=24?b="R":24>a&&a>=16?b="Q":16>a&&a>=8?b="P":8>a&&a>=0?b="N":0>a&&a>=-8?b="M":-8>a&&a>=-16?b="L":-16>a&&a>=-24?b="K":-24>a&&a>=-32?b="J":-32>a&&a>=-40?b="H":-40>a&&a>=-48?b="G":-48>a&&a>=-56?b="F":-56>a&&a>=-64?b="E":-64>a&&a>=-72?b="D":-72>a&&a>=-80&&(b="C"),b}function i(a,b){var c=""+a.easting,d=""+a.northing;return a.zoneNumber+a.zoneLetter+j(a.easting,a.northing,a.zoneNumber)+c.substr(c.length-5,b)+d.substr(d.length-5,b)}function j(a,b,c){var d=k(c),e=Math.floor(a/1e5),f=Math.floor(b/1e5)%20;return l(e,f,d)}function k(a){var b=a%q;return 0===b&&(b=q),b}function l(a,b,c){var d=c-1,e=r.charCodeAt(d),f=s.charCodeAt(d),g=e+a-1,h=f+b,i=!1;g>x&&(g=g-x+t-1,i=!0),(g===u||u>e&&g>u||(g>u||u>e)&&i)&&g++,(g===v||v>e&&g>v||(g>v||v>e)&&i)&&(g++,g===u&&g++),g>x&&(g=g-x+t-1),h>w?(h=h-w+t-1,i=!0):i=!1,(h===u||u>f&&h>u||(h>u||u>f)&&i)&&h++,(h===v||v>f&&h>v||(h>v||v>f)&&i)&&(h++,h===u&&h++),h>w&&(h=h-w+t-1);var j=String.fromCharCode(g)+String.fromCharCode(h);return j}function m(a){if(a&&0===a.length)throw"MGRSPoint coverting from nothing";for(var b,c=a.length,d=null,e="",f=0;!/[A-Z]/.test(b=a.charAt(f));){if(f>=2)throw"MGRSPoint bad conversion from: "+a;e+=b,f++}var g=parseInt(e,10);if(0===f||f+3>c)throw"MGRSPoint bad conversion from: "+a;var h=a.charAt(f++);if("A">=h||"B"===h||"Y"===h||h>="Z"||"I"===h||"O"===h)throw"MGRSPoint zone letter "+h+" not handled: "+a;d=a.substring(f,f+=2);for(var i=k(g),j=n(d.charAt(0),i),l=o(d.charAt(1),i);l0&&(q=1e5/Math.pow(10,v),r=a.substring(f,f+v),w=parseFloat(r)*q,s=a.substring(f+v),x=parseFloat(s)*q),t=w+j,u=x+l,{easting:t,northing:u,zoneLetter:h,zoneNumber:g,accuracy:q}}function n(a,b){for(var c=r.charCodeAt(b-1),d=1e5,e=!1;c!==a.charCodeAt(0);){if(c++,c===u&&c++,c===v&&c++,c>x){if(e)throw"Bad character: "+a;c=t,e=!0}d+=1e5}return d}function o(a,b){if(a>"V")throw"MGRSPoint given invalid Northing "+a;for(var c=s.charCodeAt(b-1),d=0,e=!1;c!==a.charCodeAt(0);){if(c++,c===u&&c++,c===v&&c++,c>w){if(e)throw"Bad character: "+a;c=t,e=!0}d+=1e5}return d}function p(a){var b;switch(a){case"C":b=11e5;break;case"D":b=2e6;break;case"E":b=28e5;break;case"F":b=37e5;break;case"G":b=46e5;break;case"H":b=55e5;break;case"J":b=64e5;break;case"K":b=73e5;break;case"L":b=82e5;break;case"M":b=91e5;break;case"N":b=0;break;case"P":b=8e5;break;case"Q":b=17e5;break;case"R":b=26e5;break;case"S":b=35e5;break;case"T":b=44e5;break;case"U":b=53e5;break;case"V":b=62e5;break;case"W":b=7e6;break;case"X":b=79e5;break;default:b=-1}if(b>=0)return b;throw"Invalid zone letter: "+a}var q=6,r="AJSAJS",s="AFAFAF",t=65,u=73,v=79,w=86,x=90;c.forward=function(a,b){return b=b||5,i(f({lat:a.lat,lon:a.lon}),b)},c.inverse=function(a){var b=g(m(a.toUpperCase()));return[b.left,b.bottom,b.right,b.top]}},{}],18:[function(a,b){var c=a("./common"),d=a("./constants/index");b.exports=function(a){var b={},e={};a.split("+").map(function(a){return a.trim()}).filter(function(a){return a}).forEach(function(a){var b=a.split("=");b.push(!0),e[b[0].toLowerCase()]=b[1]});var f,g,h,i={proj:"projName",datum:"datumCode",rf:function(a){b.rf=parseFloat(a,10)},lat_0:function(a){b.lat0=a*c.D2R},lat_1:function(a){b.lat1=a*c.D2R},lat_2:function(a){b.lat2=a*c.D2R},lat_ts:function(a){b.lat_ts=a*c.D2R},lon_0:function(a){b.long0=a*c.D2R},lon_1:function(a){b.long1=a*c.D2R},lon_2:function(a){b.long2=a*c.D2R},alpha:function(a){b.alpha=parseFloat(a)*c.D2R},lonc:function(a){b.longc=a*c.D2R},x_0:function(a){b.x0=parseFloat(a,10)},y_0:function(a){b.y0=parseFloat(a,10)},k_0:function(a){b.k0=parseFloat(a,10)},k:function(a){b.k0=parseFloat(a,10)},r_a:function(){b.R_A=!0},zone:function(a){b.zone=parseInt(a,10)},south:function(){b.utmSouth=!0},towgs84:function(a){b.datum_params=a.split(",").map(function(a){return parseFloat(a,10)})},to_meter:function(a){b.to_meter=parseFloat(a,10)},from_greenwich:function(a){b.from_greenwich=a*c.D2R},pm:function(a){b.from_greenwich=(d.PrimeMeridian[a]?d.PrimeMeridian[a]:parseFloat(a,10))*c.D2R},nadgrids:function(a){"@null"===a?b.datumCode="none":b.nadgrids=a},axis:function(a){var c="ewnsud";3===a.length&&-1!==c.indexOf(a.substr(0,1))&&-1!==c.indexOf(a.substr(1,1))&&-1!==c.indexOf(a.substr(2,1))&&(b.axis=a)}};for(f in e)g=e[f],f in i?(h=i[f],"function"==typeof h?h(g):b[h]=g):b[f]=g;return b}},{"./common":4,"./constants/index":9}],19:[function(a,b,c){var d=a("../common");c.init=function(){Math.abs(this.lat1+this.lat2)d.EPSLN?(this.ms1*this.ms1-this.ms2*this.ms2)/(this.qs2-this.qs1):this.con,this.c=this.ms1*this.ms1+this.ns0*this.qs1,this.rh=this.a*Math.sqrt(this.c-this.ns0*this.qs0)/this.ns0)},c.forward=function(a){var b=a.x,c=a.y;this.sin_phi=Math.sin(c),this.cos_phi=Math.cos(c);var e=d.qsfnz(this.e3,this.sin_phi,this.cos_phi),f=this.a*Math.sqrt(this.c-this.ns0*e)/this.ns0,g=this.ns0*d.adjust_lon(b-this.long0),h=f*Math.sin(g)+this.x0,i=this.rh-f*Math.cos(g)+this.y0;return a.x=h,a.y=i,a},c.inverse=function(a){var b,c,e,f,g,h;return a.x-=this.x0,a.y=this.rh-a.y+this.y0,this.ns0>=0?(b=Math.sqrt(a.x*a.x+a.y*a.y),e=1):(b=-Math.sqrt(a.x*a.x+a.y*a.y),e=-1),f=0,0!==b&&(f=Math.atan2(e*a.x,e*a.y)),e=b*this.ns0/this.a,this.sphere?h=Math.asin((this.c-e*e)/(2*this.ns0)):(c=(this.c-e*e)/this.ns0,h=this.phi1z(this.e3,c)),g=d.adjust_lon(f/this.ns0+this.long0),a.x=g,a.y=h,a},c.phi1z=function(a,b){var c,e,f,g,h,i=d.asinz(.5*b);if(a=k;k++)if(c=Math.sin(i),e=Math.cos(i),f=a*c,g=1-f*f,h=.5*g*g/e*(b/(1-j)-c/g+.5/a*Math.log((1-f)/(1+f))),i+=h,Math.abs(h)<=1e-7)return i;return null},c.names=["Albers_Conic_Equal_Area","Albers","aea"]},{"../common":4}],20:[function(a,b,c){var d=a("../common");c.init=function(){this.sin_p12=Math.sin(this.lat0),this.cos_p12=Math.cos(this.lat0)},c.forward=function(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z=a.x,A=a.y,B=Math.sin(a.y),C=Math.cos(a.y),D=d.adjust_lon(z-this.long0);return this.sphere?Math.abs(this.sin_p12-1)<=d.EPSLN?(a.x=this.x0+this.a*(d.HALF_PI-A)*Math.sin(D),a.y=this.y0-this.a*(d.HALF_PI-A)*Math.cos(D),a):Math.abs(this.sin_p12+1)<=d.EPSLN?(a.x=this.x0+this.a*(d.HALF_PI+A)*Math.sin(D),a.y=this.y0+this.a*(d.HALF_PI+A)*Math.cos(D),a):(t=this.sin_p12*B+this.cos_p12*C*Math.cos(D),r=Math.acos(t),s=r/Math.sin(r),a.x=this.x0+this.a*s*C*Math.sin(D),a.y=this.y0+this.a*s*(this.cos_p12*B-this.sin_p12*C*Math.cos(D)),a):(b=d.e0fn(this.es),c=d.e1fn(this.es),e=d.e2fn(this.es),f=d.e3fn(this.es),Math.abs(this.sin_p12-1)<=d.EPSLN?(g=this.a*d.mlfn(b,c,e,f,d.HALF_PI),h=this.a*d.mlfn(b,c,e,f,A),a.x=this.x0+(g-h)*Math.sin(D),a.y=this.y0-(g-h)*Math.cos(D),a):Math.abs(this.sin_p12+1)<=d.EPSLN?(g=this.a*d.mlfn(b,c,e,f,d.HALF_PI),h=this.a*d.mlfn(b,c,e,f,A),a.x=this.x0+(g+h)*Math.sin(D),a.y=this.y0+(g+h)*Math.cos(D),a):(i=B/C,j=d.gN(this.a,this.e,this.sin_p12),k=d.gN(this.a,this.e,B),l=Math.atan((1-this.es)*i+this.es*j*this.sin_p12/(k*C)),m=Math.atan2(Math.sin(D),this.cos_p12*Math.tan(l)-this.sin_p12*Math.cos(D)),u=0===m?Math.asin(this.cos_p12*Math.sin(l)-this.sin_p12*Math.cos(l)):Math.abs(Math.abs(m)-d.PI)<=d.EPSLN?-Math.asin(this.cos_p12*Math.sin(l)-this.sin_p12*Math.cos(l)):Math.asin(Math.sin(D)*Math.cos(l)/Math.sin(m)),n=this.e*this.sin_p12/Math.sqrt(1-this.es),o=this.e*this.cos_p12*Math.cos(m)/Math.sqrt(1-this.es),p=n*o,q=o*o,v=u*u,w=v*u,x=w*u,y=x*u,r=j*u*(1-v*q*(1-q)/6+w/8*p*(1-2*q)+x/120*(q*(4-7*q)-3*n*n*(1-7*q))-y/48*p),a.x=this.x0+r*Math.sin(m),a.y=this.y0+r*Math.cos(m),a))},c.inverse=function(a){a.x-=this.x0,a.y-=this.y0; +var b,c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y;if(this.sphere){if(b=Math.sqrt(a.x*a.x+a.y*a.y),b>2*d.HALF_PI*this.a)return;return c=b/this.a,e=Math.sin(c),f=Math.cos(c),g=this.long0,Math.abs(b)<=d.EPSLN?h=this.lat0:(h=d.asinz(f*this.sin_p12+a.y*e*this.cos_p12/b),i=Math.abs(this.lat0)-d.HALF_PI,g=Math.abs(i)<=d.EPSLN?this.lat0>=0?d.adjust_lon(this.long0+Math.atan2(a.x,-a.y)):d.adjust_lon(this.long0-Math.atan2(-a.x,a.y)):d.adjust_lon(this.long0+Math.atan2(a.x*e,b*this.cos_p12*f-a.y*this.sin_p12*e))),a.x=g,a.y=h,a}return j=d.e0fn(this.es),k=d.e1fn(this.es),l=d.e2fn(this.es),m=d.e3fn(this.es),Math.abs(this.sin_p12-1)<=d.EPSLN?(n=this.a*d.mlfn(j,k,l,m,d.HALF_PI),b=Math.sqrt(a.x*a.x+a.y*a.y),o=n-b,h=d.imlfn(o/this.a,j,k,l,m),g=d.adjust_lon(this.long0+Math.atan2(a.x,-1*a.y)),a.x=g,a.y=h,a):Math.abs(this.sin_p12+1)<=d.EPSLN?(n=this.a*d.mlfn(j,k,l,m,d.HALF_PI),b=Math.sqrt(a.x*a.x+a.y*a.y),o=b-n,h=d.imlfn(o/this.a,j,k,l,m),g=d.adjust_lon(this.long0+Math.atan2(a.x,a.y)),a.x=g,a.y=h,a):(b=Math.sqrt(a.x*a.x+a.y*a.y),r=Math.atan2(a.x,a.y),p=d.gN(this.a,this.e,this.sin_p12),s=Math.cos(r),t=this.e*this.cos_p12*s,u=-t*t/(1-this.es),v=3*this.es*(1-u)*this.sin_p12*this.cos_p12*s/(1-this.es),w=b/p,x=w-u*(1+u)*Math.pow(w,3)/6-v*(1+3*u)*Math.pow(w,4)/24,y=1-u*x*x/2-w*x*x*x/6,q=Math.asin(this.sin_p12*Math.cos(x)+this.cos_p12*Math.sin(x)*s),g=d.adjust_lon(this.long0+Math.asin(Math.sin(r)*Math.sin(x)/Math.cos(q))),h=Math.atan((1-this.es*y*this.sin_p12/Math.sin(q))*Math.tan(q)/(1-this.es)),a.x=g,a.y=h,a)},c.names=["Azimuthal_Equidistant","aeqd"]},{"../common":4}],21:[function(a,b,c){var d=a("../common");c.init=function(){this.sphere||(this.e0=d.e0fn(this.es),this.e1=d.e1fn(this.es),this.e2=d.e2fn(this.es),this.e3=d.e3fn(this.es),this.ml0=this.a*d.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0))},c.forward=function(a){var b,c,e=a.x,f=a.y;if(e=d.adjust_lon(e-this.long0),this.sphere)b=this.a*Math.asin(Math.cos(f)*Math.sin(e)),c=this.a*(Math.atan2(Math.tan(f),Math.cos(e))-this.lat0);else{var g=Math.sin(f),h=Math.cos(f),i=d.gN(this.a,this.e,g),j=Math.tan(f)*Math.tan(f),k=e*Math.cos(f),l=k*k,m=this.es*h*h/(1-this.es),n=this.a*d.mlfn(this.e0,this.e1,this.e2,this.e3,f);b=i*k*(1-l*j*(1/6-(8-j+8*m)*l/120)),c=n-this.ml0+i*g/h*l*(.5+(5-j+6*m)*l/24)}return a.x=b+this.x0,a.y=c+this.y0,a},c.inverse=function(a){a.x-=this.x0,a.y-=this.y0;var b,c,e=a.x/this.a,f=a.y/this.a;if(this.sphere){var g=f+this.lat0;b=Math.asin(Math.sin(g)*Math.cos(e)),c=Math.atan2(Math.tan(e),Math.cos(g))}else{var h=this.ml0/this.a+f,i=d.imlfn(h,this.e0,this.e1,this.e2,this.e3);if(Math.abs(Math.abs(i)-d.HALF_PI)<=d.EPSLN)return a.x=this.long0,a.y=d.HALF_PI,0>f&&(a.y*=-1),a;var j=d.gN(this.a,this.e,Math.sin(i)),k=j*j*j/this.a/this.a*(1-this.es),l=Math.pow(Math.tan(i),2),m=e*this.a/j,n=m*m;b=i-j*Math.tan(i)/k*m*m*(.5-(1+3*l)*m*m/24),c=m*(1-n*(l/3+(1+3*l)*l*n/15))/Math.cos(i)}return a.x=d.adjust_lon(c+this.long0),a.y=d.adjust_lat(b),a},c.names=["Cassini","Cassini_Soldner","cass"]},{"../common":4}],22:[function(a,b,c){var d=a("../common");c.init=function(){this.sphere||(this.k0=d.msfnz(this.e,Math.sin(this.lat_ts),Math.cos(this.lat_ts)))},c.forward=function(a){var b,c,e=a.x,f=a.y,g=d.adjust_lon(e-this.long0);if(this.sphere)b=this.x0+this.a*g*Math.cos(this.lat_ts),c=this.y0+this.a*Math.sin(f)/Math.cos(this.lat_ts);else{var h=d.qsfnz(this.e,Math.sin(f));b=this.x0+this.a*this.k0*g,c=this.y0+this.a*h*.5/this.k0}return a.x=b,a.y=c,a},c.inverse=function(a){a.x-=this.x0,a.y-=this.y0;var b,c;return this.sphere?(b=d.adjust_lon(this.long0+a.x/this.a/Math.cos(this.lat_ts)),c=Math.asin(a.y/this.a*Math.cos(this.lat_ts))):(c=d.iqsfnz(this.e,2*a.y*this.k0/this.a),b=d.adjust_lon(this.long0+a.x/(this.a*this.k0))),a.x=b,a.y=c,a},c.names=["cea"]},{"../common":4}],23:[function(a,b,c){var d=a("../common");c.init=function(){this.x0=this.x0||0,this.y0=this.y0||0,this.lat0=this.lat0||0,this.long0=this.long0||0,this.lat_ts=this.lat_t||0,this.title=this.title||"Equidistant Cylindrical (Plate Carre)",this.rc=Math.cos(this.lat_ts)},c.forward=function(a){var b=a.x,c=a.y,e=d.adjust_lon(b-this.long0),f=d.adjust_lat(c-this.lat0);return a.x=this.x0+this.a*e*this.rc,a.y=this.y0+this.a*f,a},c.inverse=function(a){var b=a.x,c=a.y;return a.x=d.adjust_lon(this.long0+(b-this.x0)/(this.a*this.rc)),a.y=d.adjust_lat(this.lat0+(c-this.y0)/this.a),a},c.names=["Equirectangular","Equidistant_Cylindrical","eqc"]},{"../common":4}],24:[function(a,b,c){var d=a("../common");c.init=function(){return Math.abs(this.lat1+this.lat2)=0?(c=Math.sqrt(a.x*a.x+a.y*a.y),b=1):(c=-Math.sqrt(a.x*a.x+a.y*a.y),b=-1);var g=0;if(0!==c&&(g=Math.atan2(b*a.x,b*a.y)),this.sphere)return f=d.adjust_lon(this.long0+g/this.ns),e=d.adjust_lat(this.g-c/this.a),a.x=f,a.y=e,a;var h=this.g-c/this.a;return e=d.imlfn(h,this.e0,this.e1,this.e2,this.e3),f=d.adjust_lon(this.long0+g/this.ns),a.x=f,a.y=e,a},c.names=["Equidistant_Conic","eqdc"]},{"../common":4}],25:[function(a,b,c){var d=a("../common");c.init=function(){var a=Math.sin(this.lat0),b=Math.cos(this.lat0);b*=b,this.rc=Math.sqrt(1-this.es)/(1-this.es*a*a),this.C=Math.sqrt(1+this.es*b*b/(1-this.es)),this.phic0=Math.asin(a/this.C),this.ratexp=.5*this.C*this.e,this.K=Math.tan(.5*this.phic0+d.FORTPI)/(Math.pow(Math.tan(.5*this.lat0+d.FORTPI),this.C)*d.srat(this.e*a,this.ratexp))},c.forward=function(a){var b=a.x,c=a.y;return a.y=2*Math.atan(this.K*Math.pow(Math.tan(.5*c+d.FORTPI),this.C)*d.srat(this.e*Math.sin(c),this.ratexp))-d.HALF_PI,a.x=this.C*b,a},c.inverse=function(a){for(var b=1e-14,c=a.x/this.C,e=a.y,f=Math.pow(Math.tan(.5*e+d.FORTPI)/this.K,1/this.C),g=d.MAX_ITER;g>0&&(e=2*Math.atan(f*d.srat(this.e*Math.sin(a.y),-.5*this.e))-d.HALF_PI,!(Math.abs(e-a.y)0||Math.abs(h)<=d.EPSLN?(i=this.x0+this.a*g*c*Math.sin(e)/h,j=this.y0+this.a*g*(this.cos_p14*b-this.sin_p14*c*f)/h):(i=this.x0+this.infinity_dist*c*Math.sin(e),j=this.y0+this.infinity_dist*(this.cos_p14*b-this.sin_p14*c*f)),a.x=i,a.y=j,a},c.inverse=function(a){var b,c,e,f,g,h;return a.x=(a.x-this.x0)/this.a,a.y=(a.y-this.y0)/this.a,a.x/=this.k0,a.y/=this.k0,(b=Math.sqrt(a.x*a.x+a.y*a.y))?(f=Math.atan2(b,this.rc),c=Math.sin(f),e=Math.cos(f),h=d.asinz(e*this.sin_p14+a.y*c*this.cos_p14/b),g=Math.atan2(a.x*c,b*this.cos_p14*e-a.y*this.sin_p14*c),g=d.adjust_lon(this.long0+g)):(h=this.phic0,g=0),a.x=g,a.y=h,a},c.names=["gnom"]},{"../common":4}],27:[function(a,b,c){function d(a,b){var c=g.length;return a.names?(g[c]=a,a.names.forEach(function(a){f[a.toLowerCase()]=c}),this):(console.log(b),!0)}var e=[a("./tmerc"),a("./utm"),a("./sterea"),a("./stere"),a("./somerc"),a("./omerc"),a("./lcc"),a("./krovak"),a("./cass"),a("./laea"),a("./merc"),a("./aea"),a("./gnom"),a("./cea"),a("./eqc"),a("./poly"),a("./nzmg"),a("./mill"),a("./sinu"),a("./moll"),a("./eqdc"),a("./vandg"),a("./aeqd"),a("./longlat")],f={},g=[];c.add=d,c.get=function(a){if(!a)return!1;var b=a.toLowerCase();return"undefined"!=typeof f[b]&&g[f[b]]?g[f[b]]:void 0},c.start=function(){e.forEach(d)}},{"./aea":19,"./aeqd":20,"./cass":21,"./cea":22,"./eqc":23,"./eqdc":24,"./gnom":26,"./krovak":28,"./laea":29,"./lcc":30,"./longlat":31,"./merc":32,"./mill":33,"./moll":34,"./nzmg":35,"./omerc":36,"./poly":37,"./sinu":38,"./somerc":39,"./stere":40,"./sterea":41,"./tmerc":42,"./utm":43,"./vandg":44}],28:[function(a,b,c){var d=a("../common");c.init=function(){this.a=6377397.155,this.es=.006674372230614,this.e=Math.sqrt(this.es),this.lat0||(this.lat0=.863937979737193),this.long0||(this.long0=.4334234309119251),this.k0||(this.k0=.9999),this.s45=.785398163397448,this.s90=2*this.s45,this.fi0=this.lat0,this.e2=this.es,this.e=Math.sqrt(this.e2),this.alfa=Math.sqrt(1+this.e2*Math.pow(Math.cos(this.fi0),4)/(1-this.e2)),this.uq=1.04216856380474,this.u0=Math.asin(Math.sin(this.fi0)/this.alfa),this.g=Math.pow((1+this.e*Math.sin(this.fi0))/(1-this.e*Math.sin(this.fi0)),this.alfa*this.e/2),this.k=Math.tan(this.u0/2+this.s45)/Math.pow(Math.tan(this.fi0/2+this.s45),this.alfa)*this.g,this.k1=this.k0,this.n0=this.a*Math.sqrt(1-this.e2)/(1-this.e2*Math.pow(Math.sin(this.fi0),2)),this.s0=1.37008346281555,this.n=Math.sin(this.s0),this.ro0=this.k1*this.n0/Math.tan(this.s0),this.ad=this.s90-this.uq},c.forward=function(a){var b,c,e,f,g,h,i,j=a.x,k=a.y,l=d.adjust_lon(j-this.long0);return b=Math.pow((1+this.e*Math.sin(k))/(1-this.e*Math.sin(k)),this.alfa*this.e/2),c=2*(Math.atan(this.k*Math.pow(Math.tan(k/2+this.s45),this.alfa)/b)-this.s45),e=-l*this.alfa,f=Math.asin(Math.cos(this.ad)*Math.sin(c)+Math.sin(this.ad)*Math.cos(c)*Math.cos(e)),g=Math.asin(Math.cos(c)*Math.sin(e)/Math.cos(f)),h=this.n*g,i=this.ro0*Math.pow(Math.tan(this.s0/2+this.s45),this.n)/Math.pow(Math.tan(f/2+this.s45),this.n),a.y=i*Math.cos(h)/1,a.x=i*Math.sin(h)/1,this.czech||(a.y*=-1,a.x*=-1),a},c.inverse=function(a){var b,c,d,e,f,g,h,i,j=a.x;a.x=a.y,a.y=j,this.czech||(a.y*=-1,a.x*=-1),g=Math.sqrt(a.x*a.x+a.y*a.y),f=Math.atan2(a.y,a.x),e=f/Math.sin(this.s0),d=2*(Math.atan(Math.pow(this.ro0/g,1/this.n)*Math.tan(this.s0/2+this.s45))-this.s45),b=Math.asin(Math.cos(this.ad)*Math.sin(d)-Math.sin(this.ad)*Math.cos(d)*Math.cos(e)),c=Math.asin(Math.cos(d)*Math.sin(e)/Math.cos(b)),a.x=this.long0-c/this.alfa,h=b,i=0;var k=0;do a.y=2*(Math.atan(Math.pow(this.k,-1/this.alfa)*Math.pow(Math.tan(b/2+this.s45),1/this.alfa)*Math.pow((1+this.e*Math.sin(h))/(1-this.e*Math.sin(h)),this.e/2))-this.s45),Math.abs(h-a.y)<1e-10&&(i=1),h=a.y,k+=1;while(0===i&&15>k);return k>=15?null:a},c.names=["Krovak","krovak"]},{"../common":4}],29:[function(a,b,c){var d=a("../common");c.S_POLE=1,c.N_POLE=2,c.EQUIT=3,c.OBLIQ=4,c.init=function(){var a=Math.abs(this.lat0);if(this.mode=Math.abs(a-d.HALF_PI)0){var b;switch(this.qp=d.qsfnz(this.e,1),this.mmf=.5/(1-this.es),this.apa=this.authset(this.es),this.mode){case this.N_POLE:this.dd=1;break;case this.S_POLE:this.dd=1;break;case this.EQUIT:this.rq=Math.sqrt(.5*this.qp),this.dd=1/this.rq,this.xmf=1,this.ymf=.5*this.qp;break;case this.OBLIQ:this.rq=Math.sqrt(.5*this.qp),b=Math.sin(this.lat0),this.sinb1=d.qsfnz(this.e,b)/this.qp,this.cosb1=Math.sqrt(1-this.sinb1*this.sinb1),this.dd=Math.cos(this.lat0)/(Math.sqrt(1-this.es*b*b)*this.rq*this.cosb1),this.ymf=(this.xmf=this.rq)/this.dd,this.xmf*=this.dd}}else this.mode===this.OBLIQ&&(this.sinph0=Math.sin(this.lat0),this.cosph0=Math.cos(this.lat0))},c.forward=function(a){var b,c,e,f,g,h,i,j,k,l,m=a.x,n=a.y;if(m=d.adjust_lon(m-this.long0),this.sphere){if(g=Math.sin(n),l=Math.cos(n),e=Math.cos(m),this.mode===this.OBLIQ||this.mode===this.EQUIT){if(c=this.mode===this.EQUIT?1+l*e:1+this.sinph0*g+this.cosph0*l*e,c<=d.EPSLN)return null;c=Math.sqrt(2/c),b=c*l*Math.sin(m),c*=this.mode===this.EQUIT?g:this.cosph0*g-this.sinph0*l*e}else if(this.mode===this.N_POLE||this.mode===this.S_POLE){if(this.mode===this.N_POLE&&(e=-e),Math.abs(n+this.phi0)=0?(b=(k=Math.sqrt(h))*f,c=e*(this.mode===this.S_POLE?k:-k)):b=c=0}}return a.x=this.a*b+this.x0,a.y=this.a*c+this.y0,a},c.inverse=function(a){a.x-=this.x0,a.y-=this.y0;var b,c,e,f,g,h,i,j=a.x/this.a,k=a.y/this.a;if(this.sphere){var l,m=0,n=0;if(l=Math.sqrt(j*j+k*k),c=.5*l,c>1)return null;switch(c=2*Math.asin(c),(this.mode===this.OBLIQ||this.mode===this.EQUIT)&&(n=Math.sin(c),m=Math.cos(c)),this.mode){case this.EQUIT:c=Math.abs(l)<=d.EPSLN?0:Math.asin(k*n/l),j*=n,k=m*l;break;case this.OBLIQ:c=Math.abs(l)<=d.EPSLN?this.phi0:Math.asin(m*this.sinph0+k*n*this.cosph0/l),j*=n*this.cosph0,k=(m-Math.sin(c)*this.sinph0)*l;break;case this.N_POLE:k=-k,c=d.HALF_PI-c;break;case this.S_POLE:c-=d.HALF_PI}b=0!==k||this.mode!==this.EQUIT&&this.mode!==this.OBLIQ?Math.atan2(j,k):0}else{if(i=0,this.mode===this.OBLIQ||this.mode===this.EQUIT){if(j/=this.dd,k*=this.dd,h=Math.sqrt(j*j+k*k),hd.EPSLN?Math.log(e/i)/Math.log(f/j):b,isNaN(this.ns)&&(this.ns=b),this.f0=e/(this.ns*Math.pow(f,this.ns)),this.rh=this.a*this.f0*Math.pow(k,this.ns),this.title||(this.title="Lambert Conformal Conic")}},c.forward=function(a){var b=a.x,c=a.y;Math.abs(2*Math.abs(c)-d.PI)<=d.EPSLN&&(c=d.sign(c)*(d.HALF_PI-2*d.EPSLN));var e,f,g=Math.abs(Math.abs(c)-d.HALF_PI);if(g>d.EPSLN)e=d.tsfnz(this.e,c,Math.sin(c)),f=this.a*this.f0*Math.pow(e,this.ns);else{if(g=c*this.ns,0>=g)return null;f=0}var h=this.ns*d.adjust_lon(b-this.long0);return a.x=this.k0*f*Math.sin(h)+this.x0,a.y=this.k0*(this.rh-f*Math.cos(h))+this.y0,a},c.inverse=function(a){var b,c,e,f,g,h=(a.x-this.x0)/this.k0,i=this.rh-(a.y-this.y0)/this.k0;this.ns>0?(b=Math.sqrt(h*h+i*i),c=1):(b=-Math.sqrt(h*h+i*i),c=-1);var j=0;if(0!==b&&(j=Math.atan2(c*h,c*i)),0!==b||this.ns>0){if(c=1/this.ns,e=Math.pow(b/(this.a*this.f0),c),f=d.phi2z(this.e,e),-9999===f)return null}else f=-d.HALF_PI;return g=d.adjust_lon(j/this.ns+this.long0),a.x=g,a.y=f,a},c.names=["Lambert Tangential Conformal Conic Projection","Lambert_Conformal_Conic","Lambert_Conformal_Conic_2SP","lcc"]},{"../common":4}],31:[function(a,b,c){function d(a){return a}c.init=function(){},c.forward=d,c.inverse=d,c.names=["longlat","identity"]},{}],32:[function(a,b,c){var d=a("../common");c.init=function(){var a=this.b/this.a;this.es=1-a*a,this.e=Math.sqrt(this.es),this.lat_ts?this.k0=this.sphere?Math.cos(this.lat_ts):d.msfnz(this.e,Math.sin(this.lat_ts),Math.cos(this.lat_ts)):this.k0||(this.k0=this.k?this.k:1)},c.forward=function(a){var b=a.x,c=a.y;if(c*d.R2D>90&&c*d.R2D<-90&&b*d.R2D>180&&b*d.R2D<-180)return null;var e,f;if(Math.abs(Math.abs(c)-d.HALF_PI)<=d.EPSLN)return null;if(this.sphere)e=this.x0+this.a*this.k0*d.adjust_lon(b-this.long0),f=this.y0+this.a*this.k0*Math.log(Math.tan(d.FORTPI+.5*c));else{var g=Math.sin(c),h=d.tsfnz(this.e,c,g);e=this.x0+this.a*this.k0*d.adjust_lon(b-this.long0),f=this.y0-this.a*this.k0*Math.log(h)}return a.x=e,a.y=f,a},c.inverse=function(a){var b,c,e=a.x-this.x0,f=a.y-this.y0;if(this.sphere)c=d.HALF_PI-2*Math.atan(Math.exp(-f/(this.a*this.k0)));else{var g=Math.exp(-f/(this.a*this.k0));if(c=d.phi2z(this.e,g),-9999===c)return null}return b=d.adjust_lon(this.long0+e/(this.a*this.k0)),a.x=b,a.y=c,a},c.names=["Mercator","Popular Visualisation Pseudo Mercator","Mercator_1SP","Mercator_Auxiliary_Sphere","merc"]},{"../common":4}],33:[function(a,b,c){var d=a("../common");c.init=function(){},c.forward=function(a){var b=a.x,c=a.y,e=d.adjust_lon(b-this.long0),f=this.x0+this.a*e,g=this.y0+this.a*Math.log(Math.tan(d.PI/4+c/2.5))*1.25;return a.x=f,a.y=g,a},c.inverse=function(a){a.x-=this.x0,a.y-=this.y0;var b=d.adjust_lon(this.long0+a.x/this.a),c=2.5*(Math.atan(Math.exp(.8*a.y/this.a))-d.PI/4);return a.x=b,a.y=c,a},c.names=["Miller_Cylindrical","mill"]},{"../common":4}],34:[function(a,b,c){var d=a("../common");c.init=function(){},c.forward=function(a){for(var b=a.x,c=a.y,e=d.adjust_lon(b-this.long0),f=c,g=d.PI*Math.sin(c),h=0;!0;h++){var i=-(f+Math.sin(f)-g)/(1+Math.cos(f));if(f+=i,Math.abs(i).999999999999&&(c=.999999999999),b=Math.asin(c);var e=d.adjust_lon(this.long0+a.x/(.900316316158*this.a*Math.cos(b)));e<-d.PI&&(e=-d.PI),e>d.PI&&(e=d.PI),c=(2*b+Math.sin(2*b))/d.PI,Math.abs(c)>1&&(c=1);var f=Math.asin(c);return a.x=e,a.y=f,a},c.names=["Mollweide","moll"]},{"../common":4}],35:[function(a,b,c){var d=a("../common");c.iterations=1,c.init=function(){this.A=[],this.A[1]=.6399175073,this.A[2]=-.1358797613,this.A[3]=.063294409,this.A[4]=-.02526853,this.A[5]=.0117879,this.A[6]=-.0055161,this.A[7]=.0026906,this.A[8]=-.001333,this.A[9]=67e-5,this.A[10]=-34e-5,this.B_re=[],this.B_im=[],this.B_re[1]=.7557853228,this.B_im[1]=0,this.B_re[2]=.249204646,this.B_im[2]=.003371507,this.B_re[3]=-.001541739,this.B_im[3]=.04105856,this.B_re[4]=-.10162907,this.B_im[4]=.01727609,this.B_re[5]=-.26623489,this.B_im[5]=-.36249218,this.B_re[6]=-.6870983,this.B_im[6]=-1.1651967,this.C_re=[],this.C_im=[],this.C_re[1]=1.3231270439,this.C_im[1]=0,this.C_re[2]=-.577245789,this.C_im[2]=-.007809598,this.C_re[3]=.508307513,this.C_im[3]=-.112208952,this.C_re[4]=-.15094762,this.C_im[4]=.18200602,this.C_re[5]=1.01418179,this.C_im[5]=1.64497696,this.C_re[6]=1.9660549,this.C_im[6]=2.5127645,this.D=[],this.D[1]=1.5627014243,this.D[2]=.5185406398,this.D[3]=-.03333098,this.D[4]=-.1052906,this.D[5]=-.0368594,this.D[6]=.007317,this.D[7]=.0122,this.D[8]=.00394,this.D[9]=-.0013},c.forward=function(a){var b,c=a.x,e=a.y,f=e-this.lat0,g=c-this.long0,h=f/d.SEC_TO_RAD*1e-5,i=g,j=1,k=0;for(b=1;10>=b;b++)j*=h,k+=this.A[b]*j;var l,m,n=k,o=i,p=1,q=0,r=0,s=0;for(b=1;6>=b;b++)l=p*n-q*o,m=q*n+p*o,p=l,q=m,r=r+this.B_re[b]*p-this.B_im[b]*q,s=s+this.B_im[b]*p+this.B_re[b]*q;return a.x=s*this.a+this.x0,a.y=r*this.a+this.y0,a},c.inverse=function(a){var b,c,e,f=a.x,g=a.y,h=f-this.x0,i=g-this.y0,j=i/this.a,k=h/this.a,l=1,m=0,n=0,o=0;for(b=1;6>=b;b++)c=l*j-m*k,e=m*j+l*k,l=c,m=e,n=n+this.C_re[b]*l-this.C_im[b]*m,o=o+this.C_im[b]*l+this.C_re[b]*m;for(var p=0;p=b;b++)q=s*n-t*o,r=t*n+s*o,s=q,t=r,u+=(b-1)*(this.B_re[b]*s-this.B_im[b]*t),v+=(b-1)*(this.B_im[b]*s+this.B_re[b]*t);s=1,t=0;var w=this.B_re[1],x=this.B_im[1];for(b=2;6>=b;b++)q=s*n-t*o,r=t*n+s*o,s=q,t=r,w+=b*(this.B_re[b]*s-this.B_im[b]*t),x+=b*(this.B_im[b]*s+this.B_re[b]*t);var y=w*w+x*x;n=(u*w+v*x)/y,o=(v*w-u*x)/y}var z=n,A=o,B=1,C=0;for(b=1;9>=b;b++)B*=z,C+=this.D[b]*B;var D=this.lat0+C*d.SEC_TO_RAD*1e5,E=this.long0+A;return a.x=E,a.y=D,a},c.names=["New_Zealand_Map_Grid","nzmg"]},{"../common":4}],36:[function(a,b,c){var d=a("../common");c.init=function(){this.no_off=this.no_off||!1,this.no_rot=this.no_rot||!1,isNaN(this.k0)&&(this.k0=1);var a=Math.sin(this.lat0),b=Math.cos(this.lat0),c=this.e*a;this.bl=Math.sqrt(1+this.es/(1-this.es)*Math.pow(b,4)),this.al=this.a*this.bl*this.k0*Math.sqrt(1-this.es)/(1-c*c);var e=d.tsfnz(this.e,this.lat0,a),f=this.bl/b*Math.sqrt((1-this.es)/(1-c*c));1>f*f&&(f=1);var g,h;if(isNaN(this.longc)){var i=d.tsfnz(this.e,this.lat1,Math.sin(this.lat1)),j=d.tsfnz(this.e,this.lat2,Math.sin(this.lat2));this.el=this.lat0>=0?(f+Math.sqrt(f*f-1))*Math.pow(e,this.bl):(f-Math.sqrt(f*f-1))*Math.pow(e,this.bl);var k=Math.pow(i,this.bl),l=Math.pow(j,this.bl);g=this.el/k,h=.5*(g-1/g);var m=(this.el*this.el-l*k)/(this.el*this.el+l*k),n=(l-k)/(l+k),o=d.adjust_lon(this.long1-this.long2);this.long0=.5*(this.long1+this.long2)-Math.atan(m*Math.tan(.5*this.bl*o)/n)/this.bl,this.long0=d.adjust_lon(this.long0);var p=d.adjust_lon(this.long1-this.long0);this.gamma0=Math.atan(Math.sin(this.bl*p)/h),this.alpha=Math.asin(f*Math.sin(this.gamma0))}else g=this.lat0>=0?f+Math.sqrt(f*f-1):f-Math.sqrt(f*f-1),this.el=g*Math.pow(e,this.bl),h=.5*(g-1/g),this.gamma0=Math.asin(Math.sin(this.alpha)/f),this.long0=this.longc-Math.asin(h*Math.tan(this.gamma0))/this.bl;this.uc=this.no_off?0:this.lat0>=0?this.al/this.bl*Math.atan2(Math.sqrt(f*f-1),Math.cos(this.alpha)):-1*this.al/this.bl*Math.atan2(Math.sqrt(f*f-1),Math.cos(this.alpha))},c.forward=function(a){var b,c,e,f=a.x,g=a.y,h=d.adjust_lon(f-this.long0);if(Math.abs(Math.abs(g)-d.HALF_PI)<=d.EPSLN)e=g>0?-1:1,c=this.al/this.bl*Math.log(Math.tan(d.FORTPI+e*this.gamma0*.5)),b=-1*e*d.HALF_PI*this.al/this.bl;else{var i=d.tsfnz(this.e,g,Math.sin(g)),j=this.el/Math.pow(i,this.bl),k=.5*(j-1/j),l=.5*(j+1/j),m=Math.sin(this.bl*h),n=(k*Math.sin(this.gamma0)-m*Math.cos(this.gamma0))/l;c=Math.abs(Math.abs(n)-1)<=d.EPSLN?Number.POSITIVE_INFINITY:.5*this.al*Math.log((1-n)/(1+n))/this.bl,b=Math.abs(Math.cos(this.bl*h))<=d.EPSLN?this.al*this.bl*h:this.al*Math.atan2(k*Math.cos(this.gamma0)+m*Math.sin(this.gamma0),Math.cos(this.bl*h))/this.bl}return this.no_rot?(a.x=this.x0+b,a.y=this.y0+c):(b-=this.uc,a.x=this.x0+c*Math.cos(this.alpha)+b*Math.sin(this.alpha),a.y=this.y0+b*Math.cos(this.alpha)-c*Math.sin(this.alpha)),a},c.inverse=function(a){var b,c;this.no_rot?(c=a.y-this.y0,b=a.x-this.x0):(c=(a.x-this.x0)*Math.cos(this.alpha)-(a.y-this.y0)*Math.sin(this.alpha),b=(a.y-this.y0)*Math.cos(this.alpha)+(a.x-this.x0)*Math.sin(this.alpha),b+=this.uc);var e=Math.exp(-1*this.bl*c/this.al),f=.5*(e-1/e),g=.5*(e+1/e),h=Math.sin(this.bl*b/this.al),i=(h*Math.cos(this.gamma0)+f*Math.sin(this.gamma0))/g,j=Math.pow(this.el/Math.sqrt((1+i)/(1-i)),1/this.bl);return Math.abs(i-1)1e-7;){if(++l>20)return;i=1/this.alpha*(Math.log(Math.tan(Math.PI/4+f/2))-this.K)+this.e*Math.log(Math.tan(Math.PI/4+Math.asin(this.e*Math.sin(j))/2)),k=j,j=2*Math.atan(Math.exp(i))-Math.PI/2}return a.x=h,a.y=j,a},c.names=["somerc"]},{}],40:[function(a,b,c){var d=a("../common");c.ssfn_=function(a,b,c){return b*=c,Math.tan(.5*(d.HALF_PI+a))*Math.pow((1-b)/(1+b),.5*c)},c.init=function(){this.coslat0=Math.cos(this.lat0),this.sinlat0=Math.sin(this.lat0),this.sphere?1===this.k0&&!isNaN(this.lat_ts)&&Math.abs(this.coslat0)<=d.EPSLN&&(this.k0=.5*(1+d.sign(this.lat0)*Math.sin(this.lat_ts))):(Math.abs(this.coslat0)<=d.EPSLN&&(this.con=this.lat0>0?1:-1),this.cons=Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e)),1===this.k0&&!isNaN(this.lat_ts)&&Math.abs(this.coslat0)<=d.EPSLN&&(this.k0=.5*this.cons*d.msfnz(this.e,Math.sin(this.lat_ts),Math.cos(this.lat_ts))/d.tsfnz(this.e,this.con*this.lat_ts,this.con*Math.sin(this.lat_ts))),this.ms1=d.msfnz(this.e,this.sinlat0,this.coslat0),this.X0=2*Math.atan(this.ssfn_(this.lat0,this.sinlat0,this.e))-d.HALF_PI,this.cosX0=Math.cos(this.X0),this.sinX0=Math.sin(this.X0))},c.forward=function(a){var b,c,e,f,g,h,i=a.x,j=a.y,k=Math.sin(j),l=Math.cos(j),m=d.adjust_lon(i-this.long0);return Math.abs(Math.abs(i-this.long0)-d.PI)<=d.EPSLN&&Math.abs(j+this.lat0)<=d.EPSLN?(a.x=0/0,a.y=0/0,a):this.sphere?(b=2*this.k0/(1+this.sinlat0*k+this.coslat0*l*Math.cos(m)),a.x=this.a*b*l*Math.sin(m)+this.x0,a.y=this.a*b*(this.coslat0*k-this.sinlat0*l*Math.cos(m))+this.y0,a):(c=2*Math.atan(this.ssfn_(j,k,this.e))-d.HALF_PI,f=Math.cos(c),e=Math.sin(c),Math.abs(this.coslat0)<=d.EPSLN?(g=d.tsfnz(this.e,j*this.con,this.con*k),h=2*this.a*this.k0*g/this.cons,a.x=this.x0+h*Math.sin(i-this.long0),a.y=this.y0-this.con*h*Math.cos(i-this.long0),a):(Math.abs(this.sinlat0)0?d.adjust_lon(this.long0+Math.atan2(a.x,-1*a.y)):d.adjust_lon(this.long0+Math.atan2(a.x,a.y)):d.adjust_lon(this.long0+Math.atan2(a.x*Math.sin(i),h*this.coslat0*Math.cos(i)-a.y*this.sinlat0*Math.sin(i))),a.x=b,a.y=c,a)}if(Math.abs(this.coslat0)<=d.EPSLN){if(h<=d.EPSLN)return c=this.lat0,b=this.long0,a.x=b,a.y=c,a;a.x*=this.con,a.y*=this.con,e=h*this.cons/(2*this.a*this.k0),c=this.con*d.phi2z(this.e,e),b=this.con*d.adjust_lon(this.con*this.long0+Math.atan2(a.x,-1*a.y))}else f=2*Math.atan(h*this.cosX0/(2*this.a*this.k0*this.ms1)),b=this.long0,h<=d.EPSLN?g=this.X0:(g=Math.asin(Math.cos(f)*this.sinX0+a.y*Math.sin(f)*this.cosX0/h),b=d.adjust_lon(this.long0+Math.atan2(a.x*Math.sin(f),h*this.cosX0*Math.cos(f)-a.y*this.sinX0*Math.sin(f)))),c=-1*d.phi2z(this.e,Math.tan(.5*(d.HALF_PI+g))); +return a.x=b,a.y=c,a},c.names=["stere"]},{"../common":4}],41:[function(a,b,c){var d=a("../common"),e=a("./gauss");c.init=function(){e.init.apply(this),this.rc&&(this.sinc0=Math.sin(this.phic0),this.cosc0=Math.cos(this.phic0),this.R2=2*this.rc,this.title||(this.title="Oblique Stereographic Alternative"))},c.forward=function(a){var b,c,f,g;return a.x=d.adjust_lon(a.x-this.long0),e.forward.apply(this,[a]),b=Math.sin(a.y),c=Math.cos(a.y),f=Math.cos(a.x),g=this.k0*this.R2/(1+this.sinc0*b+this.cosc0*c*f),a.x=g*c*Math.sin(a.x),a.y=g*(this.cosc0*b-this.sinc0*c*f),a.x=this.a*a.x+this.x0,a.y=this.a*a.y+this.y0,a},c.inverse=function(a){var b,c,f,g,h;if(a.x=(a.x-this.x0)/this.a,a.y=(a.y-this.y0)/this.a,a.x/=this.k0,a.y/=this.k0,h=Math.sqrt(a.x*a.x+a.y*a.y)){var i=2*Math.atan2(h,this.R2);b=Math.sin(i),c=Math.cos(i),g=Math.asin(c*this.sinc0+a.y*b*this.cosc0/h),f=Math.atan2(a.x*b,h*this.cosc0*c-a.y*this.sinc0*b)}else g=this.phic0,f=0;return a.x=f,a.y=g,e.inverse.apply(this,[a]),a.x=d.adjust_lon(a.x+this.long0),a},c.names=["Stereographic_North_Pole","Oblique_Stereographic","Polar_Stereographic","sterea","Oblique Stereographic Alternative"]},{"../common":4,"./gauss":25}],42:[function(a,b,c){var d=a("../common");c.init=function(){this.e0=d.e0fn(this.es),this.e1=d.e1fn(this.es),this.e2=d.e2fn(this.es),this.e3=d.e3fn(this.es),this.ml0=this.a*d.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0)},c.forward=function(a){var b,c,e,f=a.x,g=a.y,h=d.adjust_lon(f-this.long0),i=Math.sin(g),j=Math.cos(g);if(this.sphere){var k=j*Math.sin(h);if(Math.abs(Math.abs(k)-1)<1e-10)return 93;c=.5*this.a*this.k0*Math.log((1+k)/(1-k)),b=Math.acos(j*Math.cos(h)/Math.sqrt(1-k*k)),0>g&&(b=-b),e=this.a*this.k0*(b-this.lat0)}else{var l=j*h,m=Math.pow(l,2),n=this.ep2*Math.pow(j,2),o=Math.tan(g),p=Math.pow(o,2);b=1-this.es*Math.pow(i,2);var q=this.a/Math.sqrt(b),r=this.a*d.mlfn(this.e0,this.e1,this.e2,this.e3,g);c=this.k0*q*l*(1+m/6*(1-p+n+m/20*(5-18*p+Math.pow(p,2)+72*n-58*this.ep2)))+this.x0,e=this.k0*(r-this.ml0+q*o*m*(.5+m/24*(5-p+9*n+4*Math.pow(n,2)+m/30*(61-58*p+Math.pow(p,2)+600*n-330*this.ep2))))+this.y0}return a.x=c,a.y=e,a},c.inverse=function(a){var b,c,e,f,g,h,i=6;if(this.sphere){var j=Math.exp(a.x/(this.a*this.k0)),k=.5*(j-1/j),l=this.lat0+a.y/(this.a*this.k0),m=Math.cos(l);b=Math.sqrt((1-m*m)/(1+k*k)),g=d.asinz(b),0>l&&(g=-g),h=0===k&&0===m?this.long0:d.adjust_lon(Math.atan2(k,m)+this.long0)}else{var n=a.x-this.x0,o=a.y-this.y0;for(b=(this.ml0+o/this.k0)/this.a,c=b,f=0;!0&&(e=(b+this.e1*Math.sin(2*c)-this.e2*Math.sin(4*c)+this.e3*Math.sin(6*c))/this.e0-c,c+=e,!(Math.abs(e)<=d.EPSLN));f++)if(f>=i)return 95;if(Math.abs(c)=0?this.y0+d.PI*this.R*Math.tan(.5*h):this.y0+d.PI*this.R*-Math.tan(.5*h));var i=.5*Math.abs(d.PI/g-g/d.PI),j=i*i,k=Math.sin(h),l=Math.cos(h),m=l/(k+l-1),n=m*m,o=m*(2/k-1),p=o*o,q=d.PI*this.R*(i*(m-p)+Math.sqrt(j*(m-p)*(m-p)-(p+j)*(n-p)))/(p+j);0>g&&(q=-q),b=this.x0+q;var r=j+m;return q=d.PI*this.R*(o*r-i*Math.sqrt((p+j)*(j+1)-r*r))/(p+j),c=f>=0?this.y0+q:this.y0-q,a.x=b,a.y=c,a},c.inverse=function(a){var b,c,e,f,g,h,i,j,k,l,m,n,o;return a.x-=this.x0,a.y-=this.y0,m=d.PI*this.R,e=a.x/m,f=a.y/m,g=e*e+f*f,h=-Math.abs(f)*(1+g),i=h-2*f*f+e*e,j=-2*h+1+2*f*f+g*g,o=f*f/j+(2*i*i*i/j/j/j-9*h*i/j/j)/27,k=(h-i*i/3/j)/j,l=2*Math.sqrt(-k/3),m=3*o/k/l,Math.abs(m)>1&&(m=m>=0?1:-1),n=Math.acos(m)/3,c=a.y>=0?(-l*Math.cos(n+d.PI/3)-i/3/j)*d.PI:-(-l*Math.cos(n+d.PI/3)-i/3/j)*d.PI,b=Math.abs(e)-1?(b[e]={name:a[0].toLowerCase(),convert:a[1]},3===a.length&&(b[e].auth=a[2])):"SPHEROID"===e?(b[e]={name:a[0],a:a[1],rf:a[2]},4===a.length&&(b[e].auth=a[3])):["GEOGCS","GEOCCS","DATUM","VERT_CS","COMPD_CS","LOCAL_CS","FITTED_CS","LOCAL_DATUM"].indexOf(e)>-1?(a[0]=["name",a[0]],c(b,e,a)):a.every(function(a){return Array.isArray(a)})?c(b,e,a):d(a,b[e])):b[e]=!0,void 0):(b[a]=!0,void 0)}function e(a,b){var c=b[0],d=b[1];!(c in a)&&d in a&&(a[c]=a[d],3===b.length&&(a[c]=b[2](a[c])))}function f(a){return a*h.D2R}function g(a){function b(b){var c=a.to_meter||1;return parseFloat(b,10)*c}"GEOGCS"===a.type?a.projName="longlat":"LOCAL_CS"===a.type?(a.projName="identity",a.local=!0):a.projName="object"==typeof a.PROJECTION?Object.keys(a.PROJECTION)[0]:a.PROJECTION,a.UNIT&&(a.units=a.UNIT.name.toLowerCase(),"metre"===a.units&&(a.units="meter"),a.UNIT.convert&&(a.to_meter=parseFloat(a.UNIT.convert,10))),a.GEOGCS&&(a.datumCode=a.GEOGCS.DATUM?a.GEOGCS.DATUM.name.toLowerCase():a.GEOGCS.name.toLowerCase(),"d_"===a.datumCode.slice(0,2)&&(a.datumCode=a.datumCode.slice(2)),("new_zealand_geodetic_datum_1949"===a.datumCode||"new_zealand_1949"===a.datumCode)&&(a.datumCode="nzgd49"),"wgs_1984"===a.datumCode&&("Mercator_Auxiliary_Sphere"===a.PROJECTION&&(a.sphere=!0),a.datumCode="wgs84"),"_ferro"===a.datumCode.slice(-6)&&(a.datumCode=a.datumCode.slice(0,-6)),"_jakarta"===a.datumCode.slice(-8)&&(a.datumCode=a.datumCode.slice(0,-8)),a.GEOGCS.DATUM&&a.GEOGCS.DATUM.SPHEROID&&(a.ellps=a.GEOGCS.DATUM.SPHEROID.name.replace("_19","").replace(/[Cc]larke\_18/,"clrk"),"international"===a.ellps.toLowerCase().slice(0,13)&&(a.ellps="intl"),a.a=a.GEOGCS.DATUM.SPHEROID.a,a.rf=parseFloat(a.GEOGCS.DATUM.SPHEROID.rf,10))),a.b&&!isFinite(a.b)&&(a.b=a.a);var c=function(b){return e(a,b)},d=[["standard_parallel_1","Standard_Parallel_1"],["standard_parallel_2","Standard_Parallel_2"],["false_easting","False_Easting"],["false_northing","False_Northing"],["central_meridian","Central_Meridian"],["latitude_of_origin","Latitude_Of_Origin"],["scale_factor","Scale_Factor"],["k0","scale_factor"],["latitude_of_center","Latitude_of_center"],["lat0","latitude_of_center",f],["longitude_of_center","Longitude_Of_Center"],["longc","longitude_of_center",f],["x0","false_easting",b],["y0","false_northing",b],["long0","central_meridian",f],["lat0","latitude_of_origin",f],["lat0","standard_parallel_1",f],["lat1","standard_parallel_1",f],["lat2","standard_parallel_2",f],["alpha","azimuth",f],["srsCode","name"]];d.forEach(c),a.long0||!a.longc||"Albers_Conic_Equal_Area"!==a.PROJECTION&&"Lambert_Azimuthal_Equal_Area"!==a.PROJECTION||(a.long0=a.longc)}var h=a("./common"),i=a("./extend");b.exports=function(a,b){var c=JSON.parse((","+a).replace(/\s*\,\s*([A-Z_0-9]+?)(\[)/g,',["$1",').slice(1).replace(/\s*\,\s*([A-Z_0-9]+?)\]/g,',"$1"]')),e=c.shift(),f=c.shift();c.unshift(["name",f]),c.unshift(["type",e]),c.unshift("output");var h={};return d(c,h),g(h.output),i(b,h.output)}},{"./common":4,"./extend":14}]},{},[16])(16)}); \ No newline at end of file diff --git a/gui-src/js/maps/proj4leaflet.js b/gui-src/js/maps/proj4leaflet.js new file mode 100644 index 0000000..0e559b9 --- /dev/null +++ b/gui-src/js/maps/proj4leaflet.js @@ -0,0 +1,227 @@ +(function (factory) { + var L, proj4; + if (typeof define === 'function' && define.amd) { + // AMD + define(['leaflet', 'proj4'], factory); + } else if (typeof module !== 'undefined') { + // Node/CommonJS + L = require('leaflet'); + proj4 = require('proj4'); + module.exports = factory(L, proj4); + } else { + // Browser globals + if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined') + throw "Leaflet and proj4 must be loaded first"; + factory(window.L, window.proj4); + } +}(function (L, proj4) { + +L.Proj = {}; + +L.Proj._isProj4Obj = function(a) { + return (typeof a['inverse'] !== 'undefined' + && typeof a['forward'] !== 'undefined'); +}; + +L.Proj.ScaleDependantTransformation = function(scaleTransforms) { + this.scaleTransforms = scaleTransforms; + } + +L.Proj.ScaleDependantTransformation.prototype.transform = function(point, scale) { + return this.scaleTransforms[scale].transform(point, scale); +}; + +L.Proj.ScaleDependantTransformation.prototype.untransform = function(point, scale) { + return this.scaleTransforms[scale].untransform(point, scale); +}; + +L.Proj.Projection = L.Class.extend({ + initialize: function(a, def) { + if (L.Proj._isProj4Obj(a)) { + this._proj = a; + } else { + var code = a; + if (def) { + proj4.defs(code, def); + } else if (proj4.defs[code] === undefined) { + var urn = code.split(':'); + if (urn.length > 3) + code = urn[urn.length - 3] + ':' + urn[urn.length - 1]; + if (proj4.defs[code] === undefined) + throw "No projection definition for code " + code; + } + this._proj = proj4(code); + } + }, + + project: function (latlng) { + var point = this._proj.forward([latlng.lng, latlng.lat]); + return new L.Point(point[0], point[1]); + }, + + unproject: function (point, unbounded) { + var point2 = this._proj.inverse([point.x, point.y]); + return new L.LatLng(point2[1], point2[0], unbounded); + } +}); + +L.Proj.CRS = L.Class.extend({ + includes: L.CRS, + + options: { + transformation: new L.Transformation(1, 0, -1, 0) + }, + + initialize: function(a, b, c) { + var code, proj, def, options; + + if (L.Proj._isProj4Obj(a)) { + proj = a; + code = proj.srsCode; + options = b || {}; + + this.projection = new L.Proj.Projection(proj); + } else { + code = a; + def = b; + options = c || {}; + this.projection = new L.Proj.Projection(code, def); + } + + L.Util.setOptions(this, options); + this.code = code; + this.transformation = this.options.transformation; + + if (this.options.origin) { + this.transformation = + new L.Transformation(1, -this.options.origin[0], + -1, this.options.origin[1]); + } + + if (this.options.scales) { + this.scale = function(zoom) { + return this.options.scales[zoom]; + } + } else if (this.options.resolutions) { + this.scale = function(zoom) { + return 1 / this.options.resolutions[zoom]; + } + } + } +}); + +L.Proj.CRS.TMS = L.Proj.CRS.extend({ + initialize: function(a, b, c, d) { + if (L.Proj._isProj4Obj(a)) { + var proj = a, + projectedBounds = b, + options = c || {}; + options.origin = [projectedBounds[0], projectedBounds[3]]; + L.Proj.CRS.prototype.initialize.call(this, proj, options); + } else { + var code = a, + def = b, + projectedBounds = c, + options = d || {}; + options.origin = [projectedBounds[0], projectedBounds[3]]; + L.Proj.CRS.prototype.initialize.call(this, code, def, options); + } + + this.projectedBounds = projectedBounds; + } +}); + +L.Proj.TileLayer = {}; + +L.Proj.TileLayer.TMS = L.TileLayer.extend({ + options: { + tms: true, + continuousWorld: true + }, + + initialize: function(urlTemplate, crs, options) { + var boundsMatchesGrid = true, + scaleTransforms, + upperY, + crsBounds; + + if (!(crs instanceof L.Proj.CRS.TMS)) { + throw new Error("CRS is not L.Proj.CRS.TMS."); + } + + L.TileLayer.prototype.initialize.call(this, urlTemplate, options); + this.crs = crs; + crsBounds = this.crs.projectedBounds; + + // Verify grid alignment + for (var i = this.options.minZoom; i < this.options.maxZoom && boundsMatchesGrid; i++) { + var gridHeight = (crsBounds[3] - crsBounds[1]) / + this._projectedTileSize(i); + boundsMatchesGrid = Math.abs(gridHeight - Math.round(gridHeight)) > 1e-3; + } + + if (!boundsMatchesGrid) { + scaleTransforms = {}; + for (var i = this.options.minZoom; i < this.options.maxZoom; i++) { + upperY = crsBounds[1] + Math.ceil((crsBounds[3] - crsBounds[1]) / + this._projectedTileSize(i)) * this._projectedTileSize(i); + scaleTransforms[this.crs.scale(i)] = new L.Transformation(1, -crsBounds[0], -1, upperY); + } + + this.crs = new L.Proj.CRS.TMS(this.crs.projection._proj, crsBounds, this.crs.options); + this.crs.transformation = new L.Proj.ScaleDependantTransformation(scaleTransforms); + } + }, + + getTileUrl: function(tilePoint, zoom) { + var gridHeight = Math.ceil( + (this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) / + this._projectedTileSize(zoom) + ); + + return L.Util.template(this._url, L.Util.extend({ + s: this._getSubdomain(tilePoint), + z: zoom, + x: tilePoint.x, + y: gridHeight - tilePoint.y - 1 + }, this.options)); + }, + + _projectedTileSize: function(zoom) { + return (this.options.tileSize / this.crs.scale(zoom)); + } +}); + +L.Proj.GeoJSON = L.GeoJSON.extend({ + initialize: function(geojson, options) { + if (geojson.crs && geojson.crs.type == 'name') { + var crs = new L.Proj.CRS(geojson.crs.properties.name) + options = options || {}; + options.coordsToLatLng = function(coords) { + var point = L.point(coords[0], coords[1]); + return crs.projection.unproject(point); + }; + } + L.GeoJSON.prototype.initialize.call(this, geojson, options); + } +}); + +L.Proj.geoJson = function(geojson, options) { + return new L.Proj.GeoJSON(geojson, options); +}; + +if (typeof L.CRS !== 'undefined') { + // This is left here for backwards compatibility + L.CRS.proj4js = (function () { + return function (code, def, transformation, options) { + options = options || {}; + if (transformation) options.transformation = transformation; + + return new L.Proj.CRS(code, def, options); + }; + }()); +} + +return L.Proj; + +})); diff --git a/gui-src/js/maps/test.runner.js b/gui-src/js/maps/test.runner.js new file mode 100644 index 0000000..1c9c044 --- /dev/null +++ b/gui-src/js/maps/test.runner.js @@ -0,0 +1,158 @@ +(function( definition ) { // execute immeidately + + if ( typeof module !== 'undefined' && + typeof module.exports !== 'undefined' ) { + module.exports = definition(); + } + else if ( typeof window === "object" ) { + // example run syntax: BBOX_T( { 'url' : '/js/maps/testdata.js' } ); + window.BBOX_T = definition(); + } + + +})( function() { + 'use strict'; + + /* + ** + ** constructor + ** + */ + var TestRunner = function( options ) { + options || ( options = {} ); + + if( !this || !(this instanceof TestRunner )){ + return new TestRunner( options ); + } + + this.test_url = options.url || ""; + + this.global_setup(); // execute immediately + }; + + /* + ** + ** functions + ** + */ + TestRunner.prototype.global_setup = function() { + + var self = this; // hold ref to instance + + $.ajax({ + 'url' : this.test_url , + 'dataType' : 'json' + }) + .done( function( json_data ) { + self.run_this_mother.call( self, json_data ); + }) + .fail( function( error ) { + console.log( "The test data didn't load: ", error ); + }); + + }; + + TestRunner.prototype.single_setup = function() { + this.get_layer_count(); + }; + + TestRunner.prototype.tear_down = function() { + if( this._draw_delete_handler ){ + this._draw_delete_handler.off('draw:deleted'); + } + }; + + TestRunner.prototype.run_this_mother = function( json_data ) { + for( var key in json_data ){ + console.log( "[ RUNNING ]: test " + json_data[key]['type'] + "->" + "simple=" + json_data[key]['simple'] ); + var data = json_data[key]['data']; + if( json_data[key]['type'] === 'geojson' ) { + data = JSON.stringify( data ); + } + + /* + ** run different tests + ** the context here is jQuery, so change + ** to reference the instance + */ + this.single_setup(); + + this.test_parsing( data, json_data ); + this.test_add2map( json_data ); + this.test_deletable( json_data ); + + this.tear_down(); + } + }; + + TestRunner.prototype.test_deletable = function(identifier){ // TODO: this needs work + var toolbar = null; + // get the right toolbar, depending on attributes + for( var key in drawControl._toolbars ){ + var tbar = drawControl._toolbars[key]; + if ( !(tbar instanceof L.EditToolbar ) ){ + continue; + } + + toolbar = tbar; // set the right one; + } + + // create delete handler that makes sure things are deleted + this._draw_delete_handler = map.on('draw:deleted', function (e) { + try { + e.layers.eachLayer(function (l) { + drawnItems.removeLayer(l); + }); + console.warn( "[ PASSED ]: test_deletable" ); + } + catch ( err ) { + console.error( "[ DELETE TEST FAIL ]: ", err.message, identifier ); + } + }); + + + // loop through this toolbars featureGroup, delete layers + if ( !toolbar._activeMode ) { + toolbar._modes['remove'].button.click(); // enable deletable + } + for( var indx in toolbar.options['featureGroup']._layers ) { + try { + var lyr = toolbar.options['featureGroup']._layers[indx]; + lyr.fire( 'click' ); // triggers delete + } + catch ( err ){ + console.error( "[ DELETE TEST FAIL ]: ", err.message, identifier ); + } + } + // WTF? + $('a[title="Save changes."]')[0].click(); // disable deletable + + }; + + TestRunner.prototype.test_add2map = function(identifier){ + var current_num = Object.keys( map._layers ).length; + if( current_num <= this.num_layers_before_parse ){ + console.error( "[ ADD2MAP TEST FAIL ]: ", identifier ); + } + else { + console.warn( "[ PASSED ]: test_add2map" ); + } + }; + + TestRunner.prototype.get_layer_count = function(){ + this.num_layers_before_parse = Object.keys( map._layers ).length; + }; + + TestRunner.prototype.test_parsing = function( data, identifier ){ + var is_valid = FormatSniffer( { data : data } ).sniff(); + if ( !is_valid ) { + console.error( "[ PARSE TEST FAIL ]: ", identifier ); + } + else { + console.warn( "[ PASSED ]: test_parsing" ); + } + }; + + return TestRunner; // return class def + +}); diff --git a/gui-src/js/maps/wkt.parser.js b/gui-src/js/maps/wkt.parser.js new file mode 100644 index 0000000..cc172af --- /dev/null +++ b/gui-src/js/maps/wkt.parser.js @@ -0,0 +1,549 @@ +/* +** +** taking only necessary pieces from +** https://raw.github.com/arthur-e/Wicket/master/wicket.src.js +** +*/ +var Wkt = (function () { // Execute function immediately + var beginsWith, endsWith; + + /** + * Returns true if the substring is found at the beginning of the string. + * @param str {String} The String to search + * @param sub {String} The substring of interest + * @return {Boolean} + * @private + */ + beginsWith = function (str, sub) { + return str.substring(0, sub.length) === sub; + }; + + /** + * Returns true if the substring is found at the end of the string. + * @param str {String} The String to search + * @param sub {String} The substring of interest + * @return {Boolean} + * @private + */ + endsWith = function (str, sub) { + return str.substring(str.length - sub.length) === sub; + }; + + return { + /** + * The default delimiter for separating components of atomic geometry (coordinates) + * @ignore + */ + delimiter: ' ', + + /** + * Determines whether or not the passed Object is an Array. + * @param obj {Object} The Object in question + * @return {Boolean} + * @member Wkt.isArray + * @method + */ + isArray: function (obj) { + return !!(obj && obj.constructor === Array); + }, + + /** + * Removes given character String(s) from a String. + * @param str {String} The String to search + * @param sub {String} The String character(s) to trim + * @return {String} The trimmed string + * @member Wkt.trim + * @method + */ + trim: function (str, sub) { + sub = sub || ' '; // Defaults to trimming spaces + // Trim beginning spaces + while (beginsWith(str, sub)) { + str = str.substring(1); + } + // Trim ending spaces + while (endsWith(str, sub)) { + str = str.substring(0, str.length - 1); + } + return str; + }, + + /** + * An object for reading WKT strings and writing geographic features + * @constructor Wkt.Wkt + * @param initializer {String} An optional WKT string for immediate read + * @property {Array} components - Holder for atomic geometry objects (internal representation of geometric components) + * @property {String} delimiter - The default delimiter for separating components of atomic geometry (coordinates) + * @property {Object} regExes - Some regular expressions copied from OpenLayers.Format.WKT.js + * @property {String} type - The Well-Known Text name (e.g. 'point') of the geometry + * @property {Boolean} wrapVerticies - True to wrap vertices in MULTIPOINT geometries; If true: MULTIPOINT((30 10),(10 30),(40 40)); If false: MULTIPOINT(30 10,10 30,40 40) + * @return {Wkt.Wkt} + * @memberof Wkt + */ + Wkt: function (initializer) { + + /** + * The default delimiter between X and Y coordinates. + * @ignore + */ + this.delimiter = Wkt.delimiter; + + /** + * Configuration parameter for controlling how Wicket seralizes + * MULTIPOINT strings. Examples; both are valid WKT: + * If true: MULTIPOINT((30 10),(10 30),(40 40)) + * If false: MULTIPOINT(30 10,10 30,40 40) + * @ignore + */ + this.wrapVertices = true; + + /** + * Some regular expressions copied from OpenLayers.Format.WKT.js + * @ignore + */ + this.regExes = { + 'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/, + 'spaces': /\s+|\+/, // Matches the '+' or the empty space + 'numeric': /-*\d+(\.*\d+)?/, + 'comma': /\s*,\s*/, + 'parenComma': /\)\s*,\s*\(/, + 'coord': /-*\d+\.*\d+ -*\d+\.*\d+/, // e.g. "24 -14" + 'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/, + 'trimParens': /^\s*\(?(.*?)\)?\s*$/ + }; + + /** + * The internal representation of geometry--the "components" of geometry. + * @ignore + */ + this.components = undefined; + + // An initial WKT string may be provided + if (initializer && typeof initializer === 'string') { + this.read(initializer); + } else if (initializer && typeof initializer !== undefined) { + this.fromObject(initializer); + } + + } + + }; + +}()); + +/** + * Returns true if the internal geometry is a collection of geometries. + * @return {Boolean} Returns true when it is a collection + * @memberof Wkt.Wkt + * @method + */ +Wkt.Wkt.prototype.isCollection = function () { + switch (this.type.slice(0, 5)) { + case 'multi': + // Trivial; any multi-geometry is a collection + return true; + case 'polyg': + // Polygons with holes are "collections" of rings + return true; + default: + // Any other geometry is not a collection + return false; + } +}; + +/** + * Compares two x,y coordinates for equality. + * @param a {Object} An object with x and y properties + * @param b {Object} An object with x and y properties + * @return {Boolean} + * @memberof Wkt.Wkt + * @method + */ +Wkt.Wkt.prototype.sameCoords = function (a, b) { + return (a.x === b.x && a.y === b.y); +}; + +/** + * Sets internal geometry (components) from framework geometry (e.g. + * Google Polygon objects or google.maps.Polygon). + * @param obj {Object} The framework-dependent geometry representation + * @return {Wkt.Wkt} The object itself + * @memberof Wkt.Wkt + * @method + */ +Wkt.Wkt.prototype.fromObject = function (obj) { + var result = this.deconstruct.call(this, obj); + this.components = result.components; + this.isRectangle = result.isRectangle || false; + this.type = result.type; + return this; +}; + +/** + * Creates external geometry objects based on a plug-in framework's + * construction methods and available geometry classes. + * @param config {Object} An optional framework-dependent properties specification + * @return {Object} The framework-dependent geometry representation + * @memberof Wkt.Wkt + * @method + */ +Wkt.Wkt.prototype.toObject = function (config) { + return this.construct[this.type].call(this, config); +}; + +/** + * Absorbs the geometry of another Wkt.Wkt instance, merging it with its own, + * creating a collection (MULTI-geometry) based on their types, which must agree. + * For example, creates a MULTIPOLYGON from a POLYGON type merged with another +<<<<<<< HEAD + * POLYGON type. +======= + * POLYGON type, or adds a POLYGON instance to a MULTIPOLYGON instance. +>>>>>>> dev + * @memberof Wkt.Wkt + * @method + */ +Wkt.Wkt.prototype.merge = function (wkt) { + var prefix = this.type.slice(0, 5); + + if (this.type !== wkt.type) { + if (this.type.slice(5, this.type.length) !== wkt.type) { + throw TypeError('The input geometry types must agree or the calling Wkt.Wkt instance must be a multigeometry of the other'); + } + } + + switch (prefix) { + + case 'point': + this.components = [this.components.concat(wkt.components)]; + break; + + case 'multi': + this.components = this.components.concat((wkt.type.slice(0, 5) === 'multi') ? wkt.components : [wkt.components]); + break; + + default: + this.components = [ + this.components, + wkt.components + ] + break; + + } + + if (prefix !== 'multi') { + this.type = 'multi' + this.type; + } +}; + +/** + * Reads a WKT string, validating and incorporating it. + * @param wkt {String} A WKT string + * @return {Array} An Array of internal geometry objects + * @memberof Wkt.Wkt + * @method + */ +Wkt.Wkt.prototype.read = function (wkt) { + var matches; + matches = this.regExes.typeStr.exec(wkt); + if (matches) { + this.type = matches[1].toLowerCase(); + this.base = matches[2]; + if (this.ingest[this.type]) { + this.components = this.ingest[this.type].apply(this, [this.base]); + } + } else { + console.log("Invalid WKT string provided to read()"); + throw { + name: "WKTError", + message: "Invalid WKT string provided to read()" + }; + } + return this.components; +}; // eo readWkt + + +/** + * This object contains functions as property names that ingest WKT + * strings into the internal representation. + * @memberof Wkt.Wkt + * @namespace Wkt.Wkt.ingest + * @instance + */ +Wkt.Wkt.prototype.ingest = { + + /** + * Return point feature given a point WKT fragment. + * @param str {String} A WKT fragment representing the point + * @memberof Wkt.Wkt.ingest + * @instance + */ + point: function (str) { + var coords = Wkt.trim(str).split(this.regExes.spaces); + // In case a parenthetical group of coordinates is passed... + return [{ // ...Search for numeric substrings + x: parseFloat(this.regExes.numeric.exec(coords[0])[0]), + y: parseFloat(this.regExes.numeric.exec(coords[1])[0]) + }]; + }, + + /** + * Return a multipoint feature given a multipoint WKT fragment. + * @param str {String} A WKT fragment representing the multipoint + * @memberof Wkt.Wkt.ingest + * @instance + */ + multipoint: function (str) { + var i, components, points; + components = []; + points = Wkt.trim(str).split(this.regExes.comma); + for (i = 0; i < points.length; i += 1) { + components.push(this.ingest.point.apply(this, [points[i]])); + } + return components; + }, + + /** + * Return a linestring feature given a linestring WKT fragment. + * @param str {String} A WKT fragment representing the linestring + * @memberof Wkt.Wkt.ingest + * @instance + */ + linestring: function (str) { + var i, multipoints, components; + + // In our x-and-y representation of components, parsing + // multipoints is the same as parsing linestrings + multipoints = this.ingest.multipoint.apply(this, [str]); + + // However, the points need to be joined + components = []; + for (i = 0; i < multipoints.length; i += 1) { + components = components.concat(multipoints[i]); + } + return components; + }, + + /** + * Return a multilinestring feature given a multilinestring WKT fragment. + * @param str {String} A WKT fragment representing the multilinestring + * @memberof Wkt.Wkt.ingest + * @instance + */ + multilinestring: function (str) { + var i, components, line, lines; + components = []; + + lines = Wkt.trim(str).split(this.regExes.doubleParenComma); + if (lines.length === 1) { // If that didn't work... + lines = Wkt.trim(str).split(this.regExes.parenComma); + } + + for (i = 0; i < lines.length; i += 1) { + line = lines[i].replace(this.regExes.trimParens, '$1'); + components.push(this.ingest.linestring.apply(this, [line])); + } + + return components; + }, + + /** + * Return a polygon feature given a polygon WKT fragment. + * @param str {String} A WKT fragment representing the polygon + * @memberof Wkt.Wkt.ingest + * @instance + */ + polygon: function (str) { + var i, j, components, subcomponents, ring, rings; + rings = Wkt.trim(str).split(this.regExes.parenComma); + components = []; // Holds one or more rings + for (i = 0; i < rings.length; i += 1) { + ring = rings[i].replace(this.regExes.trimParens, '$1').split(this.regExes.comma); + subcomponents = []; // Holds the outer ring and any inner rings (holes) + for (j = 0; j < ring.length; j += 1) { + // Split on the empty space or '+' character (between coordinates) + subcomponents.push({ + x: parseFloat(ring[j].split(this.regExes.spaces)[0]), + y: parseFloat(ring[j].split(this.regExes.spaces)[1]) + }); + } + components.push(subcomponents); + } + return components; + }, + + /** + * Return a multipolygon feature given a multipolygon WKT fragment. + * @param str {String} A WKT fragment representing the multipolygon + * @memberof Wkt.Wkt.ingest + * @instance + */ + multipolygon: function (str) { + var i, components, polygon, polygons; + components = []; + polygons = Wkt.trim(str).split(this.regExes.doubleParenComma); + for (i = 0; i < polygons.length; i += 1) { + polygon = polygons[i].replace(this.regExes.trimParens, '$1'); + components.push(this.ingest.polygon.apply(this, [polygon])); + } + return components; + }, + + /** + * Return an array of features given a geometrycollection WKT fragment. + * @param str {String} A WKT fragment representing the geometry collection + * @memberof Wkt.Wkt.ingest + * @instance + */ + geometrycollection: function (str) { + console.log('The geometrycollection WKT type is not yet supported.'); + } + +}; // eo ingest + +/** + * @augments Wkt.Wkt + * Truncates an Array of coordinates by the closing coordinate when it is + * equal to the first coordinate given--this is only to be used for closed + * geometries in order to provide merely an "implied" closure to Leaflet. + * @param coords {Array} An Array of x,y coordinates (objects) + * @return {Array} + */ +Wkt.Wkt.prototype.trunc = function (coords) { + var i, verts = []; + + for (i = 0; i < coords.length; i += 1) { + if (Wkt.isArray(coords[i])) { + verts.push(this.trunc(coords[i])); + + } else { + + // Add the first coord, but skip the last if it is identical + if (i === 0 || !this.sameCoords(coords[0], coords[i])) { + verts.push(coords[i]); + } + } + } + + return verts; +}; + +/** + * @augments Wkt.Wkt + * An object of framework-dependent construction methods used to generate + * objects belonging to the various geometry classes of the framework. + */ +Wkt.Wkt.prototype.construct = { + /** + * Creates the framework's equivalent point geometry object. + * @param config {Object} An optional properties hash the object should use + * @param component {Object} An optional component to build from + * @return {L.marker} + */ + point: function (config, component) { + var coord = component || this.components; + if (coord instanceof Array) { + coord = coord[0]; + } + + return L.marker(this.coordsToLatLng(coord), config); + }, + + /** + * Creates the framework's equivalent multipoint geometry object. + * @param config {Object} An optional properties hash the object should use + * @return {L.featureGroup} + */ + multipoint: function (config) { + var i, + layers = [], + coords = this.components; + + for (i = 0; i < coords.length; i += 1) { + layers.push(this.construct.point.call(this, config, coords[i])); + } + + return L.featureGroup(layers, config); + }, + + /** + * Creates the framework's equivalent linestring geometry object. + * @param config {Object} An optional properties hash the object should use + * @param component {Object} An optional component to build from + * @return {L.polyline} + */ + linestring: function (config, component) { + var coords = component || this.components, + latlngs = this.coordsToLatLngs(coords); + + return L.polyline(latlngs, config); + }, + + /** + * Creates the framework's equivalent multilinestring geometry object. + * @param config {Object} An optional properties hash the object should use + * @return {L.multiPolyline} + */ + multilinestring: function (config) { + var coords = this.components, + latlngs = this.coordsToLatLngs(coords, 1); + + return L.multiPolyline(latlngs, config); + }, + + /** + * Creates the framework's equivalent polygon geometry object. + * @param config {Object} An optional properties hash the object should use + * @return {L.multiPolygon} + */ + polygon: function (config) { + // Truncate the coordinates to remove the closing coordinate + var coords = this.trunc(this.components), + latlngs = this.coordsToLatLngs(coords, 1); + return L.polygon(latlngs, config); + }, + + /** + * Creates the framework's equivalent multipolygon geometry object. + * @param config {Object} An optional properties hash the object should use + * @return {L.multiPolygon} + */ + multipolygon: function (config) { + // Truncate the coordinates to remove the closing coordinate + var coords = this.trunc(this.components), + latlngs = this.coordsToLatLngs(coords, 2); + + return L.multiPolygon(latlngs, config); + }, + + /** + * Creates the framework's equivalent collection of geometry objects. + * @param config {Object} An optional properties hash the object should use + * @return {L.featureGroup} + */ + geometrycollection: function (config) { + var comps, i, layers; + + comps = this.trunc(this.components); + layers = []; + for (i = 0; i < this.components.length; i += 1) { + layers.push(this.construct[comps[i].type].call(this, comps[i])); + } + + return L.featureGroup(layers, config); + + } +}; + +L.Util.extend(Wkt.Wkt.prototype, { + coordsToLatLngs: L.GeoJSON.coordsToLatLngs, + // TODO Why doesn't the coordsToLatLng function in L.GeoJSON already suffice? + coordsToLatLng: function (coords, reverse) { + var lat = reverse ? coords.x : coords.y, + lng = reverse ? coords.y : coords.x; + + return L.latLng(lat, lng, true); + } +}); + + diff --git a/gui-src/maps.html b/gui-src/maps.html new file mode 100644 index 0000000..ae1ac32 --- /dev/null +++ b/gui-src/maps.html @@ -0,0 +1,60 @@ + + + Map View + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + +
+
+
+
+ BBOX + +
+
+
+
+ BBOX + +
+
+
+
+ + + + + diff --git a/icons/128x128.png b/icons/128x128.png new file mode 100644 index 0000000..f9687fe Binary files /dev/null and b/icons/128x128.png differ diff --git a/icons/128x128@2x.png b/icons/128x128@2x.png new file mode 100644 index 0000000..da19fd0 Binary files /dev/null and b/icons/128x128@2x.png differ diff --git a/icons/32x32.png b/icons/32x32.png new file mode 100644 index 0000000..1d45067 Binary files /dev/null and b/icons/32x32.png differ diff --git a/icons/icon.icns b/icons/icon.icns new file mode 100644 index 0000000..5042644 Binary files /dev/null and b/icons/icon.icns differ diff --git a/icons/icon.ico b/icons/icon.ico new file mode 100644 index 0000000..72318eb Binary files /dev/null and b/icons/icon.ico differ diff --git a/icons/icon.png b/icons/icon.png new file mode 100644 index 0000000..f85c193 Binary files /dev/null and b/icons/icon.png differ diff --git a/src/block_definitions.rs b/src/block_definitions.rs index 7c79826..cb7d1e4 100644 --- a/src/block_definitions.rs +++ b/src/block_definitions.rs @@ -145,31 +145,31 @@ impl Block { pub fn properties(&self) -> Option { match self.id { 105 => Some(Value::Compound({ - let mut map = HashMap::new(); + let mut map: HashMap = HashMap::new(); map.insert("age".to_string(), Value::String("7".to_string())); map })), 106 => Some(Value::Compound({ - let mut map = HashMap::new(); + let mut map: HashMap = HashMap::new(); map.insert("half".to_string(), Value::String("lower".to_string())); map })), 107 => Some(Value::Compound({ - let mut map = HashMap::new(); + let mut map: HashMap = HashMap::new(); map.insert("half".to_string(), Value::String("upper".to_string())); map })), 108 => Some(Value::Compound({ - let mut map = HashMap::new(); + let mut map: HashMap = HashMap::new(); map.insert("age".to_string(), Value::String("7".to_string())); map })), 109 => Some(Value::Compound({ - let mut map = HashMap::new(); + let mut map: HashMap = HashMap::new(); map.insert("age".to_string(), Value::String("7".to_string())); map })), diff --git a/src/colors.rs b/src/colors.rs index 467949f..64a6f84 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -19,29 +19,29 @@ pub fn color_text_to_rgb_tuple(text: &str) -> Option { fn full_hex_color_to_rgb_tuple(text: &str) -> Option { if text.len() != 7 || !text.starts_with("#") - || !text.chars().skip(1).all(|c| c.is_ascii_hexdigit()) + || !text.chars().skip(1).all(|c: char| c.is_ascii_hexdigit()) { return None; } - let r = u8::from_str_radix(&text[1..3], 16).unwrap(); - let g = u8::from_str_radix(&text[3..5], 16).unwrap(); - let b = u8::from_str_radix(&text[5..7], 16).unwrap(); + let r: u8 = u8::from_str_radix(&text[1..3], 16).unwrap(); + let g: u8 = u8::from_str_radix(&text[3..5], 16).unwrap(); + let b: u8 = u8::from_str_radix(&text[5..7], 16).unwrap(); Some((r, g, b)) } fn short_hex_color_to_rgb_tuple(text: &str) -> Option { if text.len() != 4 || !text.starts_with("#") - || text.chars().skip(1).all(|c| c.is_ascii_hexdigit()) + || text.chars().skip(1).all(|c: char| c.is_ascii_hexdigit()) { return None; } - let r = u8::from_str_radix(&text[1..2], 16).unwrap(); - let r = r | r << 4; - let g = u8::from_str_radix(&text[2..3], 16).unwrap(); - let g = g | g << 4; - let b = u8::from_str_radix(&text[3..4], 16).unwrap(); - let b = b | b << 4; + let r: u8 = u8::from_str_radix(&text[1..2], 16).unwrap(); + let r: u8 = r | r << 4; + let g: u8 = u8::from_str_radix(&text[2..3], 16).unwrap(); + let g: u8 = g | g << 4; + let b: u8 = u8::from_str_radix(&text[3..4], 16).unwrap(); + let b: u8 = b | b << 4; Some((r, g, b)) } @@ -78,11 +78,11 @@ fn color_name_to_rgb_tuple(text: &str) -> Option { pub fn rgb_distance(from: &RGBTuple, to: &RGBTuple) -> u32 { // i32 because .pow(2) returns the same data type as self and 255^2 wouldn't fit - let difference = ( + let difference: (i32, i32, i32) = ( from.0 as i32 - to.0 as i32, from.1 as i32 - to.1 as i32, from.2 as i32 - to.2 as i32, ); - let distance = difference.0.pow(2) + difference.1.pow(2) + difference.2.pow(2); + let distance: i32 = difference.0.pow(2) + difference.1.pow(2) + difference.2.pow(2); distance as u32 } diff --git a/src/data_processing.rs b/src/data_processing.rs index 199f6c7..05bb7ee 100644 --- a/src/data_processing.rs +++ b/src/data_processing.rs @@ -1,37 +1,45 @@ use crate::args::Args; -use crate::block_definitions::{BEDROCK, DIRT, GRASS_BLOCK, STONE}; +use crate::block_definitions::{DIRT, GRASS_BLOCK}; use crate::element_processing::*; use crate::osm_parser::ProcessedElement; +use crate::progress::emit_gui_progress_update; use crate::world_editor::WorldEditor; use colored::Colorize; use indicatif::{ProgressBar, ProgressStyle}; -const MIN_Y: i32 = -64; -const MAX_Y: i32 = 256; -const GROUND_LEVEL: i32 = 65; +const GROUND_LEVEL: i32 = -62; pub fn generate_world( elements: Vec, args: &Args, scale_factor_x: f64, scale_factor_z: f64, -) { +) -> Result<(), String> { println!("{} Processing data...", "[3/5]".bold()); + emit_gui_progress_update(10.0, "Processing data..."); let region_dir: String = format!("{}/region", args.path); - let mut editor: WorldEditor = WorldEditor::new(®ion_dir, scale_factor_x, scale_factor_z, args); // Process data - let process_pb: ProgressBar = ProgressBar::new(elements.len() as u64); + let elements_count: usize = elements.len(); + let process_pb: ProgressBar = ProgressBar::new(elements_count as u64); process_pb.set_style(ProgressStyle::default_bar() .template("{spinner:.green} [{elapsed_precise}] [{bar:45.white/black}] {pos}/{len} elements ({eta}) {msg}") .unwrap() .progress_chars("█▓░")); + let progress_increment_prcs: f64 = 50.0 / elements_count as f64; + let mut current_progress_prcs: f64 = 10.0; + let mut last_emitted_progress: f64 = current_progress_prcs; for element in &elements { process_pb.inc(1); + current_progress_prcs += progress_increment_prcs; + if (current_progress_prcs - last_emitted_progress).abs() > 0.25 { + emit_gui_progress_update(current_progress_prcs, ""); + last_emitted_progress = current_progress_prcs; + } if args.debug { process_pb.set_message(format!( @@ -149,6 +157,8 @@ pub fn generate_world( let mut block_counter: u64 = 0; println!("{} Generating ground layer...", "[4/5]".bold()); + emit_gui_progress_update(60.0, "Generating ground layer..."); + let ground_pb: ProgressBar = ProgressBar::new(total_blocks); ground_pb.set_style( ProgressStyle::default_bar() @@ -157,34 +167,26 @@ pub fn generate_world( .progress_chars("█▓░"), ); + let mut gui_progress_grnd: f64 = 60.0; + let mut last_emitted_progress: f64 = gui_progress_grnd; + let total_iterations_grnd: f64 = (scale_factor_x + 1.0) * (scale_factor_z + 1.0); + let progress_increment_grnd: f64 = 30.0 / total_iterations_grnd; + for x in 0..=(scale_factor_x as i32) { for z in 0..=(scale_factor_z as i32) { - // Use the smaller of [current block y, ground level y] - let max_y = (MIN_Y..MAX_Y) - .find(|y| editor.block_at(x, *y, z)) - .unwrap_or(MAX_Y) - .min(GROUND_LEVEL); - - // 1 layer of grass - editor.set_block(GRASS_BLOCK, x, max_y, z, None, None); - - // 3 layers of dirt - for y in (max_y - 3)..max_y { - editor.set_block(DIRT, x, y, z, None, None); - } - - // n - 1 layers of stone - for y in (MIN_Y + 1)..(max_y - 3) { - editor.set_block(STONE, x, y, z, None, None); - } - - // 1 layer of bedrock - editor.set_block(BEDROCK, x, MIN_Y, z, None, None); + editor.set_block(GRASS_BLOCK, x, GROUND_LEVEL, z, None, None); + editor.set_block(DIRT, x, GROUND_LEVEL - 1, z, None, None); block_counter += 1; if block_counter % batch_size == 0 { ground_pb.inc(batch_size); } + + gui_progress_grnd += progress_increment_grnd; + if (gui_progress_grnd - last_emitted_progress).abs() > 0.25 { + emit_gui_progress_update(gui_progress_grnd, ""); + last_emitted_progress = gui_progress_grnd; + } } } @@ -194,5 +196,7 @@ pub fn generate_world( // Save world editor.save(); - println!("{}", "Done! World generation complete.".green().bold()); + emit_gui_progress_update(100.0, "Done! World generation completed."); + println!("{}", "Done! World generation completed.".green().bold()); + Ok(()) } diff --git a/src/element_processing/amenities.rs b/src/element_processing/amenities.rs index 6409380..2b803c7 100644 --- a/src/element_processing/amenities.rs +++ b/src/element_processing/amenities.rs @@ -26,7 +26,10 @@ pub fn generate_amenities( } if let Some(amenity_type) = element.tags().get("amenity") { - let first_node = element.nodes().map(|n| (n.x, n.z)).next(); + let first_node: Option<(i32, i32)> = element + .nodes() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .next(); match amenity_type.as_str() { "waste_disposal" | "waste_basket" => { // Place a cauldron for waste disposal or waste basket @@ -41,10 +44,13 @@ pub fn generate_amenities( } } "bicycle_parking" => { - let ground_block = OAK_PLANKS; - let roof_block = STONE_BLOCK_SLAB; + let ground_block: Block = OAK_PLANKS; + let roof_block: Block = STONE_BLOCK_SLAB; - let polygon_coords: Vec<(i32, i32)> = element.nodes().map(|n| (n.x, n.z)).collect(); + let polygon_coords: Vec<(i32, i32)> = element + .nodes() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .collect(); let floor_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); @@ -55,8 +61,8 @@ pub fn generate_amenities( // Place fences and roof slabs at each corner node directly for node in element.nodes() { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; for y in 1..=4 { editor.set_block(ground_block, x, ground_level, z, None, None); @@ -98,8 +104,8 @@ pub fn generate_amenities( _ => GRAY_CONCRETE, }; for node in element.nodes() { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; if let Some(prev) = previous_node { // Create borders for fountain or parking area diff --git a/src/element_processing/barriers.rs b/src/element_processing/barriers.rs index 4223930..c3cd85c 100644 --- a/src/element_processing/barriers.rs +++ b/src/element_processing/barriers.rs @@ -28,13 +28,13 @@ pub fn generate_barriers(editor: &mut WorldEditor, element: &ProcessedElement, g // Process nodes to create the barrier wall for i in 1..way.nodes.len() { - let prev = &way.nodes[i - 1]; - let x1 = prev.x; - let z1 = prev.z; + let prev: &crate::osm_parser::ProcessedNode = &way.nodes[i - 1]; + let x1: i32 = prev.x; + let z1: i32 = prev.z; - let cur = &way.nodes[i]; - let x2 = cur.x; - let z2 = cur.z; + let cur: &crate::osm_parser::ProcessedNode = &way.nodes[i]; + let x2: i32 = cur.x; + let z2: i32 = cur.z; // Generate the line of coordinates between the two nodes let bresenham_points: Vec<(i32, i32, i32)> = diff --git a/src/element_processing/bridges.rs b/src/element_processing/bridges.rs index 2285f8d..f8a9384 100644 --- a/src/element_processing/bridges.rs +++ b/src/element_processing/bridges.rs @@ -15,27 +15,27 @@ pub fn generate_bridges(editor: &mut WorldEditor, element: &ProcessedWay, ground let total_steps: usize = element .nodes .windows(2) - .map(|nodes| { - let x1 = nodes[0].x; - let z1 = nodes[0].z; - let x2 = nodes[1].x; - let z2 = nodes[1].z; + .map(|nodes: &[crate::osm_parser::ProcessedNode]| { + let x1: i32 = nodes[0].x; + let z1: i32 = nodes[0].z; + let x2: i32 = nodes[1].x; + let z2: i32 = nodes[1].z; bresenham_line(x1, ground_level, z1, x2, ground_level, z2).len() }) .sum(); - let half_steps = total_steps / 2; // Calculate midpoint for descending after rising - let mut current_step = 0; + let half_steps: usize = total_steps / 2; // Calculate midpoint for descending after rising + let mut current_step: usize = 0; for i in 1..element.nodes.len() { - let prev = &element.nodes[i - 1]; - let x1 = prev.x; - let z1 = prev.z; + let prev: &crate::osm_parser::ProcessedNode = &element.nodes[i - 1]; + let x1: i32 = prev.x; + let z1: i32 = prev.z; - let cur = &element.nodes[i]; - let x2 = cur.x; - let z2 = cur.z; + let cur: &crate::osm_parser::ProcessedNode = &element.nodes[i]; + let x2: i32 = cur.x; + let z2: i32 = cur.z; // Generate the line of coordinates between the two nodes let bresenham_points: Vec<(i32, i32, i32)> = diff --git a/src/element_processing/buildings.rs b/src/element_processing/buildings.rs index c8af217..0734e60 100644 --- a/src/element_processing/buildings.rs +++ b/src/element_processing/buildings.rs @@ -24,26 +24,28 @@ pub fn generate_buildings( let variation_index_wall: usize = rng.gen_range(0..building_wall_variations().len()); let variation_index_floor: usize = rng.gen_range(0..building_floor_variations().len()); - let corner_block = building_corner_variations()[variation_index_corner]; - let wall_block = element + let corner_block: Block = building_corner_variations()[variation_index_corner]; + let wall_block: Block = element .tags .get("building:colour") - .and_then(|building_colour| { - color_text_to_rgb_tuple(building_colour) - .map(|rgb| find_nearest_block_in_color_map(&rgb, building_wall_color_map())) + .and_then(|building_colour: &String| { + color_text_to_rgb_tuple(building_colour).map(|rgb: (u8, u8, u8)| { + find_nearest_block_in_color_map(&rgb, building_wall_color_map()) + }) }) .flatten() .unwrap_or_else(|| building_wall_variations()[variation_index_wall]); - let floor_block = element + let floor_block: Block = element .tags .get("roof:colour") - .and_then(|roof_colour| { - color_text_to_rgb_tuple(roof_colour) - .map(|rgb| find_nearest_block_in_color_map(&rgb, building_floor_color_map())) + .and_then(|roof_colour: &String| { + color_text_to_rgb_tuple(roof_colour).map(|rgb: (u8, u8, u8)| { + find_nearest_block_in_color_map(&rgb, building_floor_color_map()) + }) }) .flatten() .unwrap_or_else(|| building_floor_variations()[variation_index_floor]); - let window_block = WHITE_STAINED_GLASS; + let window_block: Block = WHITE_STAINED_GLASS; // Set to store processed flood fill points let mut processed_points: HashSet<(i32, i32)> = HashSet::new(); @@ -84,11 +86,14 @@ pub fn generate_buildings( building_height = 2; if element.tags.contains_key("bicycle_parking") { - let ground_block = OAK_PLANKS; - let roof_block = STONE_BLOCK_SLAB; + let ground_block: Block = OAK_PLANKS; + let roof_block: Block = STONE_BLOCK_SLAB; - let polygon_coords: Vec<(i32, i32)> = - element.nodes.iter().map(|n| (n.x, n.z)).collect(); + let polygon_coords: Vec<(i32, i32)> = element + .nodes + .iter() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .collect(); let floor_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); @@ -99,8 +104,8 @@ pub fn generate_buildings( // Place fences and roof slabs at each corner node directly for node in &element.nodes { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; for y in 1..=4 { editor.set_block(ground_block, x, ground_level, z, None, None); @@ -118,12 +123,12 @@ pub fn generate_buildings( return; } } else if building_type == "roof" { - let roof_height = ground_level + 5; + let roof_height: i32 = ground_level + 5; // Iterate through the nodes to create the roof edges using Bresenham's line algorithm for node in &element.nodes { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; if let Some(prev) = previous_node { let bresenham_points: Vec<(i32, i32, i32)> = @@ -142,8 +147,11 @@ pub fn generate_buildings( } // Use flood-fill to fill the interior of the roof - let polygon_coords: Vec<(i32, i32)> = - element.nodes.iter().map(|node| (node.x, node.z)).collect(); + let polygon_coords: Vec<(i32, i32)> = element + .nodes + .iter() + .map(|node: &crate::osm_parser::ProcessedNode| (node.x, node.z)) + .collect(); let roof_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); // Use flood-fill to determine the area // Fill the interior of the roof with STONE_BRICK_SLAB @@ -171,8 +179,8 @@ pub fn generate_buildings( // Process nodes to create walls and corners for node in &element.nodes { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; if let Some(prev) = previous_node { // Calculate walls and corners using Bresenham line @@ -211,7 +219,11 @@ pub fn generate_buildings( // Flood-fill interior with floor variation if corner_addup != (0, 0, 0) { - let polygon_coords: Vec<(i32, i32)> = element.nodes.iter().map(|n| (n.x, n.z)).collect(); + let polygon_coords: Vec<(i32, i32)> = element + .nodes + .iter() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .collect(); let floor_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); for (x, z) in floor_area { @@ -264,21 +276,21 @@ fn generate_bridge( floodfill_timeout: Option<&Duration>, ) { // Calculate the bridge level - let mut bridge_level = base_level; + let mut bridge_level: i32 = base_level; if let Some(level_str) = element.tags.get("level") { if let Ok(level) = level_str.parse::() { bridge_level += (level * 3) + 1; // Adjust height by levels } } - let floor_block = STONE; - let railing_block = STONE_BRICKS; + let floor_block: Block = STONE; + let railing_block: Block = STONE_BRICKS; // Process the nodes to create bridge pathways and railings let mut previous_node: Option<(i32, i32)> = None; for node in &element.nodes { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; // Create bridge path using Bresenham's line if let Some(prev) = previous_node { @@ -293,7 +305,11 @@ fn generate_bridge( } // Flood fill the area between the bridge path nodes - let polygon_coords: Vec<(i32, i32)> = element.nodes.iter().map(|n| (n.x, n.z)).collect(); + let polygon_coords: Vec<(i32, i32)> = element + .nodes + .iter() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .collect(); let bridge_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); for (x, z) in bridge_area { editor.set_block(floor_block, x, bridge_level, z, None, None); diff --git a/src/element_processing/doors.rs b/src/element_processing/doors.rs index 53ebeeb..1a98f13 100644 --- a/src/element_processing/doors.rs +++ b/src/element_processing/doors.rs @@ -14,8 +14,8 @@ pub fn generate_doors(editor: &mut WorldEditor, element: &ProcessedNode, ground_ } } - let x = element.x; - let z = element.z; + let x: i32 = element.x; + let z: i32 = element.z; // Set the ground block and the door blocks editor.set_block(GRAY_CONCRETE, x, ground_level, z, None, None); diff --git a/src/element_processing/highways.rs b/src/element_processing/highways.rs index 66d10a9..273e65d 100644 --- a/src/element_processing/highways.rs +++ b/src/element_processing/highways.rs @@ -16,8 +16,8 @@ pub fn generate_highways( if highway_type == "street_lamp" { // Handle street lamps if let ProcessedElement::Node(first_node) = element { - let x = first_node.x; - let z = first_node.z; + let x: i32 = first_node.x; + let z: i32 = first_node.z; for y in 1..=4 { editor.set_block(OAK_FENCE, x, ground_level + y, z, None, None); } @@ -28,8 +28,8 @@ pub fn generate_highways( if let Some(crossing_type) = element.tags().get("crossing") { if crossing_type == "traffic_signals" { if let ProcessedElement::Node(node) = element { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; for y in 1..=3 { editor.set_block(COBBLESTONE_WALL, x, ground_level + y, z, None, None); } @@ -43,8 +43,8 @@ pub fn generate_highways( } else if highway_type == "bus_stop" { // Handle bus stops if let ProcessedElement::Node(node) = element { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; for y in 1..=3 { editor.set_block(COBBLESTONE_WALL, x, ground_level + y, z, None, None); } @@ -52,13 +52,17 @@ pub fn generate_highways( editor.set_block(WHITE_WOOL, x, ground_level + 4, z, None, None); editor.set_block(WHITE_WOOL, x + 1, ground_level + 4, z, None, None); } - } else if element.tags().get("area").map_or(false, |v| v == "yes") { + } else if element + .tags() + .get("area") + .map_or(false, |v: &String| v == "yes") + { let ProcessedElement::Way(way) = element else { return; }; // Handle areas like pedestrian plazas - let mut surface_block = STONE; // Default block + let mut surface_block: Block = STONE; // Default block // Determine the block type based on the 'surface' tag if let Some(surface) = element.tags().get("surface") { @@ -77,8 +81,12 @@ pub fn generate_highways( } // Fill the area using flood fill or by iterating through the nodes - let polygon_coords: Vec<(i32, i32)> = way.nodes.iter().map(|n| (n.x, n.z)).collect(); - let filled_area = flood_fill_area(&polygon_coords, floodfill_timeout); + let polygon_coords: Vec<(i32, i32)> = way + .nodes + .iter() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .collect(); + let filled_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); for (x, z) in filled_area { editor.set_block(surface_block, x, ground_level, z, None, None); @@ -144,17 +152,17 @@ pub fn generate_highways( for node in &way.nodes { if let Some(prev) = previous_node { let (x1, z1) = prev; - let x2 = node.x; - let z2 = node.z; + let x2: i32 = node.x; + let z2: i32 = node.z; // Generate the line of coordinates between the two nodes let bresenham_points: Vec<(i32, i32, i32)> = bresenham_line(x1, ground_level, z1, x2, ground_level, z2); // Variables to manage dashed line pattern - let mut stripe_length = 0; - let dash_length = 5; // Length of the solid part of the stripe - let gap_length = 5; // Length of the gap part of the stripe + let mut stripe_length: i32 = 0; + let dash_length: i32 = 5; // Length of the solid part of the stripe + let gap_length: i32 = 5; // Length of the gap part of the stripe for (x, _, z) in bresenham_points { // Draw the road surface for the entire width @@ -253,11 +261,11 @@ pub fn generate_highways( /// Generates a siding using stone brick slabs pub fn generate_siding(editor: &mut WorldEditor, element: &ProcessedWay, ground_level: i32) { let mut previous_node: Option<(i32, i32)> = None; - let siding_block = STONE_BRICK_SLAB; + let siding_block: Block = STONE_BRICK_SLAB; for node in &element.nodes { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; // Draw the siding using Bresenham's line algorithm between nodes if let Some(prev) = previous_node { diff --git a/src/element_processing/landuse.rs b/src/element_processing/landuse.rs index 131a376..25da3ba 100644 --- a/src/element_processing/landuse.rs +++ b/src/element_processing/landuse.rs @@ -41,8 +41,8 @@ pub fn generate_landuse( // Process landuse nodes to fill the area for node in &element.nodes { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; if let Some(prev) = previous_node { // Generate the line of coordinates between the two nodes @@ -166,7 +166,7 @@ pub fn generate_landuse( if random_choice == 20 { create_tree(editor, x, ground_level + 1, z, rng.gen_range(1..=3)); } else if random_choice == 2 { - let flower_block = match rng.gen_range(1..=4) { + let flower_block: Block = match rng.gen_range(1..=4) { 1 => RED_FLOWER, 2 => BLUE_FLOWER, 3 => YELLOW_FLOWER, @@ -198,7 +198,7 @@ pub fn generate_landuse( // If a random condition is met, place a special object if rng.gen_range(0..76) == 0 { - let special_choice = rng.gen_range(1..=10); + let special_choice: i32 = rng.gen_range(1..=10); if special_choice <= 2 { create_tree( editor, @@ -271,7 +271,7 @@ pub fn generate_landuse( ); } } else if random_choice < 30 { - let construction_items = [ + let construction_items: [Block; 11] = [ OAK_LOG, COBBLESTONE, GRAVEL, diff --git a/src/element_processing/leisure.rs b/src/element_processing/leisure.rs index f901689..2890507 100644 --- a/src/element_processing/leisure.rs +++ b/src/element_processing/leisure.rs @@ -20,7 +20,7 @@ pub fn generate_leisure( let mut current_leisure: Vec<(i32, i32)> = vec![]; // Determine block type based on leisure type - let block_type = match leisure_type.as_str() { + let block_type: Block = match leisure_type.as_str() { "park" => GRASS_BLOCK, "playground" | "recreation_ground" | "pitch" => { if let Some(surface) = element.tags.get("surface") { @@ -73,8 +73,11 @@ pub fn generate_leisure( // Flood-fill the interior of the leisure area if corner_addup != (0, 0, 0) { - let polygon_coords: Vec<(i32, i32)> = - element.nodes.iter().map(|n| (n.x, n.z)).collect(); + let polygon_coords: Vec<(i32, i32)> = element + .nodes + .iter() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .collect(); let filled_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); for (x, z) in filled_area { diff --git a/src/element_processing/natural.rs b/src/element_processing/natural.rs index bd72634..d1510aa 100644 --- a/src/element_processing/natural.rs +++ b/src/element_processing/natural.rs @@ -17,8 +17,8 @@ pub fn generate_natural( if let Some(natural_type) = element.tags().get("natural") { if natural_type == "tree" { if let ProcessedElement::Node(node) = element { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; let mut rng: rand::prelude::ThreadRng = rand::thread_rng(); create_tree(editor, x, ground_level + 1, z, rng.gen_range(1..=3)); @@ -29,7 +29,7 @@ pub fn generate_natural( let mut current_natural: Vec<(i32, i32)> = vec![]; // Determine block type based on natural tag - let block_type = match natural_type.as_str() { + let block_type: Block = match natural_type.as_str() { "scrub" | "grassland" | "wood" => GRASS_BLOCK, "beach" | "sand" => SAND, "tree_row" => GRASS_BLOCK, @@ -43,8 +43,8 @@ pub fn generate_natural( // Process natural nodes to fill the area for node in &way.nodes { - let x = node.x; - let z = node.z; + let x: i32 = node.x; + let z: i32 = node.z; if let Some(prev) = previous_node { // Generate the line of coordinates between the two nodes @@ -63,8 +63,11 @@ pub fn generate_natural( // If there are natural nodes, flood-fill the area if corner_addup != (0, 0, 0) { - let polygon_coords: Vec<(i32, i32)> = - way.nodes.iter().map(|n| (n.x, n.z)).collect(); + let polygon_coords: Vec<(i32, i32)> = way + .nodes + .iter() + .map(|n: &crate::osm_parser::ProcessedNode| (n.x, n.z)) + .collect(); let filled_area: Vec<(i32, i32)> = flood_fill_area(&polygon_coords, floodfill_timeout); diff --git a/src/element_processing/railways.rs b/src/element_processing/railways.rs index 4cdf5c9..a38615b 100644 --- a/src/element_processing/railways.rs +++ b/src/element_processing/railways.rs @@ -22,13 +22,13 @@ pub fn generate_railways(editor: &mut WorldEditor, element: &ProcessedWay, groun } for i in 1..element.nodes.len() { - let prev = &element.nodes[i - 1]; - let x1 = prev.x; - let z1 = prev.z; + let prev: &crate::osm_parser::ProcessedNode = &element.nodes[i - 1]; + let x1: i32 = prev.x; + let z1: i32 = prev.z; - let cur = &element.nodes[i]; - let x2 = cur.x; - let z2 = cur.z; + let cur: &crate::osm_parser::ProcessedNode = &element.nodes[i]; + let x2: i32 = cur.x; + let z2: i32 = cur.z; // Generate the line of coordinates between the two nodes let bresenham_points: Vec<(i32, i32, i32)> = diff --git a/src/element_processing/tourisms.rs b/src/element_processing/tourisms.rs index 408637f..2bc71fe 100644 --- a/src/element_processing/tourisms.rs +++ b/src/element_processing/tourisms.rs @@ -17,11 +17,11 @@ pub fn generate_tourisms(editor: &mut WorldEditor, element: &ProcessedNode, grou } if let Some(tourism_type) = element.tags.get("tourism") { - let x = element.x; - let z = element.z; + let x: i32 = element.x; + let z: i32 = element.z; if tourism_type == "information" { - if let Some("board") = element.tags.get("information").map(|x| x.as_str()) { + if let Some("board") = element.tags.get("information").map(|x: &String| x.as_str()) { // TODO draw a sign editor.set_block(OAK_PLANKS, x, ground_level + 1, z, None, None); } diff --git a/src/element_processing/tree.rs b/src/element_processing/tree.rs index adeece9..bab2534 100644 --- a/src/element_processing/tree.rs +++ b/src/element_processing/tree.rs @@ -47,7 +47,7 @@ fn round3(editor: &mut WorldEditor, material: Block, x: i32, y: i32, z: i32) { /// Function to create different types of trees. pub fn create_tree(editor: &mut WorldEditor, x: i32, y: i32, z: i32, typetree: u8) { - let mut blacklist = Vec::new(); + let mut blacklist: Vec = Vec::new(); blacklist.extend(building_corner_variations()); blacklist.extend(building_wall_variations()); blacklist.extend(building_floor_variations()); diff --git a/src/element_processing/water_areas.rs b/src/element_processing/water_areas.rs index bac8a36..fc026a6 100644 --- a/src/element_processing/water_areas.rs +++ b/src/element_processing/water_areas.rs @@ -22,8 +22,8 @@ pub fn generate_water_areas( } } - let mut outers = vec![]; - let mut inners = vec![]; + let mut outers: Vec> = vec![]; + let mut inners: Vec> = vec![]; for mem in &element.members { match mem.role { @@ -43,13 +43,21 @@ pub fn generate_water_areas( } let (max_x, max_z) = editor.get_max_coords(); - let outers = outers + let outers: Vec> = outers .iter() - .map(|x| x.iter().map(|y| (y.x as f64, y.z as f64)).collect()) + .map(|x: &Vec| { + x.iter() + .map(|y: &ProcessedNode| (y.x as f64, y.z as f64)) + .collect() + }) .collect(); - let inners = inners + let inners: Vec> = inners .iter() - .map(|x| x.iter().map(|y| (y.x as f64, y.z as f64)).collect()) + .map(|x: &Vec| { + x.iter() + .map(|y: &ProcessedNode| (y.x as f64, y.z as f64)) + .collect() + }) .collect(); inverse_floodfill(max_x, max_z, outers, inners, editor, ground_level); @@ -57,8 +65,8 @@ pub fn generate_water_areas( // Merges ways that share nodes into full loops fn merge_loopy_loops(loops: &mut Vec>) { - let mut removed = vec![]; - let mut merged = vec![]; + let mut removed: Vec = vec![]; + let mut merged: Vec> = vec![]; for i in 0..loops.len() { for j in 0..loops.len() { @@ -70,8 +78,8 @@ fn merge_loopy_loops(loops: &mut Vec>) { continue; } - let x = &loops[i]; - let y = &loops[j]; + let x: &Vec = &loops[i]; + let y: &Vec = &loops[j]; // it's looped already if x[0].id == x.last().unwrap().id { @@ -87,7 +95,7 @@ fn merge_loopy_loops(loops: &mut Vec>) { removed.push(i); removed.push(j); - let mut x = x.clone(); + let mut x: Vec = x.clone(); x.reverse(); x.extend(y.iter().skip(1).cloned()); merged.push(x); @@ -95,7 +103,7 @@ fn merge_loopy_loops(loops: &mut Vec>) { removed.push(i); removed.push(j); - let mut x = x.clone(); + let mut x: Vec = x.clone(); x.extend(y.iter().rev().skip(1).cloned()); merged.push(x); @@ -103,7 +111,7 @@ fn merge_loopy_loops(loops: &mut Vec>) { removed.push(i); removed.push(j); - let mut y = y.clone(); + let mut y: Vec = y.clone(); y.extend(x.iter().skip(1).cloned()); merged.push(y); @@ -117,7 +125,7 @@ fn merge_loopy_loops(loops: &mut Vec>) { loops.remove(*r); } - let merged_len = merged.len(); + let merged_len: usize = merged.len(); for m in merged { loops.push(m); } @@ -128,7 +136,7 @@ fn merge_loopy_loops(loops: &mut Vec>) { } fn verify_loopy_loops(loops: &[Vec]) -> bool { - let mut valid = true; + let mut valid: bool = true; for l in loops { if l[0].id != l.last().unwrap().id { eprintln!("WARN: Disconnected loop"); @@ -150,17 +158,17 @@ fn inverse_floodfill( editor: &mut WorldEditor, ground_level: i32, ) { - let min_x = 0; - let min_z = 0; + let min_x: i32 = 0; + let min_z: i32 = 0; let inners: Vec<_> = inners .into_iter() - .map(|x| Polygon::new(LineString::from(x), vec![])) + .map(|x: Vec<(f64, f64)>| Polygon::new(LineString::from(x), vec![])) .collect(); let outers: Vec<_> = outers .into_iter() - .map(|x| Polygon::new(LineString::from(x), vec![])) + .map(|x: Vec<(f64, f64)>| Polygon::new(LineString::from(x), vec![])) .collect(); inverse_floodfill_recursive( @@ -193,9 +201,9 @@ fn inverse_floodfill_recursive( return; } - let center_x = (min.0 + max.0) / 2; - let center_z = (min.1 + max.1) / 2; - let quadrants = [ + let center_x: i32 = (min.0 + max.0) / 2; + let center_z: i32 = (min.1 + max.1) / 2; + let quadrants: [(i32, i32, i32, i32); 4] = [ (min.0, center_x, min.1, center_z), (center_x, max.0, min.1, center_z), (min.0, center_x, center_z, max.1), @@ -203,13 +211,13 @@ fn inverse_floodfill_recursive( ]; for (min_x, max_x, min_z, max_z) in quadrants { - let rect = Rect::new( + let rect: Rect = Rect::new( Point::new(min_x as f64, min_z as f64), Point::new(max_x as f64, max_z as f64), ); - if outers.iter().any(|outer| outer.contains(&rect)) - && !inners.iter().any(|inner| inner.intersects(&rect)) + if outers.iter().any(|outer: &Polygon| outer.contains(&rect)) + && !inners.iter().any(|inner: &Polygon| inner.intersects(&rect)) { // every block in rect is water // so we can safely just set the whole thing to water @@ -223,7 +231,7 @@ fn inverse_floodfill_recursive( // This saves on processing time let outers_intersects: Vec<_> = outers .iter() - .filter(|poly| poly.intersects(&rect)) + .filter(|poly: &&Polygon| poly.intersects(&rect)) .cloned() .collect(); @@ -231,7 +239,7 @@ fn inverse_floodfill_recursive( // I assume it changes how the compiler is able to optimize it let inners_intersects: Vec<_> = inners .iter() - .filter(|poly| poly.intersects(&rect)) + .filter(|poly: &&Polygon| poly.intersects(&rect)) .cloned() .collect(); @@ -261,10 +269,10 @@ fn inverse_floodfill_iterative( ) { for x in min.0..max.0 { for z in min.1..max.1 { - let p = Point::new(x as f64, z as f64); + let p: Point = Point::new(x as f64, z as f64); - if outers.iter().any(|poly| poly.contains(&p)) - && inners.iter().all(|poly| !poly.contains(&p)) + if outers.iter().any(|poly: &Polygon| poly.contains(&p)) + && inners.iter().all(|poly: &Polygon| !poly.contains(&p)) { editor.set_block(WATER, x, ground_level, z, None, None); } diff --git a/src/floodfill.rs b/src/floodfill.rs index b159282..da66681 100644 --- a/src/floodfill.rs +++ b/src/floodfill.rs @@ -13,7 +13,7 @@ pub fn flood_fill_area( return vec![]; // Not a valid polygon } - let start_time = Instant::now(); + let start_time: Instant = Instant::now(); // Calculate bounding box of the polygon using itertools let (min_x, max_x) = polygon_coords @@ -41,8 +41,8 @@ pub fn flood_fill_area( let polygon: Polygon = Polygon::new(exterior, vec![]); // Create Polygon using LineString // Determine safe step sizes for grid sampling - let step_x = ((max_x - min_x) / 10).max(1); // Ensure step is at least 1 - let step_z = ((max_z - min_z) / 10).max(1); // Ensure step is at least 1 + let step_x: i32 = ((max_x - min_x) / 10).max(1); // Ensure step is at least 1 + let step_z: i32 = ((max_z - min_z) / 10).max(1); // Ensure step is at least 1 // Sample multiple starting points within the bounding box let mut candidate_points: VecDeque<(i32, i32)> = VecDeque::new(); diff --git a/src/main.rs b/src/main.rs index f793459..4a6ddd6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + mod args; mod block_definitions; mod bresenham; @@ -6,6 +8,7 @@ mod data_processing; mod element_processing; mod floodfill; mod osm_parser; +mod progress; mod retrieve_data; mod version_check; mod world_editor; @@ -13,8 +16,10 @@ mod world_editor; use args::Args; use clap::Parser; use colored::*; +use rfd::FileDialog; use std::fs::File; use std::io::Write; +use std::{env, path::PathBuf}; fn print_banner() { let version: &str = env!("CARGO_PKG_VERSION"); @@ -40,58 +45,211 @@ fn print_banner() { } fn main() { - print_banner(); + // Parse arguments to decide whether to launch the UI or CLI + let raw_args: Vec = std::env::args().collect(); - // Check for updates - if let Err(e) = version_check::check_for_updates() { - eprintln!( - "{}: {}", - "Error checking for version updates".red().bold(), - e - ); + // Check if either `--help` or `--path` is present to run command-line mode + let is_help: bool = raw_args.iter().any(|arg: &String| arg == "--help"); + let is_path_provided: bool = raw_args + .iter() + .any(|arg: &String| arg.starts_with("--path")); + + if is_help || is_path_provided { + print_banner(); + + // Check for updates + if let Err(e) = version_check::check_for_updates() { + eprintln!( + "{}: {}", + "Error checking for version updates".red().bold(), + e + ); + } + + // Parse input arguments + let args: Args = Args::parse(); + args.run(); + + let bbox: Vec = args + .bbox + .as_ref() + .expect("Bounding box is required") + .split(',') + .map(|s: &str| s.parse::().expect("Invalid bbox coordinate")) + .collect::>(); + + let bbox_tuple: (f64, f64, f64, f64) = (bbox[0], bbox[1], bbox[2], bbox[3]); + + // Fetch data + let raw_data: serde_json::Value = + retrieve_data::fetch_data(bbox_tuple, args.file.as_deref(), args.debug, "requests") + .expect("Failed to fetch data"); + + // Parse raw data + let (mut parsed_elements, scale_factor_x, scale_factor_z) = + osm_parser::parse_osm_data(&raw_data, bbox_tuple, &args); + parsed_elements.sort_by_key(|element: &osm_parser::ProcessedElement| { + osm_parser::get_priority(element) + }); + + // Write the parsed OSM data to a file for inspection + if args.debug { + let mut output_file: File = + File::create("parsed_osm_data.txt").expect("Failed to create output file"); + for element in &parsed_elements { + writeln!( + output_file, + "Element ID: {}, Type: {}, Tags: {:?}", + element.id(), + element.kind(), + element.tags(), + ) + .expect("Failed to write to output file"); + } + } + + // Generate world + let _ = + data_processing::generate_world(parsed_elements, &args, scale_factor_x, scale_factor_z); + } else { + // Launch the UI + println!("Launching UI..."); + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![ + gui_pick_directory, + gui_start_generation, + gui_get_version, + gui_check_for_updates + ]) + .setup(|app| { + let app_handle = app.handle(); + let main_window = tauri::Manager::get_webview_window(app_handle, "main") + .expect("Failed to get main window"); + progress::set_main_window(main_window); + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("Error while starting the application UI (Tauri)"); } +} - // Parse input arguments - let args: Args = Args::parse(); - args.run(); +#[tauri::command] +fn gui_pick_directory() -> Result { + // Determine the default Minecraft 'saves' directory based on the OS + let default_dir: Option = if cfg!(target_os = "windows") { + env::var("APPDATA") + .ok() + .map(|appdata: String| PathBuf::from(appdata).join(".minecraft").join("saves")) + } else if cfg!(target_os = "macos") { + dirs::home_dir().map(|home: PathBuf| { + home.join("Library/Application Support/minecraft") + .join("saves") + }) + } else if cfg!(target_os = "linux") { + dirs::home_dir().map(|home: PathBuf| home.join(".minecraft").join("saves")) + } else { + None + }; - let bbox: Vec = args - .bbox - .as_ref() - .expect("Bounding box is required") - .split(',') - .map(|s: &str| s.parse::().expect("Invalid bbox coordinate")) - .collect::>(); + // Check if the default directory exists + let starting_directory: Option = default_dir.filter(|dir: &PathBuf| dir.exists()); - let bbox_tuple: (f64, f64, f64, f64) = (bbox[0], bbox[1], bbox[2], bbox[3]); + // Open the directory picker dialog + let dialog: FileDialog = FileDialog::new(); + let dialog: FileDialog = if let Some(start_dir) = starting_directory { + dialog.set_directory(start_dir) + } else { + dialog + }; - // Fetch data - let raw_data: serde_json::Value = - retrieve_data::fetch_data(bbox_tuple, args.file.as_deref(), args.debug, "requests") - .expect("Failed to fetch data"); + if let Some(path) = dialog.pick_folder() { + // Print the full path to the console + println!("Selected world path: {}", path.display()); - // Parse raw data - let (mut parsed_elements, scale_factor_x, scale_factor_z) = - osm_parser::parse_osm_data(&raw_data, bbox_tuple, &args); - parsed_elements - .sort_by_key(|element: &osm_parser::ProcessedElement| osm_parser::get_priority(element)); - - // Write the parsed OSM data to a file for inspection - if args.debug { - let mut output_file: File = - File::create("parsed_osm_data.txt").expect("Failed to create output file"); - for element in &parsed_elements { - writeln!( - output_file, - "Element ID: {}, Type: {}, Tags: {:?}", - element.id(), - element.kind(), - element.tags(), - ) - .expect("Failed to write to output file"); + // Check if the "region" folder exists within the selected directory + if path.join("region").exists() { + return Ok(path.display().to_string()); + } else { + // Notify the frontend that no valid Minecraft world was found + return Err("Invalid Minecraft world".to_string()); } } - // Generate world - data_processing::generate_world(parsed_elements, &args, scale_factor_x, scale_factor_z); + // If no folder was selected, return an error message + Err("No world selected".to_string()) +} + +#[tauri::command] +fn gui_get_version() -> String { + env!("CARGO_PKG_VERSION").to_string() +} + +#[tauri::command] +fn gui_check_for_updates() -> Result { + match version_check::check_for_updates() { + Ok(is_newer) => Ok(is_newer), + Err(e) => Err(format!("Error checking for updates: {}", e)), + } +} + +#[tauri::command] +fn gui_start_generation(bbox_text: String, selected_world: String) -> Result<(), String> { + tauri::async_runtime::spawn(async move { + if let Err(e) = tokio::task::spawn_blocking(move || { + // Utility function to reorder bounding box coordinates + fn reorder_bbox(bbox: &[f64]) -> (f64, f64, f64, f64) { + (bbox[1], bbox[0], bbox[3], bbox[2]) + } + + // Parse bounding box string and validate it + let bbox: Vec = bbox_text + .split_whitespace() + .map(|s| s.parse::().expect("Invalid bbox coordinate")) + .collect(); + + if bbox.len() != 4 { + return Err("Invalid bounding box format".to_string()); + } + + // Create an Args instance with the chosen bounding box and world directory path + let args: Args = Args { + bbox: Some(bbox_text), + file: None, + path: selected_world, + downloader: "requests".to_string(), + scale: 1.0, + debug: false, + timeout: None, + }; + + // Reorder bounding box coordinates for further processing + let reordered_bbox: (f64, f64, f64, f64) = reorder_bbox(&bbox); + + // Run data fetch and world generation + match retrieve_data::fetch_data(reordered_bbox, None, args.debug, "requests") { + Ok(raw_data) => { + let (mut parsed_elements, scale_factor_x, scale_factor_z) = + osm_parser::parse_osm_data(&raw_data, reordered_bbox, &args); + parsed_elements.sort_by_key(|element: &osm_parser::ProcessedElement| { + osm_parser::get_priority(element) + }); + + let _ = data_processing::generate_world( + parsed_elements, + &args, + scale_factor_x, + scale_factor_z, + ); + Ok(()) + } + Err(e) => Err(format!("Failed to start generation: {}", e)), + } + }) + .await + { + eprintln!("Error in blocking task: {}", e); + } + }); + + Ok(()) } diff --git a/src/osm_parser.rs b/src/osm_parser.rs index 6e9b146..14309c6 100644 --- a/src/osm_parser.rs +++ b/src/osm_parser.rs @@ -1,4 +1,4 @@ -use crate::args::Args; +use crate::{args::Args, progress::emit_gui_progress_update}; use colored::Colorize; use serde::Deserialize; use serde_json::Value; @@ -39,7 +39,7 @@ pub struct ProcessedNode { pub id: u64, pub tags: HashMap, - // minecraft coords + // Minecraft coordinates pub x: i32, pub z: i32, } @@ -138,6 +138,7 @@ pub fn parse_osm_data( args: &Args, ) -> (Vec, f64, f64) { println!("{} Parsing data...", "[2/5]".bold()); + emit_gui_progress_update(5.0, "Parsing data..."); // Deserialize the JSON data into the OSMData structure let data: OsmData = @@ -145,16 +146,16 @@ pub fn parse_osm_data( // Determine which dimension is larger and assign scale factors accordingly let (scale_factor_z, scale_factor_x) = geo_distance(bbox.1, bbox.3, bbox.0, bbox.2); - let scale_factor_z = scale_factor_z.floor() * args.scale; - let scale_factor_x = scale_factor_x.floor() * args.scale; + let scale_factor_z: f64 = scale_factor_z.floor() * args.scale; + let scale_factor_x: f64 = scale_factor_x.floor() * args.scale; if args.debug { println!("Scale factor X: {}", scale_factor_x); println!("Scale factor Z: {}", scale_factor_z); } - let mut nodes_map = HashMap::new(); - let mut ways_map = HashMap::new(); + let mut nodes_map: HashMap = HashMap::new(); + let mut ways_map: HashMap = HashMap::new(); let mut processed_elements: Vec = Vec::new(); @@ -165,7 +166,7 @@ pub fn parse_osm_data( let (x, z) = lat_lon_to_minecraft_coords(lat, lon, bbox, scale_factor_z, scale_factor_x); - let processed = ProcessedNode { + let processed: ProcessedNode = ProcessedNode { id: element.id, tags: element.tags.clone().unwrap_or_default(), x, @@ -190,7 +191,7 @@ pub fn parse_osm_data( continue; } - let mut nodes = vec![]; + let mut nodes: Vec = vec![]; if let Some(node_ids) = &element.nodes { for &node_id in node_ids { if let Some(node) = nodes_map.get(&node_id) { @@ -199,7 +200,7 @@ pub fn parse_osm_data( } } - let processed = ProcessedWay { + let processed: ProcessedWay = ProcessedWay { id: element.id, tags: element.tags.clone().unwrap_or_default(), nodes, @@ -223,14 +224,14 @@ pub fn parse_osm_data( }; // Only process multipolygons for now - if tags.get("type").map(|x| x.as_str()) != Some("multipolygon") { + if tags.get("type").map(|x: &String| x.as_str()) != Some("multipolygon") { continue; }; - let members = element + let members: Vec = element .members .iter() - .filter_map(|mem| { + .filter_map(|mem: &OsmMember| { if mem.r#type != "way" { eprintln!("WARN: Unknown relation type {}", mem.r#type); return None; @@ -247,7 +248,7 @@ pub fn parse_osm_data( } }; - let way = ways_map + let way: ProcessedWay = ways_map .get(&mem.r#ref) .expect("Missing a way referenced by a rel") .clone(); @@ -263,6 +264,8 @@ pub fn parse_osm_data( })); } + emit_gui_progress_update(10.0, ""); + (processed_elements, scale_factor_x, scale_factor_z) } @@ -284,10 +287,10 @@ pub fn get_priority(element: &ProcessedElement) -> usize { // (lat meters, lon meters) fn geo_distance(lat1: f64, lat2: f64, lon1: f64, lon2: f64) -> (f64, f64) { - let z = lat_distance(lat1, lat2); + let z: f64 = lat_distance(lat1, lat2); // distance between two lons depends on their latitude. In this case we'll just average them - let x = lon_distance((lat1 + lat2) / 2.0, lon1, lon2); + let x: f64 = lon_distance((lat1 + lat2) / 2.0, lon1, lon2); (z, x) } @@ -296,10 +299,10 @@ fn geo_distance(lat1: f64, lat2: f64, lon1: f64, lon2: f64) -> (f64, f64) { // returns meters fn lon_distance(lat: f64, lon1: f64, lon2: f64) -> f64 { const R: f64 = 6_371_000.0; - let d_lon = (lon2 - lon1).to_radians(); - let a = + let d_lon: f64 = (lon2 - lon1).to_radians(); + let a: f64 = lat.to_radians().cos() * lat.to_radians().cos() * (d_lon / 2.0).sin() * (d_lon / 2.0).sin(); - let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt()); + let c: f64 = 2.0 * a.sqrt().atan2((1.0 - a).sqrt()); R * c } @@ -308,9 +311,9 @@ fn lon_distance(lat: f64, lon1: f64, lon2: f64) -> f64 { // returns meters fn lat_distance(lat1: f64, lat2: f64) -> f64 { const R: f64 = 6_371_000.0; - let d_lat = (lat2 - lat1).to_radians(); - let a = (d_lat / 2.0).sin() * (d_lat / 2.0).sin(); - let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt()); + let d_lat: f64 = (lat2 - lat1).to_radians(); + let a: f64 = (d_lat / 2.0).sin() * (d_lat / 2.0).sin(); + let c: f64 = 2.0 * a.sqrt().atan2((1.0 - a).sqrt()); R * c } diff --git a/src/progress.rs b/src/progress.rs new file mode 100644 index 0000000..488ea48 --- /dev/null +++ b/src/progress.rs @@ -0,0 +1,46 @@ +use once_cell::sync::OnceCell; +use serde_json::json; +use tauri::{Emitter, WebviewWindow}; + +pub static MAIN_WINDOW: OnceCell = OnceCell::new(); + +pub fn set_main_window(window: WebviewWindow) { + MAIN_WINDOW.set(window).ok(); +} + +pub fn get_main_window() -> Option<&'static WebviewWindow> { + MAIN_WINDOW.get() +} + +/// This function checks if the program is running with a GUI window. +/// Returns `true` if a GUI window is initialized, `false` otherwise. +pub fn is_running_with_gui() -> bool { + get_main_window().is_some() +} + +/// This code manages a multi-step process with a progress bar indicating the overall completion. +/// The progress updates are mapped to specific steps in the pipeline: +/// +/// [1/5] Fetching data... - Starts at: 0% / Completes at: 5% +/// [2/5] Parsing data... - Starts at: 5% / Completes at: 10% +/// [3/5] Processing data... - Starts at: 10% / Completes at: 60% +/// [4/5] Generating ground layer... - Starts at: 60% / Completes at: 90% +/// [5/5] Saving world... - Starts at: 90% / Completes at: 100% +/// +/// The function `emit_gui_progress_update` is used to send real-time progress updates to the UI. +pub fn emit_gui_progress_update(progress: f64, message: &str) { + if let Some(window) = get_main_window() { + let payload = json!({ + "progress": progress, + "message": message + }); + + if let Err(e) = window.emit("progress-update", payload) { + eprintln!("Failed to emit progress event: {}", e); + } + } +} + +pub fn emit_gui_error(message: &str) { + emit_gui_progress_update(0.0, &format!("Error! {}", message)); +} diff --git a/src/retrieve_data.rs b/src/retrieve_data.rs index c27b1c6..60da3d7 100644 --- a/src/retrieve_data.rs +++ b/src/retrieve_data.rs @@ -1,3 +1,4 @@ +use crate::progress::{emit_gui_error, emit_gui_progress_update, is_running_with_gui}; use colored::Colorize; use rand::seq::SliceRandom; use reqwest::blocking::Client; @@ -14,7 +15,8 @@ fn download_with_reqwest(url: &str, query: &str) -> Result = + client.get(url).query(&[("data", query)]).send(); match response { Ok(resp) => { @@ -32,10 +34,17 @@ fn download_with_reqwest(url: &str, query: &str) -> Result Result> { println!("{} Fetching data...", "[1/5]".bold()); + emit_gui_progress_update(1.0, "Fetching data..."); // List of Overpass API servers let api_servers: Vec<&str> = vec![ @@ -146,22 +156,33 @@ pub fn fetch_data( // Check if the remark mentions memory or other runtime errors if remark.contains("runtime error") && remark.contains("out of memory") { eprintln!("{}", "Error! The query ran out of memory on the Overpass API server. Try using a smaller area.".red().bold()); + emit_gui_error("Try using a smaller area."); } else { // Handle other Overpass API errors if present in the remark field eprintln!( "{}", format!("Error! API returned: {}", remark).red().bold() ); + emit_gui_error(&format!("API returned: {}", remark)); } } else { // General case for when there are no elements and no specific remark - eprintln!("{}", "Error! No data available.".red().bold()); + eprintln!( + "{}", + "Error! No data available in this region.".red().bold() + ); + emit_gui_error("No data available in this region."); } if debug { println!("Additional debug information: {}", data); } - std::process::exit(1); + + if !is_running_with_gui() { + std::process::exit(1); + } else { + return Err("Data fetch failed".into()); + } } // If debug is enabled, write data to file @@ -170,6 +191,8 @@ pub fn fetch_data( file.write_all(response.as_bytes())?; } + emit_gui_progress_update(5.0, ""); + Ok(data) } } diff --git a/src/version_check.rs b/src/version_check.rs index b29901f..b2ee03d 100644 --- a/src/version_check.rs +++ b/src/version_check.rs @@ -9,8 +9,8 @@ const REMOTE_CARGO_TOML_URL: &str = "https://raw.githubusercontent.com/louis-e/arnis/main/Cargo.toml"; /// Fetches the latest version from the remote Cargo.toml file and compares it with the local version. -/// If a newer version is available, prints a message. -pub fn check_for_updates() -> Result<(), Box> { +/// Returns `true` if a newer version is available, `false` otherwise. +pub fn check_for_updates() -> Result> { let client: Client = Client::new(); // Fetch the remote Cargo.toml file with a User-Agent header @@ -24,7 +24,7 @@ pub fn check_for_updates() -> Result<(), Box> { // If the response status is not 200 OK, handle it as an HTTP error if !res.status().is_success() { handle_http_error(res.status()); - return Ok(()); + return Ok(false); } let response_text: String = res.text()?; @@ -40,12 +40,16 @@ pub fn check_for_updates() -> Result<(), Box> { local_version, remote_version ); + return Ok(true); // Newer version is available } - } - Err(err) => handle_request_error(err), - } - Ok(()) + Ok(false) // Local version is up-to-date + } + Err(err) => { + handle_request_error(err); + Ok(false) // Treat request failures as no new version available + } + } } /// Extracts the version from the contents of a Cargo.toml file. diff --git a/src/world_editor.rs b/src/world_editor.rs index 06d4449..9c21f9a 100644 --- a/src/world_editor.rs +++ b/src/world_editor.rs @@ -1,5 +1,6 @@ use crate::args::Args; use crate::block_definitions::*; +use crate::progress::emit_gui_progress_update; use colored::Colorize; use fastanvil::Region; use fastnbt::{LongArray, Value}; @@ -192,11 +193,11 @@ impl WorldToModify { fn get_block(&self, x: i32, y: i32, z: i32) -> Option { let chunk_x: i32 = x >> 4; let chunk_z: i32 = z >> 4; - let region_x = chunk_x >> 5; - let region_z = chunk_z >> 5; + let region_x: i32 = chunk_x >> 5; + let region_z: i32 = chunk_z >> 5; - let region = self.get_region(region_x, region_z)?; - let chunk = region.get_chunk(chunk_x & 31, chunk_z & 31)?; + let region: &RegionToModify = self.get_region(region_x, region_z)?; + let chunk: &ChunkToModify = region.get_chunk(chunk_x & 31, chunk_z & 31)?; chunk.get_block( (x & 15).try_into().unwrap(), @@ -208,11 +209,11 @@ impl WorldToModify { fn set_block(&mut self, x: i32, y: i32, z: i32, block: Block) { let chunk_x: i32 = x >> 4; let chunk_z: i32 = z >> 4; - let region_x = chunk_x >> 5; - let region_z = chunk_z >> 5; + let region_x: i32 = chunk_x >> 5; + let region_z: i32 = chunk_z >> 5; - let region = self.get_or_create_region(region_x, region_z); - let chunk = region.get_or_create_chunk(chunk_x & 31, chunk_z & 31); + let region: &mut RegionToModify = self.get_or_create_region(region_x, region_z); + let chunk: &mut ChunkToModify = region.get_or_create_chunk(chunk_x & 31, chunk_z & 31); chunk.set_block( (x & 15).try_into().unwrap(), @@ -249,7 +250,7 @@ impl<'a> WorldEditor<'a> { const REGION_TEMPLATE: &[u8] = include_bytes!("region.template"); - let mut region_file = File::options() + let mut region_file: File = File::options() .read(true) .write(true) .create(true) @@ -268,9 +269,10 @@ impl<'a> WorldEditor<'a> { (self.scale_factor_x as i32, self.scale_factor_x as i32) } - pub fn block_at(&self, x: i32, y: i32, z: i32) -> bool { + // Unused and not tested + /*pub fn block_at(&self, x: i32, y: i32, z: i32) -> bool { self.world.get_block(x, y, z).is_some() - } + }*/ /// Sets a block of the specified type at the given coordinates. pub fn set_block( @@ -292,11 +294,11 @@ impl<'a> WorldEditor<'a> { if let Some(whitelist) = override_whitelist { whitelist .iter() - .any(|whitelisted_block| whitelisted_block.id() == existing_block.id()) + .any(|whitelisted_block: &Block| whitelisted_block.id() == existing_block.id()) } else if let Some(blacklist) = override_blacklist { !blacklist .iter() - .any(|blacklisted_block| blacklisted_block.id() == existing_block.id()) + .any(|blacklisted_block: &Block| blacklisted_block.id() == existing_block.id()) } else { false } @@ -351,7 +353,7 @@ impl<'a> WorldEditor<'a> { if let Some(whitelist) = whitelist { if whitelist .iter() - .any(|whitelisted_block| whitelisted_block.id() == existing_block.id()) + .any(|whitelisted_block: &Block| whitelisted_block.id() == existing_block.id()) { return true; // Block is in whitelist } @@ -359,7 +361,7 @@ impl<'a> WorldEditor<'a> { if let Some(blacklist) = blacklist { if blacklist .iter() - .any(|blacklisted_block| blacklisted_block.id() == existing_block.id()) + .any(|blacklisted_block: &Block| blacklisted_block.id() == existing_block.id()) { return true; // Block is in blacklist } @@ -372,6 +374,7 @@ impl<'a> WorldEditor<'a> { /// Saves all changes made to the world by writing modified chunks to the appropriate region files. pub fn save(&mut self) { println!("{} Saving world...", "[5/5]".bold()); + emit_gui_progress_update(90.0, "Saving world..."); let _debug: bool = self.args.debug; let total_regions: u64 = self.world.regions.len() as u64; @@ -386,12 +389,17 @@ impl<'a> WorldEditor<'a> { .progress_chars("█▓░"), ); + let total_steps: f64 = 10.0; + let progress_increment_save: f64 = total_steps / total_regions as f64; + let mut current_progress_save: f64 = 90.0; + let mut last_emitted_progress: f64 = current_progress_save; + for ((region_x, region_z), region_to_modify) in &self.world.regions { - let mut region = self.create_region(*region_x, *region_z); + let mut region: Region = self.create_region(*region_x, *region_z); for chunk_x in 0..32 { for chunk_z in 0..32 { - let data = region + let data: Vec = region .read_chunk(chunk_x as usize, chunk_z as usize) .unwrap() .unwrap(); @@ -418,6 +426,12 @@ impl<'a> WorldEditor<'a> { } save_pb.inc(1); + + current_progress_save += progress_increment_save; + if (current_progress_save - last_emitted_progress).abs() > 0.25 { + emit_gui_progress_update(current_progress_save, "Saving world..."); + last_emitted_progress = current_progress_save; + } } save_pb.finish(); diff --git a/tauri.conf.json b/tauri.conf.json new file mode 100644 index 0000000..749fc95 --- /dev/null +++ b/tauri.conf.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "Arnis", + "version": "2.1.0", + "identifier": "com.louisdev.arnis", + "build": { + "frontendDist": "gui-src" + }, + "app": { + "withGlobalTauri": true, + "windows": [ + { + "title": "Arnis", + "width": 1000, + "height": 650, + "resizable": false, + "transparent": true, + "center": true + } + ], + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] + } +}